[llvm-branch-commits] [lldb] r198366 - IOHandler rewrite which replaced InputReader classes with classes that properly manage stdin/out/err.

Greg Clayton gclayton at apple.com
Thu Jan 2 14:40:15 PST 2014


Author: gclayton
Date: Thu Jan  2 16:40:14 2014
New Revision: 198366

URL: http://llvm.org/viewvc/llvm-project?rev=198366&view=rev
Log:
IOHandler rewrite which replaced InputReader classes with classes that properly manage stdin/out/err.

Benefits:
- curses is now supported as a IOHandler (run and hit a breakpoint and try the new "gui" command) 
- editline abilities become available to any IOHandler
- the ability to edit any lines when entering multiple lines (hit up and down arrow when editing multiple lines, use ^B and ^N for history when in multi-line mode)
- separate editline history for all multi-line readers (script, commands, prompts, etc)
- readline support is now enabled for python when in multi-line mode (history, line editing, and auto completion)
- auto complete is now enabled when entering multi-line commands in "breakpoint command add" and any other commands that push IOHandlers

So please try out this branch and fix anything that needs fixing so we can get all the kinks worked out so we can switch to it and merge it back into mainline.



Added:
    lldb/branches/iohandler/include/lldb/Core/IOHandler.h
    lldb/branches/iohandler/include/lldb/Host/Editline.h
    lldb/branches/iohandler/source/Commands/CommandObjectGUI.cpp
    lldb/branches/iohandler/source/Commands/CommandObjectGUI.h
    lldb/branches/iohandler/source/Core/IOHandler.cpp
    lldb/branches/iohandler/source/Host/common/Editline.cpp
Removed:
    lldb/branches/iohandler/include/lldb/API/SBInputReader.h
    lldb/branches/iohandler/include/lldb/Core/InputReader.h
    lldb/branches/iohandler/include/lldb/Core/InputReaderEZ.h
    lldb/branches/iohandler/include/lldb/Core/InputReaderStack.h
    lldb/branches/iohandler/scripts/Python/interface/SBInputReader.i
    lldb/branches/iohandler/source/API/SBInputReader.cpp
    lldb/branches/iohandler/source/Core/InputReader.cpp
    lldb/branches/iohandler/source/Core/InputReaderEZ.cpp
    lldb/branches/iohandler/source/Core/InputReaderStack.cpp
    lldb/branches/iohandler/tools/driver/IOChannel.cpp
    lldb/branches/iohandler/tools/driver/IOChannel.h
Modified:
    lldb/branches/iohandler/include/lldb/API/LLDB.h
    lldb/branches/iohandler/include/lldb/API/SBDebugger.h
    lldb/branches/iohandler/include/lldb/API/SBDefines.h
    lldb/branches/iohandler/include/lldb/API/SBError.h
    lldb/branches/iohandler/include/lldb/Core/Debugger.h
    lldb/branches/iohandler/include/lldb/Core/SourceManager.h
    lldb/branches/iohandler/include/lldb/Core/StreamAsynchronousIO.h
    lldb/branches/iohandler/include/lldb/Core/StringList.h
    lldb/branches/iohandler/include/lldb/Core/ValueObjectList.h
    lldb/branches/iohandler/include/lldb/Host/File.h
    lldb/branches/iohandler/include/lldb/Interpreter/CommandInterpreter.h
    lldb/branches/iohandler/include/lldb/Interpreter/PythonDataObjects.h
    lldb/branches/iohandler/include/lldb/Interpreter/ScriptInterpreterPython.h
    lldb/branches/iohandler/include/lldb/Target/Process.h
    lldb/branches/iohandler/include/lldb/Target/Target.h
    lldb/branches/iohandler/include/lldb/lldb-enumerations.h
    lldb/branches/iohandler/include/lldb/lldb-forward.h
    lldb/branches/iohandler/include/lldb/lldb-private-enumerations.h
    lldb/branches/iohandler/lldb.xcodeproj/project.pbxproj
    lldb/branches/iohandler/scripts/Python/build-swig-Python.sh
    lldb/branches/iohandler/scripts/Python/interface/SBDebugger.i
    lldb/branches/iohandler/scripts/Python/python-extensions.swig
    lldb/branches/iohandler/scripts/Python/python-swigsafecast.swig
    lldb/branches/iohandler/scripts/Python/python-typemaps.swig
    lldb/branches/iohandler/scripts/Python/python-wrapper.swig
    lldb/branches/iohandler/scripts/lldb.swig
    lldb/branches/iohandler/source/API/SBDebugger.cpp
    lldb/branches/iohandler/source/Commands/CommandObjectBreakpointCommand.cpp
    lldb/branches/iohandler/source/Commands/CommandObjectBreakpointCommand.h
    lldb/branches/iohandler/source/Commands/CommandObjectCommands.cpp
    lldb/branches/iohandler/source/Commands/CommandObjectExpression.cpp
    lldb/branches/iohandler/source/Commands/CommandObjectExpression.h
    lldb/branches/iohandler/source/Commands/CommandObjectProcess.cpp
    lldb/branches/iohandler/source/Commands/CommandObjectQuit.cpp
    lldb/branches/iohandler/source/Commands/CommandObjectTarget.cpp
    lldb/branches/iohandler/source/Commands/CommandObjectType.cpp
    lldb/branches/iohandler/source/Commands/CommandObjectWatchpointCommand.cpp
    lldb/branches/iohandler/source/Commands/CommandObjectWatchpointCommand.h
    lldb/branches/iohandler/source/Core/Broadcaster.cpp
    lldb/branches/iohandler/source/Core/Debugger.cpp
    lldb/branches/iohandler/source/Core/SourceManager.cpp
    lldb/branches/iohandler/source/Core/StreamAsynchronousIO.cpp
    lldb/branches/iohandler/source/Core/StringList.cpp
    lldb/branches/iohandler/source/Expression/ClangExpressionParser.cpp
    lldb/branches/iohandler/source/Host/common/File.cpp
    lldb/branches/iohandler/source/Interpreter/CommandInterpreter.cpp
    lldb/branches/iohandler/source/Interpreter/PythonDataObjects.cpp
    lldb/branches/iohandler/source/Interpreter/ScriptInterpreterNone.cpp
    lldb/branches/iohandler/source/Interpreter/ScriptInterpreterPython.cpp
    lldb/branches/iohandler/source/Interpreter/embedded_interpreter.py
    lldb/branches/iohandler/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
    lldb/branches/iohandler/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
    lldb/branches/iohandler/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
    lldb/branches/iohandler/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
    lldb/branches/iohandler/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/branches/iohandler/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
    lldb/branches/iohandler/source/Symbol/ClangASTType.cpp
    lldb/branches/iohandler/source/Target/ExecutionContext.cpp
    lldb/branches/iohandler/source/Target/Platform.cpp
    lldb/branches/iohandler/source/Target/Process.cpp
    lldb/branches/iohandler/source/Target/Target.cpp
    lldb/branches/iohandler/source/Target/ThreadPlanTracer.cpp
    lldb/branches/iohandler/tools/driver/Driver.cpp
    lldb/branches/iohandler/tools/driver/Driver.h

Modified: lldb/branches/iohandler/include/lldb/API/LLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/API/LLDB.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/API/LLDB.h (original)
+++ lldb/branches/iohandler/include/lldb/API/LLDB.h Thu Jan  2 16:40:14 2014
@@ -33,7 +33,6 @@
 #include "lldb/API/SBFrame.h"
 #include "lldb/API/SBFunction.h"
 #include "lldb/API/SBHostOS.h"
-#include "lldb/API/SBInputReader.h"
 #include "lldb/API/SBInstruction.h"
 #include "lldb/API/SBInstructionList.h"
 #include "lldb/API/SBLineEntry.h"

Modified: lldb/branches/iohandler/include/lldb/API/SBDebugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/API/SBDebugger.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/API/SBDebugger.h (original)
+++ lldb/branches/iohandler/include/lldb/API/SBDebugger.h Thu Jan  2 16:40:14 2014
@@ -228,15 +228,6 @@ public:
     void
     DispatchInputEndOfFile ();
     
-    void
-    PushInputReader (lldb::SBInputReader &reader);
-
-    void
-    NotifyTopInputReader (lldb::InputReaderAction notification);
-
-    bool
-    InputReaderIsTopReader (const lldb::SBInputReader &reader);
-
     const char *
     GetInstanceName  ();
 
@@ -313,10 +304,12 @@ public:
     GetSyntheticForType (SBTypeNameSpecifier);
 #endif
 
+    void
+    RunCommandInterpreter (bool auto_handle_events);
+
 private:
 
     friend class SBCommandInterpreter;
-    friend class SBInputReader;
     friend class SBListener;
     friend class SBProcess;
     friend class SBSourceManager;

Modified: lldb/branches/iohandler/include/lldb/API/SBDefines.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/API/SBDefines.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/API/SBDefines.h (original)
+++ lldb/branches/iohandler/include/lldb/API/SBDefines.h Thu Jan  2 16:40:14 2014
@@ -48,7 +48,6 @@ class SBFileSpecList;
 class SBFrame;
 class SBFunction;
 class SBHostOS;
-class SBInputReader;
 class SBInstruction;
 class SBInstructionList;
 class SBLineEntry;

Modified: lldb/branches/iohandler/include/lldb/API/SBError.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/API/SBError.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/API/SBError.h (original)
+++ lldb/branches/iohandler/include/lldb/API/SBError.h Thu Jan  2 16:40:14 2014
@@ -71,7 +71,6 @@ protected:
     friend class SBDebugger;
     friend class SBCommunication;
     friend class SBHostOS;
-    friend class SBInputReader;
     friend class SBPlatform;
     friend class SBProcess;
     friend class SBThread;

Removed: lldb/branches/iohandler/include/lldb/API/SBInputReader.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/API/SBInputReader.h?rev=198365&view=auto
==============================================================================
--- lldb/branches/iohandler/include/lldb/API/SBInputReader.h (original)
+++ lldb/branches/iohandler/include/lldb/API/SBInputReader.h (removed)
@@ -1,97 +0,0 @@
-//===-- SBInputReader.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_SBInputReader_h_
-#define LLDB_SBInputReader_h_
-
-#include "lldb/API/SBDefines.h"
-
-namespace lldb {
-
-class SBInputReader
-{
-public:
-
-    typedef size_t (*Callback) (void *baton, 
-                                SBInputReader *reader, 
-                                InputReaderAction notification,
-                                const char *bytes, 
-                                size_t bytes_len);
-
-    SBInputReader ();
-
-    SBInputReader (const lldb::InputReaderSP &reader_sp);
-
-    SBInputReader (const lldb::SBInputReader &rhs);
-
-    ~SBInputReader ();
-
-
-    SBError
-    Initialize (SBDebugger &debugger,
-                Callback callback,
-                void *callback_baton,
-                lldb::InputReaderGranularity granularity,
-                const char *end_token,
-                const char *prompt,
-                bool echo);
-    
-    bool
-    IsValid () const;
-
-    const lldb::SBInputReader &
-    operator = (const lldb::SBInputReader &rhs);
-
-    bool
-    IsActive () const;
-
-    bool
-    IsDone () const;
-
-    void
-    SetIsDone (bool value);
-
-    InputReaderGranularity
-    GetGranularity ();
-
-protected:
-    friend class SBDebugger;
-
-    lldb_private::InputReader *
-    operator->() const;
-
-    lldb::InputReaderSP &
-    operator *();
-
-    const lldb::InputReaderSP &
-    operator *() const;
-
-    lldb_private::InputReader *
-    get() const;
-
-    lldb_private::InputReader &
-    ref() const;
-
-private:
-
-    static size_t
-    PrivateCallback (void *baton, 
-                     lldb_private::InputReader &reader, 
-                     lldb::InputReaderAction notification,
-                     const char *bytes, 
-                     size_t bytes_len);
-
-    lldb::InputReaderSP m_opaque_sp;
-    Callback m_callback_function;
-    void *m_callback_baton;
-};
-
-} // namespace lldb
-
-#endif // LLDB_SBInputReader_h_

Modified: lldb/branches/iohandler/include/lldb/Core/Debugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Core/Debugger.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/Core/Debugger.h (original)
+++ lldb/branches/iohandler/include/lldb/Core/Debugger.h Thu Jan  2 16:40:14 2014
@@ -19,9 +19,8 @@
 #include "lldb/lldb-public.h"
 #include "lldb/Core/Broadcaster.h"
 #include "lldb/Core/Communication.h"
-#include "lldb/Core/InputReaderStack.h"
+#include "lldb/Core/IOHandler.h"
 #include "lldb/Core/Listener.h"
-#include "lldb/Core/StreamFile.h"
 #include "lldb/Core/SourceManager.h"
 #include "lldb/Core/UserID.h"
 #include "lldb/Core/UserSettingsController.h"
@@ -91,22 +90,22 @@ public:
     void
     SetAsyncExecution (bool async);
 
-    File &
+    lldb::StreamFileSP
     GetInputFile ()
     {
-        return m_input_file.GetFile();
+        return m_input_file_sp;
     }
 
-    File &
+    lldb::StreamFileSP
     GetOutputFile ()
     {
-        return m_output_file.GetFile();
+        return m_output_file_sp;
     }
 
-    File &
+    lldb::StreamFileSP
     GetErrorFile ()
     {
-        return m_error_file.GetFile();
+        return m_error_file_sp;
     }
     
     void
@@ -124,18 +123,6 @@ public:
     void
     RestoreInputTerminalState();
 
-    Stream&
-    GetOutputStream ()
-    {
-        return m_output_file;
-    }
-
-    Stream&
-    GetErrorStream ()
-    {
-        return m_error_file;
-    }
-
     lldb::StreamSP
     GetAsyncOutputStream ();
     
@@ -201,23 +188,27 @@ public:
     DispatchInputEndOfFile ();
 
     void
-    DispatchInput (const char *bytes, size_t bytes_len);
+    GetIOHandlerFiles (IOHandler &reader);
 
+//    bool
+//    TryPushIOHandler (const lldb::IOHandlerSP& reader_sp);
+//
     void
-    WriteToDefaultReader (const char *bytes, size_t bytes_len);
+    PushIOHandler (const lldb::IOHandlerSP& reader_sp);
 
+    bool
+    PopIOHandler (const lldb::IOHandlerSP& reader_sp);
+    
+    // Synchronously run an input reader until it is done
     void
-    PushInputReader (const lldb::InputReaderSP& reader_sp);
-
+    RunIOHandler (const lldb::IOHandlerSP& reader_sp);
+    
     bool
-    PopInputReader (const lldb::InputReaderSP& reader_sp);
+    HideTopIOHandler();
 
     void
-    NotifyTopInputReader (lldb::InputReaderAction notification);
+    RefreshTopIOHandler();
 
-    bool
-    InputReaderIsTopReader (const lldb::InputReaderSP& reader_sp);
-    
     static lldb::DebuggerSP
     FindDebuggerWithID (lldb::user_id_t id);
     
@@ -240,7 +231,7 @@ public:
 
 
     void
-    CleanUpInputReaders ();
+    ClearIOHandlers ();
 
     static int
     TestDebuggerRefCount ();
@@ -338,29 +329,57 @@ public:
     bool
     LoadPlugin (const FileSpec& spec, Error& error);
 
+    void
+    ExecuteIOHanders();
+    
+    bool
+    IsForwardingEvents ();
+
+    void
+    EnableForwardEvents (const lldb::ListenerSP &listener_sp);
+
+    void
+    CancelForwardEvents (const lldb::ListenerSP &listener_sp);
 protected:
 
-    static void
-    DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len);
+    friend class CommandInterpreter;
+
+    bool
+    StartEventHandlerThread();
 
-    lldb::InputReaderSP
-    GetCurrentInputReader ();
+    void
+    StopEventHandlerThread();
+    
+
+    static lldb::thread_result_t
+    EventHandlerThread (lldb::thread_arg_t arg);
     
     void
-    ActivateInputReader (const lldb::InputReaderSP &reader_sp);
+    DefaultEventHandler();
 
-    bool
-    CheckIfTopInputReaderIsDone ();
+    void
+    HandleBreakpointEvent (const lldb::EventSP &event_sp);
+    
+    void
+    HandleProcessEvent (const lldb::EventSP &event_sp);
+
+    void
+    HandleThreadEvent (const lldb::EventSP &event_sp);
+
+    size_t
+    GetProcessSTDOUT (Process *process, Stream *stream);
     
+    size_t
+    GetProcessSTDERR (Process *process, Stream *stream);
+
     SourceManager::SourceFileCache &
     GetSourceFileCache ()
     {
         return m_source_file_cache;
     }
-    Communication m_input_comm;
-    StreamFile m_input_file;
-    StreamFile m_output_file;
-    StreamFile m_error_file;
+    lldb::StreamFileSP m_input_file_sp;
+    lldb::StreamFileSP m_output_file_sp;
+    lldb::StreamFileSP m_error_file_sp;
     TerminalState m_terminal_state;
     TargetList m_target_list;
     PlatformList m_platform_list;
@@ -370,8 +389,7 @@ protected:
                                                         // source file cache.
     std::unique_ptr<CommandInterpreter> m_command_interpreter_ap;
 
-    InputReaderStack m_input_reader_stack;
-    std::string m_input_reader_data;
+    IOHandlerStack m_input_reader_stack;
     typedef std::map<std::string, lldb::StreamWP> LogStreamMap;
     LogStreamMap m_log_streams;
     lldb::StreamSP m_log_callback_stream_sp;
@@ -379,7 +397,9 @@ protected:
     static LoadPluginCallbackType g_load_plugin_callback;
     typedef std::vector<lldb::DynamicLibrarySP> LoadedPluginsList;
     LoadedPluginsList m_loaded_plugins;
-    
+    lldb::thread_t m_event_handler_thread;
+    lldb::ListenerSP m_forward_listener_sp;
+    bool m_event_handler_thread_alive;
     void
     InstanceInitialize ();
     

Added: lldb/branches/iohandler/include/lldb/Core/IOHandler.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Core/IOHandler.h?rev=198366&view=auto
==============================================================================
--- lldb/branches/iohandler/include/lldb/Core/IOHandler.h (added)
+++ lldb/branches/iohandler/include/lldb/Core/IOHandler.h Thu Jan  2 16:40:14 2014
@@ -0,0 +1,558 @@
+//===-- IOHandler.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_IOHandler_h_
+#define liblldb_IOHandler_h_
+
+#include <string.h>
+
+#include <stack>
+
+#include "lldb/lldb-public.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Host/Mutex.h"
+
+namespace curses
+{
+    class Application;
+    typedef std::unique_ptr<Application> ApplicationAP;
+}
+
+namespace lldb_private {
+
+    class IOHandler
+    {
+    public:
+        IOHandler (Debugger &debugger);
+
+        IOHandler (Debugger &debugger,
+                   const lldb::StreamFileSP &input_sp,
+                   const lldb::StreamFileSP &output_sp,
+                   const lldb::StreamFileSP &error_sp);
+
+        virtual
+        ~IOHandler ();
+
+        // Each IOHandler gets to run until it is done. It should read data
+        // from the "in" and place output into "out" and "err and return
+        // when done.
+        virtual void
+        Run () = 0;
+
+        // Hide any characters that have been displayed so far so async
+        // output can be displayed. Refresh() will be called after the
+        // output has been displayed.
+        virtual void
+        Hide () = 0;
+        
+        // Called when the async output has been received in order to update
+        // the input reader (refresh the prompt and redisplay any current
+        // line(s) that are being edited
+        virtual void
+        Refresh () = 0;
+
+        virtual void
+        Interrupt () = 0;
+        
+        virtual void
+        GotEOF() = 0;
+        
+        virtual bool
+        IsActive ()
+        {
+            return m_active && !m_done;
+        }
+
+        virtual void
+        SetIsDone (bool b)
+        {
+            m_done = b;
+        }
+
+        virtual bool
+        GetIsDone ()
+        {
+            return m_done;
+        }
+
+        virtual void
+        Activate ()
+        {
+            m_active = true;
+        }
+        
+        virtual void
+        Deactivate ()
+        {
+            m_active = false;
+        }
+
+        virtual const char *
+        GetPrompt ()
+        {
+            // Prompt support isn't mandatory
+            return NULL;
+        }
+        
+        virtual bool
+        SetPrompt (const char *prompt)
+        {
+            // Prompt support isn't mandatory
+            return false;
+        }
+        
+        int
+        GetInputFD();
+        
+        int
+        GetOutputFD();
+        
+        int
+        GetErrorFD();
+
+        FILE *
+        GetInputFILE();
+        
+        FILE *
+        GetOutputFILE();
+        
+        FILE *
+        GetErrorFILE();
+
+        lldb::StreamFileSP &
+        GetInputStreamFile();
+        
+        lldb::StreamFileSP &
+        GetOutputStreamFile();
+        
+        lldb::StreamFileSP &
+        GetErrorStreamFile();
+
+        Debugger &
+        GetDebugger()
+        {
+            return m_debugger;
+        }
+
+        void *
+        GetUserData ()
+        {
+            return m_user_data;
+        }
+
+        void
+        SetUserData (void *user_data)
+        {
+            m_user_data = user_data;
+        }
+
+    protected:
+        Debugger &m_debugger;
+        lldb::StreamFileSP m_input_sp;
+        lldb::StreamFileSP m_output_sp;
+        lldb::StreamFileSP m_error_sp;
+        void *m_user_data;
+        bool m_done;
+        bool m_active;
+
+    private:
+        DISALLOW_COPY_AND_ASSIGN (IOHandler);
+    };
+
+    
+    //------------------------------------------------------------------
+    /// A delegate class for use with IOHandler subclasses.
+    ///
+    /// The IOHandler delegate is designed to be mixed into classes so
+    /// they can use an IOHandler subclass to fetch input and notify the
+    /// object that inherits from this delegate class when a token is
+    /// received.
+    //------------------------------------------------------------------
+    class IOHandlerDelegate
+    {
+    public:
+        enum class Completion {
+            None,
+            LLDBCommand,
+            Expression
+        };
+        
+        IOHandlerDelegate (Completion completion = Completion::None) :
+            m_completion(completion),
+            m_io_handler_done (false)
+        {
+        }
+        
+        virtual
+        ~IOHandlerDelegate()
+        {
+        }
+        
+        virtual void
+        IOHandlerActivated (IOHandler &io_handler)
+        {
+        }
+        
+        virtual 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);
+        
+        //------------------------------------------------------------------
+        /// Called when a line or lines have been retrieved.
+        ///
+        /// This funtion can handle the current line and possibly call
+        /// IOHandler::SetIsDone(true) when the IO handler is done like when
+        /// "quit" is entered as a command, of when an empty line is
+        /// received. It is up to the delegate to determine when a line
+        /// should cause a IOHandler to exit.
+        //------------------------------------------------------------------
+        virtual void
+        IOHandlerInputComplete (IOHandler &io_handler, std::string &data) = 0;
+        
+        //------------------------------------------------------------------
+        /// Called when a line in \a lines has been updated when doing
+        /// multi-line input.
+        ///
+        /// @return
+        ///     Return an enumeration to indicate the status of the current
+        ///     line:
+        ///         Success - The line is good and should be added to the
+        ///                   multiple lines
+        ///         Error - There is an error with the current line and it
+        ///                 need to be re-edited before it is acceptable
+        ///         Done - The lines collection is complete and ready to be
+        ///                returned.
+        //------------------------------------------------------------------
+        virtual LineStatus
+        IOHandlerLinesUpdated (IOHandler &io_handler,
+                               StringList &lines,
+                               uint32_t line_idx,
+                               Error &error)
+        {
+            return LineStatus::Done; // Stop getting lines on the first line that is updated
+            // subclasses should do something more intelligent here.
+            // This function will not be called on IOHandler objects
+            // that are getting single lines.
+        }
+        
+    protected:
+        Completion m_completion; // Support for common builtin completions
+        bool m_io_handler_done;
+    };
+
+    //----------------------------------------------------------------------
+    // IOHandlerDelegateMultiline
+    //
+    // A IOHandlerDelegate that handles terminating multi-line input when
+    // the last line is equal to "end_line" which is specified in the
+    // constructor.
+    //----------------------------------------------------------------------
+    class IOHandlerDelegateMultiline :
+        public IOHandlerDelegate
+    {
+    public:
+        IOHandlerDelegateMultiline (const char *end_line,
+                                    Completion completion = Completion::None) :
+            IOHandlerDelegate (completion),
+            m_end_line((end_line && end_line[0]) ? end_line : "")
+        {
+        }
+        
+        virtual
+        ~IOHandlerDelegateMultiline ()
+        {
+        }
+        
+        virtual LineStatus
+        IOHandlerLinesUpdated (IOHandler &io_handler,
+                               StringList &lines,
+                               uint32_t line_idx,
+                               Error &error)
+        {
+            if (line_idx == UINT32_MAX)
+            {
+                // Remove the last empty line from "lines" so it doesn't appear
+                // in our final expression and return true to indicate we are done
+                // getting lines
+                lines.PopBack();
+                return LineStatus::Done;
+            }
+            else if (line_idx + 1 == lines.GetSize())
+            {
+                // The last line was edited, if this line is empty, then we are done
+                // getting our multiple lines.
+                if (lines[line_idx] == m_end_line)
+                    return LineStatus::Done;
+            }
+            return LineStatus::Success;
+        }
+    protected:
+        const std::string m_end_line;
+    };
+    
+    
+    class IOHandlerEditline : public IOHandler
+    {
+    public:
+        IOHandlerEditline (Debugger &debugger,
+                           const char *editline_name, // Used for saving history files
+                           const char *prompt,
+                           bool multi_line,
+                           IOHandlerDelegate &delegate);
+
+        IOHandlerEditline (Debugger &debugger,
+                           const lldb::StreamFileSP &input_sp,
+                           const lldb::StreamFileSP &output_sp,
+                           const lldb::StreamFileSP &error_sp,
+                           const char *editline_name, // Used for saving history files
+                           const char *prompt,
+                           bool multi_line,
+                           IOHandlerDelegate &delegate);
+        
+        virtual
+        ~IOHandlerEditline ();
+        
+        virtual void
+        Run ();
+        
+        virtual void
+        Hide ();
+
+        virtual void
+        Refresh ();
+
+        virtual void
+        Interrupt ();
+        
+        virtual void
+        GotEOF();
+        
+        virtual void
+        Activate ()
+        {
+            IOHandler::Activate();
+            m_delegate.IOHandlerActivated(*this);
+        }
+
+        virtual const char *
+        GetPrompt ();
+        
+        virtual bool
+        SetPrompt (const char *prompt);
+
+        bool
+        GetLine (std::string &line);
+        
+        bool
+        GetLines (StringList &lines);
+
+    private:
+        static LineStatus
+        LineCompletedCallback (Editline *editline,
+                               StringList &lines,
+                               uint32_t line_idx,
+                               Error &error,
+                               void *baton);
+
+        static int AutoCompleteCallback (const char *current_line,
+                                         const char *cursor,
+                                         const char *last_char,
+                                         int skip_first_n_matches,
+                                         int max_matches,
+                                         StringList &matches,
+                                         void *baton);
+
+    protected:
+        std::unique_ptr<Editline> m_editline_ap;
+        IOHandlerDelegate &m_delegate;
+        bool m_multi_line;
+        
+    };
+    
+    class IOHandlerConfirm :
+        public IOHandlerEditline,
+        public IOHandlerDelegate
+    {
+    public:
+        IOHandlerConfirm (Debugger &debugger,
+                          const char *prompt,
+                          bool default_response);
+        
+        virtual
+        ~IOHandlerConfirm ();
+                
+        bool
+        GetResponse () const
+        {
+            return m_user_response;
+        }
+        
+        virtual 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);
+        
+        virtual void
+        IOHandlerInputComplete (IOHandler &io_handler, std::string &data);
+
+    protected:
+        const bool m_default_response;
+        bool m_user_response;
+    };
+
+    class IOHandlerCursesGUI :
+        public IOHandler
+    {
+    public:
+        IOHandlerCursesGUI (Debugger &debugger);
+        
+        virtual
+        ~IOHandlerCursesGUI ();
+        
+        virtual void
+        Run ();
+        
+        virtual void
+        Hide ();
+        
+        virtual void
+        Refresh ();
+        
+        virtual void
+        Interrupt ();
+        
+        virtual void
+        GotEOF();
+        
+        virtual void
+        Activate ();
+        
+        virtual void
+        Deactivate ();
+
+    protected:
+        curses::ApplicationAP m_app_ap;
+    };
+
+    class IOHandlerCursesValueObjectList :
+        public IOHandler
+    {
+    public:
+        IOHandlerCursesValueObjectList (Debugger &debugger, ValueObjectList &valobj_list);
+        
+        virtual
+        ~IOHandlerCursesValueObjectList ();
+        
+        virtual void
+        Run ();
+        
+        virtual void
+        Hide ();
+        
+        virtual void
+        Refresh ();
+        
+        virtual void
+        Interrupt ();
+        
+        virtual void
+        GotEOF();
+    protected:
+        ValueObjectList m_valobj_list;
+    };
+
+    class IOHandlerStack
+    {
+    public:
+        
+        IOHandlerStack () :
+            m_stack(),
+            m_mutex(Mutex::eMutexTypeRecursive)
+        {
+        }
+        
+        ~IOHandlerStack ()
+        {
+        }
+        
+        size_t
+        GetSize () const
+        {
+            Mutex::Locker locker (m_mutex);
+            return m_stack.size();
+        }
+        
+        void
+        Push (const lldb::IOHandlerSP& sp)
+        {
+            if (sp)
+            {
+                Mutex::Locker locker (m_mutex);
+                m_stack.push (sp);
+            }
+        }
+        
+        bool
+        IsEmpty () const
+        {
+            Mutex::Locker locker (m_mutex);
+            return m_stack.empty();
+        }
+        
+        lldb::IOHandlerSP
+        Top ()
+        {
+            lldb::IOHandlerSP sp;
+            {
+                Mutex::Locker locker (m_mutex);
+                if (!m_stack.empty())
+                    sp = m_stack.top();
+            }
+            return sp;
+        }
+        
+        void
+        Pop ()
+        {
+            Mutex::Locker locker (m_mutex);
+            if (!m_stack.empty())
+                m_stack.pop();
+        }
+
+        Mutex &
+        GetMutex()
+        {
+            return m_mutex;
+        }
+        
+    protected:
+        
+        std::stack<lldb::IOHandlerSP> m_stack;
+        mutable Mutex m_mutex;
+        
+    private:
+        
+        DISALLOW_COPY_AND_ASSIGN (IOHandlerStack);
+    };
+
+} // namespace lldb_private
+
+#endif // #ifndef liblldb_IOHandler_h_

Removed: lldb/branches/iohandler/include/lldb/Core/InputReader.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Core/InputReader.h?rev=198365&view=auto
==============================================================================
--- lldb/branches/iohandler/include/lldb/Core/InputReader.h (original)
+++ lldb/branches/iohandler/include/lldb/Core/InputReader.h (removed)
@@ -1,274 +0,0 @@
-//===-- InputReader.h -------------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_InputReader_h_
-#define liblldb_InputReader_h_
-
-#include <string.h>
-
-#include "lldb/lldb-public.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/StringList.h"
-#include "lldb/Host/Predicate.h"
-
-
-namespace lldb_private {
-
-class InputReader
-{
-public:
-
-    typedef size_t (*Callback) (void *baton, 
-                                InputReader &reader, 
-                                lldb::InputReaderAction notification,
-                                const char *bytes, 
-                                size_t bytes_len);
-    
-    struct HandlerData
-    {
-        InputReader& reader;
-        const char *bytes;
-        size_t bytes_len;
-        void* baton;
-        
-        HandlerData(InputReader& r,
-                    const char* b,
-                    size_t l,
-                    void* t) : 
-        reader(r),
-        bytes(b),
-        bytes_len(l),
-        baton(t)
-        {
-        }
-        
-        lldb::StreamSP
-        GetOutStream();
-        
-        bool
-        GetBatchMode();
-    };
-    
-    struct InitializationParameters
-    {
-    private:
-        void* m_baton;
-        lldb::InputReaderGranularity m_token_size;
-        char* m_end_token;
-        char* m_prompt;
-        bool m_echo;
-        bool m_save_user_input;
-    public:
-        InitializationParameters() :
-        m_baton(NULL),
-        m_token_size(lldb::eInputReaderGranularityLine),
-        m_echo(true),
-        m_save_user_input(false)
-        {
-            SetEndToken("DONE");
-            SetPrompt("> ");
-        }
-        
-        InitializationParameters&
-        SetEcho(bool e)
-        {
-            m_echo = e;
-            return *this;
-        }
-        
-        InitializationParameters&
-        SetSaveUserInput(bool s)
-        {
-            m_save_user_input = s;
-            return *this;
-        }
-        
-        InitializationParameters&
-        SetBaton(void* b)
-        {
-            m_baton = b;
-            return *this;
-        }
-        
-        InitializationParameters&
-        SetGranularity(lldb::InputReaderGranularity g)
-        {
-            m_token_size = g;
-            return *this;
-        }
-        
-        InitializationParameters&
-        SetEndToken(const char* e)
-        {
-            m_end_token = new char[strlen(e)+1];
-            ::strcpy(m_end_token,e);
-            return *this;
-        }
-        
-        InitializationParameters&
-        SetPrompt(const char* p)
-        {
-            m_prompt = new char[strlen(p)+1];
-            ::strcpy(m_prompt,p);
-            return *this;
-        }
-        
-        friend class InputReaderEZ;
-        
-    };
-
-    InputReader (Debugger &debugger);
-
-    virtual
-    ~InputReader ();
-
-    virtual Error
-    Initialize (Callback callback, 
-                void *baton,
-                lldb::InputReaderGranularity token_size,
-                const char *end_token,
-                const char *prompt,
-                bool echo);
-    
-    virtual Error Initialize(void* baton,
-                             lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine,
-                             const char* end_token = "DONE",
-                             const char *prompt = "> ",
-                             bool echo = true)
-    {
-        return Error("unimplemented");
-    }
-    
-    virtual Error
-    Initialize(InitializationParameters& params)
-    {
-        return Error("unimplemented");
-    }
-    
-    // to use these handlers instead of the Callback function, you must subclass
-    // InputReaderEZ, and redefine the handlers for the events you care about
-    virtual void
-    ActivateHandler(HandlerData&) {}
-    
-    virtual void
-    DeactivateHandler(HandlerData&) {}
-    
-    virtual void
-    ReactivateHandler(HandlerData&) {}
-    
-    virtual void
-    AsynchronousOutputWrittenHandler(HandlerData&) {}
-    
-    virtual void
-    GotTokenHandler(HandlerData&) {}
-    
-    virtual void
-    InterruptHandler(HandlerData&) {}
-    
-    virtual void
-    EOFHandler(HandlerData&) {}
-    
-    virtual void
-    DoneHandler(HandlerData&) {}
-    
-    bool
-    IsDone () const
-    {
-        return m_done;
-    }
-
-    void
-    SetIsDone (bool b)
-    {
-        m_done = b;
-    }
-
-    lldb::InputReaderGranularity
-    GetGranularity () const
-    {
-        return m_granularity;
-    }
-
-    bool
-    GetEcho () const
-    {
-        return m_echo;
-    }
-    
-    StringList&
-    GetUserInput()
-    {
-        return m_user_input;
-    }
-    
-    virtual bool
-    GetSaveUserInput()
-    {
-        return false;
-    }
-
-    // Subclasses _can_ override this function to get input as it comes in
-    // without any granularity
-    virtual size_t
-    HandleRawBytes (const char *bytes, size_t bytes_len);
-
-    Debugger &
-    GetDebugger()
-    {
-        return m_debugger;
-    }
-
-    bool 
-    IsActive () const
-    {
-        return m_active;
-    }
-
-    const char *
-    GetPrompt () const;
-
-    void
-    RefreshPrompt();
-    
-    // If you want to read from an input reader synchronously, then just initialize the
-    // reader and then call WaitOnReaderIsDone, which will return when the reader is popped.
-    void
-    WaitOnReaderIsDone ();
-
-    static const char *
-    GranularityAsCString (lldb::InputReaderGranularity granularity);
-
-protected:
-    friend class Debugger;
-
-    void
-    Notify (lldb::InputReaderAction notification);
-
-    Debugger &m_debugger;
-    Callback m_callback;
-    void *m_callback_baton;
-    std::string m_end_token;
-    std::string m_prompt;
-    lldb::InputReaderGranularity m_granularity;
-    bool m_done;
-    bool m_echo;
-    bool m_active;
-    Predicate<bool> m_reader_done;
-    StringList m_user_input;
-    bool m_save_user_input;
-
-private:
-    DISALLOW_COPY_AND_ASSIGN (InputReader);
-
-};
-
-} // namespace lldb_private
-
-#endif // #ifndef liblldb_InputReader_h_

Removed: lldb/branches/iohandler/include/lldb/Core/InputReaderEZ.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Core/InputReaderEZ.h?rev=198365&view=auto
==============================================================================
--- lldb/branches/iohandler/include/lldb/Core/InputReaderEZ.h (original)
+++ lldb/branches/iohandler/include/lldb/Core/InputReaderEZ.h (removed)
@@ -1,87 +0,0 @@
-//===-- InputReaderEZ.h -----------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_InputReaderEZ_h_
-#define liblldb_InputReaderEZ_h_
-
-#include "lldb/Core/InputReader.h"
-
-namespace lldb_private {
-
-class InputReaderEZ : public InputReader
-{
-
-private:
-    
-    static size_t Callback_Impl(void *baton,
-                                InputReader &reader,
-                                lldb::InputReaderAction notification,
-                                const char *bytes,
-                                size_t bytes_len);
-public:
-    
-    InputReaderEZ (Debugger &debugger) :
-    InputReader(debugger)
-    {}
-
-    virtual
-    ~InputReaderEZ ();
-
-    using InputReader::Initialize;
-    virtual Error
-    Initialize(void* baton,
-               lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine,
-               const char* end_token = "DONE",
-               const char *prompt = "> ",
-               bool echo = true);
-        
-    virtual Error
-    Initialize(InitializationParameters& params);
-    
-    virtual void
-    ActivateHandler(HandlerData&) {}
-    
-    virtual void
-    DeactivateHandler(HandlerData&) {}
-    
-    virtual void
-    ReactivateHandler(HandlerData&) {}
-    
-    virtual void
-    AsynchronousOutputWrittenHandler(HandlerData&) {}
-    
-    virtual void
-    GotTokenHandler(HandlerData&) {}
-    
-    virtual void
-    InterruptHandler(HandlerData&) {}
-    
-    virtual void
-    EOFHandler(HandlerData&) {}
-    
-    virtual void
-    DoneHandler(HandlerData&) {}
-    
-    virtual bool
-    GetSaveUserInput()
-    {
-        return m_save_user_input;
-    }
-    
-protected:
-    friend class Debugger;
-
-private:
-    DISALLOW_COPY_AND_ASSIGN (InputReaderEZ);
-
-};
-
-} // namespace lldb_private
-
-#endif // #ifndef liblldb_InputReaderEZ_h_

Removed: lldb/branches/iohandler/include/lldb/Core/InputReaderStack.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Core/InputReaderStack.h?rev=198365&view=auto
==============================================================================
--- lldb/branches/iohandler/include/lldb/Core/InputReaderStack.h (original)
+++ lldb/branches/iohandler/include/lldb/Core/InputReaderStack.h (removed)
@@ -1,58 +0,0 @@
-//===-- InputReaderStack.h --------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_InputReaderStack_h_
-#define liblldb_InputReaderStack_h_
-
-#include <stack>
-
-#include "lldb/lldb-private.h"
-#include "lldb/Host/Mutex.h"
-
-namespace lldb_private {
-
-class InputReaderStack
-{
-public:
-
-    InputReaderStack ();
-    
-    ~InputReaderStack ();
-
-    size_t
-    GetSize () const;
-    
-    void
-    Push (const lldb::InputReaderSP& reader_sp);
-    
-    bool
-    IsEmpty () const;
-    
-    lldb::InputReaderSP
-    Top ();
-    
-    void
-    Pop ();
-    
-    Mutex &
-    GetStackMutex ();
-    
-protected:
-
-    std::stack<lldb::InputReaderSP> m_input_readers;
-    mutable Mutex m_input_readers_mutex;
-    
-private:
-
-    DISALLOW_COPY_AND_ASSIGN (InputReaderStack);
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_InputReaderStack_h_

Modified: lldb/branches/iohandler/include/lldb/Core/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Core/SourceManager.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/Core/SourceManager.h (original)
+++ lldb/branches/iohandler/include/lldb/Core/SourceManager.h Thu Jan  2 16:40:14 2014
@@ -70,6 +70,15 @@ public:
             return m_source_map_mod_id;
         }
         
+        const char *
+        PeekLineData (uint32_t line);
+
+        uint32_t
+        GetLineLength (uint32_t line, bool include_newline_chars);
+
+        uint32_t
+        GetNumLines ();
+        
     protected:
 
         bool
@@ -167,11 +176,11 @@ public:
                             uint32_t start_line, 
                             uint32_t end_line, 
                             std::vector<uint32_t> &match_lines);
-
-protected:
-
+    
     FileSP
     GetFile (const FileSpec &file_spec);
+
+protected:
     
     //------------------------------------------------------------------
     // Classes that inherit from SourceManager can see and modify these

Modified: lldb/branches/iohandler/include/lldb/Core/StreamAsynchronousIO.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Core/StreamAsynchronousIO.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/Core/StreamAsynchronousIO.h (original)
+++ lldb/branches/iohandler/include/lldb/Core/StreamAsynchronousIO.h Thu Jan  2 16:40:14 2014
@@ -13,7 +13,6 @@
 #include <string>
 
 #include "lldb/Core/Stream.h"
-#include "lldb/Core/StreamString.h"
 
 namespace lldb_private {
 
@@ -35,7 +34,7 @@ public:
 private:
     Broadcaster &m_broadcaster;
     uint32_t m_broadcast_event_type;
-    StreamString m_accumulated_data;
+    std::string m_accumulated_data;
 };
 
 } // namespace lldb_private

Modified: lldb/branches/iohandler/include/lldb/Core/StringList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Core/StringList.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/Core/StringList.h (original)
+++ lldb/branches/iohandler/include/lldb/Core/StringList.h Thu Jan  2 16:40:14 2014
@@ -34,6 +34,9 @@ public:
     AppendString (const std::string &s);
     
     void
+    AppendString (std::string &&s);
+    
+    void
     AppendString (const char *str);
 
     void
@@ -51,6 +54,31 @@ public:
     size_t
     GetSize () const;
 
+    void
+    SetSize (size_t n)
+    {
+        m_strings.resize(n);
+    }
+    
+    std::string &
+    operator [](size_t idx)
+    {
+        // No bounds checking, verify "idx" is good prior to calling this function
+        return m_strings[idx];
+    }
+    
+    const std::string &
+    operator [](size_t idx) const
+    {
+        // No bounds checking, verify "idx" is good prior to calling this function
+        return m_strings[idx];
+    }
+
+    void
+    PopBack ()
+    {
+        m_strings.pop_back();
+    }
     const char *
     GetStringAtIndex (size_t idx) const;
 
@@ -64,6 +92,12 @@ public:
     LongestCommonPrefix (std::string &common_prefix);
 
     void
+    InsertStringAtIndex (size_t idx, const std::string &str);
+    
+    void
+    InsertStringAtIndex (size_t idx, std::string &&str);
+    
+    void
     InsertStringAtIndex (size_t id, const char *str);
 
     void
@@ -73,11 +107,14 @@ public:
     RemoveBlankLines ();
 
     size_t
+    SplitIntoLines (const std::string &lines);
+
+    size_t
     SplitIntoLines (const char *lines, size_t len);
     
     std::string
     CopyList(const char* item_preamble = NULL,
-             const char* items_sep = "\n");
+             const char* items_sep = "\n") const;
     
     StringList&
     operator << (const char* str);

Modified: lldb/branches/iohandler/include/lldb/Core/ValueObjectList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Core/ValueObjectList.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/Core/ValueObjectList.h (original)
+++ lldb/branches/iohandler/include/lldb/Core/ValueObjectList.h Thu Jan  2 16:40:14 2014
@@ -75,6 +75,12 @@ public:
     void
     Swap (ValueObjectList &value_object_list);
     
+    void
+    Clear ()
+    {
+        m_value_objects.clear();
+    }
+
 protected:
     typedef std::vector<lldb::ValueObjectSP> collection;
     //------------------------------------------------------------------

Added: lldb/branches/iohandler/include/lldb/Host/Editline.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Host/Editline.h?rev=198366&view=auto
==============================================================================
--- lldb/branches/iohandler/include/lldb/Host/Editline.h (added)
+++ lldb/branches/iohandler/include/lldb/Host/Editline.h Thu Jan  2 16:40:14 2014
@@ -0,0 +1,209 @@
+//===-- Editline.h ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Editline_h_
+#define liblldb_Editline_h_
+#if defined(__cplusplus)
+
+#include "lldb/lldb-private.h"
+
+#include <stdio.h>
+#ifdef _WIN32
+#include "ELWrapper.h"
+#else
+#include <histedit.h>
+#endif
+
+#include <string>
+#include <vector>
+
+#include "lldb/Host/Condition.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class Editline Editline.h "lldb/Host/Editline.h"
+/// @brief A class that encapsulates editline functionality.
+//----------------------------------------------------------------------
+class Editline
+{
+public:
+    typedef LineStatus (*LineCompletedCallbackType) (
+        Editline *editline,
+        StringList &lines,
+        uint32_t line_idx,
+        Error &error,
+        void *baton);
+    
+    typedef int (*CompleteCallbackType) (
+        const char *current_line,
+        const char *cursor,
+        const char *last_char,
+        int skip_first_n_matches,
+        int max_matches,
+        StringList &matches,
+        void *baton);
+
+    typedef int (*GetCharCallbackType) (
+        ::EditLine *,
+        char *c);
+    
+    Editline(const char *prog,  // Used for the history file and for editrc program name
+             const char *prompt,
+             FILE *fin,
+             FILE *fout,
+             FILE *ferr);
+
+    ~Editline();
+
+    Error
+    GetLine (std::string &line);
+
+    Error
+    GetLines (const std::string &end_line, StringList &lines);
+
+    bool
+    LoadHistory ();
+    
+    bool
+    SaveHistory ();
+    
+    FILE *
+    GetInputFile ();
+    
+    FILE *
+    GetOutputFile ();
+    
+    FILE *
+    GetErrorFile ();
+
+    bool
+    GettingLine () const
+    {
+        return m_getting_line;
+    }
+
+    void
+    Hide ();
+
+    void
+    Refresh();
+
+    void
+    Interrupt ();
+
+    void
+    SetAutoCompleteCallback (CompleteCallbackType callback,
+                             void *baton)
+    {
+        m_completion_callback = callback;
+        m_completion_callback_baton = baton;
+    }
+
+    void
+    SetLineCompleteCallback (LineCompletedCallbackType callback,
+                             void *baton)
+    {
+        m_line_complete_callback = callback;
+        m_line_complete_callback_baton = baton;
+    }
+
+    size_t
+    Push (const char *bytes, size_t len);
+
+    // Cache bytes and use them for input without using a FILE. Calling this function
+    // will set the getc callback in the editline
+    size_t
+    SetInputBuffer (const char *c, size_t len);
+    
+    static int
+    GetCharFromInputFileCallback (::EditLine *e, char *c);
+
+    void
+    SetGetCharCallback (GetCharCallbackType callback);
+    
+    const char *
+    GetPrompt();
+    
+    void
+    SetPrompt (const char *p);
+
+private:
+
+    Error
+    PrivateGetLine(std::string &line);
+    
+    FileSpec
+    GetHistoryFile();
+
+    unsigned char
+    HandleCompletion (int ch);
+    
+    int
+    GetChar (char *c);
+
+
+    static unsigned char
+    CallbackEditPrevLine (::EditLine *e, int ch);
+    
+    static unsigned char
+    CallbackEditNextLine (::EditLine *e, int ch);
+    
+    static unsigned char
+    CallbackComplete (::EditLine *e, int ch);
+
+    static const char *
+    GetPromptCallback (::EditLine *e);
+
+    static Editline *
+    GetClientData (::EditLine *e);
+    
+    static FILE *
+    GetFilePointer (::EditLine *e, int fd);
+
+    static int
+    GetCharInputBufferCallback (::EditLine *e, char *c);
+
+    enum class Command
+    {
+        None = 0,
+        EditPrevLine,
+        EditNextLine,
+    };
+    ::EditLine *m_editline;
+    ::History *m_history;
+    ::HistEvent m_history_event;
+    std::string m_program;
+    std::string m_prompt;
+    std::string m_lines_prompt;
+    std::string m_getc_buffer;
+    Mutex m_getc_mutex;
+    Condition m_getc_cond;
+    CompleteCallbackType m_completion_callback;
+    void *m_completion_callback_baton;
+//    Mutex m_gets_mutex; // Make sure only one thread
+    LineCompletedCallbackType m_line_complete_callback;
+    void *m_line_complete_callback_baton;
+    Command m_lines_command;
+    uint32_t m_lines_curr_line;
+    uint32_t m_lines_max_line;
+    bool m_prompt_with_line_numbers;
+    bool m_getting_line;
+    bool m_got_eof;    // Set to true when we detect EOF
+    bool m_interrupted;
+    
+    DISALLOW_COPY_AND_ASSIGN(Editline);
+};
+
+} // namespace lldb_private
+
+#endif  // #if defined(__cplusplus)
+#endif  // liblldb_Host_h_

Modified: lldb/branches/iohandler/include/lldb/Host/File.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Host/File.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/Host/File.h (original)
+++ lldb/branches/iohandler/include/lldb/Host/File.h Thu Jan  2 16:40:14 2014
@@ -476,6 +476,12 @@ public:
     size_t
     PrintfVarArg(const char *format, va_list args);
 
+    
+    void
+    SetOptions (uint32_t options)
+    {
+        m_options = options;
+    }
 protected:
     
     

Modified: lldb/branches/iohandler/include/lldb/Interpreter/CommandInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Interpreter/CommandInterpreter.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/Interpreter/CommandInterpreter.h (original)
+++ lldb/branches/iohandler/include/lldb/Interpreter/CommandInterpreter.h Thu Jan  2 16:40:14 2014
@@ -17,6 +17,7 @@
 #include "lldb/lldb-private.h"
 #include "lldb/Core/Broadcaster.h"
 #include "lldb/Core/Debugger.h"
+#include "lldb/Core/IOHandler.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Interpreter/CommandHistory.h"
 #include "lldb/Interpreter/CommandObject.h"
@@ -29,7 +30,8 @@ namespace lldb_private {
 
 class CommandInterpreter :
     public Broadcaster,
-    public Properties
+    public Properties,
+    public IOHandlerDelegate
 {
 public:
     typedef std::map<std::string, OptionArgVectorSP> OptionArgMap;
@@ -317,20 +319,12 @@ public:
     const char *
     ProcessEmbeddedScriptCommands (const char *arg);
 
-    const char *
-    GetPrompt ();
-
     void
-    SetPrompt (const char *);
-    
-    bool Confirm (const char *message, bool default_answer);
+    UpdatePrompt (const char *);
     
-    static size_t
-    GetConfirmationInputReaderCallback (void *baton,
-                                        InputReader &reader,
-                                        lldb::InputReaderAction action,
-                                        const char *bytes,
-                                        size_t bytes_len);
+    bool
+    Confirm (const char *message,
+             bool default_answer);
     
     void
     LoadCommandDictionary ();
@@ -395,8 +389,12 @@ public:
     bool
     GetBatchCommandMode () { return m_batch_command_mode; }
     
-    void
-    SetBatchCommandMode (bool value) { m_batch_command_mode = value; }
+    bool
+    SetBatchCommandMode (bool value) {
+        const bool old_value = m_batch_command_mode;
+        m_batch_command_mode = value;
+        return old_value;
+    }
     
     void
     ChildrenTruncated ()
@@ -435,6 +433,21 @@ public:
         return m_command_history;
     }
     
+    void
+    RunCommandInterpreter(bool auto_handle_events);
+
+    void
+    GetLLDBCommandsFromIOHandler (const char *prompt,
+                                  IOHandlerDelegate &delegate,
+                                  bool asynchronously,
+                                  void *baton);
+
+    void
+    GetPythonCommandsFromIOHandler (const char *prompt,
+                                    IOHandlerDelegate &delegate,
+                                    bool asynchronously,
+                                    void *baton);
+
     //------------------------------------------------------------------
     // Properties
     //------------------------------------------------------------------
@@ -450,6 +463,16 @@ public:
 protected:
     friend class Debugger;
 
+    //------------------------------------------------------------------
+    // IOHandler::Delegate functions
+    //------------------------------------------------------------------
+    virtual void
+    IOHandlerInputComplete (IOHandler &io_handler,
+                            std::string &line);
+
+    size_t
+    GetProcessOutput ();
+
     void
     SetSynchronous (bool value);
 
@@ -473,6 +496,7 @@ private:
     CommandHistory m_command_history;
     std::string m_repeat_command;               // Stores the command that will be executed for an empty command string.
     std::unique_ptr<ScriptInterpreter> m_script_interpreter_ap;
+    lldb::IOHandlerSP m_command_io_handler_sp;
     char m_comment_char;
     bool m_batch_command_mode;
     ChildrenTruncatedWarningStatus m_truncation_warning;    // Whether we truncated children and whether the user has been told

Modified: lldb/branches/iohandler/include/lldb/Interpreter/PythonDataObjects.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Interpreter/PythonDataObjects.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/Interpreter/PythonDataObjects.h (original)
+++ lldb/branches/iohandler/include/lldb/Interpreter/PythonDataObjects.h Thu Jan  2 16:40:14 2014
@@ -31,7 +31,7 @@ namespace lldb_private {
         {
         }
         
-        PythonObject (PyObject* py_obj) :
+        explicit PythonObject (PyObject* py_obj) :
             m_py_obj(NULL)
         {
             Reset (py_obj);
@@ -43,7 +43,7 @@ namespace lldb_private {
             Reset (rhs.m_py_obj);
         }
         
-        PythonObject (const lldb::ScriptInterpreterObjectSP &script_object_sp);
+        explicit PythonObject (const lldb::ScriptInterpreterObjectSP &script_object_sp);
 
         virtual
         ~PythonObject ()
@@ -51,18 +51,10 @@ namespace lldb_private {
             Reset (NULL);
         }
 
-        const PythonObject &
-        operator = (const PythonObject &rhs)
-        {
-            if (this != &rhs)
-                Reset (rhs.m_py_obj);
-            return *this;
-        }
-
         bool
         Reset (const PythonObject &object)
         {
-            return Reset(object.GetPythonObject());
+            return Reset(object.get());
         }
 
         virtual bool
@@ -90,7 +82,7 @@ namespace lldb_private {
         Dump (Stream &strm) const;
 
         PyObject*
-        GetPythonObject () const
+        get () const
         {
             return m_py_obj;
         }
@@ -159,7 +151,7 @@ namespace lldb_private {
     {
     public:
         
-        PythonList ();
+        PythonList (bool create_empty);
         PythonList (PyObject* py_obj);
         PythonList (const PythonObject &object);
         PythonList (const lldb::ScriptInterpreterObjectSP &script_object_sp);
@@ -186,7 +178,7 @@ namespace lldb_private {
     {
     public:
         
-        PythonDictionary ();
+        explicit PythonDictionary (bool create_empty);
         PythonDictionary (PyObject* object);
         PythonDictionary (const PythonObject &object);
         PythonDictionary (const lldb::ScriptInterpreterObjectSP &script_object_sp);
@@ -221,6 +213,9 @@ namespace lldb_private {
         GetValueAtPosition (uint32_t pos) const;
         
         void
+        SetItemForKey (const PythonString &key, PyObject *value);
+
+        void
         SetItemForKey (const PythonString &key, const PythonObject& value);
     };
     

Modified: lldb/branches/iohandler/include/lldb/Interpreter/ScriptInterpreterPython.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Interpreter/ScriptInterpreterPython.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/Interpreter/ScriptInterpreterPython.h (original)
+++ lldb/branches/iohandler/include/lldb/Interpreter/ScriptInterpreterPython.h Thu Jan  2 16:40:14 2014
@@ -19,16 +19,21 @@
 
 #include "lldb/lldb-python.h"
 #include "lldb/lldb-private.h"
+#include "lldb/Core/IOHandler.h"
 #include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Core/InputReader.h"
+#include "lldb/Interpreter/PythonDataObjects.h"
 #include "lldb/Host/Terminal.h"
 
 namespace lldb_private {
     
-class ScriptInterpreterPython : public ScriptInterpreter
+class ScriptInterpreterPython :
+    public ScriptInterpreter,
+    public IOHandlerDelegateMultiline
 {
 public:
 
+    friend class IOHandlerPythonInterpreter;
+
     ScriptInterpreterPython (CommandInterpreter &interpreter);
 
     ~ScriptInterpreterPython ();
@@ -134,20 +139,20 @@ public:
     bool
     GenerateWatchpointCommandCallbackData (StringList &input, std::string& output);
 
-    static size_t
-    GenerateBreakpointOptionsCommandCallback (void *baton, 
-                                              InputReader &reader, 
-                                              lldb::InputReaderAction notification,
-                                              const char *bytes, 
-                                              size_t bytes_len);
-        
-    static size_t
-    GenerateWatchpointOptionsCommandCallback (void *baton, 
-                                              InputReader &reader, 
-                                              lldb::InputReaderAction notification,
-                                              const char *bytes, 
-                                              size_t bytes_len);
-        
+//    static size_t
+//    GenerateBreakpointOptionsCommandCallback (void *baton, 
+//                                              InputReader &reader, 
+//                                              lldb::InputReaderAction notification,
+//                                              const char *bytes, 
+//                                              size_t bytes_len);
+//    
+//    static size_t
+//    GenerateWatchpointOptionsCommandCallback (void *baton, 
+//                                              InputReader &reader, 
+//                                              lldb::InputReaderAction notification,
+//                                              const char *bytes, 
+//                                              size_t bytes_len);
+    
     static bool
     BreakpointCallbackFunction (void *baton, 
                                 StoppointCallbackContext *context, 
@@ -238,9 +243,6 @@ public:
     virtual void
     ResetOutputFileHandle (FILE *new_fh);
     
-    static lldb::thread_result_t
-    RunEmbeddedPythonInterpreter (lldb::thread_arg_t baton);
-
     static void
     InitializePrivate ();
 
@@ -266,10 +268,29 @@ public:
                            SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
                            SWIGPython_GetDynamicSetting swig_plugin_get);
 
+    const char *
+    GetDictionaryName ()
+    {
+        return m_dictionary_name.c_str();
+    }
+
+    
+    //----------------------------------------------------------------------
+    // IOHandlerDelegate
+    //----------------------------------------------------------------------
+    virtual void
+    IOHandlerActivated (IOHandler &io_handler);
+
+    virtual void
+    IOHandlerInputComplete (IOHandler &io_handler, std::string &data);
+
 protected:
 
     bool
-    EnterSession (bool init_lldb_globals);
+    EnterSession (bool init_lldb_globals,
+                  FILE *in,
+                  FILE *out,
+                  FILE *err);
     
     void
     LeaveSession ();
@@ -279,8 +300,6 @@ protected:
 
     void
     RestoreTerminalState ();
-
-private:
     
     class SynchronicityHandler
     {
@@ -322,7 +341,7 @@ private:
         private:
             DISALLOW_COPY_AND_ASSIGN (ScriptInterpreterPythonObject);
     };
-    
+public:
 	class Locker : public ScriptInterpreterLocker
 	{
 	public:
@@ -344,7 +363,9 @@ private:
         Locker (ScriptInterpreterPython *py_interpreter = NULL,
                 uint16_t on_entry = AcquireLock | InitSession,
                 uint16_t on_leave = FreeLock | TearDownSession,
-                FILE* wait_msg_handle = NULL);
+                FILE *in = NULL,
+                FILE *out = NULL,
+                FILE *err = NULL);
         
     	~Locker ();
 
@@ -354,7 +375,7 @@ private:
         DoAcquireLock ();
         
         bool
-        DoInitSession (bool init_lldb_globals);
+        DoInitSession (bool init_lldb_globals, FILE *in, FILE *out, FILE *err);
         
         bool
         DoFreeLock ();
@@ -367,59 +388,40 @@ private:
         
     	bool                     m_teardown_session;
     	ScriptInterpreterPython *m_python_interpreter;
-    	FILE*                    m_tmp_fh;
+//    	FILE*                    m_tmp_fh;
         PyGILState_STATE         m_GILState;
 	};
-    
-    class PythonInputReaderManager
-    {
-    public:
-        PythonInputReaderManager (ScriptInterpreterPython *interpreter);
-        
-        explicit operator bool()
-        {
-            return m_error;
-        }
-        
-        ~PythonInputReaderManager();
-        
-    private:
-        
-        static size_t
-        InputReaderCallback (void *baton,
-                                           InputReader &reader,
-                                           lldb::InputReaderAction notification,
-                                           const char *bytes,
-                                           size_t bytes_len);
-        
-        static lldb::thread_result_t
-        RunPythonInputReader (lldb::thread_arg_t baton);
-        
-        ScriptInterpreterPython *m_interpreter;
-        lldb::DebuggerSP m_debugger_sp;
-        lldb::InputReaderSP m_reader_sp;
-        bool m_error;
+private:
+
+    enum ActiveIOHandler {
+        eIOHandlerNone,
+        eIOHandlerBreakpoint,
+        eIOHandlerWatchpoint
     };
+    PythonObject &
+    GetMainModule ();
+    
+    PythonDictionary &
+    GetSessionDictionary ();
+    
+    PythonDictionary &
+    GetSysModuleDictionary ();
 
-    static size_t
-    InputReaderCallback (void *baton, 
-                         InputReader &reader, 
-                         lldb::InputReaderAction notification,
-                         const char *bytes, 
-                         size_t bytes_len);
-
-
-    lldb_utility::PseudoTerminal m_embedded_thread_pty;
-    lldb_utility::PseudoTerminal m_embedded_python_pty;
-    lldb::InputReaderSP m_embedded_thread_input_reader_sp;
-    lldb::InputReaderSP m_embedded_python_input_reader_sp;
-    FILE *m_dbg_stdout;
-    PyObject *m_new_sysout;
-    PyObject *m_old_sysout;
-    PyObject *m_old_syserr;
-    PyObject *m_run_one_line;
+    bool
+    GetEmbeddedInterpreterModuleObjects ();
+    
+    PythonObject m_saved_stdin;
+    PythonObject m_saved_stdout;
+    PythonObject m_saved_stderr;
+    PythonObject m_main_module;
+    PythonObject m_lldb_module;
+    PythonDictionary m_session_dict;
+    PythonDictionary m_sys_module_dict;
+    PythonObject m_run_one_line_function;
+    PythonObject m_run_one_line_str_global;
     std::string m_dictionary_name;
     TerminalState m_terminal_state;
+    ActiveIOHandler m_active_io_handler;
     bool m_session_is_active;
     bool m_pty_slave_is_open;
     bool m_valid_session;

Modified: lldb/branches/iohandler/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Target/Process.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/Target/Process.h (original)
+++ lldb/branches/iohandler/include/lldb/Target/Process.h Thu Jan  2 16:40:14 2014
@@ -535,7 +535,8 @@ public:
         m_resume_count (0),
         m_monitor_callback (NULL),
         m_monitor_callback_baton (NULL),
-        m_monitor_signals (false)
+        m_monitor_signals (false),
+        m_hijack_listener_sp ()
     {
     }
 
@@ -554,7 +555,8 @@ public:
         m_resume_count (0),
         m_monitor_callback (NULL),
         m_monitor_callback_baton (NULL),
-        m_monitor_signals (false)
+        m_monitor_signals (false),
+        m_hijack_listener_sp ()
     {
         if (stdin_path)
         {
@@ -781,6 +783,7 @@ public:
         m_flags.Clear();
         m_file_actions.clear();
         m_resume_count = 0;
+        m_hijack_listener_sp.reset();
     }
 
     bool
@@ -819,6 +822,19 @@ public:
     {
         return m_pty;
     }
+    
+    lldb::ListenerSP
+    GetHijackListener () const
+    {
+        return m_hijack_listener_sp;
+    }
+    
+    void
+    SetHijackListener (const lldb::ListenerSP &listener_sp)
+    {
+        m_hijack_listener_sp = listener_sp;
+    }
+
 
 protected:
     std::string m_working_dir;
@@ -831,7 +847,7 @@ protected:
     Host::MonitorChildProcessCallback m_monitor_callback;
     void *m_monitor_callback_baton;
     bool m_monitor_signals;
-
+    lldb::ListenerSP m_hijack_listener_sp;
 };
 
 //----------------------------------------------------------------------
@@ -864,6 +880,7 @@ public:
         ProcessInfo::operator= (launch_info);
         SetProcessPluginName (launch_info.GetProcessPluginName());
         SetResumeCount (launch_info.GetResumeCount());
+        SetHijackListener(launch_info.GetHijackListener());
     }
     
     bool
@@ -953,7 +970,22 @@ public:
             return true;
         return false;
     }
+    
+    lldb::ListenerSP
+    GetHijackListener () const
+    {
+        return m_hijack_listener_sp;
+    }
+    
+    void
+    SetHijackListener (const lldb::ListenerSP &listener_sp)
+    {
+        m_hijack_listener_sp = listener_sp;
+    }
+    
+
 protected:
+    lldb::ListenerSP m_hijack_listener_sp;
     std::string m_plugin_name;
     uint32_t m_resume_count; // How many times do we resume after launching
     bool m_wait_for_launch;
@@ -1367,10 +1399,11 @@ class Process :
     public ExecutionContextScope,
     public PluginInterface
 {
-friend class ThreadList;
-friend class ClangFunction; // For WaitForStateChangeEventsPrivate
-friend class ProcessEventData;
-friend class StopInfo;
+    friend class ClangFunction; // For WaitForStateChangeEventsPrivate
+    friend class ProcessEventData;
+    friend class StopInfo;
+    friend class Target;
+    friend class ThreadList;
 
 public:
 
@@ -3368,10 +3401,15 @@ public:
     // is set to the event which triggered the stop. If wait_always = false,
     // and the process is already stopped, this function returns immediately.
     lldb::StateType
-    WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr = NULL, bool wait_always = true);
+    WaitForProcessToStop (const TimeValue *timeout,
+                          lldb::EventSP *event_sp_ptr = NULL,
+                          bool wait_always = true,
+                          Listener *hijack_listener = NULL);
 
     lldb::StateType
-    WaitForStateChangedEvents (const TimeValue *timeout, lldb::EventSP &event_sp);
+    WaitForStateChangedEvents (const TimeValue *timeout,
+                               lldb::EventSP &event_sp,
+                               Listener *hijack_listener); // Pass NULL to use builtin listener
     
     Event *
     PeekAtStateChangedEvents ();
@@ -3538,6 +3576,12 @@ public:
     void
     SetSTDIOFileDescriptor (int file_descriptor);
 
+    void
+    WatchForSTDIN (IOHandler &io_handler);
+    
+    void
+    CancelWatchForSTDIN (bool exited);
+    
     //------------------------------------------------------------------
     // Add a permanent region of memory that should never be read or 
     // written to. This can be used to ensure that memory reads or writes
@@ -3724,7 +3768,7 @@ protected:
     std::unique_ptr<SystemRuntime> m_system_runtime_ap;
     UnixSignals                 m_unix_signals;         /// This is the current signal set for this process.
     lldb::ABISP                 m_abi_sp;
-    lldb::InputReaderSP         m_process_input_reader;
+    lldb::IOHandlerSP           m_process_input_reader;
     Communication               m_stdio_communication;
     Mutex                       m_stdio_communication_mutex;
     std::string                 m_stdout_data;
@@ -3819,21 +3863,14 @@ protected:
     STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
     
     void
-    PushProcessInputReader ();
+    PushProcessIOHandler ();
     
     void 
-    PopProcessInputReader ();
+    PopProcessIOHandler ();
     
     void
-    ResetProcessInputReader ();
-    
-    static size_t
-    ProcessInputReaderCallback (void *baton,
-                                InputReader &reader,
-                                lldb::InputReaderAction notification,
-                                const char *bytes,
-                                size_t bytes_len);
-    
+    ResetProcessIOHandler ();
+        
     Error
     HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp);
     

Modified: lldb/branches/iohandler/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/Target/Target.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/Target/Target.h (original)
+++ lldb/branches/iohandler/include/lldb/Target/Target.h Thu Jan  2 16:40:14 2014
@@ -1171,7 +1171,7 @@ public:
         std::unique_ptr<ThreadSpec> m_thread_spec_ap;
         bool m_active;
         
-        // Use AddStopHook to make a new empty stop hook.  The GetCommandPointer and fill it with commands,
+        // Use CreateStopHook to make a new empty stop hook. The GetCommandPointer and fill it with commands,
         // and SetSpecifier to set the specifier shared pointer (can be null, that will match anything.)
         StopHook (lldb::TargetSP target_sp, lldb::user_id_t uid);
         friend class Target;
@@ -1180,8 +1180,8 @@ public:
     
     // Add an empty stop hook to the Target's stop hook list, and returns a shared pointer to it in new_hook.  
     // Returns the id of the new hook.        
-    lldb::user_id_t
-    AddStopHook (StopHookSP &new_hook);
+    StopHookSP
+    CreateStopHook ();
     
     void
     RunStopHooks ();

Modified: lldb/branches/iohandler/include/lldb/lldb-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/lldb-enumerations.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/lldb-enumerations.h (original)
+++ lldb/branches/iohandler/include/lldb/lldb-enumerations.h Thu Jan  2 16:40:14 2014
@@ -231,19 +231,6 @@ namespace lldb {
         eValueTypeConstResult       = 7     // constant result variables
     } ValueType;
 
-    //----------------------------------------------------------------------
-    // Token size/granularities for Input Readers
-    //----------------------------------------------------------------------
-
-    typedef enum InputReaderGranularity
-    {
-        eInputReaderGranularityInvalid = 0,
-        eInputReaderGranularityByte,
-        eInputReaderGranularityWord,
-        eInputReaderGranularityLine,
-        eInputReaderGranularityAll
-    } InputReaderGranularity;
-
     //------------------------------------------------------------------
     /// These mask bits allow a common interface for queries that can
     /// limit the amount of information that gets parsed to only the
@@ -273,18 +260,6 @@ namespace lldb {
         ePermissionsExecutable  = (1u << 2)
     } Permissions;
 
-    typedef enum InputReaderAction
-    {
-        eInputReaderActivate,   // reader is newly pushed onto the reader stack 
-        eInputReaderAsynchronousOutputWritten, // an async output event occurred; the reader may want to do something
-        eInputReaderReactivate, // reader is on top of the stack again after another reader was popped off 
-        eInputReaderDeactivate, // another reader was pushed on the stack 
-        eInputReaderGotToken,   // reader got one of its tokens (granularity)
-        eInputReaderInterrupt,  // reader received an interrupt signal (probably from a control-c)
-        eInputReaderEndOfFile,  // reader received an EOF char (probably from a control-d)
-        eInputReaderDone        // reader was just popped off the stack and is done
-    } InputReaderAction;
-
     typedef enum BreakpointEventType
     {
         eBreakpointEventTypeInvalidType         = (1u << 0),

Modified: lldb/branches/iohandler/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/lldb-forward.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/lldb-forward.h (original)
+++ lldb/branches/iohandler/include/lldb/lldb-forward.h Thu Jan  2 16:40:14 2014
@@ -82,6 +82,7 @@ class   Disassembler;
 struct  DumpValueObjectOptions;
 class   DynamicLibrary;
 class   DynamicLoader;
+class   Editline;
 class   EmulateInstruction;
 class   Error;
 class   EvaluateExpressionOptions;
@@ -102,9 +103,9 @@ class   FuncUnwinders;
 class   Function;
 class   FunctionInfo;
 class   InlineFunctionInfo;
-class   InputReader;
 class   Instruction;
 class   InstructionList;
+class   IOHandler;
 class   IRExecutionUnit;
 class   LanguageRuntime;
 class   SystemRuntime;
@@ -302,8 +303,8 @@ namespace lldb {
     typedef std::shared_ptr<lldb_private::Function> FunctionSP;
     typedef std::shared_ptr<lldb_private::FuncUnwinders> FuncUnwindersSP;
     typedef std::shared_ptr<lldb_private::InlineFunctionInfo> InlineFunctionInfoSP;
-    typedef std::shared_ptr<lldb_private::InputReader> InputReaderSP;
     typedef std::shared_ptr<lldb_private::Instruction> InstructionSP;
+    typedef std::shared_ptr<lldb_private::IOHandler> IOHandlerSP;
     typedef std::shared_ptr<lldb_private::LanguageRuntime> LanguageRuntimeSP;
     typedef std::shared_ptr<lldb_private::SystemRuntime> SystemRuntimeSP;
     typedef std::shared_ptr<lldb_private::LineTable> LineTableSP;
@@ -358,6 +359,7 @@ namespace lldb {
     typedef std::shared_ptr<lldb_private::StoppointLocation> StoppointLocationSP;
     typedef std::shared_ptr<lldb_private::Stream> StreamSP;
     typedef std::weak_ptr<lldb_private::Stream> StreamWP;
+    typedef std::shared_ptr<lldb_private::StreamFile> StreamFileSP;
     typedef std::shared_ptr<lldb_private::StringSummaryFormat> StringTypeSummaryImplSP;
     typedef std::shared_ptr<lldb_private::SymbolFile> SymbolFileSP;
     typedef std::shared_ptr<lldb_private::SymbolFileType> SymbolFileTypeSP;

Modified: lldb/branches/iohandler/include/lldb/lldb-private-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/include/lldb/lldb-private-enumerations.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/include/lldb/lldb-private-enumerations.h (original)
+++ lldb/branches/iohandler/include/lldb/lldb-private-enumerations.h Thu Jan  2 16:40:14 2014
@@ -253,6 +253,15 @@ typedef enum MemoryModuleLoadLevel {
 } MemoryModuleLoadLevel;
     
 
+//----------------------------------------------------------------------
+// Result enums for when reading multiple lines from IOHandlers
+//----------------------------------------------------------------------
+enum class LineStatus {
+    Success,    // The line that was just edited if good and should be added to the lines
+    Error,      // There is an error with the current line and it needs to be re-edited before it can be accepted
+    Done        // Lines are complete
+};
+
 } // namespace lldb_private
 
 

Modified: lldb/branches/iohandler/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/lldb.xcodeproj/project.pbxproj?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/branches/iohandler/lldb.xcodeproj/project.pbxproj Thu Jan  2 16:40:14 2014
@@ -54,6 +54,8 @@
 		2606EDDE184E68940034641B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 260C876910F538E700BB2B04 /* Foundation.framework */; };
 		2606EDDF184E68A10034641B /* liblldb-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2689FFCA13353D7A00698AC0 /* liblldb-core.a */; };
 		260A248E15D06C50009981B0 /* OptionValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 260A248D15D06C4F009981B0 /* OptionValues.h */; };
+		260A63171861008E00FECF8E /* IOHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 260A63161861008E00FECF8E /* IOHandler.h */; };
+		260A63191861009E00FECF8E /* IOHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260A63181861009E00FECF8E /* IOHandler.cpp */; };
 		260CC62E15D04377002BF2E0 /* OptionValueArgs.h in Headers */ = {isa = PBXBuildFile; fileRef = 260CC62115D04377002BF2E0 /* OptionValueArgs.h */; };
 		260CC62F15D04377002BF2E0 /* OptionValueArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 260CC62215D04377002BF2E0 /* OptionValueArray.h */; };
 		260CC63015D04377002BF2E0 /* OptionValueBoolean.h in Headers */ = {isa = PBXBuildFile; fileRef = 260CC62315D04377002BF2E0 /* OptionValueBoolean.h */; };
@@ -113,7 +115,6 @@
 		265205AA13D3E3F700132FE2 /* RegisterContextKDP_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A413D3E3F700132FE2 /* RegisterContextKDP_i386.cpp */; };
 		265205AC13D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A613D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp */; };
 		2660AAB914622483003A9694 /* LLDBWrapPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */; };
-		2663E379152BD1890091EC22 /* ReadWriteLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 2663E378152BD1890091EC22 /* ReadWriteLock.h */; };
 		26651A18133BF9E0005B64B7 /* Opcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26651A17133BF9DF005B64B7 /* Opcode.cpp */; };
 		266603CA1345B5A8004DA8B6 /* ConnectionSharedMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266603C91345B5A8004DA8B6 /* ConnectionSharedMemory.cpp */; };
 		2668020E115FD12C008E1FE4 /* lldb-defines.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2510F1B3BC00F91463 /* lldb-defines.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -156,9 +157,12 @@
 		26680337116005F1008E1FE4 /* SBBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AF16A9C11402D5B007A7B3F /* SBBreakpoint.cpp */; };
 		2668035C11601108008E1FE4 /* LLDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26680207115FD0ED008E1FE4 /* LLDB.framework */; };
 		266DFE9713FD656E00D0C574 /* OperatingSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266DFE9613FD656E00D0C574 /* OperatingSystem.cpp */; };
+		2670F8121862B44A006B332C /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2670F8111862B44A006B332C /* libncurses.dylib */; };
 		2671A0D013482601003A87BB /* ConnectionMachPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */; };
 		26744EF11338317700EF765A /* GDBRemoteCommunicationClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */; };
 		26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */; };
+		26780C611867C33D00234593 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2670F8111862B44A006B332C /* libncurses.dylib */; };
+		26780C651867C34500234593 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2670F8111862B44A006B332C /* libncurses.dylib */; };
 		267C012B136880DF006E963E /* OptionGroupValueObjectDisplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */; };
 		267C01371368C49C006E963E /* OptionGroupOutputFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BCFC531368B3E4006DC050 /* OptionGroupOutputFile.cpp */; };
 		268648C416531BF800F04704 /* com.apple.debugserver.posix.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 268648C116531BF800F04704 /* com.apple.debugserver.posix.plist */; };
@@ -218,7 +222,6 @@
 		2689003C13353E0400698AC0 /* Error.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7810F1B85900F91463 /* Error.cpp */; };
 		2689003D13353E0400698AC0 /* Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7910F1B85900F91463 /* Event.cpp */; };
 		2689003E13353E0400698AC0 /* FileSpecList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7B10F1B85900F91463 /* FileSpecList.cpp */; };
-		2689003F13353E0400698AC0 /* InputReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AA69DB5118A027A00D753A0 /* InputReader.cpp */; };
 		2689004013353E0400698AC0 /* Language.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7D10F1B85900F91463 /* Language.cpp */; };
 		2689004113353E0400698AC0 /* Listener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7E10F1B85900F91463 /* Listener.cpp */; };
 		2689004213353E0400698AC0 /* Log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7F10F1B85900F91463 /* Log.cpp */; };
@@ -451,6 +454,13 @@
 		26C72C961243229A0068DC16 /* SBStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C72C951243229A0068DC16 /* SBStream.cpp */; };
 		26CA97A1172B1FD5005DC71B /* RegisterContextThreadMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26CA979F172B1FD5005DC71B /* RegisterContextThreadMemory.cpp */; };
 		26CA97A2172B1FD5005DC71B /* RegisterContextThreadMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = 26CA97A0172B1FD5005DC71B /* RegisterContextThreadMemory.h */; };
+		26CEB5EF18761CB2008F575A /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32A10F3DFDD009D5894 /* libedit.dylib */; };
+		26CEB5F218762056008F575A /* CommandObjectGUI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26CEB5F018762056008F575A /* CommandObjectGUI.cpp */; };
+		26CEB5F318762056008F575A /* CommandObjectGUI.h in Headers */ = {isa = PBXBuildFile; fileRef = 26CEB5F118762056008F575A /* CommandObjectGUI.h */; };
+		26CFDCA11861638D000E63E5 /* Editline.h in Headers */ = {isa = PBXBuildFile; fileRef = 26CFDCA01861638D000E63E5 /* Editline.h */; };
+		26CFDCA3186163A4000E63E5 /* Editline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26CFDCA2186163A4000E63E5 /* Editline.cpp */; };
+		26CFDCA71861646C000E63E5 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32A10F3DFDD009D5894 /* libedit.dylib */; };
+		26CFDCA818616473000E63E5 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32A10F3DFDD009D5894 /* libedit.dylib */; };
 		26D1803E16CEBFD300EDFB5B /* KQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D1803C16CEBFD300EDFB5B /* KQueue.cpp */; };
 		26D1804216CEDF0700EDFB5B /* TimeSpecTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D1804016CEDF0700EDFB5B /* TimeSpecTimeout.cpp */; };
 		26D1804516CEE12500EDFB5B /* KQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 26D1804416CEE12500EDFB5B /* KQueue.h */; };
@@ -491,8 +501,6 @@
 		26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */; };
 		26F4A21C13FBA31A0064B613 /* ThreadMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F4A21A13FBA31A0064B613 /* ThreadMemory.cpp */; };
 		26F5C27710F3D9E4009D5894 /* Driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F5C27310F3D9E4009D5894 /* Driver.cpp */; };
-		26F5C27810F3D9E4009D5894 /* IOChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F5C27510F3D9E4009D5894 /* IOChannel.cpp */; };
-		26F5C32C10F3DFDD009D5894 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32A10F3DFDD009D5894 /* libedit.dylib */; };
 		26F5C32D10F3DFDD009D5894 /* libtermcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32B10F3DFDD009D5894 /* libtermcap.dylib */; };
 		26F73062139D8FDB00FD51C7 /* History.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F73061139D8FDB00FD51C7 /* History.cpp */; };
 		26FFC19914FC072100087D58 /* AuxVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FFC19314FC072100087D58 /* AuxVector.cpp */; };
@@ -529,7 +537,6 @@
 		4CF3D80C15AF4DC800845BF3 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDB919B414F6F10D008FF64B /* Security.framework */; };
 		4CF52AF51428291E0051E832 /* SBFileSpecList.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF52AF41428291E0051E832 /* SBFileSpecList.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		4CF52AF8142829390051E832 /* SBFileSpecList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF52AF7142829390051E832 /* SBFileSpecList.cpp */; };
-		94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */; };
 		94094C6B163B6F840083A547 /* ValueObjectCast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94094C69163B6CD90083A547 /* ValueObjectCast.cpp */; };
 		94145431175E63B500284436 /* lldb-versioning.h in Headers */ = {isa = PBXBuildFile; fileRef = 94145430175D7FDE00284436 /* lldb-versioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		941BCC7F14E48C4000BB969C /* SBTypeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568614E355F2003A195C /* SBTypeFilter.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -595,10 +602,7 @@
 		9A3576A8116E9AB700E8ED2F /* SBHostOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A3576A7116E9AB700E8ED2F /* SBHostOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		9A3576AA116E9AC700E8ED2F /* SBHostOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */; };
 		9A4F35101368A51A00823F52 /* StreamAsynchronousIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */; };
-		9A9E1EFF1398086D005AC039 /* InputReaderStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9E1EFE1398086D005AC039 /* InputReaderStack.cpp */; };
 		9AA69DA61188F52100D753A0 /* PseudoTerminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */; };
-		9AA69DAF118A023300D753A0 /* SBInputReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AA69DAE118A023300D753A0 /* SBInputReader.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		9AA69DB1118A024600D753A0 /* SBInputReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AA69DB0118A024600D753A0 /* SBInputReader.cpp */; };
 		9AC7038E117674FB0086C050 /* SBInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AC7038D117674EB0086C050 /* SBInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		9AC70390117675270086C050 /* SBInstructionList.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AC7038F117675270086C050 /* SBInstructionList.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703AE117675410086C050 /* SBInstruction.cpp */; };
@@ -804,6 +808,8 @@
 		260A63111860FDB600FECF8E /* Queue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Queue.h; path = include/lldb/Target/Queue.h; sourceTree = "<group>"; };
 		260A63121860FDBD00FECF8E /* QueueItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QueueItem.h; path = include/lldb/Target/QueueItem.h; sourceTree = "<group>"; };
 		260A63131860FDC700FECF8E /* QueueList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QueueList.h; path = include/lldb/Target/QueueList.h; sourceTree = "<group>"; };
+		260A63161861008E00FECF8E /* IOHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IOHandler.h; path = include/lldb/Core/IOHandler.h; sourceTree = "<group>"; };
+		260A63181861009E00FECF8E /* IOHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IOHandler.cpp; path = source/Core/IOHandler.cpp; sourceTree = "<group>"; };
 		260C6EA013011578005E16B0 /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = File.h; path = include/lldb/Host/File.h; sourceTree = "<group>"; };
 		260C6EA213011581005E16B0 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = "<group>"; };
 		260C847110F50EFC00BB2B04 /* ThreadPlanBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanBase.cpp; path = source/Target/ThreadPlanBase.cpp; sourceTree = "<group>"; };
@@ -923,7 +929,6 @@
 		2611FEFE142D83060017FEA3 /* SBFrame.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBFrame.i; sourceTree = "<group>"; };
 		2611FEFF142D83060017FEA3 /* SBFunction.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBFunction.i; sourceTree = "<group>"; };
 		2611FF00142D83060017FEA3 /* SBHostOS.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBHostOS.i; sourceTree = "<group>"; };
-		2611FF01142D83060017FEA3 /* SBInputReader.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBInputReader.i; sourceTree = "<group>"; };
 		2611FF02142D83060017FEA3 /* SBInstruction.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBInstruction.i; sourceTree = "<group>"; };
 		2611FF03142D83060017FEA3 /* SBInstructionList.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBInstructionList.i; sourceTree = "<group>"; };
 		2611FF04142D83060017FEA3 /* SBLineEntry.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBLineEntry.i; sourceTree = "<group>"; };
@@ -1026,7 +1031,6 @@
 		2660D9F611922A1300958FBD /* StringExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractor.cpp; path = source/Utility/StringExtractor.cpp; sourceTree = "<group>"; };
 		2660D9F711922A1300958FBD /* StringExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringExtractor.h; path = source/Utility/StringExtractor.h; sourceTree = "<group>"; };
 		2660D9FE11922A7F00958FBD /* ThreadPlanStepUntil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepUntil.cpp; path = source/Target/ThreadPlanStepUntil.cpp; sourceTree = "<group>"; };
-		2663E378152BD1890091EC22 /* ReadWriteLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReadWriteLock.h; path = include/lldb/Host/ReadWriteLock.h; sourceTree = "<group>"; };
 		26651A14133BEC76005B64B7 /* lldb-public.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-public.h"; path = "include/lldb/lldb-public.h"; sourceTree = "<group>"; };
 		26651A15133BF9CC005B64B7 /* Opcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Opcode.h; path = include/lldb/Core/Opcode.h; sourceTree = "<group>"; };
 		26651A17133BF9DF005B64B7 /* Opcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Opcode.cpp; path = source/Core/Opcode.cpp; sourceTree = "<group>"; };
@@ -1048,6 +1052,7 @@
 		266DFE9613FD656E00D0C574 /* OperatingSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OperatingSystem.cpp; path = source/Target/OperatingSystem.cpp; sourceTree = "<group>"; };
 		266DFE9813FD658300D0C574 /* OperatingSystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OperatingSystem.h; path = include/lldb/Target/OperatingSystem.h; sourceTree = "<group>"; };
 		266F5CBB12FC846200DFCE33 /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/Config.h; sourceTree = "<group>"; };
+		2670F8111862B44A006B332C /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = /usr/lib/libncurses.dylib; sourceTree = "<absolute>"; };
 		2671A0CD134825F6003A87BB /* ConnectionMachPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectionMachPort.h; path = include/lldb/Core/ConnectionMachPort.h; sourceTree = "<group>"; };
 		2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConnectionMachPort.cpp; path = source/Core/ConnectionMachPort.cpp; sourceTree = "<group>"; };
 		2672D8461189055500FF4019 /* CommandObjectFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = CommandObjectFrame.cpp; path = source/Commands/CommandObjectFrame.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
@@ -1408,7 +1413,11 @@
 		26C81CA511335651004BDC5A /* UUID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UUID.cpp; path = source/Core/UUID.cpp; sourceTree = "<group>"; };
 		26CA979F172B1FD5005DC71B /* RegisterContextThreadMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextThreadMemory.cpp; path = Utility/RegisterContextThreadMemory.cpp; sourceTree = "<group>"; };
 		26CA97A0172B1FD5005DC71B /* RegisterContextThreadMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextThreadMemory.h; path = Utility/RegisterContextThreadMemory.h; sourceTree = "<group>"; };
+		26CEB5F018762056008F575A /* CommandObjectGUI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectGUI.cpp; path = source/Commands/CommandObjectGUI.cpp; sourceTree = "<group>"; };
+		26CEB5F118762056008F575A /* CommandObjectGUI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectGUI.h; path = source/Commands/CommandObjectGUI.h; sourceTree = "<group>"; };
 		26CF992414428766001E4138 /* AnsiTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnsiTerminal.h; path = include/lldb/Utility/AnsiTerminal.h; sourceTree = "<group>"; };
+		26CFDCA01861638D000E63E5 /* Editline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Editline.h; path = include/lldb/Host/Editline.h; sourceTree = "<group>"; };
+		26CFDCA2186163A4000E63E5 /* Editline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Editline.cpp; sourceTree = "<group>"; };
 		26D0DD5010FE554D00271C65 /* BreakpointResolverAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverAddress.h; path = include/lldb/Breakpoint/BreakpointResolverAddress.h; sourceTree = "<group>"; };
 		26D0DD5110FE554D00271C65 /* BreakpointResolverFileLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverFileLine.h; path = include/lldb/Breakpoint/BreakpointResolverFileLine.h; sourceTree = "<group>"; };
 		26D0DD5210FE554D00271C65 /* BreakpointResolverName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverName.h; path = include/lldb/Breakpoint/BreakpointResolverName.h; sourceTree = "<group>"; };
@@ -1482,8 +1491,6 @@
 		26F5C27210F3D9E4009D5894 /* lldb-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "lldb-Info.plist"; path = "tools/driver/lldb-Info.plist"; sourceTree = "<group>"; };
 		26F5C27310F3D9E4009D5894 /* Driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Driver.cpp; path = tools/driver/Driver.cpp; sourceTree = "<group>"; };
 		26F5C27410F3D9E4009D5894 /* Driver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Driver.h; path = tools/driver/Driver.h; sourceTree = "<group>"; };
-		26F5C27510F3D9E4009D5894 /* IOChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IOChannel.cpp; path = tools/driver/IOChannel.cpp; sourceTree = "<group>"; };
-		26F5C27610F3D9E4009D5894 /* IOChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IOChannel.h; path = tools/driver/IOChannel.h; sourceTree = "<group>"; };
 		26F5C32410F3DF23009D5894 /* libpython.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpython.dylib; path = /usr/lib/libpython.dylib; sourceTree = "<absolute>"; };
 		26F5C32A10F3DFDD009D5894 /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = /usr/lib/libedit.dylib; sourceTree = "<absolute>"; };
 		26F5C32B10F3DFDD009D5894 /* libtermcap.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtermcap.dylib; path = /usr/lib/libtermcap.dylib; sourceTree = "<absolute>"; };
@@ -1620,8 +1627,6 @@
 		69A01E201236C5D400C660B5 /* TimeValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeValue.cpp; sourceTree = "<group>"; };
 		94005E0313F438DF001EF42D /* python-wrapper.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-wrapper.swig"; sourceTree = "<group>"; };
 		94005E0513F45A1B001EF42D /* embedded_interpreter.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = embedded_interpreter.py; path = source/Interpreter/embedded_interpreter.py; sourceTree = "<group>"; };
-		94031A9B13CF484600DCFF3C /* InputReaderEZ.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InputReaderEZ.h; path = include/lldb/Core/InputReaderEZ.h; sourceTree = "<group>"; };
-		94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InputReaderEZ.cpp; path = source/Core/InputReaderEZ.cpp; sourceTree = "<group>"; };
 		94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PriorityPointerPair.h; path = include/lldb/Utility/PriorityPointerPair.h; sourceTree = "<group>"; };
 		94094C68163B6CCC0083A547 /* ValueObjectCast.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectCast.h; path = include/lldb/Core/ValueObjectCast.h; sourceTree = "<group>"; };
 		94094C69163B6CD90083A547 /* ValueObjectCast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectCast.cpp; path = source/Core/ValueObjectCast.cpp; sourceTree = "<group>"; };
@@ -1761,12 +1766,6 @@
 		9A9831081125FC5800A56CB0 /* SBTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBTarget.h; path = include/lldb/API/SBTarget.h; sourceTree = "<group>"; };
 		9A9831091125FC5800A56CB0 /* SBThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBThread.cpp; path = source/API/SBThread.cpp; sourceTree = "<group>"; };
 		9A98310A1125FC5800A56CB0 /* SBThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBThread.h; path = include/lldb/API/SBThread.h; sourceTree = "<group>"; };
-		9A9E1EFE1398086D005AC039 /* InputReaderStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InputReaderStack.cpp; path = source/Core/InputReaderStack.cpp; sourceTree = "<group>"; };
-		9A9E1F0013980943005AC039 /* InputReaderStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InputReaderStack.h; path = include/lldb/Core/InputReaderStack.h; sourceTree = "<group>"; };
-		9AA69DAE118A023300D753A0 /* SBInputReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBInputReader.h; path = include/lldb/API/SBInputReader.h; sourceTree = "<group>"; };
-		9AA69DB0118A024600D753A0 /* SBInputReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBInputReader.cpp; path = source/API/SBInputReader.cpp; sourceTree = "<group>"; };
-		9AA69DB5118A027A00D753A0 /* InputReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InputReader.cpp; path = source/Core/InputReader.cpp; sourceTree = "<group>"; };
-		9AA69DBB118A029E00D753A0 /* InputReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InputReader.h; path = include/lldb/Core/InputReader.h; sourceTree = "<group>"; };
 		9AC7033D11752C4C0086C050 /* AddressResolverFileLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AddressResolverFileLine.h; path = include/lldb/Core/AddressResolverFileLine.h; sourceTree = "<group>"; };
 		9AC7033E11752C540086C050 /* AddressResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AddressResolver.h; path = include/lldb/Core/AddressResolver.h; sourceTree = "<group>"; };
 		9AC7033F11752C590086C050 /* AddressResolverName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AddressResolverName.h; path = include/lldb/Core/AddressResolverName.h; sourceTree = "<group>"; };
@@ -1862,6 +1861,8 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				2670F8121862B44A006B332C /* libncurses.dylib in Frameworks */,
+				26CEB5EF18761CB2008F575A /* libedit.dylib in Frameworks */,
 				26D55235159A7DB100708D8D /* libxml2.dylib in Frameworks */,
 				268901161335BBC300698AC0 /* liblldb-core.a in Frameworks */,
 				2668022F115FD19D008E1FE4 /* CoreFoundation.framework in Frameworks */,
@@ -1881,6 +1882,8 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				26780C651867C34500234593 /* libncurses.dylib in Frameworks */,
+				26CFDCA71861646C000E63E5 /* libedit.dylib in Frameworks */,
 				26D6F3FA183E888800194858 /* liblldb-core.a in Frameworks */,
 				2606EDDE184E68940034641B /* Foundation.framework in Frameworks */,
 			);
@@ -1890,6 +1893,8 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				26780C611867C33D00234593 /* libncurses.dylib in Frameworks */,
+				26CFDCA818616473000E63E5 /* libedit.dylib in Frameworks */,
 				2606EDDF184E68A10034641B /* liblldb-core.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -1898,7 +1903,6 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				26F5C32C10F3DFDD009D5894 /* libedit.dylib in Frameworks */,
 				26F5C32D10F3DFDD009D5894 /* libtermcap.dylib in Frameworks */,
 				2668035C11601108008E1FE4 /* LLDB.framework in Frameworks */,
 			);
@@ -2213,7 +2217,6 @@
 				4CE4F676162CE1E100F75CB3 /* SBExpressionOptions.i */,
 				2611FEFF142D83060017FEA3 /* SBFunction.i */,
 				2611FF00142D83060017FEA3 /* SBHostOS.i */,
-				2611FF01142D83060017FEA3 /* SBInputReader.i */,
 				2611FF02142D83060017FEA3 /* SBInstruction.i */,
 				2611FF03142D83060017FEA3 /* SBInstructionList.i */,
 				2611FF04142D83060017FEA3 /* SBLineEntry.i */,
@@ -2309,8 +2312,6 @@
 				26DE205C1161901400A093E2 /* SBFunction.cpp */,
 				9A3576A7116E9AB700E8ED2F /* SBHostOS.h */,
 				9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */,
-				9AA69DAE118A023300D753A0 /* SBInputReader.h */,
-				9AA69DB0118A024600D753A0 /* SBInputReader.cpp */,
 				9AC7038D117674EB0086C050 /* SBInstruction.h */,
 				9AC703AE117675410086C050 /* SBInstruction.cpp */,
 				9AC7038F117675270086C050 /* SBInstructionList.h */,
@@ -2716,12 +2717,8 @@
 				26BC7D6410F1B77400F91463 /* Flags.h */,
 				26F7305F139D8FC900FD51C7 /* History.h */,
 				26F73061139D8FDB00FD51C7 /* History.cpp */,
-				9AA69DBB118A029E00D753A0 /* InputReader.h */,
-				9AA69DB5118A027A00D753A0 /* InputReader.cpp */,
-				94031A9B13CF484600DCFF3C /* InputReaderEZ.h */,
-				94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */,
-				9A9E1F0013980943005AC039 /* InputReaderStack.h */,
-				9A9E1EFE1398086D005AC039 /* InputReaderStack.cpp */,
+				260A63161861008E00FECF8E /* IOHandler.h */,
+				260A63181861009E00FECF8E /* IOHandler.cpp */,
 				26BC7D6510F1B77400F91463 /* IOStreamMacros.h */,
 				26BC7D6610F1B77400F91463 /* Language.h */,
 				26BC7E7D10F1B85900F91463 /* Language.cpp */,
@@ -2954,6 +2951,8 @@
 				26BC7E3110F1B84700F91463 /* CommandObjectExpression.cpp */,
 				2672D8471189055500FF4019 /* CommandObjectFrame.h */,
 				2672D8461189055500FF4019 /* CommandObjectFrame.cpp */,
+				26CEB5F118762056008F575A /* CommandObjectGUI.h */,
+				26CEB5F018762056008F575A /* CommandObjectGUI.cpp */,
 				26BC7D1A10F1B76300F91463 /* CommandObjectHelp.h */,
 				26BC7E3310F1B84700F91463 /* CommandObjectHelp.cpp */,
 				264AD83911095BBD00E0B039 /* CommandObjectLog.h */,
@@ -3048,6 +3047,7 @@
 				26BC7DD210F1B7D500F91463 /* Condition.h */,
 				266F5CBB12FC846200DFCE33 /* Config.h */,
 				9456F2231616645A00656F91 /* DynamicLibrary.h */,
+				26CFDCA01861638D000E63E5 /* Editline.h */,
 				26BC7DD310F1B7D500F91463 /* Endian.h */,
 				260C6EA013011578005E16B0 /* File.h */,
 				26FA4315130103F400E71120 /* FileSpec.h */,
@@ -3055,7 +3055,6 @@
 				26BC7DD510F1B7D500F91463 /* Mutex.h */,
 				A36FF33D17D8E98800244D40 /* OptionParser.h */,
 				26BC7DD610F1B7D500F91463 /* Predicate.h */,
-				2663E378152BD1890091EC22 /* ReadWriteLock.h */,
 				26D7E45B13D5E2F9007FD12B /* SocketAddress.h */,
 				26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */,
 				2689B0A4113EE3CD00A4AEDB /* Symbols.h */,
@@ -3411,8 +3410,6 @@
 				26F5C27210F3D9E4009D5894 /* lldb-Info.plist */,
 				26F5C27410F3D9E4009D5894 /* Driver.h */,
 				26F5C27310F3D9E4009D5894 /* Driver.cpp */,
-				26F5C27610F3D9E4009D5894 /* IOChannel.h */,
-				26F5C27510F3D9E4009D5894 /* IOChannel.cpp */,
 			);
 			name = Driver;
 			sourceTree = "<group>";
@@ -3425,6 +3422,7 @@
 				260C876910F538E700BB2B04 /* Foundation.framework */,
 				26F5C32A10F3DFDD009D5894 /* libedit.dylib */,
 				2689FFCA13353D7A00698AC0 /* liblldb-core.a */,
+				2670F8111862B44A006B332C /* libncurses.dylib */,
 				26F5C37410F3F61B009D5894 /* libobjc.dylib */,
 				26F5C32410F3DF23009D5894 /* libpython.dylib */,
 				26F5C32B10F3DFDD009D5894 /* libtermcap.dylib */,
@@ -3538,6 +3536,7 @@
 			children = (
 				AF37E10917C861F20061E18E /* ProcessRunLock.cpp */,
 				9456F2211616644B00656F91 /* DynamicLibrary.cpp */,
+				26CFDCA2186163A4000E63E5 /* Editline.cpp */,
 				260C6EA213011581005E16B0 /* File.cpp */,
 				26FA43171301048600E71120 /* FileSpec.cpp */,
 				69A01E1B1236C5D400C660B5 /* Condition.cpp */,
@@ -3667,7 +3666,6 @@
 				26680225115FD13D008E1FE4 /* SBFrame.h in Headers */,
 				26DE205311618FAC00A093E2 /* SBFunction.h in Headers */,
 				9A3576A8116E9AB700E8ED2F /* SBHostOS.h in Headers */,
-				9AA69DAF118A023300D753A0 /* SBInputReader.h in Headers */,
 				9AC7038E117674FB0086C050 /* SBInstruction.h in Headers */,
 				9AC70390117675270086C050 /* SBInstructionList.h in Headers */,
 				26DE205911618FE700A093E2 /* SBLineEntry.h in Headers */,
@@ -3719,7 +3717,6 @@
 				2694E9A514FC0BBD0076DE67 /* PlatformLinux.h in Headers */,
 				26AB54121832DC3400EADFF3 /* RegisterCheckpoint.h in Headers */,
 				26AB92131819D74600E63F3E /* DWARFDataExtractor.h in Headers */,
-				2663E379152BD1890091EC22 /* ReadWriteLock.h in Headers */,
 				945759681534941F005A9070 /* PlatformPOSIX.h in Headers */,
 				26B1EFAF154638AF00E2DAC7 /* DWARFDeclContext.h in Headers */,
 				260CC62E15D04377002BF2E0 /* OptionValueArgs.h in Headers */,
@@ -3729,7 +3726,9 @@
 				260CC63215D04377002BF2E0 /* OptionValueDictionary.h in Headers */,
 				262173A118395D3800C52091 /* SectionLoadHistory.h in Headers */,
 				260CC63315D04377002BF2E0 /* OptionValueEnumeration.h in Headers */,
+				260A63171861008E00FECF8E /* IOHandler.h in Headers */,
 				260CC63415D04377002BF2E0 /* OptionValueFileSpec.h in Headers */,
+				26CFDCA11861638D000E63E5 /* Editline.h in Headers */,
 				AF9B8F34182DB52900DA866F /* SystemRuntimeMacOSX.h in Headers */,
 				26D1804716CEE12C00EDFB5B /* TimeSpecTimeout.h in Headers */,
 				260CC63515D04377002BF2E0 /* OptionValueFileSpecList.h in Headers */,
@@ -3752,6 +3751,7 @@
 				947A1D651616476B0017C8D1 /* CommandObjectPlugin.h in Headers */,
 				262ED0051631FA2800879631 /* OptionGroupString.h in Headers */,
 				944372DD171F6B4300E57C32 /* RegisterContextDummy.h in Headers */,
+				26CEB5F318762056008F575A /* CommandObjectGUI.h in Headers */,
 				AF061F8B182C980000B6A19C /* HistoryThread.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -4118,7 +4118,6 @@
 				9A3576AA116E9AC700E8ED2F /* SBHostOS.cpp in Sources */,
 				9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */,
 				9AC703B1117675490086C050 /* SBInstructionList.cpp in Sources */,
-				9AA69DB1118A024600D753A0 /* SBInputReader.cpp in Sources */,
 				268F9D55123AA16600B91E9B /* SBSymbolContextList.cpp in Sources */,
 				26C72C961243229A0068DC16 /* SBStream.cpp in Sources */,
 				9443B122140C18C40013457C /* SBData.cpp in Sources */,
@@ -4208,7 +4207,6 @@
 				2689003C13353E0400698AC0 /* Error.cpp in Sources */,
 				2689003D13353E0400698AC0 /* Event.cpp in Sources */,
 				2689003E13353E0400698AC0 /* FileSpecList.cpp in Sources */,
-				2689003F13353E0400698AC0 /* InputReader.cpp in Sources */,
 				2689004013353E0400698AC0 /* Language.cpp in Sources */,
 				2689004113353E0400698AC0 /* Listener.cpp in Sources */,
 				2689004213353E0400698AC0 /* Log.cpp in Sources */,
@@ -4278,6 +4276,7 @@
 				2689007C13353E1A00698AC0 /* Symbols.cpp in Sources */,
 				2689007D13353E2200698AC0 /* Args.cpp in Sources */,
 				2689007F13353E2200698AC0 /* CommandCompletions.cpp in Sources */,
+				26CEB5F218762056008F575A /* CommandObjectGUI.cpp in Sources */,
 				2689008013353E2200698AC0 /* CommandInterpreter.cpp in Sources */,
 				AF9B8F33182DB52900DA866F /* SystemRuntimeMacOSX.cpp in Sources */,
 				2689008113353E2200698AC0 /* CommandObject.cpp in Sources */,
@@ -4288,6 +4287,7 @@
 				2689008713353E2200698AC0 /* ScriptInterpreter.cpp in Sources */,
 				2689008813353E2200698AC0 /* ScriptInterpreterNone.cpp in Sources */,
 				2689008913353E2200698AC0 /* ScriptInterpreterPython.cpp in Sources */,
+				260A63191861009E00FECF8E /* IOHandler.cpp in Sources */,
 				2689008D13353E4200698AC0 /* DynamicLoaderMacOSXDYLD.cpp in Sources */,
 				2689008E13353E4200698AC0 /* DynamicLoaderStatic.cpp in Sources */,
 				2689009613353E4200698AC0 /* ObjectContainerBSDArchive.cpp in Sources */,
@@ -4441,7 +4441,6 @@
 				26D1803E16CEBFD300EDFB5B /* KQueue.cpp in Sources */,
 				26A69C5F137A17A500262477 /* RegisterValue.cpp in Sources */,
 				2690B3711381D5C300ECFBAE /* Memory.cpp in Sources */,
-				9A9E1EFF1398086D005AC039 /* InputReaderStack.cpp in Sources */,
 				B28058A1139988B0002D96D0 /* InferiorCallPOSIX.cpp in Sources */,
 				26F73062139D8FDB00FD51C7 /* History.cpp in Sources */,
 				4CCA644D13B40B82003BDF98 /* ItaniumABILanguageRuntime.cpp in Sources */,
@@ -4453,7 +4452,6 @@
 				9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */,
 				49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */,
 				26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */,
-				94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */,
 				2642FBAE13D003B400ED6808 /* CommunicationKDP.cpp in Sources */,
 				2642FBB013D003B400ED6808 /* ProcessKDP.cpp in Sources */,
 				2642FBB213D003B400ED6808 /* ProcessKDPLog.cpp in Sources */,
@@ -4475,6 +4473,7 @@
 				94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */,
 				949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */,
 				B27318421416AC12006039C8 /* WatchpointList.cpp in Sources */,
+				26CFDCA3186163A4000E63E5 /* Editline.cpp in Sources */,
 				26E152261419CAD4007967D0 /* ObjectFilePECOFF.cpp in Sources */,
 				B2462247141AD37D00F3D409 /* OptionGroupWatchpoint.cpp in Sources */,
 				49A71FE7141FFA5C00D59478 /* IRInterpreter.cpp in Sources */,
@@ -4563,7 +4562,6 @@
 			buildActionMask = 2147483647;
 			files = (
 				26F5C27710F3D9E4009D5894 /* Driver.cpp in Sources */,
-				26F5C27810F3D9E4009D5894 /* IOChannel.cpp in Sources */,
 				9AA69DA61188F52100D753A0 /* PseudoTerminal.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

Modified: lldb/branches/iohandler/scripts/Python/build-swig-Python.sh
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/scripts/Python/build-swig-Python.sh?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/scripts/Python/build-swig-Python.sh (original)
+++ lldb/branches/iohandler/scripts/Python/build-swig-Python.sh Thu Jan  2 16:40:14 2014
@@ -99,7 +99,6 @@ HEADER_FILES="${SRC_ROOT}/include/lldb/l
 " ${SRC_ROOT}/include/lldb/API/SBFrame.h"\
 " ${SRC_ROOT}/include/lldb/API/SBFunction.h"\
 " ${SRC_ROOT}/include/lldb/API/SBHostOS.h"\
-" ${SRC_ROOT}/include/lldb/API/SBInputReader.h"\
 " ${SRC_ROOT}/include/lldb/API/SBInstruction.h"\
 " ${SRC_ROOT}/include/lldb/API/SBInstructionList.h"\
 " ${SRC_ROOT}/include/lldb/API/SBLineEntry.h"\
@@ -147,7 +146,6 @@ INTERFACE_FILES="${SRC_ROOT}/scripts/Pyt
 " ${SRC_ROOT}/scripts/Python/interface/SBFrame.i"\
 " ${SRC_ROOT}/scripts/Python/interface/SBFunction.i"\
 " ${SRC_ROOT}/scripts/Python/interface/SBHostOS.i"\
-" ${SRC_ROOT}/scripts/Python/interface/SBInputReader.i"\
 " ${SRC_ROOT}/scripts/Python/interface/SBInstruction.i"\
 " ${SRC_ROOT}/scripts/Python/interface/SBInstructionList.i"\
 " ${SRC_ROOT}/scripts/Python/interface/SBLineEntry.i"\

Modified: lldb/branches/iohandler/scripts/Python/interface/SBDebugger.i
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/scripts/Python/interface/SBDebugger.i?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/scripts/Python/interface/SBDebugger.i (original)
+++ lldb/branches/iohandler/scripts/Python/interface/SBDebugger.i Thu Jan  2 16:40:14 2014
@@ -292,15 +292,6 @@ public:
     void
     DispatchInputEndOfFile ();
     
-    void
-    PushInputReader (lldb::SBInputReader &reader);
-
-    void
-    NotifyTopInputReader (lldb::InputReaderAction notification);
-
-    bool
-    InputReaderIsTopReader (const lldb::SBInputReader &reader);
-
     const char *
     GetInstanceName  ();
 
@@ -372,7 +363,10 @@ public:
 
     lldb::SBTypeSynthetic
     GetSyntheticForType (lldb::SBTypeNameSpecifier);
-                
+    
+    void
+    RunCommandInterpreter (bool auto_handle_events);
+
 }; // class SBDebugger
 
 } // namespace lldb

Removed: lldb/branches/iohandler/scripts/Python/interface/SBInputReader.i
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/scripts/Python/interface/SBInputReader.i?rev=198365&view=auto
==============================================================================
--- lldb/branches/iohandler/scripts/Python/interface/SBInputReader.i (original)
+++ lldb/branches/iohandler/scripts/Python/interface/SBInputReader.i (removed)
@@ -1,53 +0,0 @@
-//===-- SWIG Interface for SBInputREader ------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-namespace lldb {
-
-class SBInputReader
-{
-public:
-
-    typedef size_t (*Callback) (void *baton, 
-                                SBInputReader *reader, 
-                                InputReaderAction notification,
-                                const char *bytes, 
-                                size_t bytes_len);
-
-    SBInputReader ();
-
-    SBInputReader (const lldb::SBInputReader &rhs);
-
-    ~SBInputReader ();
-
-    SBError
-    Initialize (SBDebugger &debugger,
-                Callback callback,
-                void *callback_baton,
-                lldb::InputReaderGranularity granularity,
-                const char *end_token,
-                const char *prompt,
-                bool echo);
-    
-    bool
-    IsValid () const;
-
-    bool
-    IsActive () const;
-
-    bool
-    IsDone () const;
-
-    void
-    SetIsDone (bool value);
-
-    InputReaderGranularity
-    GetGranularity ();
-};
-
-} // namespace lldb

Modified: lldb/branches/iohandler/scripts/Python/python-extensions.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/scripts/Python/python-extensions.swig?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/scripts/Python/python-extensions.swig (original)
+++ lldb/branches/iohandler/scripts/Python/python-extensions.swig Thu Jan  2 16:40:14 2014
@@ -777,15 +777,6 @@
 //                 Py_XDECREF($self->GetCallbackBaton());
 //         }
 // }
-// %extend lldb::SBInputReader {
-//         // FIXME: m_callback_function is private and we have no other
-//         // way to access it.
-//         PyObject *lldb::SBInputReader::__del__ (){
-//             // Only call Py_XDECREF if we have a Python object (or NULL)
-//             if (LLDBSwigPythonCallSBInputReaderCallback == $self->m_callback_function)
-//                 Py_XDECREF($self->m_callback_baton);
-//         }
-// }
 
 %pythoncode %{
 

Modified: lldb/branches/iohandler/scripts/Python/python-swigsafecast.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/scripts/Python/python-swigsafecast.swig?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/scripts/Python/python-swigsafecast.swig (original)
+++ lldb/branches/iohandler/scripts/Python/python-swigsafecast.swig Thu Jan  2 16:40:14 2014
@@ -112,10 +112,3 @@ SBTypeToSWIGWrapper (lldb::SBCommandRetu
 {
     return SWIG_NewPointerObj((void *) cmd_ret_obj_sb, SWIGTYPE_p_lldb__SBCommandReturnObject, 0);
 }
-
-template <>
-PyObject*
-SBTypeToSWIGWrapper (lldb::SBInputReader* input_reader_sb)
-{
-    return SWIG_NewPointerObj((void *) input_reader_sb, SWIGTYPE_p_lldb__SBInputReader, 0);
-}

Modified: lldb/branches/iohandler/scripts/Python/python-typemaps.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/scripts/Python/python-typemaps.swig?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/scripts/Python/python-typemaps.swig (original)
+++ lldb/branches/iohandler/scripts/Python/python-typemaps.swig Thu Jan  2 16:40:14 2014
@@ -355,28 +355,6 @@
     free($1);
 }
 
-// For lldb::SBInputReader::Callback
-%typemap(in) (lldb::SBInputReader::Callback callback, void *callback_baton) {
-  if (!($input == Py_None || PyCallable_Check(reinterpret_cast<PyObject*>($input)))) {
-    PyErr_SetString(PyExc_TypeError, "Need a callable object or None!");
-    return NULL;
-  }
-
-  // FIXME (filcab): We can't currently check if our callback is already
-  // LLDBSwigPythonCallPythonLogOutputCallback (to DECREF the previous
-  // baton) nor can we just remove all traces of a callback, if we want to
-  // revert to a file logging mechanism.
-
-  // Don't lose the callback reference
-  Py_INCREF($input);
-  $1 = LLDBSwigPythonCallSBInputReaderCallback;
-  $2 = $input;
-}
-
-%typemap(typecheck) (lldb::SBInputReader::Callback callback, void *baton) {
-  $1 = $input == Py_None;
-  $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject*>($input));
-}
 
 // For Log::LogOutputCallback
 %typemap(in) (lldb::LogOutputCallback log_callback, void *baton) {

Modified: lldb/branches/iohandler/scripts/Python/python-wrapper.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/scripts/Python/python-wrapper.swig?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/scripts/Python/python-wrapper.swig (original)
+++ lldb/branches/iohandler/scripts/Python/python-wrapper.swig Thu Jan  2 16:40:14 2014
@@ -929,10 +929,6 @@ LLDBSwigPythonCallModuleInit
 
 %runtime %{
 // Forward declaration to be inserted at the start of LLDBWrapPython.h
-// I used runtime as a hack to make SWIG place it where it's needed.
-// This is needed to use LLDBSwigPythonCallSBInputReaderCallback in the
-// typemaps and in the extensions (SBInputReader.__del__()).
-#include "lldb/API/SBInputReader.h"
 #include "lldb/API/SBDebugger.h"
 #include "lldb/API/SBValue.h"
  
@@ -952,13 +948,6 @@ LLDBSWIGPython_GetValueObjectSPFromSBVal
 extern "C" {
 #endif
 
-size_t
-LLDBSwigPythonCallSBInputReaderCallback(void *baton,
-                                        lldb::SBInputReader *reader,
-                                        lldb::InputReaderAction notification,
-                                        const char*bytes,
-                                        size_t bytes_len);
-
 void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton);
 
 #ifdef __cplusplus
@@ -967,47 +956,7 @@ void LLDBSwigPythonCallPythonLogOutputCa
 %}
 
 %wrapper %{
-// For the InputReader Callback functions
-SWIGEXPORT size_t
-LLDBSwigPythonCallSBInputReaderCallback(void *baton,
-                                        lldb::SBInputReader *reader,
-                                        lldb::InputReaderAction notification,
-                                        const char*bytes,
-                                        size_t bytes_len) {
-    if (baton != Py_None) {
-        SWIG_PYTHON_THREAD_BEGIN_BLOCK;
-    
-        PyObject *py_InputReader = SBTypeToSWIGWrapper(reader);
-        PyObject *py_Notification = PyInt_FromLong(notification);
-        PyObject *py_Bytes = PyBytes_FromStringAndSize(bytes, bytes_len);
-    
-        PyObject *tuple = PyTuple_Pack(3, py_InputReader, py_Notification, py_Bytes);
-        PyObject *res = PyObject_Call(reinterpret_cast<PyObject*>(baton), tuple, NULL);
-        Py_XDECREF(tuple);
-        Py_XDECREF(py_InputReader);
-        Py_XDECREF(py_Notification);
-        Py_XDECREF(py_Bytes);
-    
-        if (res == NULL) {
-          PyObject *exc = PyErr_Occurred();
-          if (exc) {
-            ::puts("\nErroring out at LLDBSwigPythonCallSBInputReaderCallback");
-            PyErr_Print();
-          }
-          return 0;
-        }
-    
-        size_t result = 0;
-        // If the callback misbehaves and returns Py_None, assume it returned 0
-        if (res != Py_None)
-          result = static_cast<size_t>(PyInt_AsSsize_t(res));
-    
-        Py_XDECREF(res);
-        SWIG_PYTHON_THREAD_END_BLOCK;
-        return result;
-    }
-    return 0;
-}
+
 
 // For the LogOutputCallback functions
 void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton) {

Modified: lldb/branches/iohandler/scripts/lldb.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/scripts/lldb.swig?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/scripts/lldb.swig (original)
+++ lldb/branches/iohandler/scripts/lldb.swig Thu Jan  2 16:40:14 2014
@@ -72,7 +72,6 @@ import os
 #include "lldb/API/SBFrame.h"
 #include "lldb/API/SBFunction.h"
 #include "lldb/API/SBHostOS.h"
-#include "lldb/API/SBInputReader.h"
 #include "lldb/API/SBInstruction.h"
 #include "lldb/API/SBInstructionList.h"
 #include "lldb/API/SBLineEntry.h"
@@ -139,7 +138,6 @@ import os
 %include "./Python/interface/SBFrame.i"
 %include "./Python/interface/SBFunction.i"
 %include "./Python/interface/SBHostOS.i"
-%include "./Python/interface/SBInputReader.i"
 %include "./Python/interface/SBInstruction.i"
 %include "./Python/interface/SBInstructionList.i"
 %include "./Python/interface/SBLineEntry.i"

Modified: lldb/branches/iohandler/source/API/SBDebugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/API/SBDebugger.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/API/SBDebugger.cpp (original)
+++ lldb/branches/iohandler/source/API/SBDebugger.cpp Thu Jan  2 16:40:14 2014
@@ -20,7 +20,6 @@
 #include "lldb/API/SBError.h"
 #include "lldb/API/SBEvent.h"
 #include "lldb/API/SBFrame.h"
-#include "lldb/API/SBInputReader.h"
 #include "lldb/API/SBProcess.h"
 #include "lldb/API/SBSourceManager.h"
 #include "lldb/API/SBStream.h"
@@ -37,6 +36,7 @@
 
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/State.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/DataFormatters/DataVisualization.h"
 #include "lldb/Host/DynamicLibrary.h"
 #include "lldb/Interpreter/Args.h"
@@ -111,7 +111,7 @@ SBDebugger::Clear ()
         log->Printf ("SBDebugger(%p)::Clear ()", m_opaque_sp.get());
         
     if (m_opaque_sp)
-        m_opaque_sp->CleanUpInputReaders ();
+        m_opaque_sp->ClearIOHandlers ();
 
     m_opaque_sp.reset();
 }
@@ -309,7 +309,11 @@ FILE *
 SBDebugger::GetInputFileHandle ()
 {
     if (m_opaque_sp)
-        return m_opaque_sp->GetInputFile().GetStream();
+    {
+        StreamFileSP stream_file_sp (m_opaque_sp->GetInputFile());
+        if (stream_file_sp)
+            return stream_file_sp->GetFile().GetStream();
+    }
     return NULL;
 }
 
@@ -317,7 +321,11 @@ FILE *
 SBDebugger::GetOutputFileHandle ()
 {
     if (m_opaque_sp)
-        return m_opaque_sp->GetOutputFile().GetStream();
+    {
+        StreamFileSP stream_file_sp (m_opaque_sp->GetOutputFile());
+        if (stream_file_sp)
+            return stream_file_sp->GetFile().GetStream();
+    }
     return NULL;
 }
 
@@ -325,7 +333,12 @@ FILE *
 SBDebugger::GetErrorFileHandle ()
 {
     if (m_opaque_sp)
-        return m_opaque_sp->GetErrorFile().GetStream();
+        if (m_opaque_sp)
+        {
+            StreamFileSP stream_file_sp (m_opaque_sp->GetErrorFile());
+            if (stream_file_sp)
+                return stream_file_sp->GetFile().GetStream();
+        }
     return NULL;
 }
 
@@ -885,17 +898,17 @@ SBDebugger::DispatchInput (void* baton,
 void
 SBDebugger::DispatchInput (const void *data, size_t data_len)
 {
-    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
-    if (log)
-        log->Printf ("SBDebugger(%p)::DispatchInput (data=\"%.*s\", size_t=%" PRIu64 ")",
-                     m_opaque_sp.get(),
-                     (int) data_len,
-                     (const char *) data,
-                     (uint64_t)data_len);
-
-    if (m_opaque_sp)
-        m_opaque_sp->DispatchInput ((const char *) data, data_len);
+//    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+//
+//    if (log)
+//        log->Printf ("SBDebugger(%p)::DispatchInput (data=\"%.*s\", size_t=%" PRIu64 ")",
+//                     m_opaque_sp.get(),
+//                     (int) data_len,
+//                     (const char *) data,
+//                     (uint64_t)data_len);
+//
+//    if (m_opaque_sp)
+//        m_opaque_sp->DispatchInput ((const char *) data, data_len);
 }
 
 void
@@ -911,54 +924,12 @@ SBDebugger::DispatchInputEndOfFile ()
     if (m_opaque_sp)
         m_opaque_sp->DispatchInputEndOfFile ();
 }
-    
-bool
-SBDebugger::InputReaderIsTopReader (const lldb::SBInputReader &reader)
-{
-    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
-    if (log)
-        log->Printf ("SBDebugger(%p)::InputReaderIsTopReader (SBInputReader(%p))", m_opaque_sp.get(), &reader);
-
-    if (m_opaque_sp && reader.IsValid())
-    {
-        InputReaderSP reader_sp (*reader);
-        return m_opaque_sp->InputReaderIsTopReader (reader_sp);
-    }
-
-    return false;
-}
-
 
 void
-SBDebugger::PushInputReader (SBInputReader &reader)
+SBDebugger::RunCommandInterpreter (bool auto_handle_events)
 {
-    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
-    if (log)
-        log->Printf ("SBDebugger(%p)::PushInputReader (SBInputReader(%p))", m_opaque_sp.get(), &reader);
-
-    if (m_opaque_sp && reader.IsValid())
-    {
-        TargetSP target_sp (m_opaque_sp->GetSelectedTarget());
-        Mutex::Locker api_locker;
-        if (target_sp)
-            api_locker.Lock(target_sp->GetAPIMutex());
-        InputReaderSP reader_sp(*reader);
-        m_opaque_sp->PushInputReader (reader_sp);
-    }
-}
-
-void
-SBDebugger::NotifyTopInputReader (InputReaderAction notification)
-{
-    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
-    if (log)
-        log->Printf ("SBDebugger(%p)::NotifyTopInputReader (%d)", m_opaque_sp.get(), notification);
-        
     if (m_opaque_sp)
-        m_opaque_sp->NotifyTopInputReader (notification);
+        m_opaque_sp->GetCommandInterpreter().RunCommandInterpreter(auto_handle_events);
 }
 
 void
@@ -1050,7 +1021,7 @@ SBDebugger::GetInternalVariableValue (co
             if (!value_str.empty())
             {
                 StringList string_list;
-                string_list.SplitIntoLines(value_str.c_str(), value_str.size());
+                string_list.SplitIntoLines(value_str);
                 return SBStringList(&string_list);
             }
         }

Removed: lldb/branches/iohandler/source/API/SBInputReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/API/SBInputReader.cpp?rev=198365&view=auto
==============================================================================
--- lldb/branches/iohandler/source/API/SBInputReader.cpp (original)
+++ lldb/branches/iohandler/source/API/SBInputReader.cpp (removed)
@@ -1,216 +0,0 @@
-//===-- SBInputReader.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/lldb-enumerations.h"
-
-#include "lldb/API/SBDebugger.h"
-#include "lldb/API/SBError.h"
-#include "lldb/API/SBInputReader.h"
-#include "lldb/API/SBStream.h"
-#include "lldb/API/SBStringList.h"
-#include "lldb/Core/InputReader.h"
-#include "lldb/Core/Log.h"
-
-
-using namespace lldb;
-using namespace lldb_private;
-
-SBInputReader::SBInputReader ()  :
-    m_opaque_sp (),
-    m_callback_function (NULL),
-    m_callback_baton (NULL)
-
-{
-}
-
-SBInputReader::SBInputReader (const lldb::InputReaderSP &reader_sp) :
-    m_opaque_sp (reader_sp)
-{
-    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
-    if (log)
-        log->Printf ("SBInputReader::SBInputReader (reader_sp=%p) => SBInputReader(%p)", reader_sp.get(), 
-                     m_opaque_sp.get());
-}
-
-SBInputReader::SBInputReader (const SBInputReader &rhs) :
-    m_opaque_sp (rhs.m_opaque_sp)
-{
-    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
-    if (log)
-        log->Printf("SBInputReader::SBInputReader (rhs.sp=%p) => SBInputReader(%p)", 
-                    rhs.m_opaque_sp.get(), m_opaque_sp.get());
-}
-
-SBInputReader::~SBInputReader ()
-{
-}
-
-size_t
-SBInputReader::PrivateCallback 
-(
-    void *baton, 
-    InputReader &reader, 
-    lldb::InputReaderAction notification,
-    const char *bytes, 
-    size_t bytes_len
-)
-{
-    SBInputReader *sb_reader = (SBInputReader *)baton;
-    return sb_reader->m_callback_function (sb_reader->m_callback_baton, 
-                                           sb_reader, 
-                                           notification,
-                                           bytes,
-                                           bytes_len);
-}
-
-SBError
-SBInputReader::Initialize 
-(
-    SBDebugger &debugger,
-    Callback callback_function,
-    void *callback_baton,
-    lldb::InputReaderGranularity granularity,
-    const char *end_token,
-    const char *prompt,
-    bool echo
-)
-{
-    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
-    if (log)
-        log->Printf("SBInputReader(%p)::Initialize (SBDebugger(%p), callback_function=%p, callback_baton=%p, "
-                    "granularity=%s, end_token=\"%s\", prompt=\"%s\", echo=%i)", 
-                    m_opaque_sp.get(), 
-                    debugger.get(), 
-                    callback_function,
-                    callback_baton, 
-                    InputReader::GranularityAsCString (granularity), end_token, prompt, 
-                    echo);
-
-    SBError sb_error;
-    m_opaque_sp.reset (new InputReader (debugger.ref()));
-    
-    m_callback_function = callback_function;
-    m_callback_baton = callback_baton;
-
-    if (m_opaque_sp)
-    {
-        sb_error.SetError (m_opaque_sp->Initialize (SBInputReader::PrivateCallback,
-                                                    this,
-                                                    granularity,
-                                                    end_token,
-                                                    prompt,
-                                                    echo));
-    }
-
-    if (sb_error.Fail())
-    {
-        m_opaque_sp.reset ();
-        m_callback_function = NULL;
-        m_callback_baton = NULL;
-    }
-
-    if (log)
-    {
-        SBStream sstr;
-        sb_error.GetDescription (sstr);
-        log->Printf ("SBInputReader(%p)::Initialize (...) => SBError(%p): %s", m_opaque_sp.get(),
-                     sb_error.get(), sstr.GetData());
-    }
-
-    return sb_error;
-}
-
-bool
-SBInputReader::IsValid () const
-{
-    return (m_opaque_sp.get() != NULL);
-}
-
-const SBInputReader &
-SBInputReader::operator = (const SBInputReader &rhs)
-{
-    if (this != &rhs)
-        m_opaque_sp = rhs.m_opaque_sp;
-    return *this;
-}
-
-InputReader *
-SBInputReader::operator->() const
-{
-    return m_opaque_sp.get();
-}
-
-lldb::InputReaderSP &
-SBInputReader::operator *()
-{
-    return m_opaque_sp;
-}
-
-const lldb::InputReaderSP &
-SBInputReader::operator *() const
-{
-    return m_opaque_sp;
-}
-
-InputReader *
-SBInputReader::get() const
-{
-    return m_opaque_sp.get();
-}
-
-InputReader &
-SBInputReader::ref() const
-{
-    assert (m_opaque_sp.get());
-    return *m_opaque_sp;
-}
-
-bool
-SBInputReader::IsDone () const
-{
-    if (m_opaque_sp)
-        return m_opaque_sp->IsDone();
-    else
-        return true;
-}
-
-void
-SBInputReader::SetIsDone (bool value)
-{
-    if (m_opaque_sp)
-        m_opaque_sp->SetIsDone (value);
-}
-
-bool
-SBInputReader::IsActive () const
-{
-    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
-    bool ret_value = false;
-    if (m_opaque_sp)
-        ret_value = m_opaque_sp->IsActive();
-    
-    if (log)
-        log->Printf ("SBInputReader(%p)::IsActive () => %i", m_opaque_sp.get(), ret_value);
-
-    return ret_value;
-}
-
-InputReaderGranularity
-SBInputReader::GetGranularity ()
-{
-    if (m_opaque_sp)
-        return m_opaque_sp->GetGranularity();
-    else
-        return eInputReaderGranularityInvalid;
-}

Modified: lldb/branches/iohandler/source/Commands/CommandObjectBreakpointCommand.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectBreakpointCommand.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectBreakpointCommand.cpp (original)
+++ lldb/branches/iohandler/source/Commands/CommandObjectBreakpointCommand.cpp Thu Jan  2 16:40:14 2014
@@ -16,6 +16,7 @@
 #include "CommandObjectBreakpointCommand.h"
 #include "CommandObjectBreakpoint.h"
 
+#include "lldb/Core/IOHandler.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Target/Target.h"
@@ -34,7 +35,9 @@ using namespace lldb_private;
 //-------------------------------------------------------------------------
 
 
-class CommandObjectBreakpointCommandAdd : public CommandObjectParsed
+class CommandObjectBreakpointCommandAdd :
+    public CommandObjectParsed,
+    public IOHandlerDelegateMultiline
 {
 public:
 
@@ -43,6 +46,7 @@ public:
                              "add",
                              "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
                              NULL),
+    IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
         m_options (interpreter)
     {
         SetHelpLong (
@@ -207,42 +211,47 @@ one command per line.\n" );
         return &m_options;
     }
 
-    void
-    CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, 
-                                             CommandReturnObject &result)
+    virtual void
+    IOHandlerActivated (IOHandler &io_handler)
     {
-        InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
-        std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
-        if (reader_sp && data_ap.get())
+        StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+        if (output_sp)
         {
-            BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
-            bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
-
-            Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
-                                              bp_options,                   // baton
-                                              eInputReaderGranularityLine,  // token size, to pass to callback function
-                                              "DONE",                       // end token
-                                              "> ",                         // prompt
-                                              true));                       // echo input
-            if (err.Success())
-            {
-                m_interpreter.GetDebugger().PushInputReader (reader_sp);
-                result.SetStatus (eReturnStatusSuccessFinishNoResult);
-            }
-            else
-            {
-                result.AppendError (err.AsCString());
-                result.SetStatus (eReturnStatusFailed);
-            }
+            output_sp->PutCString(g_reader_instructions);
+            output_sp->Flush();
         }
-        else
+    }
+    
+    
+    virtual void
+    IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+    {
+        io_handler.SetIsDone(true);
+        
+        BreakpointOptions *bp_options = (BreakpointOptions *) io_handler.GetUserData();
+        if (bp_options)
         {
-            result.AppendError("out of memory");
-            result.SetStatus (eReturnStatusFailed);
+            std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+            if (data_ap.get())
+            {
+                data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
+                BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+                bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
+            }
         }
 
     }
     
+    void
+    CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, 
+                                             CommandReturnObject &result)
+    {
+        m_interpreter.GetLLDBCommandsFromIOHandler ("> ",           // Prompt
+                                                    *this,          // IOHandlerDelegate
+                                                    true,           // Run IOHandler in async mode
+                                                    bp_options);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+    }
+    
     /// Set a one-liner as the callback for the breakpoint.
     void 
     SetBreakpointCommandCallback (BreakpointOptions *bp_options,
@@ -262,93 +271,6 @@ one command per line.\n" );
 
         return;
     }
-
-    static size_t
-    GenerateBreakpointCommandCallback (void *baton, 
-                                       InputReader &reader, 
-                                       lldb::InputReaderAction notification,
-                                       const char *bytes, 
-                                       size_t bytes_len)
-    {
-        StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-        bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-        
-        switch (notification)
-        {
-        case eInputReaderActivate:
-            if (!batch_mode)
-            {
-                out_stream->Printf ("%s\n", g_reader_instructions);
-                if (reader.GetPrompt())
-                    out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush();
-            }
-            break;
-
-        case eInputReaderDeactivate:
-            break;
-
-        case eInputReaderReactivate:
-            if (reader.GetPrompt() && !batch_mode)
-            {
-                out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush();
-            }
-            break;
-
-        case eInputReaderAsynchronousOutputWritten:
-            break;
-            
-        case eInputReaderGotToken:
-            if (bytes && bytes_len && baton)
-            {
-                BreakpointOptions *bp_options = (BreakpointOptions *) baton;
-                if (bp_options)
-                {
-                    Baton *bp_options_baton = bp_options->GetBaton();
-                    if (bp_options_baton)
-                        ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len); 
-                }
-            }
-            if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
-            {
-                out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush();
-            }
-            break;
-            
-        case eInputReaderInterrupt:
-            {
-                // Finish, and cancel the breakpoint command.
-                reader.SetIsDone (true);
-                BreakpointOptions *bp_options = (BreakpointOptions *) baton;
-                if (bp_options)
-                {
-                    Baton *bp_options_baton = bp_options->GetBaton ();
-                    if (bp_options_baton)
-                    {
-                        ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
-                        ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear();
-                    }
-                }
-                if (!batch_mode)
-                {
-                    out_stream->Printf ("Warning: No command attached to breakpoint.\n");
-                    out_stream->Flush();
-                }
-            }
-            break;
-            
-        case eInputReaderEndOfFile:
-            reader.SetIsDone (true);
-            break;
-            
-        case eInputReaderDone:
-            break;
-        }
-
-        return bytes_len;
-    }
     
     static bool
     BreakpointOptionsCallbackFunction (void *baton,
@@ -623,7 +545,7 @@ private:
 };
 
 const char *
-CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.";
+CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.\n";
 
 // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
 // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.

Modified: lldb/branches/iohandler/source/Commands/CommandObjectBreakpointCommand.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectBreakpointCommand.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectBreakpointCommand.h (original)
+++ lldb/branches/iohandler/source/Commands/CommandObjectBreakpointCommand.h Thu Jan  2 16:40:14 2014
@@ -19,7 +19,6 @@
 
 #include "lldb/lldb-types.h"
 #include "lldb/Interpreter/Options.h"
-#include "lldb/Core/InputReader.h"
 #include "lldb/Interpreter/CommandObject.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Interpreter/CommandObjectMultiword.h"

Modified: lldb/branches/iohandler/source/Commands/CommandObjectCommands.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectCommands.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectCommands.cpp (original)
+++ lldb/branches/iohandler/source/Commands/CommandObjectCommands.cpp Thu Jan  2 16:40:14 2014
@@ -18,8 +18,7 @@
 
 // Project includes
 #include "lldb/Core/Debugger.h"
-#include "lldb/Core/InputReader.h"
-#include "lldb/Core/InputReaderEZ.h"
+#include "lldb/Core/IOHandler.h"
 #include "lldb/Core/StringList.h"
 #include "lldb/Interpreter/Args.h"
 #include "lldb/Interpreter/CommandHistory.h"
@@ -379,7 +378,8 @@ protected:
         {
             const char *filename = command.GetArgumentAtIndex(0);
 
-            result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
+            if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode())
+                result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
 
             FileSpec cmd_file (filename, true);
             ExecutionContext *exe_ctx = NULL;  // Just use the default context.
@@ -423,7 +423,7 @@ CommandObjectCommandsSource::CommandOpti
 
 static const char *g_python_command_instructions =   "Enter your Python command(s). Type 'DONE' to end.\n"
                                                      "You must define a Python function with this signature:\n"
-                                                     "def my_command_impl(debugger, args, result, internal_dict):";
+                                                     "def my_command_impl(debugger, args, result, internal_dict):\n";
 
 
 class CommandObjectCommandsAlias : public CommandObjectRaw
@@ -856,7 +856,9 @@ protected:
 //-------------------------------------------------------------------------
 #pragma mark CommandObjectCommandsAddRegex
 
-class CommandObjectCommandsAddRegex : public CommandObjectParsed
+class CommandObjectCommandsAddRegex :
+    public CommandObjectParsed,
+    public IOHandlerDelegate
 {
 public:
     CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
@@ -864,6 +866,7 @@ public:
                        "command regex",
                        "Allow the user to create a regular expression command.",
                        "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
+        IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand),
         m_options (interpreter)
     {
         SetHelpLong(
@@ -899,6 +902,98 @@ public:
     
     
 protected:
+    
+    virtual void
+    IOHandlerActivated (IOHandler &io_handler)
+    {
+        StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+        if (output_sp)
+        {
+            output_sp->PutCString("Enter one of more sed substitution commands in the form: 's/<regex>/<subst>/'.\nTerminate the substitution list with an empty line.\n");
+            output_sp->Flush();
+        }
+    }
+
+    virtual void
+    IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+    {
+        io_handler.SetIsDone(true);
+        if (m_regex_cmd_ap.get())
+        {
+            StringList lines;
+            if (lines.SplitIntoLines (data))
+            {
+                const size_t num_lines = lines.GetSize();
+                bool check_only = false;
+                for (size_t i=0; i<num_lines; ++i)
+                {
+                    printf ("regex[%zu] = %s\n", i, lines[i].c_str());
+                    llvm::StringRef bytes_strref (lines[i]);
+                    Error error = AppendRegexSubstitution (bytes_strref, check_only);
+                    if (error.Fail())
+                    {
+                        if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode())
+                        {
+                            StreamSP out_stream = m_interpreter.GetDebugger().GetAsyncOutputStream();
+                            out_stream->Printf("error: %s\n", error.AsCString());
+                        }
+                    }
+                }
+            }
+            if (m_regex_cmd_ap->HasRegexEntries())
+            {
+                CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
+                m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
+            }
+        }
+    }
+    
+    virtual LineStatus
+    IOHandlerLinesUpdated (IOHandler &io_handler,
+                           StringList &lines,
+                           uint32_t line_idx,
+                           Error &error)
+    {
+        if (line_idx == UINT32_MAX)
+        {
+            // Remove the last "DONE" line from "lines" so it doesn't appear
+            // in our final commands and return true to indicate we are done
+            // getting lines
+            lines.PopBack();
+            error.Clear();
+            return LineStatus::Done;
+        }
+        else
+        {
+            const size_t num_lines = lines.GetSize();
+            if (line_idx + 1 == num_lines)
+            {
+                // The last line was edited, if this line is empty, then we are done
+                // getting our multiple lines.
+                if (lines[line_idx].empty())
+                {
+                    // Remove the last empty line from "lines" so it doesn't appear
+                    // in our final expression and return true to indicate we are done
+                    // getting lines
+                    lines.PopBack();
+                    return LineStatus::Done;
+                }
+            }
+            // Check the current line to make sure it is formatted correctly
+            bool check_only = true;
+            llvm::StringRef regex_sed(lines[line_idx]);
+            error = AppendRegexSubstitution (regex_sed, check_only);
+            if (error.Fail())
+            {
+                return LineStatus::Error;
+            }
+            else
+            {
+                return LineStatus::Success;
+            }
+        }
+    }
+
     bool
     DoExecute (Args& command, CommandReturnObject &result)
     {
@@ -920,21 +1015,18 @@ protected:
 
             if (argc == 1)
             {
-                InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
-                if (reader_sp)
+                Debugger &debugger = m_interpreter.GetDebugger();
+                const bool multiple_lines = true; // Get multiple lines
+                IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
+                                                                  "lldb",      // Name of input reader for history
+                                                                  "\033[K> ",  // Prompt and clear line
+                                                                  multiple_lines,
+                                                                  *this));
+                
+                if (io_handler_sp)
                 {
-                    error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
-                                                  this,                         // baton
-                                                  eInputReaderGranularityLine,  // token size, to pass to callback function
-                                                  NULL,                         // end token
-                                                  "> ",                         // prompt
-                                                  true);                        // echo input
-                    if (error.Success())
-                    {
-                        m_interpreter.GetDebugger().PushInputReader (reader_sp);
-                        result.SetStatus (eReturnStatusSuccessFinishNoResult);
-                        return true;
-                    }
+                    debugger.PushIOHandler(io_handler_sp);
+                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
                 }
             }
             else
@@ -942,7 +1034,8 @@ protected:
                 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
                 {
                     llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx));
-                    error = AppendRegexSubstitution (arg_strref);
+                    bool check_only = false;
+                    error = AppendRegexSubstitution (arg_strref, check_only);
                     if (error.Fail())
                         break;
                 }
@@ -963,7 +1056,7 @@ protected:
     }
     
     Error
-    AppendRegexSubstitution (const llvm::StringRef &regex_sed)
+    AppendRegexSubstitution (const llvm::StringRef &regex_sed, bool check_only)
     {
         Error error;
         
@@ -1053,10 +1146,14 @@ protected:
                                            regex_sed.data());
             return error;            
         }
-        std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
-        std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
-        m_regex_cmd_ap->AddRegexCommand (regex.c_str(), 
-                                         subst.c_str());
+
+        if (check_only == false)
+        {
+            std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
+            std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
+            m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
+                                             subst.c_str());
+        }
         return error;
     }
     
@@ -1073,89 +1170,6 @@ protected:
         }
     }
 
-    void
-    InputReaderDidCancel()
-    {
-        m_regex_cmd_ap.reset();
-    }
-
-    static size_t
-    InputReaderCallback (void *baton, 
-                         InputReader &reader, 
-                         lldb::InputReaderAction notification,
-                         const char *bytes, 
-                         size_t bytes_len)
-    {
-        CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
-        bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();    
-        
-        switch (notification)
-        {
-            case eInputReaderActivate:
-                if (!batch_mode)
-                {
-                    StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream ();
-                    out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
-                    out_stream->Flush();
-                }
-                break;
-            case eInputReaderReactivate:
-                break;
-                
-            case eInputReaderDeactivate:
-                break;
-            
-            case eInputReaderAsynchronousOutputWritten:
-                break;
-                        
-            case eInputReaderGotToken:
-                while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
-                    --bytes_len;
-                if (bytes_len == 0)
-                    reader.SetIsDone(true);
-                else if (bytes)
-                {
-                    llvm::StringRef bytes_strref (bytes, bytes_len);
-                    Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
-                    if (error.Fail())
-                    {
-                        if (!batch_mode)
-                        {
-                            StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-                            out_stream->Printf("error: %s\n", error.AsCString());
-                            out_stream->Flush();
-                        }
-                        add_regex_cmd->InputReaderDidCancel ();
-                        reader.SetIsDone (true);
-                    }
-                }
-                break;
-                
-            case eInputReaderInterrupt:
-                {
-                    reader.SetIsDone (true);
-                    if (!batch_mode)
-                    {
-                        StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-                        out_stream->PutCString("Regular expression command creations was cancelled.\n");
-                        out_stream->Flush();
-                    }
-                    add_regex_cmd->InputReaderDidCancel ();
-                }
-                break;
-                
-            case eInputReaderEndOfFile:
-                reader.SetIsDone (true);
-                break;
-                
-            case eInputReaderDone:
-                add_regex_cmd->AddRegexCommandToInterpreter();
-                break;
-        }
-        
-        return bytes_len;
-    }
-
 private:
     std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
 
@@ -1526,7 +1540,9 @@ CommandObjectCommandsScriptImport::Comma
 // CommandObjectCommandsScriptAdd
 //-------------------------------------------------------------------------
 
-class CommandObjectCommandsScriptAdd : public CommandObjectParsed
+class CommandObjectCommandsScriptAdd :
+    public CommandObjectParsed,
+    public IOHandlerDelegateMultiline
 {
 public:
     CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
@@ -1534,6 +1550,7 @@ public:
                              "command script add",
                              "Add a scripted function as an LLDB command.",
                              NULL),
+        IOHandlerDelegateMultiline ("DONE"),
         m_options (interpreter)
     {
         CommandArgumentEntry arg1;
@@ -1567,7 +1584,7 @@ protected:
     public:
         
         CommandOptions (CommandInterpreter &interpreter) :
-        Options (interpreter)
+            Options (interpreter)
         {
         }
         
@@ -1586,7 +1603,7 @@ protected:
                     m_funct_name = std::string(option_arg);
                     break;
                 case 's':
-                    m_synchronous = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
+                    m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
                     if (!error.Success())
                         error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg);
                     break;
@@ -1602,7 +1619,7 @@ protected:
         OptionParsingStarting ()
         {
             m_funct_name = "";
-            m_synchronous = eScriptedCommandSynchronicitySynchronous;
+            m_synchronicity = eScriptedCommandSynchronicitySynchronous;
         }
         
         const OptionDefinition*
@@ -1618,128 +1635,81 @@ protected:
         // Instance variables to hold the values for command options.
         
         std::string m_funct_name;
-        ScriptedCommandSynchronicity m_synchronous;
+        ScriptedCommandSynchronicity m_synchronicity;
     };
 
-private:
-    class PythonAliasReader : public InputReaderEZ
+    virtual void
+    IOHandlerActivated (IOHandler &io_handler)
     {
-    private:
-        CommandInterpreter& m_interpreter;
-        std::string m_cmd_name;
-        ScriptedCommandSynchronicity m_synchronous;
-        StringList m_user_input;
-        DISALLOW_COPY_AND_ASSIGN (PythonAliasReader);
-    public:
-        PythonAliasReader(Debugger& debugger,
-                          CommandInterpreter& interpreter,
-                          std::string cmd_name,
-                          ScriptedCommandSynchronicity synch) : 
-        InputReaderEZ(debugger),
-        m_interpreter(interpreter),
-        m_cmd_name(cmd_name),
-        m_synchronous(synch),
-        m_user_input()
-        {}
-        
-        virtual
-        ~PythonAliasReader()
+        StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+        if (output_sp)
         {
+            output_sp->PutCString(g_python_command_instructions);
+            output_sp->Flush();
         }
+    }
+    
+
+    virtual void
+    IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+    {
+        StreamFileSP error_sp = io_handler.GetErrorStreamFile();
         
-        virtual void ActivateHandler(HandlerData& data)
+        ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
+        if (interpreter)
         {
-            StreamSP out_stream = data.GetOutStream();
-            bool batch_mode = data.GetBatchMode();
-            if (!batch_mode)
-            {
-                out_stream->Printf ("%s\n", g_python_command_instructions);
-                if (data.reader.GetPrompt())
-                    out_stream->Printf ("%s", data.reader.GetPrompt());
-                out_stream->Flush();
-            }
-        }
         
-        virtual void ReactivateHandler(HandlerData& data)
-        {
-            StreamSP out_stream = data.GetOutStream();
-            bool batch_mode = data.GetBatchMode();
-            if (data.reader.GetPrompt() && !batch_mode)
+            StringList lines;
+            lines.SplitIntoLines(data);
+            if (lines.GetSize() > 0)
             {
-                out_stream->Printf ("%s", data.reader.GetPrompt());
-                out_stream->Flush();
-            }
-        }
-        virtual void GotTokenHandler(HandlerData& data)
-        {
-            StreamSP out_stream = data.GetOutStream();
-            bool batch_mode = data.GetBatchMode();
-            if (data.bytes && data.bytes_len)
-            {
-                m_user_input.AppendString(data.bytes, data.bytes_len);
-            }
-            if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
-            {
-                out_stream->Printf ("%s", data.reader.GetPrompt());
-                out_stream->Flush();
+                std::string funct_name_str;
+                if (interpreter->GenerateScriptAliasFunction (lines, funct_name_str))
+                {
+                    if (funct_name_str.empty())
+                    {
+                        error_sp->Printf ("error: unable to obtain a function name, didn't add python command.\n");
+                        error_sp->Flush();
+                    }
+                    else
+                    {
+                        // everything should be fine now, let's add this alias
+                        
+                        CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter,
+                                                                                        m_cmd_name,
+                                                                                        funct_name_str.c_str(),
+                                                                                        m_synchronicity));
+                        
+                        if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true))
+                        {
+                            error_sp->Printf ("error: unable to add selected command, didn't add python command.\n");
+                            error_sp->Flush();
+                        }
+                    }
+                }
+                else
+                {
+                    error_sp->Printf ("error: unable to create function, didn't add python command.\n");
+                    error_sp->Flush();
+                }
             }
-        }
-        virtual void InterruptHandler(HandlerData& data)
-        {
-            StreamSP out_stream = data.GetOutStream();
-            bool batch_mode = data.GetBatchMode();
-            data.reader.SetIsDone (true);
-            if (!batch_mode)
+            else
             {
-                out_stream->Printf ("Warning: No script attached.\n");
-                out_stream->Flush();
+                error_sp->Printf ("error: empty function, didn't add python command.\n");
+                error_sp->Flush();
             }
         }
-        virtual void EOFHandler(HandlerData& data)
+        else
         {
-            data.reader.SetIsDone (true);
+            error_sp->Printf ("error: script interpreter missing, didn't add python command.\n");
+            error_sp->Flush();
         }
-        virtual void DoneHandler(HandlerData& data)
-        {
-            StreamSP out_stream = data.GetOutStream();
-            
-            ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
-            if (!interpreter)
-            {
-                out_stream->Printf ("Script interpreter missing: no script attached.\n");
-                out_stream->Flush();
-                return;
-            }
-            std::string funct_name_str;
-            if (!interpreter->GenerateScriptAliasFunction (m_user_input, 
-                                                           funct_name_str))
-            {
-                out_stream->Printf ("Unable to create function: no script attached.\n");
-                out_stream->Flush();
-                return;
-            }
-            if (funct_name_str.empty())
-            {
-                out_stream->Printf ("Unable to obtain a function name: no script attached.\n");
-                out_stream->Flush();
-                return;
-            }
-            // everything should be fine now, let's add this alias
-            
-            CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
-                                                                           m_cmd_name,
-                                                                           funct_name_str.c_str(),
-                                                                           m_synchronous));
-            
-            if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true))
-            {
-                out_stream->Printf ("Unable to add selected command: no script attached.\n");
-                out_stream->Flush();
-                return;
-            }
-        }
-    };
-    
+
+        io_handler.SetIsDone(true);
+        
+        
+    }
+
 protected:
     bool
     DoExecute (Args& command, CommandReturnObject &result)
@@ -1761,45 +1731,24 @@ protected:
             return false;
         }
         
-        std::string cmd_name = command.GetArgumentAtIndex(0);
+        // Store the command name and synchronicity in case we get multi-line input
+        m_cmd_name = command.GetArgumentAtIndex(0);
+        m_synchronicity = m_options.m_synchronicity;
         
         if (m_options.m_funct_name.empty())
         {
-            InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(),
-                                                            m_interpreter,
-                                                            cmd_name,
-                                                            m_options.m_synchronous));
-            
-            if (reader_sp)
-            {
-                
-                InputReaderEZ::InitializationParameters ipr;
-                
-                Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt("     ")));
-                if (err.Success())
-                {
-                    m_interpreter.GetDebugger().PushInputReader (reader_sp);
-                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
-                }
-                else
-                {
-                    result.AppendError (err.AsCString());
-                    result.SetStatus (eReturnStatusFailed);
-                }
-            }
-            else
-            {
-                result.AppendError("out of memory");
-                result.SetStatus (eReturnStatusFailed);
-            }
+            m_interpreter.GetPythonCommandsFromIOHandler ("     ",  // Prompt
+                                                          *this,    // IOHandlerDelegate
+                                                          true,     // Run IOHandler in async mode
+                                                          NULL);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
         }
         else
         {
             CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter,
-                                                                    cmd_name,
+                                                                    m_cmd_name,
                                                                     m_options.m_funct_name,
-                                                                    m_options.m_synchronous));
-            if (m_interpreter.AddUserCommand(cmd_name, new_cmd, true))
+                                                                    m_synchronicity));
+            if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
             {
                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
             }
@@ -1815,6 +1764,8 @@ protected:
     }
     
     CommandOptions m_options;
+    std::string m_cmd_name;
+    ScriptedCommandSynchronicity m_synchronicity;
 };
 
 static OptionEnumValueElement g_script_synchro_type[] =

Modified: lldb/branches/iohandler/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectExpression.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/branches/iohandler/source/Commands/CommandObjectExpression.cpp Thu Jan  2 16:40:14 2014
@@ -17,7 +17,6 @@
 // Project includes
 #include "lldb/Interpreter/Args.h"
 #include "lldb/Core/Value.h"
-#include "lldb/Core/InputReader.h"
 #include "lldb/Core/ValueObjectVariable.h"
 #include "lldb/DataFormatters/ValueObjectPrinter.h"
 #include "lldb/Expression/ClangExpressionVariable.h"
@@ -197,6 +196,7 @@ CommandObjectExpression::CommandObjectEx
                       "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.",
                       NULL,
                       eFlagProcessMustBePaused | eFlagTryTargetAPILock),
+    IOHandlerDelegate (IOHandlerDelegate::Completion::Expression),
     m_option_group (interpreter),
     m_format_options (eFormatDefault),
     m_command_options (),
@@ -254,87 +254,6 @@ CommandObjectExpression::GetOptions ()
     return &m_option_group;
 }
 
-size_t
-CommandObjectExpression::MultiLineExpressionCallback
-(
-    void *baton, 
-    InputReader &reader, 
-    lldb::InputReaderAction notification,
-    const char *bytes, 
-    size_t bytes_len
-)
-{
-    CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton;
-    bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-    
-    switch (notification)
-    {
-    case eInputReaderActivate:
-        if (!batch_mode)
-        {
-            StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream());
-            if (async_strm_sp)
-            {
-                async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
-                async_strm_sp->Flush();
-            }
-        }
-        // Fall through
-    case eInputReaderReactivate:
-        break;
-
-    case eInputReaderDeactivate:
-        break;
-
-    case eInputReaderAsynchronousOutputWritten:
-        break;
-        
-    case eInputReaderGotToken:
-        ++cmd_object_expr->m_expr_line_count;
-        if (bytes && bytes_len)
-        {
-            cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1);
-        }
-
-        if (bytes_len == 0)
-            reader.SetIsDone(true);
-        break;
-        
-    case eInputReaderInterrupt:
-        cmd_object_expr->m_expr_lines.clear();
-        reader.SetIsDone (true);
-        if (!batch_mode)
-        {
-            StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream());
-            if (async_strm_sp)
-            {
-                async_strm_sp->PutCString("Expression evaluation cancelled.\n");
-                async_strm_sp->Flush();
-            }
-        }
-        break;
-        
-    case eInputReaderEndOfFile:
-        reader.SetIsDone (true);
-        break;
-        
-    case eInputReaderDone:
-		if (cmd_object_expr->m_expr_lines.size() > 0)
-        {
-            StreamSP output_stream = reader.GetDebugger().GetAsyncOutputStream();
-            StreamSP error_stream = reader.GetDebugger().GetAsyncErrorStream();
-            cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), 
-                                                 output_stream.get(), 
-                                                 error_stream.get());
-            output_stream->Flush();
-            error_stream->Flush();
-        }
-        break;
-    }
-
-    return bytes_len;
-}
-
 bool
 CommandObjectExpression::EvaluateExpression 
 (
@@ -443,6 +362,60 @@ CommandObjectExpression::EvaluateExpress
     return true;
 }
 
+void
+CommandObjectExpression::IOHandlerActivated (IOHandler &io_handler)
+{
+    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+    if (output_sp)
+    {
+        output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
+        output_sp->Flush();
+    }
+}
+
+
+void
+CommandObjectExpression::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+{
+    io_handler.SetIsDone(true);
+//    StreamSP output_stream = io_handler.GetDebugger().GetAsyncOutputStream();
+//    StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream();
+    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+    StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+
+    EvaluateExpression (line.c_str(),
+                        output_sp.get(),
+                        error_sp.get());
+    if (output_sp)
+        output_sp->Flush();
+    if (error_sp)
+        error_sp->Flush();
+}
+
+LineStatus
+CommandObjectExpression::IOHandlerLinesUpdated (IOHandler &io_handler,
+                                                StringList &lines,
+                                                uint32_t line_idx,
+                                                Error &error)
+{
+    if (line_idx == UINT32_MAX)
+    {
+        // Remove the last line from "lines" so it doesn't appear
+        // in our final expression
+        lines.PopBack();
+        error.Clear();
+        return LineStatus::Done;
+    }
+    else if (line_idx + 1 == lines.GetSize())
+    {
+        // The last line was edited, if this line is empty, then we are done
+        // getting our multiple lines.
+        if (lines[line_idx].empty())
+            return LineStatus::Done;
+    }
+    return LineStatus::Success;
+}
+
 bool
 CommandObjectExpression::DoExecute
 (
@@ -459,31 +432,14 @@ CommandObjectExpression::DoExecute
         m_expr_lines.clear();
         m_expr_line_count = 0;
         
-        InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
-        if (reader_sp)
-        {
-            Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback,
-                                              this,                         // baton
-                                              eInputReaderGranularityLine,  // token size, to pass to callback function
-                                              NULL,                         // end token
-                                              NULL,                         // prompt
-                                              true));                       // echo input
-            if (err.Success())
-            {
-                m_interpreter.GetDebugger().PushInputReader (reader_sp);
-                result.SetStatus (eReturnStatusSuccessFinishNoResult);
-            }
-            else
-            {
-                result.AppendError (err.AsCString());
-                result.SetStatus (eReturnStatusFailed);
-            }
-        }
-        else
-        {
-            result.AppendError("out of memory");
-            result.SetStatus (eReturnStatusFailed);
-        }
+        Debugger &debugger = GetCommandInterpreter().GetDebugger();
+        const bool multiple_lines = true; // Get multiple lines
+        IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
+                                                          "lldb-expr",      // Name of input reader for history
+                                                          NULL,             // No prompt
+                                                          multiple_lines,
+                                                          *this));
+        debugger.PushIOHandler(io_handler_sp);
         return result.Succeeded();
     }
 

Modified: lldb/branches/iohandler/source/Commands/CommandObjectExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectExpression.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectExpression.h (original)
+++ lldb/branches/iohandler/source/Commands/CommandObjectExpression.h Thu Jan  2 16:40:14 2014
@@ -14,6 +14,7 @@
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
+#include "lldb/Core/IOHandler.h"
 #include "lldb/Interpreter/CommandObject.h"
 #include "lldb/Interpreter/OptionGroupFormat.h"
 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
@@ -21,7 +22,9 @@
 
 namespace lldb_private {
 
-class CommandObjectExpression : public CommandObjectRaw
+class CommandObjectExpression :
+    public CommandObjectRaw,
+    public IOHandlerDelegate
 {
 public:
 
@@ -71,17 +74,26 @@ public:
     GetOptions ();
 
 protected:
+    
+    //------------------------------------------------------------------
+    // IOHandler::Delegate functions
+    //------------------------------------------------------------------
+    virtual void
+    IOHandlerActivated (IOHandler &io_handler);
+
+    virtual void
+    IOHandlerInputComplete (IOHandler &io_handler,
+                            std::string &line);
+
+    virtual LineStatus
+    IOHandlerLinesUpdated (IOHandler &io_handler,
+                           StringList &lines,
+                           uint32_t line_idx,
+                           Error &error);
     virtual bool
     DoExecute (const char *command,
                CommandReturnObject &result);
 
-    static size_t
-    MultiLineExpressionCallback (void *baton, 
-                                 InputReader &reader, 
-                                 lldb::InputReaderAction notification,
-                                 const char *bytes, 
-                                 size_t bytes_len);
-
     bool
     EvaluateExpression (const char *expr,
                         Stream *output_stream,

Added: lldb/branches/iohandler/source/Commands/CommandObjectGUI.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectGUI.cpp?rev=198366&view=auto
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectGUI.cpp (added)
+++ lldb/branches/iohandler/source/Commands/CommandObjectGUI.cpp Thu Jan  2 16:40:14 2014
@@ -0,0 +1,56 @@
+//===-- CommandObjectGUI.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/lldb-python.h"
+
+#include "CommandObjectGUI.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectGUI
+//-------------------------------------------------------------------------
+
+CommandObjectGUI::CommandObjectGUI (CommandInterpreter &interpreter) :
+    CommandObjectParsed (interpreter, "gui", "Switch into the curses based GUI mode.", "gui")
+{
+}
+
+CommandObjectGUI::~CommandObjectGUI ()
+{
+}
+
+bool
+CommandObjectGUI::DoExecute (Args& args, CommandReturnObject &result)
+{
+    if (args.GetArgumentCount() == 0)
+    {
+        Debugger &debugger = m_interpreter.GetDebugger();
+        IOHandlerSP io_handler_sp (new IOHandlerCursesGUI (debugger));
+        if (io_handler_sp)
+            debugger.PushIOHandler(io_handler_sp);
+        result.SetStatus (eReturnStatusSuccessFinishResult);
+    }
+    else
+    {
+        result.AppendError("the gui command takes no arguments.");
+        result.SetStatus (eReturnStatusFailed);
+    }
+    return true;
+}
+

Added: lldb/branches/iohandler/source/Commands/CommandObjectGUI.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectGUI.h?rev=198366&view=auto
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectGUI.h (added)
+++ lldb/branches/iohandler/source/Commands/CommandObjectGUI.h Thu Jan  2 16:40:14 2014
@@ -0,0 +1,43 @@
+//===-- CommandObjectGUI.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectGUI_h_
+#define liblldb_CommandObjectGUI_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectGUI
+//-------------------------------------------------------------------------
+
+class CommandObjectGUI : public CommandObjectParsed
+{
+public:
+
+    CommandObjectGUI (CommandInterpreter &interpreter);
+
+    virtual
+    ~CommandObjectGUI ();
+
+protected:
+    virtual bool
+    DoExecute (Args& args,
+               CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_CommandObjectGUI_h_

Modified: lldb/branches/iohandler/source/Commands/CommandObjectProcess.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectProcess.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectProcess.cpp (original)
+++ lldb/branches/iohandler/source/Commands/CommandObjectProcess.cpp Thu Jan  2 16:40:14 2014
@@ -548,7 +548,7 @@ protected:
                     // Otherwise just return.  
                     // FIXME: in the async case it will now be possible to get to the command
                     // interpreter with a state eStateAttaching.  Make sure we handle that correctly.
-                    StateType state = process->WaitForProcessToStop (NULL);
+                    StateType state = process->WaitForProcessToStop (NULL, NULL, false);
                     
                     result.SetDidChangeProcessState (true);
 
@@ -1087,7 +1087,7 @@ protected:
             
             if (process)
             {
-                error = process->ConnectRemote (&process->GetTarget().GetDebugger().GetOutputStream(), remote_url);
+                error = process->ConnectRemote (process->GetTarget().GetDebugger().GetOutputFile().get(), remote_url);
 
                 if (error.Fail())
                 {

Modified: lldb/branches/iohandler/source/Commands/CommandObjectQuit.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectQuit.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectQuit.cpp (original)
+++ lldb/branches/iohandler/source/Commands/CommandObjectQuit.cpp Thu Jan  2 16:40:14 2014
@@ -92,7 +92,8 @@ CommandObjectQuit::DoExecute (Args& comm
             return false;
         }
     }
-    m_interpreter.BroadcastEvent (CommandInterpreter::eBroadcastBitQuitCommandReceived);
+    const uint32_t event_type = CommandInterpreter::eBroadcastBitQuitCommandReceived;
+    m_interpreter.BroadcastEvent (event_type);
     result.SetStatus (eReturnStatusQuit);
     return true;
 }

Modified: lldb/branches/iohandler/source/Commands/CommandObjectTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectTarget.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectTarget.cpp (original)
+++ lldb/branches/iohandler/source/Commands/CommandObjectTarget.cpp Thu Jan  2 16:40:14 2014
@@ -19,7 +19,7 @@
 // Project includes
 #include "lldb/Interpreter/Args.h"
 #include "lldb/Core/Debugger.h"
-#include "lldb/Core/InputReader.h"
+#include "lldb/Core/IOHandler.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/Section.h"
@@ -4759,7 +4759,9 @@ private:
 // CommandObjectTargetStopHookAdd
 //-------------------------------------------------------------------------
 
-class CommandObjectTargetStopHookAdd : public CommandObjectParsed
+class CommandObjectTargetStopHookAdd :
+    public CommandObjectParsed,
+    public IOHandlerDelegateMultiline
 {
 public:
 
@@ -4926,9 +4928,10 @@ public:
 
     CommandObjectTargetStopHookAdd (CommandInterpreter &interpreter) :
         CommandObjectParsed (interpreter,
-                             "target stop-hook add ",
+                             "target stop-hook add",
                              "Add a hook to be executed when the target stops.",
                              "target stop-hook add"),
+        IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
         m_options (interpreter)
     {
     }
@@ -4937,102 +4940,61 @@ public:
     {
     }
 
-    static size_t 
-    ReadCommandsCallbackFunction (void *baton, 
-                                  InputReader &reader, 
-                                  lldb::InputReaderAction notification,
-                                  const char *bytes, 
-                                  size_t bytes_len)
-    {
-        StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-        Target::StopHook *new_stop_hook = ((Target::StopHook *) baton);
-        static bool got_interrupted;
-        bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-
-        switch (notification)
-        {
-        case eInputReaderActivate:
-            if (!batch_mode)
-            {
-                out_stream->Printf ("%s\n", "Enter your stop hook command(s).  Type 'DONE' to end.");
-                if (reader.GetPrompt())
-                    out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush();
-            }
-            got_interrupted = false;
-            break;
-
-        case eInputReaderDeactivate:
-            break;
-
-        case eInputReaderReactivate:
-            if (reader.GetPrompt() && !batch_mode)
-            {
-                out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush();
-            }
-            got_interrupted = false;
-            break;
-
-        case eInputReaderAsynchronousOutputWritten:
-            break;
-            
-        case eInputReaderGotToken:
-            if (bytes && bytes_len && baton)
+protected:
+    
+    virtual void
+    IOHandlerActivated (IOHandler &io_handler)
+    {
+        StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+        if (output_sp)
+        {
+            output_sp->PutCString("Enter your stop hook command(s).  Type 'DONE' to end.\n");
+            output_sp->Flush();
+        }
+    }
+    
+    
+    virtual void
+    IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+    {
+        if (m_stop_hook_sp)
+        {
+            if (line.empty())
             {
-                StringList *commands = new_stop_hook->GetCommandPointer();
-                if (commands)
+                StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+                if (error_sp)
                 {
-                    commands->AppendString (bytes, bytes_len); 
+                    error_sp->Printf("error: stop hook #%" PRIu64 " aborted, no commands.\n", m_stop_hook_sp->GetID());
+                    error_sp->Flush();
                 }
+                Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+                if (target)
+                    target->RemoveStopHookByID(m_stop_hook_sp->GetID());
             }
-            if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
-            {
-                out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush();
-            }
-            break;
-            
-        case eInputReaderInterrupt:
+            else
             {
-                // Finish, and cancel the stop hook.
-                new_stop_hook->GetTarget()->RemoveStopHookByID(new_stop_hook->GetID());
-                if (!batch_mode)
+                m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
+                StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+                if (output_sp)
                 {
-                    out_stream->Printf ("Stop hook cancelled.\n");
-                    out_stream->Flush();
+                    output_sp->Printf("Stop hook #%" PRIu64 " added.\n", m_stop_hook_sp->GetID());
+                    output_sp->Flush();
                 }
-                
-                reader.SetIsDone (true);
             }
-            got_interrupted = true;
-            break;
-            
-        case eInputReaderEndOfFile:
-            reader.SetIsDone (true);
-            break;
-            
-        case eInputReaderDone:
-            if (!got_interrupted && !batch_mode)
-            {
-                out_stream->Printf ("Stop hook #%" PRIu64 " added.\n", new_stop_hook->GetID());
-                out_stream->Flush();
-            }
-            break;
+            m_stop_hook_sp.reset();
         }
-
-        return bytes_len;
+        io_handler.SetIsDone(true);
     }
-
-protected:
+    
     bool
     DoExecute (Args& command, CommandReturnObject &result)
     {
+        m_stop_hook_sp.reset();
+        
         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
         if (target)
         {
-            Target::StopHookSP new_hook_sp;
-            target->AddStopHook (new_hook_sp);
+            Target::StopHookSP new_hook_sp = target->CreateStopHook();
 
             //  First step, make the specifier.
             std::unique_ptr<SymbolContextSpecifier> specifier_ap;
@@ -5105,31 +5067,12 @@ protected:
             }
             else
             {
-                // Otherwise gather up the command list, we'll push an input reader and suck the data from that directly into
-                // the new stop hook's command string.
-                InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
-                if (!reader_sp)
-                {
-                    result.AppendError("out of memory\n");
-                    result.SetStatus (eReturnStatusFailed);
-                    target->RemoveStopHookByID (new_hook_sp->GetID());
-                    return false;
-                }
-                
-                Error err (reader_sp->Initialize (CommandObjectTargetStopHookAdd::ReadCommandsCallbackFunction,
-                                                  new_hook_sp.get(), // baton
-                                                  eInputReaderGranularityLine,  // token size, to pass to callback function
-                                                  "DONE",                       // end token
-                                                  "> ",                         // prompt
-                                                  true));                       // echo input
-                if (!err.Success())
-                {
-                    result.AppendError (err.AsCString());
-                    result.SetStatus (eReturnStatusFailed);
-                    target->RemoveStopHookByID (new_hook_sp->GetID());
-                    return false;
-                }
-                m_interpreter.GetDebugger().PushInputReader (reader_sp);
+                m_stop_hook_sp = new_hook_sp;
+                m_interpreter.GetLLDBCommandsFromIOHandler ("> ",   // Prompt
+                                                            *this,  // IOHandlerDelegate
+                                                            true,   // Run IOHandler in async mode
+                                                            NULL);  // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+
             }
             result.SetStatus (eReturnStatusSuccessFinishNoResult);
         }
@@ -5143,6 +5086,7 @@ protected:
     }
 private:
     CommandOptions m_options;
+    Target::StopHookSP m_stop_hook_sp;
 };
 
 OptionDefinition

Modified: lldb/branches/iohandler/source/Commands/CommandObjectType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectType.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectType.cpp (original)
+++ lldb/branches/iohandler/source/Commands/CommandObjectType.cpp Thu Jan  2 16:40:14 2014
@@ -19,7 +19,7 @@
 
 #include "lldb/Core/ConstString.h"
 #include "lldb/Core/Debugger.h"
-#include "lldb/Core/InputReaderEZ.h"
+#include "lldb/Core/IOHandler.h"
 #include "lldb/Core/RegularExpression.h"
 #include "lldb/Core/State.h"
 #include "lldb/Core/StringList.h"
@@ -42,7 +42,6 @@ public:
     TypeSummaryImpl::Flags m_flags;
     
     StringList m_target_types;
-    StringList m_user_source;
     
     bool m_regex;
         
@@ -74,7 +73,6 @@ public:
     bool m_skip_references;
     bool m_cascade;
     bool m_regex;
-    StringList m_user_source;
     StringList m_target_types;
     
     std::string m_category;
@@ -88,7 +86,6 @@ public:
     m_skip_references(sref),
     m_cascade(casc),
     m_regex(regx),
-    m_user_source(),
     m_target_types(),
     m_category(catg)
     {
@@ -100,7 +97,9 @@ public:
 
 
 
-class CommandObjectTypeSummaryAdd : public CommandObjectParsed
+class CommandObjectTypeSummaryAdd :
+    public CommandObjectParsed,
+    public IOHandlerDelegateMultiline
 {
     
 private:
@@ -153,10 +152,6 @@ private:
         return &m_options;
     }
     
-    void
-    CollectPythonScript(ScriptAddOptions *options,
-                        CommandReturnObject &result);
-    
     bool
     Execute_ScriptSummary (Args& command, CommandReturnObject &result);
     
@@ -178,6 +173,146 @@ public:
     {
     }
     
+    virtual void
+    IOHandlerActivated (IOHandler &io_handler)
+    {
+        static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
+        "def function (valobj,internal_dict):\n"
+        "     \"\"\"valobj: an SBValue which you want to provide a summary for\n"
+        "        internal_dict: an LLDB support object not to be used\"\"\"";
+
+        StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+        if (output_sp)
+        {
+            output_sp->PutCString(g_summary_addreader_instructions);
+            output_sp->Flush();
+        }
+    }
+    
+    
+    virtual void
+    IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+    {
+        StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+        
+        ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
+        if (interpreter)
+        {
+            StringList lines;
+            lines.SplitIntoLines(data);
+            if (lines.GetSize() > 0)
+            {
+                ScriptAddOptions *options_ptr = ((ScriptAddOptions*)io_handler.GetUserData());
+                if (options_ptr)
+                {
+                    ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
+                    
+                    ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
+                    if (interpreter)
+                    {
+                        std::string funct_name_str;
+                        if (interpreter->GenerateTypeScriptFunction (lines, funct_name_str))
+                        {
+                            if (funct_name_str.empty())
+                            {
+                                error_sp->Printf ("unable to obtain a valid function name from the script interpreter.\n");
+                                error_sp->Flush();
+                            }
+                            else
+                            {
+                                // now I have a valid function name, let's add this as script for every type in the list
+                                
+                                TypeSummaryImplSP script_format;
+                                script_format.reset(new ScriptSummaryFormat(options->m_flags,
+                                                                            funct_name_str.c_str(),
+                                                                            lines.CopyList("    ").c_str()));
+                                
+                                Error error;
+                                
+                                for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
+                                {
+                                    const char *type_name = options->m_target_types.GetStringAtIndex(i);
+                                    CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
+                                                                            script_format,
+                                                                            (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary),
+                                                                            options->m_category,
+                                                                            &error);
+                                    if (error.Fail())
+                                    {
+                                        error_sp->Printf ("error: %s", error.AsCString());
+                                        error_sp->Flush();
+                                    }
+                                }
+                                
+                                if (options->m_name)
+                                {
+                                    CommandObjectTypeSummaryAdd::AddSummary (options->m_name,
+                                                                             script_format,
+                                                                             CommandObjectTypeSummaryAdd::eNamedSummary,
+                                                                             options->m_category,
+                                                                             &error);
+                                    if (error.Fail())
+                                    {
+                                        CommandObjectTypeSummaryAdd::AddSummary (options->m_name,
+                                                                                 script_format,
+                                                                                 CommandObjectTypeSummaryAdd::eNamedSummary,
+                                                                                 options->m_category,
+                                                                                 &error);
+                                        if (error.Fail())
+                                        {
+                                            error_sp->Printf ("error: %s", error.AsCString());
+                                            error_sp->Flush();
+                                        }
+                                    }
+                                    else
+                                    {
+                                        error_sp->Printf ("error: %s", error.AsCString());
+                                        error_sp->Flush();
+                                    }
+                                }
+                                else
+                                {
+                                    if (error.AsCString())
+                                    {
+                                        error_sp->Printf ("error: %s", error.AsCString());
+                                        error_sp->Flush();
+                                    }
+                                }
+                            }
+                        }
+                        else
+                        {
+                            error_sp->Printf ("error: unable to generate a function.\n");
+                            error_sp->Flush();
+                        }
+                    }
+                    else
+                    {
+                        error_sp->Printf ("error: no script interpreter.\n");
+                        error_sp->Flush();
+                    }
+                }
+                else
+                {
+                    error_sp->Printf ("error: internal synchronization information missing or invalid.\n");
+                    error_sp->Flush();
+                }
+            }
+            else
+            {
+                error_sp->Printf ("error: empty function, didn't add python command.\n");
+                error_sp->Flush();
+            }
+        }
+        else
+        {
+            error_sp->Printf ("error: script interpreter missing, didn't add python command.\n");
+            error_sp->Flush();
+        }
+        
+        io_handler.SetIsDone(true);
+    }
+    
     static bool
     AddSummary(ConstString type_name,
                lldb::TypeSummaryImplSP entry,
@@ -190,7 +325,19 @@ protected:
     
 };
 
-class CommandObjectTypeSynthAdd : public CommandObjectParsed
+static const char *g_synth_addreader_instructions =   "Enter your Python command(s). Type 'DONE' to end.\n"
+"You must define a Python class with these methods:\n"
+"    def __init__(self, valobj, dict):\n"
+"    def num_children(self):\n"
+"    def get_child_at_index(self, index):\n"
+"    def get_child_index(self, name):\n"
+"    def update(self):\n"
+"        '''Optional'''\n"
+"class synthProvider:\n";
+
+class CommandObjectTypeSynthAdd :
+    public CommandObjectParsed,
+    public IOHandlerDelegateMultiline
 {
     
 private:
@@ -200,7 +347,7 @@ private:
     public:
         
         CommandOptions (CommandInterpreter &interpreter) :
-        Options (interpreter)
+            Options (interpreter)
         {
         }
         
@@ -296,9 +443,6 @@ private:
         return &m_options;
     }
     
-    void
-    CollectPythonScript (SynthAddOptions *options,
-                         CommandReturnObject &result);    
     bool
     Execute_HandwritePython (Args& command, CommandReturnObject &result);
     
@@ -307,8 +451,137 @@ private:
     
 protected:
     bool
-    DoExecute (Args& command, CommandReturnObject &result);
+    DoExecute (Args& command, CommandReturnObject &result)
+    {
+        if (m_options.handwrite_python)
+            return Execute_HandwritePython(command, result);
+        else if (m_options.is_class_based)
+            return Execute_PythonClass(command, result);
+        else
+        {
+            result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+    }
+    
+    virtual void
+    IOHandlerActivated (IOHandler &io_handler)
+    {
+        StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+        if (output_sp)
+        {
+            output_sp->PutCString(g_synth_addreader_instructions);
+            output_sp->Flush();
+        }
+    }
     
+    
+    virtual void
+    IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+    {
+        StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+        
+        ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
+        if (interpreter)
+        {
+            StringList lines;
+            lines.SplitIntoLines(data);
+            if (lines.GetSize() > 0)
+            {
+                SynthAddOptions *options_ptr = ((SynthAddOptions*)io_handler.GetUserData());
+                if (options_ptr)
+                {
+                    SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
+                    
+                    ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
+                    if (interpreter)
+                    {
+                        std::string class_name_str;
+                        if (interpreter->GenerateTypeSynthClass (lines, class_name_str))
+                        {
+                            if (class_name_str.empty())
+                            {
+                                error_sp->Printf ("error: unable to obtain a proper name for the class.\n");
+                                error_sp->Flush();
+                            }
+                            else
+                            {
+                                // everything should be fine now, let's add the synth provider class
+                                
+                                SyntheticChildrenSP synth_provider;
+                                synth_provider.reset(new ScriptedSyntheticChildren(SyntheticChildren::Flags().SetCascades(options->m_cascade).
+                                                                                   SetSkipPointers(options->m_skip_pointers).
+                                                                                   SetSkipReferences(options->m_skip_references),
+                                                                                   class_name_str.c_str()));
+                                
+                                
+                                lldb::TypeCategoryImplSP category;
+                                DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category);
+                                
+                                Error error;
+                                
+                                for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
+                                {
+                                    const char *type_name = options->m_target_types.GetStringAtIndex(i);
+                                    ConstString const_type_name(type_name);
+                                    if (const_type_name)
+                                    {
+                                        if (!CommandObjectTypeSynthAdd::AddSynth(const_type_name,
+                                                                                 synth_provider,
+                                                                                 options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth,
+                                                                                 options->m_category,
+                                                                                 &error))
+                                        {
+                                            error_sp->Printf("error: %s\n", error.AsCString());
+                                            error_sp->Flush();
+                                            break;
+                                        }
+                                    }
+                                    else
+                                    {
+                                        error_sp->Printf ("error: invalid type name.\n");
+                                        error_sp->Flush();
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                        else
+                        {
+                            error_sp->Printf ("error: unable to generate a class.\n");
+                            error_sp->Flush();
+                        }
+                    }
+                    else
+                    {
+                        error_sp->Printf ("error: no script interpreter.\n");
+                        error_sp->Flush();
+                    }
+                }
+                else
+                {
+                    error_sp->Printf ("error: internal synchronization data missing.\n");
+                    error_sp->Flush();
+                }
+            }
+            else
+            {
+                error_sp->Printf ("error: empty function, didn't add python command.\n");
+                error_sp->Flush();
+            }
+        }
+        else
+        {
+            error_sp->Printf ("error: script interpreter missing, didn't add python command.\n");
+            error_sp->Flush();
+        }
+        
+        io_handler.SetIsDone(true);
+        
+        
+    }
+
 public:
     
     enum SynthFormatType
@@ -1102,176 +1375,6 @@ CommandObjectTypeFormatList::CommandOpti
 // CommandObjectTypeSummaryAdd
 //-------------------------------------------------------------------------
 
-static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
-                                                       "def function (valobj,internal_dict):\n"
-                                                       "     \"\"\"valobj: an SBValue which you want to provide a summary for\n"
-                                                       "        internal_dict: an LLDB support object not to be used\"\"\"";
-
-class TypeScriptAddInputReader : public InputReaderEZ
-{
-private:
-    DISALLOW_COPY_AND_ASSIGN (TypeScriptAddInputReader);
-public:
-    TypeScriptAddInputReader(Debugger& debugger) : 
-    InputReaderEZ(debugger)
-    {}
-    
-    virtual
-    ~TypeScriptAddInputReader()
-    {
-    }
-    
-    virtual void ActivateHandler(HandlerData& data)
-    {
-        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
-        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-        if (!batch_mode)
-        {
-            out_stream->Printf ("%s\n", g_summary_addreader_instructions);
-            if (data.reader.GetPrompt())
-                out_stream->Printf ("%s", data.reader.GetPrompt());
-            out_stream->Flush();
-        }
-    }
-    
-    virtual void ReactivateHandler(HandlerData& data)
-    {
-        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
-        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-        if (data.reader.GetPrompt() && !batch_mode)
-        {
-            out_stream->Printf ("%s", data.reader.GetPrompt());
-            out_stream->Flush();
-        }
-    }
-    virtual void GotTokenHandler(HandlerData& data)
-    {
-        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
-        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-        if (data.bytes && data.bytes_len && data.baton)
-        {
-            ((ScriptAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len);
-        }
-        if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
-        {
-            out_stream->Printf ("%s", data.reader.GetPrompt());
-            out_stream->Flush();
-        }
-    }
-    virtual void InterruptHandler(HandlerData& data)
-    {
-        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
-        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-        data.reader.SetIsDone (true);
-        if (!batch_mode)
-        {
-            out_stream->Printf ("Warning: No command attached to breakpoint.\n");
-            out_stream->Flush();
-        }
-    }
-    virtual void EOFHandler(HandlerData& data)
-    {
-        data.reader.SetIsDone (true);
-    }
-    virtual void DoneHandler(HandlerData& data)
-    {
-        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
-        ScriptAddOptions *options_ptr = ((ScriptAddOptions*)data.baton);
-        if (!options_ptr)
-        {
-            out_stream->Printf ("internal synchronization information missing or invalid.\n");
-            out_stream->Flush();
-            return;
-        }
-        
-        ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
-        
-        ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
-        if (!interpreter)
-        {
-            out_stream->Printf ("no script interpreter.\n");
-            out_stream->Flush();
-            return;
-        }
-        std::string funct_name_str;
-        if (!interpreter->GenerateTypeScriptFunction (options->m_user_source, 
-                                                      funct_name_str))
-        {
-            out_stream->Printf ("unable to generate a function.\n");
-            out_stream->Flush();
-            return;
-        }
-        if (funct_name_str.empty())
-        {
-            out_stream->Printf ("unable to obtain a valid function name from the script interpreter.\n");
-            out_stream->Flush();
-            return;
-        }
-        // now I have a valid function name, let's add this as script for every type in the list
-        
-        TypeSummaryImplSP script_format;
-        script_format.reset(new ScriptSummaryFormat(options->m_flags,
-                                                    funct_name_str.c_str(),
-                                                    options->m_user_source.CopyList("     ").c_str()));
-        
-        Error error;
-        
-        for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
-        {
-            const char *type_name = options->m_target_types.GetStringAtIndex(i);
-            CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
-                                                    script_format,
-                                                    (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary),
-                                                    options->m_category,
-                                                    &error);
-            if (error.Fail())
-            {
-                out_stream->Printf ("%s", error.AsCString());
-                out_stream->Flush();
-                return;
-            }
-        }
-        
-        if (options->m_name)
-        {
-            CommandObjectTypeSummaryAdd::AddSummary (options->m_name,
-                                                     script_format,
-                                                     CommandObjectTypeSummaryAdd::eNamedSummary,
-                                                     options->m_category,
-                                                     &error);
-            if (error.Fail())
-            {
-                CommandObjectTypeSummaryAdd::AddSummary (options->m_name,
-                                                         script_format,
-                                                         CommandObjectTypeSummaryAdd::eNamedSummary,
-                                                         options->m_category,
-                                                         &error);
-                if (error.Fail())
-                {
-                    out_stream->Printf ("%s", error.AsCString());
-                    out_stream->Flush();
-                    return;
-                }
-            }
-            else
-            {
-                out_stream->Printf ("%s", error.AsCString());
-                out_stream->Flush();
-                return;
-            }
-        }
-        else
-        {
-            if (error.AsCString())
-            {
-                out_stream->PutCString (error.AsCString());
-                out_stream->Flush();
-            }
-            return;
-        }
-    }
-};
-
 #endif // #ifndef LLDB_DISABLE_PYTHON
 
 Error
@@ -1352,35 +1455,9 @@ CommandObjectTypeSummaryAdd::CommandOpti
     m_category = "default";
 }
 
+
+
 #ifndef LLDB_DISABLE_PYTHON
-void
-CommandObjectTypeSummaryAdd::CollectPythonScript (ScriptAddOptions *options,
-                                                  CommandReturnObject &result)
-{
-    InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger()));
-    if (reader_sp && options)
-    {
-        
-        InputReaderEZ::InitializationParameters ipr;
-        
-        Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt("     ")));
-        if (err.Success())
-        {
-            m_interpreter.GetDebugger().PushInputReader (reader_sp);
-            result.SetStatus (eReturnStatusSuccessFinishNoResult);
-        }
-        else
-        {
-            result.AppendError (err.AsCString());
-            result.SetStatus (eReturnStatusFailed);
-        }
-    }
-    else
-    {
-        result.AppendError("out of memory");
-        result.SetStatus (eReturnStatusFailed);
-    }
-}
 
 bool
 CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result)
@@ -1406,7 +1483,7 @@ CommandObjectTypeSummaryAdd::Execute_Scr
             return false;
         }
         
-        std::string code = ("     " + m_options.m_python_function + "(valobj,internal_dict)");
+        std::string code = ("    " + m_options.m_python_function + "(valobj,internal_dict)");
         
         script_format.reset(new ScriptSummaryFormat(m_options.m_flags,
                                                     funct_name,
@@ -1445,14 +1522,15 @@ CommandObjectTypeSummaryAdd::Execute_Scr
             return false;
         }
         
-        std::string code = "     " + m_options.m_python_script;
+        std::string code = "    " + m_options.m_python_script;
         
         script_format.reset(new ScriptSummaryFormat(m_options.m_flags,
                                                     funct_name_str.c_str(),
                                                     code.c_str()));
     }
-    else // use an InputReader to grab Python code from the user
-    {        
+    else
+    {
+        // Use an IOHandler to grab Python code from the user
         ScriptAddOptions *options = new ScriptAddOptions(m_options.m_flags,
                                                          m_options.m_regex,
                                                          m_options.m_name,
@@ -1471,7 +1549,12 @@ CommandObjectTypeSummaryAdd::Execute_Scr
             }
         }
         
-        CollectPythonScript(options,result);
+        m_interpreter.GetPythonCommandsFromIOHandler ("    ",   // Prompt
+                                                      *this,    // IOHandlerDelegate
+                                                      true,     // Run IOHandler in async mode
+                                                      options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+        result.SetStatus(eReturnStatusSuccessFinishNoResult);
+
         return result.Succeeded();
     }
     
@@ -1603,6 +1686,7 @@ CommandObjectTypeSummaryAdd::CommandObje
                          "type summary add",
                          "Add a new summary style for a type.",
                          NULL),
+    IOHandlerDelegateMultiline ("DONE"),
     m_options (interpreter)
 {
     CommandArgumentEntry type_arg;
@@ -3647,193 +3731,6 @@ CommandObjectTypeSynthClear::CommandOpti
 };
 
 
-//-------------------------------------------------------------------------
-// TypeSynthAddInputReader
-//-------------------------------------------------------------------------
-
-static const char *g_synth_addreader_instructions =   "Enter your Python command(s). Type 'DONE' to end.\n"
-                                                      "You must define a Python class with these methods:\n"
-                                                      "     def __init__(self, valobj, dict):\n"
-                                                      "     def num_children(self):\n"
-                                                      "     def get_child_at_index(self, index):\n"
-                                                      "     def get_child_index(self, name):\n"
-                                                      "Optionally, you can also define a method:\n"
-                                                      "     def update(self):\n"
-                                                      "if your synthetic provider is holding on to any per-object state variables (currently, this is not implemented because of the way LLDB handles instances of SBValue and you should not rely on object persistence and per-object state)\n"
-                                                      "class synthProvider:";
-
-class TypeSynthAddInputReader : public InputReaderEZ
-{
-public:
-    TypeSynthAddInputReader(Debugger& debugger) : 
-        InputReaderEZ(debugger)
-    {}
-    
-    virtual
-    ~TypeSynthAddInputReader()
-    {
-    }
-    
-    virtual void ActivateHandler(HandlerData& data)
-    {
-        StreamSP out_stream = data.GetOutStream();
-        bool batch_mode = data.GetBatchMode();
-        if (!batch_mode)
-        {
-            out_stream->Printf ("%s\n", g_synth_addreader_instructions);
-            if (data.reader.GetPrompt())
-                out_stream->Printf ("%s", data.reader.GetPrompt());
-            out_stream->Flush();
-        }
-    }
-    
-    virtual void ReactivateHandler(HandlerData& data)
-    {
-        StreamSP out_stream = data.GetOutStream();
-        bool batch_mode = data.GetBatchMode();
-        if (data.reader.GetPrompt() && !batch_mode)
-        {
-            out_stream->Printf ("%s", data.reader.GetPrompt());
-            out_stream->Flush();
-        }
-    }
-    virtual void GotTokenHandler(HandlerData& data)
-    {
-        StreamSP out_stream = data.GetOutStream();
-        bool batch_mode = data.GetBatchMode();
-        if (data.bytes && data.bytes_len && data.baton)
-        {
-            ((SynthAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len);
-        }
-        if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
-        {
-            out_stream->Printf ("%s", data.reader.GetPrompt());
-            out_stream->Flush();
-        }
-    }
-    virtual void InterruptHandler(HandlerData& data)
-    {
-        StreamSP out_stream = data.GetOutStream();
-        bool batch_mode = data.GetBatchMode();
-        data.reader.SetIsDone (true);
-        if (!batch_mode)
-        {
-            out_stream->Printf ("Warning: No command attached to breakpoint.\n");
-            out_stream->Flush();
-        }
-    }
-    virtual void EOFHandler(HandlerData& data)
-    {
-        data.reader.SetIsDone (true);
-    }
-    virtual void DoneHandler(HandlerData& data)
-    {
-        StreamSP out_stream = data.GetOutStream();
-        SynthAddOptions *options_ptr = ((SynthAddOptions*)data.baton);
-        if (!options_ptr)
-        {
-            out_stream->Printf ("internal synchronization data missing.\n");
-            out_stream->Flush();
-            return;
-        }
-        
-        SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
-        
-        ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
-        if (!interpreter)
-        {
-            out_stream->Printf ("no script interpreter.\n");
-            out_stream->Flush();
-            return;
-        }
-        std::string class_name_str;
-        if (!interpreter->GenerateTypeSynthClass (options->m_user_source, 
-                                                  class_name_str))
-        {
-            out_stream->Printf ("unable to generate a class.\n");
-            out_stream->Flush();
-            return;
-        }
-        if (class_name_str.empty())
-        {
-            out_stream->Printf ("unable to obtain a proper name for the class.\n");
-            out_stream->Flush();
-            return;
-        }
-
-        // everything should be fine now, let's add the synth provider class
-        
-        SyntheticChildrenSP synth_provider;
-        synth_provider.reset(new ScriptedSyntheticChildren(SyntheticChildren::Flags().SetCascades(options->m_cascade).
-                                                           SetSkipPointers(options->m_skip_pointers).
-                                                           SetSkipReferences(options->m_skip_references),
-                                                           class_name_str.c_str()));
-        
-        
-        lldb::TypeCategoryImplSP category;
-        DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category);
-        
-        Error error;
-        
-        for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
-        {
-            const char *type_name = options->m_target_types.GetStringAtIndex(i);
-            ConstString typeCS(type_name);
-            if (typeCS)
-            {
-                if (!CommandObjectTypeSynthAdd::AddSynth(typeCS,
-                                                        synth_provider,
-                                                        options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth,
-                                                        options->m_category,
-                                                        &error))
-                {
-                    out_stream->Printf("%s\n", error.AsCString());
-                    out_stream->Flush();
-                    return;
-                }
-            }
-            else
-            {
-                out_stream->Printf ("invalid type name.\n");
-                out_stream->Flush();
-                return;
-            }
-        }
-    }
-
-private:
-    DISALLOW_COPY_AND_ASSIGN (TypeSynthAddInputReader);
-};
-
-void
-CommandObjectTypeSynthAdd::CollectPythonScript (SynthAddOptions *options,
-                                                CommandReturnObject &result)
-{
-    InputReaderSP reader_sp (new TypeSynthAddInputReader(m_interpreter.GetDebugger()));
-    if (reader_sp && options)
-    {
-        
-        InputReaderEZ::InitializationParameters ipr;
-        
-        Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt("     ")));
-        if (err.Success())
-        {
-            m_interpreter.GetDebugger().PushInputReader (reader_sp);
-            result.SetStatus (eReturnStatusSuccessFinishNoResult);
-        }
-        else
-        {
-            result.AppendError (err.AsCString());
-            result.SetStatus (eReturnStatusFailed);
-        }
-    }
-    else
-    {
-        result.AppendError("out of memory");
-        result.SetStatus (eReturnStatusFailed);
-    }
-}
-    
 bool
 CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result)
 {
@@ -3858,7 +3755,11 @@ CommandObjectTypeSynthAdd::Execute_Handw
         }
     }
     
-    CollectPythonScript(options,result);
+    m_interpreter.GetPythonCommandsFromIOHandler ("    ",   // Prompt
+                                                  *this,    // IOHandlerDelegate
+                                                  true,     // Run IOHandler in async mode
+                                                  options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+    result.SetStatus(eReturnStatusSuccessFinishNoResult);
     return result.Succeeded();
 }
 
@@ -3937,6 +3838,7 @@ CommandObjectTypeSynthAdd::CommandObject
                          "type synthetic add",
                          "Add a new synthetic provider for a type.",
                          NULL),
+    IOHandlerDelegateMultiline ("DONE"),
     m_options (interpreter)
 {
     CommandArgumentEntry type_arg;
@@ -4006,21 +3908,6 @@ CommandObjectTypeSynthAdd::AddSynth(Cons
         return true;
     }
 }
-    
-bool
-CommandObjectTypeSynthAdd::DoExecute (Args& command, CommandReturnObject &result)
-{
-    if (m_options.handwrite_python)
-        return Execute_HandwritePython(command, result);
-    else if (m_options.is_class_based)
-        return Execute_PythonClass(command, result);
-    else
-    {
-        result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line");
-        result.SetStatus(eReturnStatusFailed);
-        return false;
-    }
-}
 
 OptionDefinition
 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =

Modified: lldb/branches/iohandler/source/Commands/CommandObjectWatchpointCommand.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectWatchpointCommand.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectWatchpointCommand.cpp (original)
+++ lldb/branches/iohandler/source/Commands/CommandObjectWatchpointCommand.cpp Thu Jan  2 16:40:14 2014
@@ -16,6 +16,7 @@
 #include "CommandObjectWatchpointCommand.h"
 #include "CommandObjectWatchpoint.h"
 
+#include "lldb/Core/IOHandler.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Target/Target.h"
@@ -34,7 +35,9 @@ using namespace lldb_private;
 //-------------------------------------------------------------------------
 
 
-class CommandObjectWatchpointCommandAdd : public CommandObjectParsed
+class CommandObjectWatchpointCommandAdd :
+    public CommandObjectParsed,
+    public IOHandlerDelegateMultiline
 {
 public:
 
@@ -43,6 +46,7 @@ public:
                              "add",
                              "Add a set of commands to a watchpoint, to be executed whenever the watchpoint is hit.",
                              NULL),
+        IOHandlerDelegateMultiline("DONE", IOHandlerDelegate::Completion::LLDBCommand),
         m_options (interpreter)
     {
         SetHelpLong (
@@ -185,40 +189,45 @@ but do NOT enter more than one command p
         return &m_options;
     }
 
-    void
-    CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, 
-                                             CommandReturnObject &result)
+    virtual void
+    IOHandlerActivated (IOHandler &io_handler)
     {
-        InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
-        std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
-        if (reader_sp && data_ap.get())
+        StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+        if (output_sp)
         {
-            BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
-            wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
-
-            Error err (reader_sp->Initialize (CommandObjectWatchpointCommandAdd::GenerateWatchpointCommandCallback,
-                                              wp_options,                   // callback_data
-                                              eInputReaderGranularityLine,  // token size, to pass to callback function
-                                              "DONE",                       // end token
-                                              "> ",                         // prompt
-                                              true));                       // echo input
-            if (err.Success())
-            {
-                m_interpreter.GetDebugger().PushInputReader (reader_sp);
-                result.SetStatus (eReturnStatusSuccessFinishNoResult);
-            }
-            else
-            {
-                result.AppendError (err.AsCString());
-                result.SetStatus (eReturnStatusFailed);
-            }
+            output_sp->PutCString("Enter your debugger command(s).  Type 'DONE' to end.\n");
+            output_sp->Flush();
         }
-        else
+    }
+    
+    
+    virtual void
+    IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+    {
+        io_handler.SetIsDone(true);
+        
+        // The WatchpointOptions object is owned by the watchpoint or watchpoint location
+        WatchpointOptions *wp_options = (WatchpointOptions *) io_handler.GetUserData();
+        if (wp_options)
         {
-            result.AppendError("out of memory");
-            result.SetStatus (eReturnStatusFailed);
+            std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
+            if (data_ap.get())
+            {
+                data_ap->user_source.SplitIntoLines(line);
+                BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
+                wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
+            }
         }
+    }
 
+    void
+    CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, 
+                                             CommandReturnObject &result)
+    {
+        m_interpreter.GetLLDBCommandsFromIOHandler ("> ",           // Prompt
+                                                    *this,          // IOHandlerDelegate
+                                                    true,           // Run IOHandler in async mode
+                                                    wp_options);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
     }
     
     /// Set a one-liner as the callback for the watchpoint.
@@ -240,93 +249,6 @@ but do NOT enter more than one command p
 
         return;
     }
-
-    static size_t
-    GenerateWatchpointCommandCallback (void *callback_data, 
-                                       InputReader &reader, 
-                                       lldb::InputReaderAction notification,
-                                       const char *bytes, 
-                                       size_t bytes_len)
-    {
-        StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-        bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-        
-        switch (notification)
-        {
-        case eInputReaderActivate:
-            if (!batch_mode)
-            {
-                out_stream->Printf ("%s\n", g_reader_instructions);
-                if (reader.GetPrompt())
-                    out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush();
-            }
-            break;
-
-        case eInputReaderDeactivate:
-            break;
-
-        case eInputReaderReactivate:
-            if (reader.GetPrompt() && !batch_mode)
-            {
-                out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush();
-            }
-            break;
-
-        case eInputReaderAsynchronousOutputWritten:
-            break;
-            
-        case eInputReaderGotToken:
-            if (bytes && bytes_len && callback_data)
-            {
-                WatchpointOptions *wp_options = (WatchpointOptions *) callback_data;
-                if (wp_options)
-                {
-                    Baton *wp_options_baton = wp_options->GetBaton();
-                    if (wp_options_baton)
-                        ((WatchpointOptions::CommandData *)wp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len); 
-                }
-            }
-            if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
-            {
-                out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush();
-            }
-            break;
-            
-        case eInputReaderInterrupt:
-            {
-                // Finish, and cancel the watchpoint command.
-                reader.SetIsDone (true);
-                WatchpointOptions *wp_options = (WatchpointOptions *) callback_data;
-                if (wp_options)
-                {
-                    Baton *wp_options_baton = wp_options->GetBaton ();
-                    if (wp_options_baton)
-                    {
-                        ((WatchpointOptions::CommandData *) wp_options_baton->m_data)->user_source.Clear();
-                        ((WatchpointOptions::CommandData *) wp_options_baton->m_data)->script_source.clear();
-                    }
-                }
-                if (!batch_mode)
-                {
-                    out_stream->Printf ("Warning: No command attached to watchpoint.\n");
-                    out_stream->Flush();
-                }
-            }
-            break;
-            
-        case eInputReaderEndOfFile:
-            reader.SetIsDone (true);
-            break;
-            
-        case eInputReaderDone:
-            break;
-        }
-
-        return bytes_len;
-    }
     
     static bool
     WatchpointOptionsCallbackFunction (void *baton,
@@ -579,12 +501,8 @@ protected:
 
 private:
     CommandOptions m_options;
-    static const char *g_reader_instructions;
-
 };
 
-const char *
-CommandObjectWatchpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.";
 
 // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
 // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.

Modified: lldb/branches/iohandler/source/Commands/CommandObjectWatchpointCommand.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Commands/CommandObjectWatchpointCommand.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Commands/CommandObjectWatchpointCommand.h (original)
+++ lldb/branches/iohandler/source/Commands/CommandObjectWatchpointCommand.h Thu Jan  2 16:40:14 2014
@@ -19,9 +19,6 @@
 
 #include "lldb/lldb-types.h"
 #include "lldb/Interpreter/Options.h"
-#include "lldb/Core/InputReader.h"
-#include "lldb/Interpreter/CommandObject.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Interpreter/CommandObjectMultiword.h"
 
 

Modified: lldb/branches/iohandler/source/Core/Broadcaster.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Core/Broadcaster.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Core/Broadcaster.cpp (original)
+++ lldb/branches/iohandler/source/Core/Broadcaster.cpp Thu Jan  2 16:40:14 2014
@@ -323,8 +323,10 @@ Broadcaster::RestoreBroadcaster ()
                      listener->m_name.c_str(),
                      listener);
     }
-    m_hijacking_listeners.pop_back();
-    m_hijacking_masks.pop_back();
+    if (!m_hijacking_listeners.empty())
+        m_hijacking_listeners.pop_back();
+    if (!m_hijacking_masks.empty())
+        m_hijacking_masks.pop_back();
 }
 
 ConstString &

Modified: lldb/branches/iohandler/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Core/Debugger.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Core/Debugger.cpp (original)
+++ lldb/branches/iohandler/source/Core/Debugger.cpp Thu Jan  2 16:40:14 2014
@@ -18,13 +18,13 @@
 
 #include "lldb/lldb-private.h"
 #include "lldb/Core/ConnectionFileDescriptor.h"
-#include "lldb/Core/InputReader.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/RegisterValue.h"
 #include "lldb/Core/State.h"
 #include "lldb/Core/StreamAsynchronousIO.h"
 #include "lldb/Core/StreamCallback.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/Timer.h"
 #include "lldb/Core/ValueObject.h"
@@ -180,6 +180,7 @@ Debugger::SetPropertyValue (const Execut
             std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor());
             if (str.length())
                 new_prompt = str.c_str();
+            GetCommandInterpreter().UpdatePrompt(new_prompt);
             EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));
             GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp);
         }
@@ -196,12 +197,16 @@ Debugger::SetPropertyValue (const Execut
                 StreamString feedback_stream;
                 if (!target_sp->LoadScriptingResources(errors,&feedback_stream))
                 {
-                    for (auto error : errors)
+                    StreamFileSP stream_sp (GetErrorFile());
+                    if (stream_sp)
                     {
-                        GetErrorStream().Printf("%s\n",error.AsCString());
+                        for (auto error : errors)
+                        {
+                            stream_sp->Printf("%s\n",error.AsCString());
+                        }
+                        if (feedback_stream.GetSize())
+                            stream_sp->Printf("%s",feedback_stream.GetData());
                     }
-                    if (feedback_stream.GetSize())
-                        GetErrorStream().Printf("%s",feedback_stream.GetData());
                 }
             }
         }
@@ -246,8 +251,7 @@ Debugger::SetPrompt(const char *p)
     std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor());
     if (str.length())
         new_prompt = str.c_str();
-    EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));;
-    GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp);
+    GetCommandInterpreter().UpdatePrompt(new_prompt);
 }
 
 const char *
@@ -611,10 +615,9 @@ Debugger::FindTargetWithProcess (Process
 Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) :
     UserID (g_unique_id++),
     Properties(OptionValuePropertiesSP(new OptionValueProperties())), 
-    m_input_comm("debugger.input"),
-    m_input_file (),
-    m_output_file (),
-    m_error_file (),
+    m_input_file_sp (new StreamFile (stdin, false)),
+    m_output_file_sp (new StreamFile (stdout, false)),
+    m_error_file_sp (new StreamFile (stderr, false)),
     m_terminal_state (),
     m_target_list (*this),
     m_platform_list (),
@@ -623,8 +626,10 @@ Debugger::Debugger (lldb::LogOutputCallb
     m_source_file_cache(),
     m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)),
     m_input_reader_stack (),
-    m_input_reader_data (),
-    m_instance_name()
+    m_instance_name (),
+    m_loaded_plugins (),
+    m_event_handler_thread (LLDB_INVALID_HOST_THREAD),
+    m_event_handler_thread_alive(false)
 {
     char instance_cstr[256];
     snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
@@ -667,7 +672,7 @@ Debugger::~Debugger ()
 void
 Debugger::Clear()
 {
-    CleanUpInputReaders();
+    ClearIOHandlers();
     m_listener.Clear();
     int num_targets = m_target_list.GetNumTargets();
     for (int i = 0; i < num_targets; i++)
@@ -686,23 +691,21 @@ Debugger::Clear()
     // Close the input file _before_ we close the input read communications class
     // as it does NOT own the input file, our m_input_file does.
     m_terminal_state.Clear();
-    GetInputFile().Close ();
-    // Now that we have closed m_input_file, we can now tell our input communication
-    // class to close down. Its read thread should quickly exit after we close
-    // the input file handle above.
-    m_input_comm.Clear ();
+    if (m_input_file_sp)
+        m_input_file_sp->GetFile().Close ();
 }
 
 bool
 Debugger::GetCloseInputOnEOF () const
 {
-    return m_input_comm.GetCloseOnEOF();
+//    return m_input_comm.GetCloseOnEOF();
+    return false;
 }
 
 void
 Debugger::SetCloseInputOnEOF (bool b)
 {
-    m_input_comm.SetCloseOnEOF(b);
+//    m_input_comm.SetCloseOnEOF(b);
 }
 
 bool
@@ -721,37 +724,28 @@ Debugger::SetAsyncExecution (bool async_
 void
 Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership)
 {
-    File &in_file = GetInputFile();
-    in_file.SetStream (fh, tranfer_ownership);
+    if (m_input_file_sp)
+        m_input_file_sp->GetFile().SetStream (fh, tranfer_ownership);
+    else
+        m_input_file_sp.reset (new StreamFile (fh, tranfer_ownership));
+
+    File &in_file = m_input_file_sp->GetFile();
     if (in_file.IsValid() == false)
         in_file.SetStream (stdin, true);
 
-    // Disconnect from any old connection if we had one
-    m_input_comm.Disconnect ();
-    // Pass false as the second argument to ConnectionFileDescriptor below because
-    // our "in_file" above will already take ownership if requested and we don't
-    // want to objects trying to own and close a file descriptor.
-    m_input_comm.SetConnection (new ConnectionFileDescriptor (in_file.GetDescriptor(), false));
-    m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this);
-    
     // Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState.
     SaveInputTerminalState ();
-    
-    Error error;
-    if (m_input_comm.StartReadThread (&error) == false)
-    {
-        File &err_file = GetErrorFile();
-
-        err_file.Printf ("error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error");
-        exit(1);
-    }
 }
 
 void
 Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership)
 {
-    File &out_file = GetOutputFile();
-    out_file.SetStream (fh, tranfer_ownership);
+    if (m_output_file_sp)
+        m_output_file_sp->GetFile().SetStream (fh, tranfer_ownership);
+    else
+        m_output_file_sp.reset (new StreamFile (fh, tranfer_ownership));
+    
+    File &out_file = m_output_file_sp->GetFile();
     if (out_file.IsValid() == false)
         out_file.SetStream (stdout, false);
     
@@ -766,8 +760,12 @@ Debugger::SetOutputFileHandle (FILE *fh,
 void
 Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership)
 {
-    File &err_file = GetErrorFile();
-    err_file.SetStream (fh, tranfer_ownership);
+    if (m_error_file_sp)
+        m_error_file_sp->GetFile().SetStream (fh, tranfer_ownership);
+    else
+        m_error_file_sp.reset (new StreamFile (fh, tranfer_ownership));
+    
+    File &err_file = m_error_file_sp->GetFile();
     if (err_file.IsValid() == false)
         err_file.SetStream (stderr, false);
 }
@@ -775,9 +773,12 @@ Debugger::SetErrorFileHandle (FILE *fh,
 void
 Debugger::SaveInputTerminalState ()
 {
-    File &in_file = GetInputFile();
-    if (in_file.GetDescriptor() != File::kInvalidDescriptor)
-        m_terminal_state.Save(in_file.GetDescriptor(), true);
+    if (m_input_file_sp)
+    {
+        File &in_file = m_input_file_sp->GetFile();
+        if (in_file.GetDescriptor() != File::kInvalidDescriptor)
+            m_terminal_state.Save(in_file.GetDescriptor(), true);
+    }
 }
 
 void
@@ -812,245 +813,223 @@ Debugger::GetSelectedExecutionContext ()
     return exe_ctx;
 }
 
-InputReaderSP 
-Debugger::GetCurrentInputReader ()
-{
-    InputReaderSP reader_sp;
-    
-    if (!m_input_reader_stack.IsEmpty())
-    {
-        // Clear any finished readers from the stack
-        while (CheckIfTopInputReaderIsDone()) ;
-        
-        if (!m_input_reader_stack.IsEmpty())
-            reader_sp = m_input_reader_stack.Top();
-    }
-    
-    return reader_sp;
-}
-
-void
-Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len)
-{
-    if (bytes_len > 0)
-        ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len);
-    else
-        ((Debugger *)baton)->DispatchInputEndOfFile ();
-}   
-
-
-void
-Debugger::DispatchInput (const char *bytes, size_t bytes_len)
-{
-    if (bytes == NULL || bytes_len == 0)
-        return;
-
-    WriteToDefaultReader (bytes, bytes_len);
-}
-
 void
 Debugger::DispatchInputInterrupt ()
 {
-    m_input_reader_data.clear();
-    
-    InputReaderSP reader_sp (GetCurrentInputReader ());
+    Mutex::Locker locker (m_input_reader_stack.GetMutex());
+    IOHandlerSP reader_sp (m_input_reader_stack.Top());
     if (reader_sp)
-    {
-        reader_sp->Notify (eInputReaderInterrupt);
-        
-        // If notifying the reader of the interrupt finished the reader, we should pop it off the stack.
-        while (CheckIfTopInputReaderIsDone ()) ;
-    }
+        reader_sp->Interrupt();
 }
 
 void
 Debugger::DispatchInputEndOfFile ()
 {
-    m_input_reader_data.clear();
-    
-    InputReaderSP reader_sp (GetCurrentInputReader ());
+    Mutex::Locker locker (m_input_reader_stack.GetMutex());
+    IOHandlerSP reader_sp (m_input_reader_stack.Top());
     if (reader_sp)
-    {
-        reader_sp->Notify (eInputReaderEndOfFile);
-        
-        // If notifying the reader of the end-of-file finished the reader, we should pop it off the stack.
-        while (CheckIfTopInputReaderIsDone ()) ;
-    }
+        reader_sp->GotEOF();
 }
 
 void
-Debugger::CleanUpInputReaders ()
+Debugger::ClearIOHandlers ()
 {
-    m_input_reader_data.clear();
-    
     // The bottom input reader should be the main debugger input reader.  We do not want to close that one here.
+    Mutex::Locker locker (m_input_reader_stack.GetMutex());
     while (m_input_reader_stack.GetSize() > 1)
     {
-        InputReaderSP reader_sp (GetCurrentInputReader ());
+        IOHandlerSP reader_sp (m_input_reader_stack.Top());
         if (reader_sp)
         {
-            reader_sp->Notify (eInputReaderEndOfFile);
-            reader_sp->SetIsDone (true);
+            m_input_reader_stack.Pop();
+            reader_sp->SetIsDone(true);
+            reader_sp->Interrupt();
         }
     }
 }
 
 void
-Debugger::NotifyTopInputReader (InputReaderAction notification)
+Debugger::ExecuteIOHanders()
 {
-    InputReaderSP reader_sp (GetCurrentInputReader());
-    if (reader_sp)
-	{
-        reader_sp->Notify (notification);
+    
+    while (1)
+    {
+        IOHandlerSP reader_sp(m_input_reader_stack.Top());
+        if (!reader_sp)
+            break;
 
-        // Flush out any input readers that are done.
-        while (CheckIfTopInputReaderIsDone ())
-            /* Do nothing. */;
+        reader_sp->Activate();
+        reader_sp->Run();
+        reader_sp->Deactivate();
+
+        // Remove all input readers that are done from the top of the stack
+        while (1)
+        {
+            IOHandlerSP top_reader_sp = m_input_reader_stack.Top();
+            if (top_reader_sp && top_reader_sp->GetIsDone())
+                m_input_reader_stack.Pop();
+            else
+                break;
+        }
     }
+    ClearIOHandlers();
 }
 
-bool
-Debugger::InputReaderIsTopReader (const InputReaderSP& reader_sp)
+void
+Debugger::RunIOHandler (const IOHandlerSP& reader_sp)
 {
-    InputReaderSP top_reader_sp (GetCurrentInputReader());
-
-    return (reader_sp.get() == top_reader_sp.get());
+    Mutex::Locker locker (m_input_reader_stack.GetMutex());
+    PushIOHandler (reader_sp);
+    reader_sp->Activate();
+    reader_sp->Run();
+    PopIOHandler (reader_sp);
 }
-    
 
 void
-Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len)
+Debugger::GetIOHandlerFiles (IOHandler &reader)
 {
-    if (bytes && bytes_len)
-        m_input_reader_data.append (bytes, bytes_len);
-
-    if (m_input_reader_data.empty())
-        return;
-
-    while (!m_input_reader_stack.IsEmpty() && !m_input_reader_data.empty())
+    // Before an IOHandler runs, it must have in/out/err streams.
+    // This function is called when one ore more of the streams
+    // are NULL. We use the top input reader's in/out/err streams,
+    // or fall back to the debugger file handles, or we fall back
+    // onto stdin/stdout/stderr as a last resort.
+    
+    Mutex::Locker locker (m_input_reader_stack.GetMutex());
+    IOHandlerSP top_reader_sp (m_input_reader_stack.Top());
+    // If no STDIN has been set, then set it appropriately
+    if (!reader.GetInputStreamFile())
     {
-        // Get the input reader from the top of the stack
-        InputReaderSP reader_sp (GetCurrentInputReader ());
-        if (!reader_sp)
-            break;
-
-        size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.c_str(), 
-                                                          m_input_reader_data.size());
-        if (bytes_handled)
-        {
-            m_input_reader_data.erase (0, bytes_handled);
-        }
+        if (top_reader_sp)
+            reader.GetInputStreamFile() = top_reader_sp->GetInputStreamFile();
         else
-        {
-            // No bytes were handled, we might not have reached our 
-            // granularity, just return and wait for more data
-            break;
-        }
+            reader.GetInputStreamFile() = GetInputFile();
+        
+        // If there is nothing, use stdin
+        if (!reader.GetInputStreamFile())
+            reader.GetInputStreamFile() = StreamFileSP(new StreamFile(stdin, false));
     }
-    
-    // Flush out any input readers that are done.
-    while (CheckIfTopInputReaderIsDone ())
-        /* Do nothing. */;
+    // If no STDOUT has been set, then set it appropriately
+    if (!reader.GetOutputStreamFile())
+    {
+        if (top_reader_sp)
+            reader.GetOutputStreamFile() = top_reader_sp->GetOutputStreamFile();
+        else
+            reader.GetOutputStreamFile() = GetOutputFile();
+
+        // If there is nothing, use stdout
+        if (!reader.GetOutputStreamFile())
+            reader.GetOutputStreamFile() = StreamFileSP(new StreamFile(stdout, false));
+    }
+    // If no STDERR has been set, then set it appropriately
+    if (!reader.GetErrorStreamFile())
+    {
+        if (top_reader_sp)
+            reader.GetErrorStreamFile() = top_reader_sp->GetErrorStreamFile();
+        else
+            reader.GetErrorStreamFile() = GetErrorFile();
+
+        // If there is nothing, use stderr
+        if (!reader.GetErrorStreamFile())
+            reader.GetErrorStreamFile() = StreamFileSP(new StreamFile(stdout, false));
 
+    }
 }
 
+//bool
+//Debugger::TryPushIOHandler (const IOHandlerSP& reader_sp)
+//{
+//    if (!reader_sp)
+//        return false;
+//    
+//    Mutex::Locker locker;
+//
+//    if (locker.TryLock(m_input_reader_stack.GetMutex()))
+//    {
+//        // Got the current top input reader...
+//        IOHandlerSP top_reader_sp (m_input_reader_stack.Top());
+//        
+//        // Push our new input reader
+//        m_input_reader_stack.Push (reader_sp);
+//        
+//        // Interrupt the top input reader to it will exit its Run() function
+//        // and let this new input reader take over
+//        if (top_reader_sp)
+//            top_reader_sp->Deactivate();
+//        return true;
+//    }
+//    return false;
+//}
+//
 void
-Debugger::PushInputReader (const InputReaderSP& reader_sp)
+Debugger::PushIOHandler (const IOHandlerSP& reader_sp)
 {
     if (!reader_sp)
         return;
  
-    // Deactivate the old top reader
-    InputReaderSP top_reader_sp (GetCurrentInputReader ());
+    // Got the current top input reader...
+    IOHandlerSP top_reader_sp (m_input_reader_stack.Top());
     
-    if (top_reader_sp)
-        top_reader_sp->Notify (eInputReaderDeactivate);
-
+    // Push our new input reader
     m_input_reader_stack.Push (reader_sp);
-    reader_sp->Notify (eInputReaderActivate);
-    ActivateInputReader (reader_sp);
+
+    // Interrupt the top input reader to it will exit its Run() function
+    // and let this new input reader take over
+    if (top_reader_sp)
+        top_reader_sp->Deactivate();
 }
 
 bool
-Debugger::PopInputReader (const InputReaderSP& pop_reader_sp)
+Debugger::PopIOHandler (const IOHandlerSP& pop_reader_sp)
 {
     bool result = false;
+    
+    Mutex::Locker locker (m_input_reader_stack.GetMutex());
 
     // The reader on the stop of the stack is done, so let the next
     // read on the stack referesh its prompt and if there is one...
     if (!m_input_reader_stack.IsEmpty())
     {
-        // Cannot call GetCurrentInputReader here, as that would cause an infinite loop.
-        InputReaderSP reader_sp(m_input_reader_stack.Top());
+        IOHandlerSP reader_sp(m_input_reader_stack.Top());
         
         if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
         {
+            reader_sp->Deactivate();
             m_input_reader_stack.Pop ();
-            reader_sp->Notify (eInputReaderDeactivate);
-            reader_sp->Notify (eInputReaderDone);
-            result = true;
+            
+            reader_sp = m_input_reader_stack.Top();
+            if (reader_sp)
+                reader_sp->Activate();
 
-            if (!m_input_reader_stack.IsEmpty())
-            {
-                reader_sp = m_input_reader_stack.Top();
-                if (reader_sp)
-                {
-                    ActivateInputReader (reader_sp);
-                    reader_sp->Notify (eInputReaderReactivate);
-                }
-            }
+            result = true;
         }
     }
     return result;
 }
 
 bool
-Debugger::CheckIfTopInputReaderIsDone ()
+Debugger::HideTopIOHandler()
 {
-    bool result = false;
-    if (!m_input_reader_stack.IsEmpty())
+    Mutex::Locker locker;
+    
+    if (locker.TryLock(m_input_reader_stack.GetMutex()))
     {
-        // Cannot call GetCurrentInputReader here, as that would cause an infinite loop.
-        InputReaderSP reader_sp(m_input_reader_stack.Top());
-        
-        if (reader_sp && reader_sp->IsDone())
-        {
-            result = true;
-            PopInputReader (reader_sp);
-        }
+        IOHandlerSP reader_sp(m_input_reader_stack.Top());
+        if (reader_sp)
+            reader_sp->Hide();
+        return true;
     }
-    return result;
+    return false;
 }
 
 void
-Debugger::ActivateInputReader (const InputReaderSP &reader_sp)
+Debugger::RefreshTopIOHandler()
 {
-    int input_fd = m_input_file.GetFile().GetDescriptor();
-
-    if (input_fd >= 0)
-    {
-        Terminal tty(input_fd);
-        
-        tty.SetEcho(reader_sp->GetEcho());
-                
-        switch (reader_sp->GetGranularity())
-        {
-        case eInputReaderGranularityByte:
-        case eInputReaderGranularityWord:
-            tty.SetCanonical (false);
-            break;
-
-        case eInputReaderGranularityLine:
-        case eInputReaderGranularityAll:
-            tty.SetCanonical (true);
-            break;
-
-        default:
-            break;
-        }
-    }
+    IOHandlerSP reader_sp(m_input_reader_stack.Top());
+    if (reader_sp)
+        reader_sp->Refresh();
 }
 
+
 StreamSP
 Debugger::GetAsyncOutputStream ()
 {
@@ -2624,7 +2603,7 @@ Debugger::EnableLog (const char *channel
     }
     else if (log_file == NULL || *log_file == '\0')
     {
-        log_stream_sp.reset(new StreamFile(GetOutputFile().GetDescriptor(), false));
+        log_stream_sp = GetOutputFile();
     }
     else
     {
@@ -2680,3 +2659,422 @@ Debugger::GetSourceManager ()
 }
 
 
+
+// This function handles events that were broadcast by the process.
+void
+Debugger::HandleBreakpointEvent (const EventSP &event_sp)
+{
+    using namespace lldb;
+    const uint32_t event_type = Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event_sp);
+    
+//    if (event_type & eBreakpointEventTypeAdded
+//        || event_type & eBreakpointEventTypeRemoved
+//        || event_type & eBreakpointEventTypeEnabled
+//        || event_type & eBreakpointEventTypeDisabled
+//        || event_type & eBreakpointEventTypeCommandChanged
+//        || event_type & eBreakpointEventTypeConditionChanged
+//        || event_type & eBreakpointEventTypeIgnoreChanged
+//        || event_type & eBreakpointEventTypeLocationsResolved)
+//    {
+//        // Don't do anything about these events, since the breakpoint commands already echo these actions.
+//    }
+//    
+    if (event_type & eBreakpointEventTypeLocationsAdded)
+    {
+        uint32_t num_new_locations = Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(event_sp);
+        if (num_new_locations > 0)
+        {
+            BreakpointSP breakpoint = Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
+            StreamFileSP output_sp (GetOutputFile());
+            if (output_sp)
+            {
+                output_sp->Printf("%d location%s added to breakpoint %d\n",
+                                  num_new_locations,
+                                  num_new_locations == 1 ? "" : "s",
+                                  breakpoint->GetID());
+                RefreshTopIOHandler();
+            }
+        }
+    }
+//    else if (event_type & eBreakpointEventTypeLocationsRemoved)
+//    {
+//        // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
+//    }
+//    else if (event_type & eBreakpointEventTypeLocationsResolved)
+//    {
+//        // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
+//    }
+}
+
+size_t
+Debugger::GetProcessSTDOUT (Process *process, Stream *stream)
+{
+    size_t total_bytes = 0;
+    if (stream == NULL)
+        stream = GetOutputFile().get();
+
+    if (stream)
+    {
+        //  The process has stuff waiting for stdout; get it and write it out to the appropriate place.
+        if (process == NULL)
+        {
+            TargetSP target_sp = GetTargetList().GetSelectedTarget();
+            if (target_sp)
+                process = target_sp->GetProcessSP().get();
+        }
+        if (process)
+        {
+            Error error;
+            size_t len;
+            char stdio_buffer[1024];
+            while ((len = process->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
+            {
+                stream->Write(stdio_buffer, len);
+                total_bytes += len;
+            }
+        }
+        stream->Flush();
+    }
+    return total_bytes;
+}
+
+size_t
+Debugger::GetProcessSTDERR (Process *process, Stream *stream)
+{
+    size_t total_bytes = 0;
+    if (stream == NULL)
+        stream = GetOutputFile().get();
+    
+    if (stream)
+    {
+        //  The process has stuff waiting for stderr; get it and write it out to the appropriate place.
+        if (process == NULL)
+        {
+            TargetSP target_sp = GetTargetList().GetSelectedTarget();
+            if (target_sp)
+                process = target_sp->GetProcessSP().get();
+        }
+        if (process)
+        {
+            Error error;
+            size_t len;
+            char stdio_buffer[1024];
+            while ((len = process->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
+            {
+                stream->Write(stdio_buffer, len);
+                total_bytes += len;
+            }
+        }
+        stream->Flush();
+    }
+    return total_bytes;
+}
+
+// This function handles events that were broadcast by the process.
+void
+Debugger::HandleProcessEvent (const EventSP &event_sp)
+{
+    using namespace lldb;
+    const uint32_t event_type = event_sp->GetType();
+    ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
+    
+    const bool gui_enabled = IsForwardingEvents();
+    bool top_io_handler_hid = false;
+    if (gui_enabled == false)
+        top_io_handler_hid = HideTopIOHandler();
+
+    assert (process_sp);
+    
+    if (event_type & Process::eBroadcastBitSTDOUT)
+    {
+        // The process has stdout available, get it and write it out to the
+        // appropriate place.
+        if (top_io_handler_hid)
+            GetProcessSTDOUT (process_sp.get(), NULL);
+    }
+    else if (event_type & Process::eBroadcastBitSTDERR)
+    {
+        // The process has stderr available, get it and write it out to the
+        // appropriate place.
+        if (top_io_handler_hid)
+            GetProcessSTDERR (process_sp.get(), NULL);
+    }
+    else if (event_type & Process::eBroadcastBitStateChanged)
+    {
+        // Drain all stout and stderr so we don't see any output come after
+        // we print our prompts
+        if (top_io_handler_hid)
+        {
+            StreamFileSP stream_sp (GetOutputFile());
+            GetProcessSTDOUT (process_sp.get(), stream_sp.get());
+            GetProcessSTDERR (process_sp.get(), NULL);
+            // Something changed in the process;  get the event and report the process's current status and location to
+            // the user.
+            StateType event_state = Process::ProcessEventData::GetStateFromEvent (event_sp.get());
+            if (event_state == eStateInvalid)
+                return;
+            
+            switch (event_state)
+            {
+                case eStateInvalid:
+                case eStateUnloaded:
+                case eStateConnected:
+                case eStateAttaching:
+                case eStateLaunching:
+                case eStateStepping:
+                case eStateDetached:
+                    {
+                        stream_sp->Printf("Process %" PRIu64 " %s\n",
+                                          process_sp->GetID(),
+                                          StateAsCString (event_state));
+                    }
+                    break;
+                    
+                case eStateRunning:
+                    // Don't be chatty when we run...
+                    break;
+                    
+                case eStateExited:
+                    process_sp->GetStatus(*stream_sp);
+                    break;
+                    
+                case eStateStopped:
+                case eStateCrashed:
+                case eStateSuspended:
+                    // Make sure the program hasn't been auto-restarted:
+                    if (Process::ProcessEventData::GetRestartedFromEvent (event_sp.get()))
+                    {
+                        size_t num_reasons = Process::ProcessEventData::GetNumRestartedReasons(event_sp.get());
+                        if (num_reasons > 0)
+                        {
+                            // FIXME: Do we want to report this, or would that just be annoyingly chatty?
+                            if (num_reasons == 1)
+                            {
+                                const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), 0);
+                                stream_sp->Printf("Process %" PRIu64 " stopped and restarted: %s\n",
+                                                  process_sp->GetID(),
+                                                  reason ? reason : "<UNKNOWN REASON>");
+                            }
+                            else
+                            {
+                                stream_sp->Printf("Process %" PRIu64 " stopped and restarted, reasons:\n",
+                                                   process_sp->GetID());
+                                
+
+                                for (size_t i = 0; i < num_reasons; i++)
+                                {
+                                    const char *reason = Process::ProcessEventData::GetRestartedReasonAtIndex (event_sp.get(), i);
+                                    stream_sp->Printf("\t%s\n", reason ? reason : "<UNKNOWN REASON>");
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        if (GetTargetList().GetSelectedTarget().get() == &process_sp->GetTarget())
+                        {
+                            const bool only_threads_with_stop_reason = true;
+                            const uint32_t start_frame = 0;
+                            const uint32_t num_frames = 1;
+                            const uint32_t num_frames_with_source = 1;
+                            process_sp->GetStatus(*stream_sp);
+                            process_sp->GetThreadStatus (*stream_sp,
+                                                         only_threads_with_stop_reason,
+                                                         start_frame,
+                                                         num_frames,
+                                                         num_frames_with_source);
+                        }
+                        else
+                        {
+                            uint32_t target_idx = GetTargetList().GetIndexOfTarget(process_sp->GetTarget().shared_from_this());
+                            if (target_idx != UINT32_MAX)
+                                stream_sp->Printf ("Target %d: (", target_idx);
+                            else
+                                stream_sp->Printf ("Target <unknown index>: (");
+                            process_sp->GetTarget().Dump (stream_sp.get(), eDescriptionLevelBrief);
+                            stream_sp->Printf (") stopped.\n");
+                        }
+                    }
+                    break;
+            }
+        }
+    }
+    
+    if (top_io_handler_hid)
+        RefreshTopIOHandler();
+}
+
+void
+Debugger::HandleThreadEvent (const EventSP &event_sp)
+{
+    // At present the only thread event we handle is the Frame Changed event,
+    // and all we do for that is just reprint the thread status for that thread.
+    using namespace lldb;
+    const uint32_t event_type = event_sp->GetType();
+    if (event_type == Thread::eBroadcastBitStackChanged   ||
+        event_type == Thread::eBroadcastBitThreadSelected )
+    {
+        ThreadSP thread_sp (Thread::ThreadEventData::GetThreadFromEvent (event_sp.get()));
+        if (thread_sp)
+        {
+            HideTopIOHandler();
+            StreamFileSP stream_sp (GetOutputFile());
+            thread_sp->GetStatus(*stream_sp, 0, 1, 1);
+            RefreshTopIOHandler();
+        }
+    }
+}
+
+bool
+Debugger::IsForwardingEvents ()
+{
+    return (bool)m_forward_listener_sp;
+}
+
+void
+Debugger::EnableForwardEvents (const ListenerSP &listener_sp)
+{
+    m_forward_listener_sp = listener_sp;
+}
+
+void
+Debugger::CancelForwardEvents (const ListenerSP &listener_sp)
+{
+    m_forward_listener_sp.reset();
+}
+
+
+void
+Debugger::DefaultEventHandler()
+{
+    Listener& listener(GetListener());
+    ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
+    ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
+    ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
+    BroadcastEventSpec target_event_spec (broadcaster_class_target,
+                                          Target::eBroadcastBitBreakpointChanged);
+
+    BroadcastEventSpec process_event_spec (broadcaster_class_process,
+                                           Process::eBroadcastBitStateChanged   |
+                                           Process::eBroadcastBitSTDOUT         |
+                                           Process::eBroadcastBitSTDERR);
+
+    BroadcastEventSpec thread_event_spec (broadcaster_class_thread,
+                                          Thread::eBroadcastBitStackChanged     |
+                                          Thread::eBroadcastBitThreadSelected   );
+    
+    listener.StartListeningForEventSpec (*this, target_event_spec);
+    listener.StartListeningForEventSpec (*this, process_event_spec);
+    listener.StartListeningForEventSpec (*this, thread_event_spec);
+    listener.StartListeningForEvents (m_command_interpreter_ap.get(),
+                                      CommandInterpreter::eBroadcastBitQuitCommandReceived      |
+                                      CommandInterpreter::eBroadcastBitAsynchronousOutputData   |
+                                      CommandInterpreter::eBroadcastBitAsynchronousErrorData    );
+    
+    bool done = false;
+    while (!done)
+    {
+//        Mutex::Locker locker;
+//        if (locker.TryLock(m_input_reader_stack.GetMutex()))
+//        {
+//            if (m_input_reader_stack.IsEmpty())
+//                break;
+//        }
+//
+        EventSP event_sp;
+        if (listener.WaitForEvent(NULL, event_sp))
+        {
+            if (event_sp)
+            {
+                Broadcaster *broadcaster = event_sp->GetBroadcaster();
+                if (broadcaster)
+                {
+                    uint32_t event_type = event_sp->GetType();
+                    ConstString broadcaster_class (broadcaster->GetBroadcasterClass());
+                    if (broadcaster_class == broadcaster_class_process)
+                    {
+                        HandleProcessEvent (event_sp);
+                    }
+                    else if (broadcaster_class == broadcaster_class_target)
+                    {
+                        if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(event_sp.get()))
+                        {
+                            HandleBreakpointEvent (event_sp);
+                        }
+                    }
+                    else if (broadcaster_class == broadcaster_class_thread)
+                    {
+                        HandleThreadEvent (event_sp);
+                    }
+                    else if (broadcaster == m_command_interpreter_ap.get())
+                    {
+                        if (event_type & CommandInterpreter::eBroadcastBitQuitCommandReceived)
+                        {
+                            done = true;
+                        }
+                        else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousErrorData)
+                        {
+                            const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get()));
+                            if (data && data[0])
+                            {
+                                StreamFileSP error_sp (GetErrorFile());
+                                if (error_sp)
+                                {
+                                    HideTopIOHandler();
+                                    error_sp->PutCString(data);
+                                    error_sp->Flush();
+                                    RefreshTopIOHandler();
+                                }
+                            }
+                        }
+                        else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousOutputData)
+                        {
+                            const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get()));
+                            if (data && data[0])
+                            {
+                                StreamFileSP output_sp (GetOutputFile());
+                                if (output_sp)
+                                {
+                                    HideTopIOHandler();
+                                    output_sp->PutCString(data);
+                                    output_sp->Flush();
+                                    RefreshTopIOHandler();
+                                }
+                            }
+                        }
+                    }
+                }
+                
+                if (m_forward_listener_sp)
+                    m_forward_listener_sp->AddEvent(event_sp);
+            }
+        }
+    }
+}
+
+lldb::thread_result_t
+Debugger::EventHandlerThread (lldb::thread_arg_t arg)
+{
+    ((Debugger *)arg)->DefaultEventHandler();
+    return NULL;
+}
+
+bool
+Debugger::StartEventHandlerThread()
+{
+    if (!IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread))
+        m_event_handler_thread = Host::ThreadCreate("lldb.debugger.event-handler", EventHandlerThread, this, NULL);
+    return IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread);
+}
+
+void
+Debugger::StopEventHandlerThread()
+{
+    if (IS_VALID_LLDB_HOST_THREAD(m_event_handler_thread))
+    {
+        GetCommandInterpreter().BroadcastEvent(CommandInterpreter::eBroadcastBitQuitCommandReceived);
+        Host::ThreadJoin(m_event_handler_thread, NULL, NULL);
+    }
+}
+
+

Added: lldb/branches/iohandler/source/Core/IOHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Core/IOHandler.cpp?rev=198366&view=auto
==============================================================================
--- lldb/branches/iohandler/source/Core/IOHandler.cpp (added)
+++ lldb/branches/iohandler/source/Core/IOHandler.cpp Thu Jan  2 16:40:14 2014
@@ -0,0 +1,3036 @@
+//===-- IOHandler.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/lldb-python.h"
+
+#include <stdio.h>	/* ioctl, TIOCGWINSZ */
+#include <sys/ioctl.h>	/* ioctl, TIOCGWINSZ */
+
+
+#include <string>
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/IOHandler.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Host/Editline.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Target/ThreadPlan.h"
+
+
+#include <ncurses.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+IOHandler::IOHandler (Debugger &debugger) :
+    IOHandler (debugger,
+               StreamFileSP(), // Adopt STDIN from top input reader
+               StreamFileSP(), // Adopt STDOUT from top input reader
+               StreamFileSP()) // Adopt STDERR from top input reader
+{
+}
+
+
+IOHandler::IOHandler (Debugger &debugger,
+                      const lldb::StreamFileSP &input_sp,
+                      const lldb::StreamFileSP &output_sp,
+                      const lldb::StreamFileSP &error_sp) :
+    m_debugger (debugger),
+    m_input_sp (input_sp),
+    m_output_sp (output_sp),
+    m_error_sp (error_sp),
+    m_user_data (NULL),
+    m_done (false),
+    m_active (false)
+{
+    // If any files are not specified, then adopt them from the
+    // top input reader.
+    if (!m_input_sp || !m_output_sp || !m_error_sp)
+        debugger.GetIOHandlerFiles (*this);
+}
+
+IOHandler::~IOHandler()
+{
+}
+
+
+int
+IOHandler::GetInputFD()
+{
+    if (m_input_sp)
+        return m_input_sp->GetFile().GetDescriptor();
+    return -1;
+}
+
+int
+IOHandler::GetOutputFD()
+{
+    if (m_output_sp)
+        return m_output_sp->GetFile().GetDescriptor();
+    return -1;
+}
+
+int
+IOHandler::GetErrorFD()
+{
+    if (m_error_sp)
+        return m_error_sp->GetFile().GetDescriptor();
+    return -1;
+}
+
+FILE *
+IOHandler::GetInputFILE()
+{
+    if (m_input_sp)
+        return m_input_sp->GetFile().GetStream();
+    return NULL;
+}
+
+FILE *
+IOHandler::GetOutputFILE()
+{
+    if (m_output_sp)
+        return m_output_sp->GetFile().GetStream();
+    return NULL;
+}
+
+FILE *
+IOHandler::GetErrorFILE()
+{
+    if (m_error_sp)
+        return m_error_sp->GetFile().GetStream();
+    return NULL;
+}
+
+StreamFileSP &
+IOHandler::GetInputStreamFile()
+{
+    return m_input_sp;
+}
+
+StreamFileSP &
+IOHandler::GetOutputStreamFile()
+{
+    return m_output_sp;
+}
+
+
+StreamFileSP &
+IOHandler::GetErrorStreamFile()
+{
+    return m_error_sp;
+}
+
+
+IOHandlerConfirm::IOHandlerConfirm (Debugger &debugger,
+                                    const char *prompt,
+                                    bool default_response) :
+    IOHandlerEditline(debugger,
+                      NULL,     // NULL editline_name means no history loaded/saved
+                      NULL,
+                      false,    // Multi-line
+                      *this),
+    m_default_response (default_response),
+    m_user_response (default_response)
+{
+    StreamString prompt_stream;
+    prompt_stream.PutCString(prompt);
+    if (m_default_response)
+        prompt_stream.Printf(": [Y/n] ");
+    else
+        prompt_stream.Printf(": [y/N] ");
+    
+    SetPrompt (prompt_stream.GetString().c_str());
+    
+}
+
+
+IOHandlerConfirm::~IOHandlerConfirm ()
+{
+}
+
+int
+IOHandlerConfirm::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)
+{
+    if (current_line == cursor)
+    {
+        if (m_default_response)
+        {
+            matches.AppendString("y");
+        }
+        else
+        {
+            matches.AppendString("n");
+        }
+    }
+    return matches.GetSize();
+}
+
+void
+IOHandlerConfirm::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+{
+    if (line == "y" || line == "Y" || line == "yes" || line == "YES" || line == "Yes")
+        io_handler.SetIsDone(true);
+    if (line == "n" || line == "N" || line == "no" || line == "NO" || line == "No")
+        io_handler.SetIsDone(true);
+}
+
+int
+IOHandlerDelegate::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)
+{
+    switch (m_completion)
+    {
+    case Completion::None:
+        break;
+
+    case Completion::LLDBCommand:
+        return io_handler.GetDebugger().GetCommandInterpreter().HandleCompletion (current_line,
+                                                                                  cursor,
+                                                                                  last_char,
+                                                                                  skip_first_n_matches,
+                                                                                  max_matches,
+                                                                                  matches);
+
+    case Completion::Expression:
+        {
+            bool word_complete = false;
+            const char *word_start = cursor;
+            if (cursor > current_line)
+                --word_start;
+            while (word_start > current_line && !isspace(*word_start))
+                --word_start;
+            CommandCompletions::InvokeCommonCompletionCallbacks (io_handler.GetDebugger().GetCommandInterpreter(),
+                                                                 CommandCompletions::eVariablePathCompletion,
+                                                                 word_start,
+                                                                 skip_first_n_matches,
+                                                                 max_matches,
+                                                                 NULL,
+                                                                 word_complete,
+                                                                 matches);
+            
+            size_t num_matches = matches.GetSize();
+            if (num_matches > 0)
+            {
+                std::string common_prefix;
+                matches.LongestCommonPrefix (common_prefix);
+                const size_t partial_name_len = strlen(word_start);
+                
+                // If we matched a unique single command, add a space...
+                // Only do this if the completer told us this was a complete word, however...
+                if (num_matches == 1 && word_complete)
+                {
+                    common_prefix.push_back(' ');
+                }
+                common_prefix.erase (0, partial_name_len);
+                matches.InsertStringAtIndex(0, std::move(common_prefix));
+            }
+            return num_matches;
+        }
+        break;
+    }
+    
+    
+    return 0;
+}
+
+
+IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
+                                      const char *editline_name, // Used for saving history files
+                                      const char *prompt,
+                                      bool multi_line,
+                                      IOHandlerDelegate &delegate) :
+    IOHandlerEditline(debugger,
+                      StreamFileSP(), // Inherit input from top input reader
+                      StreamFileSP(), // Inherit output from top input reader
+                      StreamFileSP(), // Inherit error from top input reader
+                      editline_name,  // Used for saving history files
+                      prompt,
+                      multi_line,
+                      delegate)
+{
+}
+
+IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
+                                      const lldb::StreamFileSP &input_sp,
+                                      const lldb::StreamFileSP &output_sp,
+                                      const lldb::StreamFileSP &error_sp,
+                                      const char *editline_name, // Used for saving history files
+                                      const char *prompt,
+                                      bool multi_line,
+                                      IOHandlerDelegate &delegate) :
+    IOHandler (debugger, input_sp, output_sp, error_sp),
+    m_editline_ap (),
+    m_delegate (delegate),
+    m_multi_line (multi_line)
+{
+    m_editline_ap.reset(new Editline (editline_name,
+                                      prompt ? prompt : "",
+                                      GetInputFILE (),
+                                      GetOutputFILE (),
+                                      GetErrorFILE ()));
+    m_editline_ap->SetLineCompleteCallback (LineCompletedCallback, this);
+    m_editline_ap->SetAutoCompleteCallback (AutoCompleteCallback, this);
+}
+
+IOHandlerEditline::~IOHandlerEditline ()
+{
+    m_editline_ap.reset();
+}
+
+
+bool
+IOHandlerEditline::GetLine (std::string &line)
+{
+    if (m_editline_ap)
+    {
+        return m_editline_ap->GetLine(line).Success();
+    }
+    else
+    {
+        FILE *in = GetInputFILE();
+        char buffer[256];
+        bool done = false;
+        while (!done)
+        {
+            if (fgets(buffer, sizeof(buffer), in) == NULL)
+                done = true;
+            else
+            {
+                const size_t buffer_len = strlen(buffer);
+                line.append(buffer, buffer_len);
+                assert (buffer[buffer_len] == '\0');
+                const char last_char = buffer[buffer_len-1];
+                if (last_char == '\r' || last_char == '\n')
+                    done = true;
+            }
+        }
+        return !line.empty();
+    }
+}
+
+
+LineStatus
+IOHandlerEditline::LineCompletedCallback (Editline *editline,
+                                          StringList &lines,
+                                          uint32_t line_idx,
+                                          Error &error,
+                                          void *baton)
+{
+    IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton;
+    return editline_reader->m_delegate.IOHandlerLinesUpdated(*editline_reader, lines, line_idx, error);
+}
+
+int
+IOHandlerEditline::AutoCompleteCallback (const char *current_line,
+                                         const char *cursor,
+                                         const char *last_char,
+                                         int skip_first_n_matches,
+                                         int max_matches,
+                                         StringList &matches,
+                                         void *baton)
+{
+    IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton;
+    if (editline_reader)
+        return editline_reader->m_delegate.IOHandlerComplete (*editline_reader,
+                                                              current_line,
+                                                              cursor,
+                                                              last_char,
+                                                              skip_first_n_matches,
+                                                              max_matches,
+                                                              matches);
+    return 0;
+}
+
+const char *
+IOHandlerEditline::GetPrompt ()
+{
+    if (m_editline_ap)
+        return m_editline_ap->GetPrompt ();
+    return false;
+}
+
+bool
+IOHandlerEditline::SetPrompt (const char *p)
+{
+    if (m_editline_ap)
+    {
+        m_editline_ap->SetPrompt (p);
+        return true;
+    }
+    return false;
+}
+
+bool
+IOHandlerEditline::GetLines (StringList &lines)
+{
+    bool success = false;
+    if (m_editline_ap)
+    {
+        std::string end_token;
+        success = m_editline_ap->GetLines(end_token, lines).Success();
+    }
+    else
+    {
+        LineStatus lines_status = LineStatus::Success;
+
+        while (lines_status == LineStatus::Success)
+        {
+            std::string line;
+            if (GetLine(line))
+            {
+                lines.AppendString(line);
+                Error error;
+                lines_status = m_delegate.IOHandlerLinesUpdated(*this, lines, lines.GetSize() - 1, error);
+            }
+            else
+            {
+                lines_status = LineStatus::Done;
+            }
+        }
+        success = lines.GetSize() > 0;
+    }
+    return success;
+}
+
+// Each IOHandler gets to run until it is done. It should read data
+// from the "in" and place output into "out" and "err and return
+// when done.
+void
+IOHandlerEditline::Run ()
+{
+    std::string line;
+    while (IsActive())
+    {
+        if (m_multi_line)
+        {
+            StringList lines;
+            if (GetLines (lines))
+            {
+                line = lines.CopyList();
+                m_delegate.IOHandlerInputComplete(*this, line);
+            }
+            else
+            {
+                m_done = true;
+            }
+        }
+        else
+        {
+            if (GetLine(line))
+            {
+                m_delegate.IOHandlerInputComplete(*this, line);
+            }
+            else
+            {
+                m_done = true;
+            }
+        }
+    }
+}
+
+void
+IOHandlerEditline::Hide ()
+{
+    if (m_editline_ap && m_editline_ap->GettingLine())
+        m_editline_ap->Hide();
+}
+
+
+void
+IOHandlerEditline::Refresh ()
+{
+    if (m_editline_ap && m_editline_ap->GettingLine())
+        m_editline_ap->Refresh();
+}
+
+void
+IOHandlerEditline::Interrupt ()
+{
+    if (m_editline_ap)
+        m_editline_ap->Interrupt();
+}
+
+void
+IOHandlerEditline::GotEOF()
+{
+    if (m_editline_ap)
+        m_editline_ap->Interrupt();
+}
+
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/StackFrame.h"
+
+#define KEY_RETURN   10
+#define KEY_ESCAPE  27
+
+namespace curses
+{
+    class Menu;
+    class MenuDelegate;
+    class Window;
+    class WindowDelegate;
+    typedef std::shared_ptr<Menu> MenuSP;
+    typedef std::shared_ptr<MenuDelegate> MenuDelegateSP;
+    typedef std::shared_ptr<Window> WindowSP;
+    typedef std::shared_ptr<WindowDelegate> WindowDelegateSP;
+    typedef std::vector<MenuSP> Menus;
+    typedef std::vector<WindowSP> Windows;
+    typedef std::vector<WindowDelegateSP> WindowDelegates;
+
+    enum HandleCharResult
+    {
+        eKeyNotHandled      = 0,
+        eKeyHandled         = 1,
+        eQuitApplication    = 2
+    };
+    
+    enum class MenuActionResult
+    {
+        Success,
+        Error,
+        Quit    // Exit all menus and quit
+    };
+
+
+    class WindowDelegate
+    {
+    public:
+        virtual
+        ~WindowDelegate()
+        {
+        }
+        
+        virtual bool
+        WindowDelegateDraw (Window &window, bool force)
+        {
+            return false; // Drawing not handled
+        }
+        
+        virtual HandleCharResult
+        WindowDelegateHandleChar (Window &window, int key)
+        {
+            return eKeyNotHandled;
+        }
+    };
+    
+
+    class Window
+    {
+    public:
+
+        Window (const char *name) :
+            m_name (name),
+            m_window (NULL),
+            m_parent (NULL),
+            m_subwindows (),
+            m_delegate_sp (),
+            m_curr_active_window_idx (UINT32_MAX),
+            m_prev_active_window_idx (UINT32_MAX),
+            m_delete (false),
+            m_needs_update (true),
+            m_can_activate (true)
+        {
+        }
+        
+        Window (const char *name, WINDOW *w, bool del = true) :
+            m_name (name),
+            m_window (w),
+            m_parent (NULL),
+            m_subwindows (),
+            m_delegate_sp (),
+            m_curr_active_window_idx (UINT32_MAX),
+            m_prev_active_window_idx (UINT32_MAX),
+            m_delete (del),
+            m_needs_update (true),
+            m_can_activate (true)
+        {
+        }
+        
+        Window (const char *name, int nlines, int ncols, int begin_y, int begin_x) :
+            m_name (name),
+            m_window (::newwin (nlines, ncols, begin_y, begin_x)),
+            m_parent (NULL),
+            m_subwindows (),
+            m_delegate_sp (),
+            m_curr_active_window_idx (UINT32_MAX),
+            m_prev_active_window_idx (UINT32_MAX),
+            m_delete (true),
+            m_needs_update (true),
+            m_can_activate (true)
+        {
+        }
+        
+        virtual
+        ~Window ()
+        {
+            RemoveSubWindows ();
+            Reset ();
+        }
+        
+        void
+        Reset (WINDOW *w = NULL, bool del = true)
+        {
+            if (m_window == w)
+                return;
+            
+            if (m_window && m_delete)
+            {
+                ::delwin (m_window);
+                m_window = NULL;
+                m_delete = false;
+            }
+            if (w)
+            {
+                m_window = w;
+                m_delete = del;
+            }
+        }
+        
+        void    AttributeOn (attr_t attr)   { ::wattron (m_window, attr); }
+        void    AttributeOff (attr_t attr)  { ::wattroff (m_window, attr); }
+        void    Box (chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) { ::box(m_window, v_char, h_char); }
+        void    Clear ()    { ::wclear (m_window); }
+        void    Erase ()    { ::werase (m_window); }
+        int     GetChar ()  { return ::wgetch (m_window); }
+        int     GetX ()     { return ::getcurx (m_window); }
+        int     GetY ()     { return ::getcury (m_window); }
+        int     GetMinX()   { return ::getbegx (m_window); }
+        int     GetMinY()   { return ::getbegy (m_window); }
+        int     GetMaxX()   { return ::getmaxx (m_window); }
+        int     GetMaxY()   { return ::getmaxy (m_window); }
+        int     GetWidth()  { return GetMaxX(); }
+        int     GetHeight() { return GetMaxY(); }
+        void    Move (int x, int y) {  ::wmove (m_window, y, x); }
+        void    PutChar (int ch)    { ::waddch (m_window, ch); }
+        void    PutCString (const char *s, int len = -1) { ::waddnstr (m_window, s, len); }
+        void    Refresh ()  { ::wrefresh (m_window); }
+        void    DeferredRefresh ()  { ::wnoutrefresh(m_window); }
+        void    SetBackground (int color_pair_idx) { ::wbkgd (m_window,COLOR_PAIR(color_pair_idx)); }
+        void    UnderlineOn ()  { AttributeOn(A_UNDERLINE); }
+        void    UnderlineOff () { AttributeOff(A_UNDERLINE); }
+
+        void
+        Printf (const char *format, ...)  __attribute__ ((format (printf, 2, 3)))
+        {
+            va_list args;
+            va_start (args, format);
+            vwprintw(m_window, format, args);
+            va_end (args);
+        }
+
+        void
+        Touch ()
+        {
+            ::touchwin (m_window);
+            if (m_parent)
+                m_parent->Touch();
+        }
+
+        void
+        AddSubWindow (const WindowSP &subwindow_sp, bool make_active)
+        {
+            subwindow_sp->m_parent = this;
+            if (make_active)
+            {
+                m_prev_active_window_idx = m_curr_active_window_idx;
+                m_curr_active_window_idx = m_subwindows.size();
+            }
+            m_subwindows.push_back(subwindow_sp);
+            m_needs_update = true;
+        }
+
+        WindowSP
+        CreateSubWindow (const char *name, int h, int w, int y, int x, bool make_active)
+        {
+            WindowSP subwindow_sp;
+            if (m_window)
+                subwindow_sp.reset(new Window(name, ::subwin (m_window, h, w, y, x), true));
+            else
+                subwindow_sp.reset(new Window(name, ::newwin (h, w, y, x), true));
+            subwindow_sp->m_parent = this;
+            if (make_active)
+            {
+                m_prev_active_window_idx = m_curr_active_window_idx;
+                m_curr_active_window_idx = m_subwindows.size();
+            }
+            m_subwindows.push_back(subwindow_sp);
+            m_needs_update = true;
+            return subwindow_sp;
+        }
+        
+        bool
+        RemoveSubWindow (Window *window)
+        {
+            Windows::iterator pos, end = m_subwindows.end();
+            size_t i = 0;
+            for (pos = m_subwindows.begin(); pos != end; ++pos, ++i)
+            {
+                if ((*pos).get() == window)
+                {
+                    if (m_prev_active_window_idx == i)
+                        m_prev_active_window_idx = UINT32_MAX;
+                    else if (m_prev_active_window_idx != UINT32_MAX && m_prev_active_window_idx > i)
+                        --m_prev_active_window_idx;
+
+                    if (m_curr_active_window_idx == i)
+                        m_curr_active_window_idx = UINT32_MAX;
+                    else if (m_curr_active_window_idx != UINT32_MAX && m_curr_active_window_idx > i)
+                        --m_curr_active_window_idx;
+                    window->Erase();
+                    m_subwindows.erase(pos);
+                    m_needs_update = true;
+                    if (m_parent)
+                        m_parent->Touch();
+                    else
+                        ::touchwin (stdscr);
+                    return true;
+                }
+            }
+            return false;
+        }
+        
+        void
+        RemoveSubWindows ()
+        {
+            m_curr_active_window_idx = UINT32_MAX;
+            m_prev_active_window_idx = UINT32_MAX;
+            for (Windows::iterator pos = m_subwindows.begin();
+                 pos != m_subwindows.end();
+                 pos = m_subwindows.erase(pos))
+            {
+                (*pos)->Erase();
+            }
+            if (m_parent)
+                m_parent->Touch();
+            else
+                ::touchwin (stdscr);
+        }
+
+        WINDOW *
+        get()
+        {
+            return m_window;
+        }
+
+        operator WINDOW *()
+        {
+            return m_window;
+        }
+        
+        //----------------------------------------------------------------------
+        // Window drawing utilities
+        //----------------------------------------------------------------------
+        void
+        DrawTitleBox (const char *title)
+        {
+            attr_t attr = 0;
+            if (IsActive())
+                attr = A_BOLD | COLOR_PAIR(2);
+            else
+                attr = 0;
+            if (attr)
+                AttributeOn(attr);
+
+            Box();
+            Move (3, 0);
+            
+            if (title && title[0])
+            {
+                PutCString ("<");
+                PutCString(title);
+                PutCString (">");
+            }
+            if (attr)
+                AttributeOff(attr);
+        }
+
+        virtual void
+        Draw (bool force)
+        {
+            if (m_delegate_sp && m_delegate_sp->WindowDelegateDraw (*this, force))
+                return;
+
+            //Erase();
+            for (auto &subwindow_sp : m_subwindows)
+            {
+                subwindow_sp->Draw(force);
+            }
+            //DeferredRefresh();
+        }
+        
+        virtual HandleCharResult
+        HandleChar (int key)
+        {
+            // Always check the active window first
+            HandleCharResult result = eKeyNotHandled;
+            WindowSP active_window_sp = GetActiveWindow ();
+            if (active_window_sp)
+            {
+                result = active_window_sp->HandleChar (key);
+                if (result != eKeyNotHandled)
+                    return result;
+            }
+            
+            if (m_delegate_sp)
+            {
+                result = m_delegate_sp->WindowDelegateHandleChar (*this, key);
+                if (result != eKeyNotHandled)
+                    return result;
+            }
+
+            // Then check for any windows that want any keys
+            // that weren't handled. This is typically only
+            // for a menubar.
+            // Make a copy of the subwindows in case any HandleChar()
+            // functions muck with the subwindows. If we don't do this,
+            // we can crash when iterating over the subwindows.
+            Windows subwindows (m_subwindows);
+            for (auto subwindow_sp : subwindows)
+            {
+                if (subwindow_sp->m_can_activate == false)
+                {
+                    HandleCharResult result = subwindow_sp->HandleChar(key);
+                    if (result != eKeyNotHandled)
+                        return result;
+                }
+            }
+
+            return eKeyNotHandled;
+        }
+
+        bool
+        SetActiveWindow (Window *window)
+        {
+            const size_t num_subwindows = m_subwindows.size();
+            for (size_t i=0; i<num_subwindows; ++i)
+            {
+                if (m_subwindows[i].get() == window)
+                {
+                    m_prev_active_window_idx = m_curr_active_window_idx;
+                    m_curr_active_window_idx = i;
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        WindowSP
+        GetActiveWindow ()
+        {
+            if (!m_subwindows.empty())
+            {
+                if (m_curr_active_window_idx >= m_subwindows.size())
+                {
+                    if (m_prev_active_window_idx < m_subwindows.size())
+                    {
+                        m_curr_active_window_idx = m_prev_active_window_idx;
+                        m_prev_active_window_idx = UINT32_MAX;
+                    }
+                    else if (IsActive())
+                    {
+                        m_prev_active_window_idx = UINT32_MAX;
+                        m_curr_active_window_idx = UINT32_MAX;
+                        
+                        // Find first window that wants to be active if this window is active
+                        const size_t num_subwindows = m_subwindows.size();
+                        for (size_t i=0; i<num_subwindows; ++i)
+                        {
+                            if (m_subwindows[i]->GetCanBeActive())
+                            {
+                                m_curr_active_window_idx = i;
+                                break;
+                            }
+                        }
+                    }
+                }
+                
+                if (m_curr_active_window_idx < m_subwindows.size())
+                    return m_subwindows[m_curr_active_window_idx];
+            }
+            return WindowSP();
+        }
+        
+        bool
+        GetCanBeActive () const
+        {
+            return m_can_activate;
+        }
+
+        void
+        SetCanBeActive (bool b)
+        {
+            m_can_activate = b;
+        }
+        
+        const WindowDelegateSP &
+        GetDelegate () const
+        {
+            return m_delegate_sp;
+        }
+
+        void
+        SetDelegate (const WindowDelegateSP &delegate_sp)
+        {
+            m_delegate_sp = delegate_sp;
+        }
+        
+        Window *
+        GetParent () const
+        {
+            return m_parent;
+        }
+        
+        bool
+        IsActive () const
+        {
+            if (m_parent)
+                return m_parent->GetActiveWindow().get() == this;
+            else
+                return true; // Top level window is always active
+        }
+        
+        void
+        SelectNextWindowAsActive ()
+        {
+            // Move active focus to next window
+            const size_t num_subwindows = m_subwindows.size();
+            if (m_curr_active_window_idx == UINT32_MAX)
+            {
+                uint32_t idx = 0;
+                for (auto subwindow_sp : m_subwindows)
+                {
+                    if (subwindow_sp->GetCanBeActive())
+                    {
+                        m_curr_active_window_idx = idx;
+                        break;
+                    }
+                    ++idx;
+                }
+            }
+            else if (m_curr_active_window_idx + 1 < num_subwindows)
+            {
+                bool handled = false;
+                m_prev_active_window_idx = m_curr_active_window_idx;
+                for (size_t idx=m_curr_active_window_idx + 1; idx<num_subwindows; ++idx)
+                {
+                    if (m_subwindows[idx]->GetCanBeActive())
+                    {
+                        m_curr_active_window_idx = idx;
+                        handled = true;
+                        break;
+                    }
+                }
+                if (!handled)
+                {
+                    for (size_t idx=0; idx<=m_prev_active_window_idx; ++idx)
+                    {
+                        if (m_subwindows[idx]->GetCanBeActive())
+                        {
+                            m_curr_active_window_idx = idx;
+                            break;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                m_prev_active_window_idx = m_curr_active_window_idx;
+                for (size_t idx=0; idx<num_subwindows; ++idx)
+                {
+                    if (m_subwindows[idx]->GetCanBeActive())
+                    {
+                        m_curr_active_window_idx = idx;
+                        break;
+                    }
+                }
+            }
+        }
+
+    protected:
+        std::string m_name;
+        WINDOW *m_window;
+        Window *m_parent;
+        Windows m_subwindows;
+        WindowDelegateSP m_delegate_sp;
+        uint32_t m_curr_active_window_idx;
+        uint32_t m_prev_active_window_idx;
+        bool m_delete;
+        bool m_needs_update;
+        bool m_can_activate;
+        
+    private:
+        DISALLOW_COPY_AND_ASSIGN(Window);
+    };
+    
+    class MenuDelegate
+    {
+    public:
+        virtual ~MenuDelegate() {}
+        
+        virtual MenuActionResult
+        MenuDelegateAction (Menu &menu) = 0;
+    };
+
+    class Menu : public WindowDelegate
+    {
+    public:
+        enum class Type
+        {
+            Invalid,
+            Bar,
+            Item,
+            Separator
+        };
+        
+        // Menubar or separator constructor
+        Menu (Type type);
+        
+        // Menuitem constructor
+        Menu (const char *name,
+              const char *key_name,
+              int key_value);
+        
+        virtual ~
+        Menu ()
+        {
+        }
+
+        const MenuDelegateSP &
+        GetDelegate () const
+        {
+            return m_delegate_sp;
+        }
+        
+        void
+        SetDelegate (const MenuDelegateSP &delegate_sp)
+        {
+            m_delegate_sp = delegate_sp;
+        }
+        
+        void
+        RecalculateNameLengths();
+
+        void
+        AddSubmenu (const MenuSP &menu_sp);
+        
+        int
+        DrawAndRunMenu (Window &window);
+        
+        void
+        DrawMenuTitle (Window &window, bool highlight);
+
+        virtual bool
+        WindowDelegateDraw (Window &window, bool force);
+        
+        virtual HandleCharResult
+        WindowDelegateHandleChar (Window &window, int key);
+
+        MenuActionResult
+        Action ()
+        {
+            if (m_delegate_sp)
+                return m_delegate_sp->MenuDelegateAction (*this);
+            return m_canned_result;
+        }
+        
+        void
+        SetCannedResult (MenuActionResult result)
+        {
+            m_canned_result = result;
+        }
+
+        Menus &
+        GetSubmenus()
+        {
+            return m_submenus;
+        }
+
+        const Menus &
+        GetSubmenus() const
+        {
+            return m_submenus;
+        }
+
+        int
+        GetSelectedSubmenuIndex () const
+        {
+            return m_selected;
+        }
+        
+        void
+        SetSelectedSubmenuIndex (int idx)
+        {
+            m_selected = idx;
+        }
+
+        Type
+        GetType () const
+        {
+            return m_type;
+        }
+        
+        int
+        GetStartingColumn() const
+        {
+            return m_start_col;
+        }
+
+        void
+        SetStartingColumn(int col)
+        {
+            m_start_col = col;
+        }
+
+        int
+        GetKeyValue() const
+        {
+            return m_key_value;
+        }
+        
+        void
+        SetKeyValue(int key_value)
+        {
+            m_key_value = key_value;
+        }
+
+        std::string &
+        GetName()
+        {
+            return m_name;
+        }
+
+        std::string &
+        GetKeyName()
+        {
+            return m_key_name;
+        }
+
+        int
+        GetDrawWidth () const
+        {
+            return m_max_submenu_name_length + m_max_submenu_key_name_length + 8;
+        }
+    protected:
+        std::string m_name;
+        std::string m_key_name;
+        Type m_type;
+        int m_key_value;
+        int m_start_col;
+        int m_max_submenu_name_length;
+        int m_max_submenu_key_name_length;
+        int m_selected;
+        Menu *m_parent;
+        Menus m_submenus;
+        WindowSP m_menu_window_sp;
+        MenuActionResult m_canned_result;
+        MenuDelegateSP m_delegate_sp;
+    };
+
+    // Menubar or separator constructor
+    Menu::Menu (Type type) :
+        m_name (),
+        m_key_name (),
+        m_type (type),
+        m_key_value (0),
+        m_start_col (0),
+        m_max_submenu_name_length (0),
+        m_max_submenu_key_name_length (0),
+        m_selected (0),
+        m_parent (NULL),
+        m_submenus (),
+        m_canned_result (MenuActionResult::Success),
+        m_delegate_sp()
+    {
+    }
+
+    // Menuitem constructor
+    Menu::Menu (const char *name,
+                const char *key_name,
+                int key_value) :
+        m_name (),
+        m_key_name (),
+        m_type (Type::Invalid),
+        m_key_value (key_value),
+        m_start_col (0),
+        m_max_submenu_name_length (0),
+        m_max_submenu_key_name_length (0),
+        m_selected (0),
+        m_parent (NULL),
+        m_submenus (),
+        m_canned_result (MenuActionResult::Success),
+        m_delegate_sp()
+    {
+        if (name && name[0])
+        {
+            m_name = name;
+            m_type = Type::Item;
+            if (key_name && key_name[0])
+                m_key_name = key_name;
+        }
+        else
+        {
+            m_type = Type::Separator;
+        }
+    }
+
+    void
+    Menu::RecalculateNameLengths()
+    {
+        m_max_submenu_name_length = 0;
+        m_max_submenu_key_name_length = 0;
+        Menus &submenus = GetSubmenus();
+        const size_t num_submenus = submenus.size();
+        for (size_t i=0; i<num_submenus; ++i)
+        {
+            Menu *submenu = submenus[i].get();
+            if (m_max_submenu_name_length < submenu->m_name.size())
+                m_max_submenu_name_length = submenu->m_name.size();
+            if (m_max_submenu_key_name_length < submenu->m_key_name.size())
+                m_max_submenu_key_name_length = submenu->m_key_name.size();
+        }
+    }
+
+    void
+    Menu::AddSubmenu (const MenuSP &menu_sp)
+    {
+        menu_sp->m_parent = this;
+        if (m_max_submenu_name_length < menu_sp->m_name.size())
+            m_max_submenu_name_length = menu_sp->m_name.size();
+        if (m_max_submenu_key_name_length < menu_sp->m_key_name.size())
+            m_max_submenu_key_name_length = menu_sp->m_key_name.size();
+        m_submenus.push_back(menu_sp);
+    }
+
+    void
+    Menu::DrawMenuTitle (Window &window, bool highlight)
+    {
+        if (m_type == Type::Separator)
+        {
+            window.Move(0, window.GetY());
+            window.PutChar(ACS_LTEE);
+            int width = window.GetWidth();
+            if (width > 2)
+            {
+                width -= 2;
+                for (size_t i=0; i< width; ++i)
+                    window.PutChar(ACS_HLINE);
+            }
+            window.PutChar(ACS_RTEE);
+        }
+        else
+        {
+            const int shortcut_key = m_key_value;
+            bool underlined_shortcut = false;
+            const attr_t hilgight_attr = A_REVERSE;
+            if (highlight)
+                window.AttributeOn(hilgight_attr);
+            if (isprint(shortcut_key))
+            {
+                size_t lower_pos = m_name.find(tolower(shortcut_key));
+                size_t upper_pos = m_name.find(toupper(shortcut_key));
+                const char *name = m_name.c_str();
+                size_t pos = std::min<size_t>(lower_pos, upper_pos);
+                if (pos != std::string::npos)
+                {
+                    underlined_shortcut = true;
+                    if (pos > 0)
+                    {
+                        window.PutCString(name, pos);
+                        name += pos;
+                    }
+                    const attr_t shortcut_attr = A_UNDERLINE|A_BOLD;
+                    window.AttributeOn (shortcut_attr);
+                    window.PutChar(name[0]);
+                    window.AttributeOff(shortcut_attr);
+                    name++;
+                    if (name[0])
+                        window.PutCString(name);
+                }
+            }
+            
+            if (!underlined_shortcut)
+            {
+                window.PutCString(m_name.c_str());
+            }
+
+            if (highlight)
+                window.AttributeOff(hilgight_attr);
+
+            if (m_key_name.empty())
+            {
+                if (!underlined_shortcut && isprint(m_key_value))
+                {
+                    window.AttributeOn (COLOR_PAIR(3));
+                    window.Printf (" (%c)", m_key_value);
+                    window.AttributeOff (COLOR_PAIR(3));
+                }
+            }
+            else
+            {
+                window.AttributeOn (COLOR_PAIR(3));
+                window.Printf (" (%s)", m_key_name.c_str());
+                window.AttributeOff (COLOR_PAIR(3));
+            }
+        }
+    }
+    
+    bool
+    Menu::WindowDelegateDraw (Window &window, bool force)
+    {
+        Menus &submenus = GetSubmenus();
+        const size_t num_submenus = submenus.size();
+        const int selected_idx = GetSelectedSubmenuIndex();
+        Menu::Type menu_type = GetType ();
+        switch (menu_type)
+        {
+        case  Menu::Type::Bar:
+            {
+                window.SetBackground(2);
+                window.Move(0, 0);
+                for (size_t i=0; i<num_submenus; ++i)
+                {
+                    Menu *menu = submenus[i].get();
+                    if (i > 0)
+                        window.PutChar(' ');
+                    menu->SetStartingColumn (window.GetX());
+                    window.PutCString("| ");
+                    menu->DrawMenuTitle (window, false);
+                }
+                window.PutCString(" |");
+                window.DeferredRefresh();
+            }
+            break;
+                
+        case Menu::Type::Item:
+            {
+                int y = 1;
+                int x = 3;
+                // Draw the menu
+                int cursor_x = 0;
+                int cursor_y = 0;
+                window.Erase();
+                window.SetBackground(2);
+                window.Box();
+                for (size_t i=0; i<num_submenus; ++i)
+                {
+                    const bool is_selected = i == selected_idx;
+                    window.Move(x, y + i);
+                    if (is_selected)
+                    {
+                        // Remember where we want the cursor to be
+                        cursor_x = x-1;
+                        cursor_y = y+i;
+                    }
+                    submenus[i]->DrawMenuTitle (window, is_selected);
+                }
+                window.Move(cursor_x, cursor_y);
+                window.DeferredRefresh();
+            }
+            break;
+
+        default:
+        case Menu::Type::Separator:
+            break;
+        }
+        return true; // Drawing handled...
+    }
+    
+    HandleCharResult
+    Menu::WindowDelegateHandleChar (Window &window, int key)
+    {
+        HandleCharResult result = eKeyNotHandled;
+        
+        Menus &submenus = GetSubmenus();
+        const size_t num_submenus = submenus.size();
+        const int selected_idx = GetSelectedSubmenuIndex();
+        Menu::Type menu_type = GetType ();
+        if (menu_type == Menu::Type::Bar)
+        {
+            MenuSP run_menu_sp;
+            switch (key)
+            {
+                case KEY_DOWN:
+                case KEY_UP:
+                    // Show last menu or first menu
+                    if (selected_idx < num_submenus)
+                        run_menu_sp = submenus[selected_idx];
+                    else if (!submenus.empty())
+                        run_menu_sp = submenus.front();
+                    result = eKeyHandled;
+                    break;
+                    
+                case KEY_RIGHT:
+                {
+                    ++m_selected;
+                    if (m_selected >= num_submenus)
+                        m_selected = 0;
+                    if (m_selected < num_submenus)
+                        run_menu_sp = submenus[m_selected];
+                    else if (!submenus.empty())
+                        run_menu_sp = submenus.front();
+                    result = eKeyHandled;
+                }
+                    break;
+                    
+                case KEY_LEFT:
+                {
+                    --m_selected;
+                    if (m_selected < 0)
+                        m_selected = num_submenus - 1;
+                    if (m_selected < num_submenus)
+                        run_menu_sp = submenus[m_selected];
+                    else if (!submenus.empty())
+                        run_menu_sp = submenus.front();
+                    result = eKeyHandled;
+                }
+                    break;
+                    
+                default:
+                    for (size_t i=0; i<num_submenus; ++i)
+                    {
+                        if (submenus[i]->GetKeyValue() == key)
+                        {
+                            SetSelectedSubmenuIndex(i);
+                            run_menu_sp = submenus[i];
+                            result = eKeyHandled;
+                            break;
+                        }
+                    }
+                    break;
+            }
+            
+            if (run_menu_sp)
+            {
+                // Run the action on this menu in case we need to populate the
+                // menu with dynamic content and also in case check marks, and
+                // any other menu decorations need to be caclulated
+                if (run_menu_sp->Action() == MenuActionResult::Quit)
+                    return eQuitApplication;
+
+                const int win_width = run_menu_sp->GetDrawWidth();
+                const int win_height = run_menu_sp->GetSubmenus().size() + 2;
+                if (m_menu_window_sp)
+                    window.GetParent()->RemoveSubWindow(m_menu_window_sp.get());
+                
+                m_menu_window_sp = window.GetParent()->CreateSubWindow (run_menu_sp->GetName().c_str(),
+                                                                        win_height,
+                                                                        win_width,
+                                                                        window.GetMinY() + 1,
+                                                                        run_menu_sp->GetStartingColumn(),
+                                                                        true);
+                m_menu_window_sp->SetDelegate (run_menu_sp);
+            }
+        }
+        else if (menu_type == Menu::Type::Item)
+        {
+            switch (key)
+            {
+                case KEY_DOWN:
+                    if (m_submenus.size() > 1)
+                    {
+                        const int start_select = m_selected;
+                        while (++m_selected != start_select)
+                        {
+                            if (m_selected >= num_submenus)
+                                m_selected = 0;
+                            if (m_submenus[m_selected]->GetType() == Type::Separator)
+                                continue;
+                            else
+                                break;
+                        }
+                        return eKeyHandled;
+                    }
+                    break;
+                    
+                case KEY_UP:
+                    if (m_submenus.size() > 1)
+                    {
+                        const int start_select = m_selected;
+                        while (--m_selected != start_select)
+                        {
+                            if (m_selected < 0)
+                                m_selected = num_submenus - 1;
+                            if (m_submenus[m_selected]->GetType() == Type::Separator)
+                                continue;
+                            else
+                                break;
+                        }
+                        return eKeyHandled;
+                    }
+                    break;
+                    
+                case KEY_RETURN:
+                    if (selected_idx < num_submenus)
+                    {
+                        if (submenus[selected_idx]->Action() == MenuActionResult::Quit)
+                            return eQuitApplication;
+                        window.GetParent()->RemoveSubWindow(&window);
+                        return eKeyHandled;
+                    }
+                    break;
+                    
+                case KEY_ESCAPE: // Beware: pressing escape key has 1 to 2 second delay in case other chars are entered for escaped sequences
+                    window.GetParent()->RemoveSubWindow(&window);
+                    return eKeyHandled;
+                    
+                default:
+                {
+                    bool handled = false;
+                    for (size_t i=0; i<num_submenus; ++i)
+                    {
+                        Menu *menu = submenus[i].get();
+                        if (menu->GetKeyValue() == key)
+                        {
+                            handled = true;
+                            SetSelectedSubmenuIndex(i);
+                            if (menu->Action() == MenuActionResult::Quit)
+                                return eQuitApplication;
+                            return eKeyHandled;
+                        }
+                    }
+                }
+                    break;
+                    
+            }
+        }
+        else if (menu_type == Menu::Type::Separator)
+        {
+            
+        }
+        return result;
+    }
+
+
+    class Application
+    {
+    public:
+        Application (FILE *in, FILE *out) :
+            m_window_sp(),
+            m_screen (NULL),
+            m_in (in),
+            m_out (out)
+        {
+            
+        }
+        
+        ~Application ()
+        {
+            m_window_delegates.clear();
+            m_window_sp.reset();
+            if (m_screen)
+            {
+                ::delscreen(m_screen);
+                m_screen = NULL;
+            }
+        }
+        
+        void
+        Initialize ()
+        {
+            ::setlocale(LC_ALL, "");
+            ::setlocale(LC_CTYPE, "");
+#if 0
+            ::initscr();
+#else
+            m_screen = ::newterm(NULL, m_out, m_in);
+#endif
+            ::start_color();
+            ::curs_set(0);
+            ::noecho();
+            ::keypad(stdscr,TRUE);
+        }
+        
+        void
+        Terminate ()
+        {
+            ::endwin();
+        }
+        
+        void
+        Run (Debugger &debugger)
+        {
+            bool done = false;
+            int delay_in_tenths_of_a_second = 1;
+            
+            // Alas the threading model in curses is a bit lame so we need to
+            // resort to polling every 0.5 seconds. We could poll for stdin
+            // ourselves and then pass the keys down but then we need to
+            // translate all of the escape sequences ourselves. So we resort to
+            // polling for input because we need to receive async process events
+            // while in this loop.
+            
+            halfdelay(delay_in_tenths_of_a_second); // Poll using some number of tenths of seconds seconds when calling Window::GetChar()
+
+            ListenerSP listener_sp (new Listener ("lldb.IOHandler.curses.Application"));
+            ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
+            ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
+            ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
+            debugger.EnableForwardEvents (listener_sp);
+
+            bool update = true;
+            while (!done)
+            {
+                if (update)
+                {
+                    m_window_sp->Draw(false);
+                
+                    // All windows should be calling Window::DeferredRefresh() instead
+                    // of Window::Refresh() so we can do a single update and avoid
+                    // any screen blinking
+                    doupdate();
+                    update = false;
+                }
+                int ch = m_window_sp->GetChar();
+                
+                if (ch == -1)
+                {
+                    if (feof(m_in) || ferror(m_in))
+                    {
+                        done = true;
+                    }
+                    else
+                    {
+                        // Just a timeout from using halfdelay(), check for events
+                        EventSP event_sp;
+                        while (listener_sp->PeekAtNextEvent())
+                        {
+                            listener_sp->GetNextEvent(event_sp);
+                            
+                            if (event_sp)
+                            {
+                                Broadcaster *broadcaster = event_sp->GetBroadcaster();
+                                if (broadcaster)
+                                {
+                                    //uint32_t event_type = event_sp->GetType();
+                                    ConstString broadcaster_class (broadcaster->GetBroadcasterClass());
+                                    if (broadcaster_class == broadcaster_class_process)
+                                    {
+                                        update = true;
+                                        continue; // Don't get any key, just update our view
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    HandleCharResult key_result = m_window_sp->HandleChar(ch);
+                    switch (key_result)
+                    {
+                        case eKeyHandled:
+                            update = true;
+                            break;
+                        case eKeyNotHandled:
+                            break;
+                        case eQuitApplication:
+                            done = true;
+                            break;
+                    }
+                }
+            }
+            
+            debugger.CancelForwardEvents (listener_sp);
+
+        }
+        
+        WindowSP &
+        GetMainWindow ()
+        {
+            if (!m_window_sp)
+                m_window_sp.reset (new Window ("main", stdscr, false));
+            return m_window_sp;
+        }
+        
+        WindowDelegates &
+        GetWindowDelegates ()
+        {
+            return m_window_delegates;
+        }
+
+    protected:
+        WindowSP m_window_sp;
+        WindowDelegates m_window_delegates;
+        SCREEN *m_screen;
+        FILE *m_in;
+        FILE *m_out;
+    };
+    
+
+} // namespace curses
+
+
+using namespace curses;
+
+struct Row
+{
+    ValueObjectSP valobj;
+    Row *parent;
+    int row_idx;
+    int x;
+    int y;
+    bool might_have_children;
+    bool expanded;
+    bool calculated_children;
+    std::vector<Row> children;
+    
+    Row (const ValueObjectSP &v, Row *p) :
+    valobj (v),
+    parent (p),
+    row_idx(0),
+    x(1),
+    y(1),
+    might_have_children (v->MightHaveChildren()),
+    expanded (false),
+    calculated_children (false),
+    children()
+    {
+    }
+    
+    size_t
+    GetDepth () const
+    {
+        if (parent)
+            return 1 + parent->GetDepth();
+        return 0;
+    }
+    
+    void
+    Expand()
+    {
+        expanded = true;
+        if (!calculated_children)
+        {
+            calculated_children = true;
+            const size_t num_children = valobj->GetNumChildren();
+            for (size_t i=0; i<num_children; ++i)
+            {
+                children.push_back(Row (valobj->GetChildAtIndex(i, true), this));
+            }
+        }
+    }
+    
+    void
+    Unexpand ()
+    {
+        expanded = false;
+    }
+    
+    void
+    DrawTree (Window &window)
+    {
+        if (parent)
+            parent->DrawTreeForChild (window, this, 0);
+        
+        if (might_have_children)
+        {
+            // It we can get UTF8 characters to work we should try to use the "symbol"
+            // UTF8 string below
+//            const char *symbol = "";
+//            if (row.expanded)
+//                symbol = "\xe2\x96\xbd ";
+//            else
+//                symbol = "\xe2\x96\xb7 ";
+//            window.PutCString (symbol);
+            
+            // The ACS_DARROW and ACS_RARROW don't look very nice they are just a
+            // 'v' or '>' character...
+//            if (expanded)
+//                window.PutChar (ACS_DARROW);
+//            else
+//                window.PutChar (ACS_RARROW);
+            // Since we can't find any good looking right arrow/down arrow
+            // symbols, just use a diamond...
+            window.PutChar (ACS_DIAMOND);
+            window.PutChar (ACS_HLINE);
+        }
+    }
+
+    void
+    DrawTreeForChild (Window &window, Row *child, uint32_t reverse_depth)
+    {
+        if (parent)
+            parent->DrawTreeForChild (window, this, reverse_depth + 1);
+        
+        if (&children.back() == child)
+        {
+            // Last child
+            if (reverse_depth == 0)
+            {
+                window.PutChar (ACS_LLCORNER);
+                window.PutChar (ACS_HLINE);
+            }
+            else
+            {
+                window.PutChar (' ');
+                window.PutChar (' ');
+            }
+        }
+        else
+        {
+            if (reverse_depth == 0)
+            {
+                window.PutChar (ACS_LTEE);
+                window.PutChar (ACS_HLINE);
+            }
+            else
+            {
+                window.PutChar (ACS_VLINE);
+                window.PutChar (' ');
+            }
+        }
+    }
+};
+
+struct DisplayOptions
+{
+    bool show_types;
+};
+
+
+class ValueObjectListDelegate : public WindowDelegate
+{
+public:
+    ValueObjectListDelegate () :
+        m_valobj_list (),
+        m_rows (),
+        m_selected_row (NULL),
+        m_selected_row_idx (0),
+        m_first_visible_row (0),
+        m_num_rows (0),
+        m_max_x (0),
+        m_max_y (0)
+    {
+    }
+    
+    ValueObjectListDelegate (ValueObjectList &valobj_list) :
+        m_valobj_list (valobj_list),
+        m_rows (),
+        m_selected_row (NULL),
+        m_selected_row_idx (0),
+        m_first_visible_row (0),
+        m_num_rows (0),
+        m_max_x (0),
+        m_max_y (0)
+    {
+        SetValues (valobj_list);
+    }
+    
+    virtual
+    ~ValueObjectListDelegate()
+    {
+    }
+
+    void
+    SetValues (ValueObjectList &valobj_list)
+    {
+        m_selected_row = NULL;
+        m_selected_row_idx = 0;
+        m_first_visible_row = 0;
+        m_num_rows = 0;
+        m_rows.clear();
+        m_valobj_list = valobj_list;
+        const size_t num_values = m_valobj_list.GetSize();
+        for (size_t i=0; i<num_values; ++i)
+            m_rows.push_back(Row(m_valobj_list.GetValueObjectAtIndex(i), NULL));
+    }
+    
+    virtual bool
+    WindowDelegateDraw (Window &window, bool force)
+    {
+        m_num_rows = 0;
+        m_min_x = 2;
+        m_min_y = 1;
+        m_max_x = window.GetMaxX();
+        m_max_y = window.GetMaxY() - 1;
+        
+        window.Erase();
+        window.DrawTitleBox ("Variables");
+        
+        const int num_visible_rows = NumVisibleRows();
+        const int num_rows = CalculateTotalNumberRows (m_rows);
+        
+        // If we unexpanded while having something selected our
+        // total number of rows is less than the num visible rows,
+        // then make sure we show all the rows by setting the first
+        // visible row accordingly.
+        if (m_first_visible_row > 0 && num_rows < num_visible_rows)
+            m_first_visible_row = 0;
+        
+        // Make sure the selected row is always visible
+        if (m_selected_row_idx < m_first_visible_row)
+            m_first_visible_row = m_selected_row_idx;
+        else if (m_first_visible_row + m_max_y < m_selected_row_idx)
+            m_first_visible_row = m_selected_row_idx - m_max_y;
+        
+        DisplayRows (window, m_rows, g_options);
+        
+        window.DeferredRefresh();
+        
+        // Get the selected row
+        m_selected_row = GetRowForRowIndex (m_selected_row_idx);
+        // Keep the cursor on the selected row so the highlight and the cursor
+        // are always on the same line
+        if (m_selected_row)
+            window.Move (m_selected_row->x,
+                         m_selected_row->y);
+        
+        return true; // Drawing handled
+    }
+    
+    virtual HandleCharResult
+    WindowDelegateHandleChar (Window &window, int c)
+    {
+        switch(c)
+        {
+            case 'x':
+            case 'X':
+            case 'o':
+            case 's':
+            case 'u':
+            case 'd':
+            case 'D':
+            case 'i':
+            case 'A':
+            case 'p':
+            case 'c':
+            case 'b':
+            case 'B':
+            case 'f':
+                // Change the format for the currently selected item
+                if (m_selected_row)
+                    m_selected_row->valobj->SetFormat (FormatForChar (c));
+                return eKeyHandled;
+                
+            case 't':
+                // Toggle showing type names
+                g_options.show_types = !g_options.show_types;
+                return eKeyHandled;
+                
+            case ',':
+            case KEY_PPAGE:
+                // Page up key
+                if (m_first_visible_row > 0)
+                {
+                    if (m_first_visible_row > m_max_y)
+                        m_first_visible_row -= m_max_y;
+                    else
+                        m_first_visible_row = 0;
+                    m_selected_row_idx = m_first_visible_row;
+                }
+                return eKeyHandled;
+                
+            case '.':
+            case KEY_NPAGE:
+                // Page down key
+                if (m_num_rows > m_max_y)
+                {
+                    if (m_first_visible_row + m_max_y < m_num_rows)
+                    {
+                        m_first_visible_row += m_max_y;
+                        m_selected_row_idx = m_first_visible_row;
+                    }
+                }
+                return eKeyHandled;
+                
+            case KEY_UP:
+                if (m_selected_row_idx > 0)
+                    --m_selected_row_idx;
+                return eKeyHandled;
+            case KEY_DOWN:
+                if (m_selected_row_idx + 1 < m_num_rows)
+                    ++m_selected_row_idx;
+                return eKeyHandled;
+                
+            case KEY_RIGHT:
+                if (m_selected_row)
+                {
+                    if (!m_selected_row->expanded)
+                        m_selected_row->Expand();
+                }
+                return eKeyHandled;
+                
+            case KEY_LEFT:
+                if (m_selected_row)
+                {
+                    if (m_selected_row->expanded)
+                        m_selected_row->Unexpand();
+                    else if (m_selected_row->parent)
+                        m_selected_row_idx = m_selected_row->parent->row_idx;
+                }
+                return eKeyHandled;
+                
+            case ' ':
+                // Toggle expansion state when SPACE is pressed
+                if (m_selected_row)
+                {
+                    if (m_selected_row->expanded)
+                        m_selected_row->Unexpand();
+                    else
+                        m_selected_row->Expand();
+                }
+                return eKeyHandled;
+                
+            default:
+                break;
+        }
+        return eKeyNotHandled;
+    }
+    
+protected:
+    ValueObjectList m_valobj_list;
+    std::vector<Row> m_rows;
+    Row *m_selected_row;
+    uint32_t m_selected_row_idx;
+    uint32_t m_first_visible_row;
+    uint32_t m_num_rows;
+    int m_min_x;
+    int m_min_y;
+    int m_max_x;
+    int m_max_y;
+
+    static Format
+    FormatForChar (int c)
+    {
+        switch (c)
+        {
+            case 'x': return eFormatHex;
+            case 'X': return eFormatHexUppercase;
+            case 'o': return eFormatOctal;
+            case 's': return eFormatCString;
+            case 'u': return eFormatUnsigned;
+            case 'd': return eFormatDecimal;
+            case 'D': return eFormatDefault;
+            case 'i': return eFormatInstruction;
+            case 'A': return eFormatAddressInfo;
+            case 'p': return eFormatPointer;
+            case 'c': return eFormatChar;
+            case 'b': return eFormatBinary;
+            case 'B': return eFormatBytesWithASCII;
+            case 'f': return eFormatFloat;
+        }
+        return eFormatDefault;
+    }
+    
+    void
+    DisplayRowObject (Window &window,
+                      Row &row,
+                      DisplayOptions &options,
+                      bool highlight,
+                      bool last_child)
+    {
+        ValueObject *valobj = row.valobj.get();
+        
+        const char *type_name = options.show_types ? valobj->GetTypeName().GetCString() : NULL;
+        const char *name = valobj->GetName().GetCString();
+        const char *value = valobj->GetValueAsCString ();
+        const char *summary = valobj->GetSummaryAsCString ();
+        
+        window.Move (row.x, row.y);
+        
+        row.DrawTree (window);
+        
+        if (highlight)
+            window.AttributeOn(A_REVERSE);
+        
+        if (type_name && type_name[0])
+            window.Printf ("(%s) ", type_name);
+        
+        if (name && name[0])
+            window.PutCString(name);
+        
+        attr_t changd_attr = 0;
+        if (valobj->GetValueDidChange())
+            changd_attr = COLOR_PAIR(5) | A_BOLD;
+        
+        if (value && value[0])
+        {
+            window.PutCString(" = ");
+            if (changd_attr)
+                window.AttributeOn(changd_attr);
+            window.PutCString (value);
+            if (changd_attr)
+                window.AttributeOff(changd_attr);
+        }
+        
+        if (summary && summary[0])
+        {
+            window.PutChar(' ');
+            if (changd_attr)
+                window.AttributeOn(changd_attr);
+            window.PutCString(summary);
+            if (changd_attr)
+                window.AttributeOff(changd_attr);
+        }
+        
+        if (highlight)
+            window.AttributeOff (A_REVERSE);
+    }
+    void
+    DisplayRows (Window &window,
+                 std::vector<Row> &rows,
+                 DisplayOptions &options)
+    {
+        // >   0x25B7
+        // \/  0x25BD
+        
+        bool window_is_active = window.IsActive();
+        for (auto &row : rows)
+        {
+            const bool last_child = row.parent && &rows[rows.size()-1] == &row;
+            // Save the row index in each Row structure
+            row.row_idx = m_num_rows;
+            if ((m_num_rows >= m_first_visible_row) &&
+                ((m_num_rows - m_first_visible_row) < NumVisibleRows()))
+            {
+                row.x = m_min_x;
+                row.y = m_num_rows - m_first_visible_row + 1;
+                DisplayRowObject (window,
+                                  row,
+                                  options,
+                                  window_is_active && m_num_rows == m_selected_row_idx,
+                                  last_child);
+            }
+            else
+            {
+                row.x = 0;
+                row.y = 0;
+            }
+            ++m_num_rows;
+            
+            if (row.expanded && !row.children.empty())
+            {
+                DisplayRows (window,
+                             row.children,
+                             options);
+            }
+        }
+    }
+    
+    int
+    CalculateTotalNumberRows (const std::vector<Row> &rows)
+    {
+        int row_count = 0;
+        for (const auto &row : rows)
+        {
+            ++row_count;
+            if (row.expanded)
+                row_count += CalculateTotalNumberRows(row.children);
+        }
+        return row_count;
+    }
+    static Row *
+    GetRowForRowIndexImpl (std::vector<Row> &rows, size_t &row_index)
+    {
+        for (auto &row : rows)
+        {
+            if (row_index == 0)
+                return &row;
+            else
+            {
+                --row_index;
+                if (row.expanded && !row.children.empty())
+                {
+                    Row *result = GetRowForRowIndexImpl (row.children, row_index);
+                    if (result)
+                        return result;
+                }
+            }
+        }
+        return NULL;
+    }
+    
+    Row *
+    GetRowForRowIndex (size_t row_index)
+    {
+        return GetRowForRowIndexImpl (m_rows, row_index);
+    }
+    
+    int
+    NumVisibleRows () const
+    {
+        return m_max_y - m_min_y;
+    }
+
+    static DisplayOptions g_options;
+};
+
+class FrameVariablesWindowDelegate : public ValueObjectListDelegate
+{
+public:
+    FrameVariablesWindowDelegate (Debugger &debugger) :
+        ValueObjectListDelegate (),
+        m_debugger (debugger),
+        m_frame_block (NULL)
+    {
+    }
+    
+    virtual
+    ~FrameVariablesWindowDelegate()
+    {
+    }
+    
+    virtual bool
+    WindowDelegateDraw (Window &window, bool force)
+    {
+        ExecutionContext exe_ctx (m_debugger.GetCommandInterpreter().GetExecutionContext());
+        Process *process = exe_ctx.GetProcessPtr();
+        Block *frame_block = NULL;
+        StackFrame *frame = NULL;
+        
+        if (process)
+        {
+            StateType state = process->GetState();
+            if (StateIsStoppedState(state, true))
+            {
+                frame = exe_ctx.GetFramePtr();
+                if (frame)
+                    frame_block = frame->GetFrameBlock ();
+            }
+            else if (StateIsRunningState(state))
+            {
+                return true; // Don't do any updating when we are running
+            }
+        }
+        
+        ValueObjectList local_values;
+        if (frame_block)
+        {
+            // Only update the variables if they have changed
+            if (m_frame_block != frame_block)
+            {
+                m_frame_block = frame_block;
+
+                VariableList *locals = frame->GetVariableList(true);
+                if (locals)
+                {
+                    const DynamicValueType use_dynamic = eDynamicDontRunTarget;
+                    const size_t num_locals = locals->GetSize();
+                    for (size_t i=0; i<num_locals; ++i)
+                        local_values.Append(frame->GetValueObjectForFrameVariable (locals->GetVariableAtIndex(i), use_dynamic));
+                    // Update the values
+                    SetValues(local_values);
+                }
+            }
+        }
+        else
+        {
+            m_frame_block = NULL;
+            // Update the values with an empty list if there is no frame
+            SetValues(local_values);
+        }
+        
+        return ValueObjectListDelegate::WindowDelegateDraw (window, force);
+
+    }
+
+protected:
+    Debugger &m_debugger;
+    Block *m_frame_block;
+};
+
+class ApplicationDelegate :
+    public WindowDelegate,
+    public MenuDelegate
+{
+public:
+    ApplicationDelegate (Debugger &debugger) :
+        WindowDelegate (),
+        MenuDelegate (),
+        m_debugger (debugger)
+    {
+    }
+    
+    virtual
+    ~ApplicationDelegate ()
+    {
+    }
+    virtual bool
+    WindowDelegateDraw (Window &window, bool force)
+    {
+        return false; // Drawing not handled, let standard window drawing happen
+    }
+
+    virtual HandleCharResult
+    WindowDelegateHandleChar (Window &window, int key)
+    {
+        if (key == '\t')
+        {
+            window.SelectNextWindowAsActive();
+            return eKeyHandled;
+        }
+        return eKeyNotHandled;
+    }
+    
+    virtual MenuActionResult
+    MenuDelegateAction (Menu &menu)
+    {
+        if (menu.GetName().compare("Process") == 0)
+        {
+            // Populate the menu with all of the threads
+            Menus &submenus = menu.GetSubmenus();
+            ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
+            Process *process = exe_ctx.GetProcessPtr();
+            if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true))
+            {
+                if (submenus.size() == 7)
+                    menu.AddSubmenu (MenuSP (new Menu(Menu::Type::Separator)));
+                else if (submenus.size() > 8)
+                    submenus.erase (submenus.begin() + 8, submenus.end());
+                
+                ThreadList &threads = process->GetThreadList();
+                Mutex::Locker locker (threads.GetMutex());
+                size_t num_threads = threads.GetSize();
+                for (size_t i=0; i<num_threads; ++i)
+                {
+                    ThreadSP thread_sp = threads.GetThreadAtIndex(i);
+                    char menu_char = '\0';
+                    if (i < 9)
+                        menu_char = '1' + i;
+                    StreamString thread_menu_title;
+                    thread_menu_title.Printf("Thread %u", thread_sp->GetIndexID());
+                    const char *thread_name = thread_sp->GetName();
+                    if (thread_name && thread_name[0])
+                        thread_menu_title.Printf (" %s", thread_name);
+                    else
+                    {
+                        const char *queue_name = thread_sp->GetQueueName();
+                        if (queue_name && queue_name[0])
+                            thread_menu_title.Printf (" %s", queue_name);
+                    }
+                    menu.AddSubmenu (MenuSP (new Menu(thread_menu_title.GetString().c_str(), NULL, menu_char)));
+                }
+            }
+            else if (submenus.size() > 7)
+            {
+                // Remove the separator and any other thread submenu items
+                // that were previously added
+                submenus.erase (submenus.begin() + 7, submenus.end());
+            }
+            // Since we are adding and removing items we need to recalculate the name lengths
+            menu.RecalculateNameLengths();
+        }
+        return MenuActionResult::Success;
+    }
+protected:
+    Debugger &m_debugger;
+};
+
+
+class StatusBarWindowDelegate : public WindowDelegate
+{
+public:
+    StatusBarWindowDelegate (Debugger &debugger) :
+        m_debugger (debugger)
+    {
+    }
+    
+    virtual
+    ~StatusBarWindowDelegate ()
+    {
+    }
+    virtual bool
+    WindowDelegateDraw (Window &window, bool force)
+    {
+        ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
+        Process *process = exe_ctx.GetProcessPtr();
+        Thread *thread = exe_ctx.GetThreadPtr();
+        StackFrame *frame = exe_ctx.GetFramePtr();
+        window.Erase();
+        window.SetBackground(2);
+        window.Move (0, 0);
+        if (process)
+        {
+            const StateType state = process->GetState();
+            window.Printf ("Process: %5" PRIu64 " %10s", process->GetID(), StateAsCString(state));
+
+            if (StateIsStoppedState(state, true))
+            {
+                window.Move (40, 0);
+                if (thread)
+                    window.Printf ("Thread: 0x%4.4" PRIx64, thread->GetID());
+
+                window.Move (60, 0);
+                if (frame)
+                    window.Printf ("Frame: %3u  PC = 0x%16.16" PRIx64, frame->GetFrameIndex(), frame->GetFrameCodeAddress().GetOpcodeLoadAddress (exe_ctx.GetTargetPtr()));
+            }
+            else if (state == eStateExited)
+            {
+                const char *exit_desc = process->GetExitDescription();
+                const int exit_status = process->GetExitStatus();
+                if (exit_desc && exit_desc[0])
+                    window.Printf (" with status = %i (%s)", exit_status, exit_desc);
+                else
+                    window.Printf (" with status = %i", exit_status);
+            }
+        }
+        window.DeferredRefresh();
+        return true;
+    }
+
+protected:
+    Debugger &m_debugger;
+};
+
+class SourceFileWindowDelegate : public WindowDelegate
+{
+public:
+    SourceFileWindowDelegate (Debugger &debugger) :
+        WindowDelegate (),
+        m_debugger (debugger),
+        m_sc (),
+        m_file_sp (),
+        m_line_width (4),
+        m_selected_line (0),
+        m_pc_line (0),
+        m_stop_id (0),
+        m_first_visible_line (0),
+        m_min_x (0),
+        m_min_y (0),
+        m_max_x (0),
+        m_max_y (0)
+    {
+    }
+    
+    
+    virtual
+    ~SourceFileWindowDelegate()
+    {
+    }
+    
+    void
+    Update (const SymbolContext &sc)
+    {
+        m_sc = sc;
+    }
+    
+    uint32_t
+    NumVisibleLines () const
+    {
+        return m_max_y - m_min_y;
+    }
+    
+    virtual bool
+    WindowDelegateDraw (Window &window, bool force)
+    {
+        window.Erase();
+        window.DrawTitleBox ("Sources");
+        m_min_x = window.GetMinX()+1;
+        m_min_y = window.GetMinY()+1;
+        m_max_x = window.GetMaxX();
+        m_max_y = window.GetMaxY();
+        const uint32_t num_visible_lines = NumVisibleLines();
+        
+        ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
+        Process *process = exe_ctx.GetProcessPtr();
+        Thread *thread = NULL;
+        StackFrameSP frame_sp;
+        const bool process_alive = process->IsAlive();
+        if (process_alive)
+        {
+            thread = exe_ctx.GetThreadPtr();
+            if (thread)
+                frame_sp = thread->GetSelectedFrame();
+        }
+        const uint32_t stop_id = process ? process->GetStopID() : 0;
+        const bool stop_id_changed = stop_id != m_stop_id;
+        m_stop_id = stop_id;
+        if (frame_sp)
+        {
+            m_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
+        }
+        else
+        {
+            m_sc.Clear(true);
+        }
+        
+        if (process_alive)
+        {
+            if (m_sc.line_entry.IsValid())
+            {
+                m_pc_line = m_sc.line_entry.line;
+                if (m_pc_line != UINT32_MAX)
+                    --m_pc_line; // Convert to zero based line number...
+                // Update the selected line if the stop ID changed...
+                if (stop_id_changed)
+                    m_selected_line = m_pc_line;
+
+                if (m_file_sp && m_file_sp->FileSpecMatches(m_sc.line_entry.file))
+                {
+                    // Same file, noting to do, we should either have the
+                    // lines or not (source file missing)
+                    if (m_selected_line >= m_first_visible_line)
+                    {
+                        if (m_selected_line >= m_first_visible_line + num_visible_lines)
+                            m_first_visible_line = m_selected_line - 10;
+                    }
+                    else
+                    {
+                        if (m_selected_line > 10)
+                            m_first_visible_line = m_selected_line - 10;
+                        else
+                            m_first_visible_line = 0;
+                    }
+                }
+                else
+                {
+                    // File changed, set selected line to the line with the PC
+                    m_selected_line = m_pc_line;
+                    m_file_sp = m_debugger.GetSourceManager().GetFile(m_sc.line_entry.file);
+                    if (m_file_sp)
+                    {
+                        const size_t num_lines = m_file_sp->GetNumLines();
+                        int m_line_width = 1;
+                        for (size_t n = num_lines; n >= 10; n = n / 10)
+                            ++m_line_width;
+                        
+                        snprintf (m_line_format, sizeof(m_line_format), " %%%iu ", m_line_width);
+                        if (num_lines < num_visible_lines || m_selected_line < num_visible_lines)
+                            m_first_visible_line = 0;
+                        else
+                            m_first_visible_line = m_selected_line - 10;
+                    }
+                }
+            }
+        }
+        else
+        {
+            m_pc_line = UINT32_MAX;
+        }
+        
+        if (m_file_sp)
+        {
+            BreakpointLines bp_lines;
+            Target *target = exe_ctx.GetTargetPtr();
+            if (target)
+            {
+                BreakpointList &bp_list = target->GetBreakpointList();
+                const size_t num_bps = bp_list.GetSize();
+                for (size_t bp_idx=0; bp_idx<num_bps; ++bp_idx)
+                {
+                    BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
+                    const size_t num_bps_locs = bp_sp->GetNumLocations();
+                    for (size_t bp_loc_idx=0; bp_loc_idx<num_bps_locs; ++bp_loc_idx)
+                    {
+                        BreakpointLocationSP bp_loc_sp = bp_sp->GetLocationAtIndex(bp_loc_idx);
+                        LineEntry bp_loc_line_entry;
+                        if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry (bp_loc_line_entry))
+                        {
+                            if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file)
+                            {
+                                bp_lines.insert(bp_loc_line_entry.line);
+                            }
+                        }
+                    }
+                }
+            }
+            
+        
+            const attr_t selected_highlight_attr = A_REVERSE;
+            const attr_t pc_highlight_attr = COLOR_PAIR(1);
+
+            const size_t num_lines = m_file_sp->GetNumLines();
+            for (int i=0; i<num_visible_lines; ++i)
+            {
+                const uint32_t curr_line = m_first_visible_line + i;
+                if (curr_line < num_lines)
+                {
+                    const int line_y = 1+i;
+                    window.Move(1, line_y);
+                    const bool is_pc_line = curr_line == m_pc_line;
+                    const bool line_is_selected = m_selected_line == curr_line;
+                    // Highlight the line as the PC line first, then if the selected line
+                    // isn't the same as the PC line, highlight it differently
+                    attr_t highlight_attr = 0;
+                    attr_t bp_attr = 0;
+                    if (is_pc_line)
+                        highlight_attr = pc_highlight_attr;
+                    else if (line_is_selected)
+                        highlight_attr = selected_highlight_attr;
+                    
+                    if (bp_lines.find(curr_line+1) != bp_lines.end())
+                        bp_attr = COLOR_PAIR(2);
+
+                    if (bp_attr)
+                        window.AttributeOn(bp_attr);
+                    
+                    window.Printf (m_line_format, curr_line + 1);
+
+                    if (bp_attr)
+                        window.AttributeOff(bp_attr);
+
+                    window.PutChar(ACS_VLINE);
+                    // Mark the line with the PC with a diamond
+                    if (is_pc_line)
+                        window.PutChar(ACS_DIAMOND);
+                    else
+                        window.PutChar(' ');
+                    
+                    if (highlight_attr)
+                        window.AttributeOn(highlight_attr);
+                    const uint32_t line_len = m_file_sp->GetLineLength(curr_line + 1, false);
+                    if (line_len > 0)
+                        window.PutCString(m_file_sp->PeekLineData(curr_line + 1), line_len);
+
+                    if (is_pc_line && frame_sp && frame_sp->GetConcreteFrameIndex() == 0)
+                    {
+                        StopInfoSP stop_info_sp;
+                        if (thread)
+                            stop_info_sp = thread->GetStopInfo();
+                        if (stop_info_sp)
+                        {
+                            const char *stop_description = stop_info_sp->GetDescription();
+                            if (stop_description && stop_description[0])
+                            {
+                                size_t stop_description_len = strlen(stop_description);
+                                int desc_x = window.GetWidth() - stop_description_len - 16;
+                                window.Printf ("%*s", desc_x - window.GetX(), "");
+                                //window.Move(window.GetWidth() - stop_description_len - 15, line_y);
+                                window.Printf ("<<< Thread %u: %s ", thread->GetIndexID(), stop_description);
+                            }
+                        }
+                        else
+                        {
+                            window.Printf ("%*s", window.GetWidth() - window.GetX() - 1, "");
+                        }
+                    }
+                    if (highlight_attr)
+                        window.AttributeOff(highlight_attr);
+
+                }
+                else
+                {
+                    break;
+                }
+            }
+        }
+        window.DeferredRefresh();
+        return true; // Drawing handled
+    }
+    
+    virtual HandleCharResult
+    WindowDelegateHandleChar (Window &window, int c)
+    {
+        const uint32_t num_visible_lines = NumVisibleLines();
+        const size_t num_lines = m_file_sp ? m_file_sp->GetNumLines() : 0;
+
+        switch (c)
+        {
+            case ',':
+            case KEY_PPAGE:
+                // Page up key
+                if (m_first_visible_line > num_visible_lines)
+                    m_first_visible_line -= num_visible_lines;
+                else
+                    m_first_visible_line = 0;
+                m_selected_line = m_first_visible_line;
+                return eKeyHandled;
+                
+            case '.':
+            case KEY_NPAGE:
+                // Page down key
+                {
+                    if (m_first_visible_line + num_visible_lines < num_lines)
+                        m_first_visible_line += num_visible_lines;
+                    else if (num_lines < num_visible_lines)
+                        m_first_visible_line = 0;
+                    else
+                        m_first_visible_line = num_lines - num_visible_lines;
+                    m_selected_line = m_first_visible_line;
+                }
+                return eKeyHandled;
+                
+            case KEY_UP:
+                if (m_selected_line > 0)
+                {
+                    m_selected_line--;
+                    if (m_first_visible_line > m_selected_line)
+                        m_first_visible_line = m_selected_line;
+                }
+                return eKeyHandled;
+
+            case KEY_DOWN:
+                if (m_selected_line + 1 < num_lines)
+                {
+                    m_selected_line++;
+                    if (m_first_visible_line + num_visible_lines < m_selected_line)
+                        m_first_visible_line++;
+                }
+                return eKeyHandled;
+                
+            case '\r':
+            case '\n':
+            case KEY_ENTER:
+                // Set a breakpoint and run to the line using a one shot breakpoint
+                if (m_file_sp && m_selected_line > 0)
+                {
+                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
+                    if (exe_ctx.HasProcessScope() && exe_ctx.GetProcessRef().IsAlive())
+                    {
+                        BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint (NULL,                      // Don't limit the breakpoint to certain modules
+                                                                                      m_file_sp->GetFileSpec(),  // Source file
+                                                                                      m_selected_line + 1,       // Source line number (m_selected_line is zero based)
+                                                                                      eLazyBoolCalculate,        // Check inlines using global setting
+                                                                                      eLazyBoolCalculate,        // Skip prologue using global setting,
+                                                                                      false,                     // internal
+                                                                                      false);                    // request_hardware
+                        // Make breakpoint one shot
+                        bp_sp->GetOptions()->SetOneShot(true);
+                        exe_ctx.GetProcessRef().Resume();
+                    }
+                }
+                return eKeyHandled;
+
+            case 'b':   // 'b' == toggle breakpoint on currently selected line
+                if (m_file_sp && m_selected_line > 0)
+                {
+                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
+                    if (exe_ctx.HasTargetScope())
+                    {
+                        BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint (NULL,                      // Don't limit the breakpoint to certain modules
+                                                                                      m_file_sp->GetFileSpec(),  // Source file
+                                                                                      m_selected_line + 1,       // Source line number (m_selected_line is zero based)
+                                                                                      eLazyBoolCalculate,        // Check inlines using global setting
+                                                                                      eLazyBoolCalculate,        // Skip prologue using global setting,
+                                                                                      false,                     // internal
+                                                                                      false);                    // request_hardware
+                    }
+                }
+                return eKeyHandled;
+
+            case 'd':   // 'd' == detach and let run
+            case 'D':   // 'D' == detach and keep stopped
+                {
+                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
+                    if (exe_ctx.HasProcessScope())
+                        exe_ctx.GetProcessRef().Detach(c == 'D');
+                }
+                return eKeyHandled;;
+
+            case 'k':
+                // 'k' == kill
+                {
+                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
+                    if (exe_ctx.HasProcessScope())
+                        exe_ctx.GetProcessRef().Destroy();
+                }
+                return eKeyHandled;
+
+            case 'c':
+                // 'c' == continue
+                {
+                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
+                    if (exe_ctx.HasProcessScope())
+                        exe_ctx.GetProcessRef().Resume();
+                }
+                return eKeyHandled;
+                
+            case 'o':
+                // 'o' == step out
+                {
+                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
+                    if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true))
+                    {
+                        Process *process = exe_ctx.GetProcessPtr();
+                        Thread *thread = exe_ctx.GetThreadPtr();
+                        bool abort_other_plans = false;
+                        bool stop_other_threads = false;
+                        ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut (abort_other_plans,
+                                                                                    NULL,
+                                                                                    false,
+                                                                                    stop_other_threads,
+                                                                                    eVoteYes,
+                                                                                    eVoteNoOpinion,
+                                                                                    0));
+                        
+                        new_plan_sp->SetIsMasterPlan(true);
+                        new_plan_sp->SetOkayToDiscard(false);
+                        
+                        // Why do we need to set the current thread by ID here???
+                        process->GetThreadList().SetSelectedThreadByID (thread->GetID());
+                        process->Resume();
+                    }
+                }
+                return eKeyHandled;
+            case 'n':
+                // 'n' == step over
+                {
+                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
+                    if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true))
+                    {
+                        Process *process = exe_ctx.GetProcessPtr();
+                        Thread *thread = exe_ctx.GetThreadPtr();
+                        StackFrameSP frame_sp = thread->GetStackFrameAtIndex (0);
+                        if (frame_sp)
+                        {
+                            bool abort_other_plans = false;
+                            lldb::RunMode stop_other_threads = eOnlyThisThread;
+                            ThreadPlanSP new_plan_sp;
+                            
+                            if (frame_sp->HasDebugInformation ())
+                            {
+                                SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
+                                new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
+                                                                                       sc.line_entry.range,
+                                                                                       sc,
+                                                                                       stop_other_threads);
+                            }
+                            else
+                            {
+                                new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
+                                                                                               abort_other_plans, 
+                                                                                               stop_other_threads);
+                            }
+                            new_plan_sp->SetIsMasterPlan(true);
+                            new_plan_sp->SetOkayToDiscard(false);
+                            
+                            // Why do we need to set the current thread by ID here???
+                            process->GetThreadList().SetSelectedThreadByID (thread->GetID());
+                            process->Resume();
+                        }
+                    }
+                }
+                return eKeyHandled;
+            case 's':
+                // 's' == step into
+                {
+                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
+                    if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true))
+                    {
+                        Process *process = exe_ctx.GetProcessPtr();
+                        Thread *thread = exe_ctx.GetThreadPtr();
+                        StackFrameSP frame_sp = thread->GetStackFrameAtIndex (0);
+                        bool abort_other_plans = false;
+                        lldb::RunMode stop_other_threads = eOnlyThisThread;
+                        ThreadPlanSP new_plan_sp;
+                        
+                        if (frame_sp && frame_sp->HasDebugInformation ())
+                        {
+                            bool avoid_code_without_debug_info = true;
+                            SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
+                            new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
+                                                                                 sc.line_entry.range,
+                                                                                 sc,
+                                                                                 NULL,
+                                                                                 stop_other_threads,
+                                                                                 avoid_code_without_debug_info);
+                        }
+                        else
+                        {
+                            new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false,
+                                                                                           abort_other_plans, 
+                                                                                           stop_other_threads);
+                        }
+                        
+                        new_plan_sp->SetIsMasterPlan(true);
+                        new_plan_sp->SetOkayToDiscard(false);
+                        
+                        // Why do we need to set the current thread by ID here???
+                        process->GetThreadList().SetSelectedThreadByID (thread->GetID());
+                        process->Resume();
+                    }
+                }
+                return eKeyHandled;
+            default:
+                break;
+        }
+        return eKeyNotHandled;
+    }
+    
+protected:
+    typedef std::set<uint32_t> BreakpointLines;
+
+    Debugger &m_debugger;
+    SymbolContext m_sc;
+    SourceManager::FileSP m_file_sp;
+    char m_line_format[8];
+    int m_line_width;
+    uint32_t m_selected_line;       // The selected line
+    uint32_t m_pc_line;             // The line with the PC
+    uint32_t m_stop_id;
+    int m_first_visible_line;
+    int m_min_x;
+    int m_min_y;
+    int m_max_x;
+    int m_max_y;
+
+};
+
+DisplayOptions ValueObjectListDelegate::g_options = { true };
+
+IOHandlerCursesGUI::IOHandlerCursesGUI (Debugger &debugger) :
+    IOHandler (debugger)
+{
+}
+
+void
+IOHandlerCursesGUI::Activate ()
+{
+    IOHandler::Activate();
+    if (!m_app_ap)
+    {
+        m_app_ap.reset (new Application (GetInputFILE(), GetOutputFILE()));
+        
+        
+        // This is both a window and a menu delegate
+        std::shared_ptr<ApplicationDelegate> app_delegate_sp(new ApplicationDelegate(m_debugger));
+        
+        
+        MenuSP lldb_menu_sp(new Menu("LLDB" , "F1", KEY_F(1)));
+        MenuSP exit_menuitem_sp(new Menu("Exit", NULL, 'x'));
+        exit_menuitem_sp->SetCannedResult(MenuActionResult::Quit);
+        lldb_menu_sp->AddSubmenu (MenuSP (new Menu("About LLDB", NULL, 'a')));
+        lldb_menu_sp->AddSubmenu (MenuSP (new Menu(Menu::Type::Separator)));
+        lldb_menu_sp->AddSubmenu (exit_menuitem_sp);
+        
+        MenuSP target_menu_sp(new Menu("Target" ,"F2", KEY_F(2)));
+        target_menu_sp->AddSubmenu (MenuSP (new Menu("Create", NULL, 'c')));
+        target_menu_sp->AddSubmenu (MenuSP (new Menu("Delete", NULL, 'd')));
+        
+        MenuSP process_menu_sp(new Menu("Process", "F3", KEY_F(3)));
+        process_menu_sp->SetDelegate(std::static_pointer_cast<MenuDelegate>(app_delegate_sp));
+        process_menu_sp->AddSubmenu (MenuSP (new Menu("Attach"  , NULL, 'a')));
+        process_menu_sp->AddSubmenu (MenuSP (new Menu("Detach"  , NULL, 'd')));
+        process_menu_sp->AddSubmenu (MenuSP (new Menu("Launch"  , NULL, 'l')));
+        process_menu_sp->AddSubmenu (MenuSP (new Menu(Menu::Type::Separator)));
+        process_menu_sp->AddSubmenu (MenuSP (new Menu("Continue", NULL, 'c')));
+        process_menu_sp->AddSubmenu (MenuSP (new Menu("Halt"    , NULL, 'h')));
+        process_menu_sp->AddSubmenu (MenuSP (new Menu("Kill"    , NULL, 'k')));
+        
+        MenuSP thread_menu_sp(new Menu("Thread", "F4", KEY_F(4)));
+        thread_menu_sp->AddSubmenu (MenuSP (new Menu("Step In"  , NULL, 'i')));
+        thread_menu_sp->AddSubmenu (MenuSP (new Menu("Step Over", NULL, 'v')));
+        thread_menu_sp->AddSubmenu (MenuSP (new Menu("Step Out" , NULL, 'o')));
+        
+        MenuSP view_menu_sp(new Menu("View", "F5", KEY_F(5)));
+        view_menu_sp->AddSubmenu (MenuSP (new Menu("Backtrace", NULL, 'b')));
+        view_menu_sp->AddSubmenu (MenuSP (new Menu("Registers", NULL, 'r')));
+        view_menu_sp->AddSubmenu (MenuSP (new Menu("Source"   , NULL, 's')));
+        view_menu_sp->AddSubmenu (MenuSP (new Menu("Threads"  , NULL, 't')));
+        view_menu_sp->AddSubmenu (MenuSP (new Menu("Variables", NULL, 'v')));
+        
+        MenuSP help_menu_sp(new Menu("Help", "F6", KEY_F(6)));
+        help_menu_sp->AddSubmenu (MenuSP (new Menu("GUI Help", NULL, 'g')));
+        
+        m_app_ap->Initialize();
+        WindowSP &main_window_sp = m_app_ap->GetMainWindow();
+        
+        MenuSP menubar_sp(new Menu(Menu::Type::Bar));
+        menubar_sp->AddSubmenu (lldb_menu_sp);
+        menubar_sp->AddSubmenu (target_menu_sp);
+        menubar_sp->AddSubmenu (process_menu_sp);
+        menubar_sp->AddSubmenu (thread_menu_sp);
+        menubar_sp->AddSubmenu (view_menu_sp);
+        menubar_sp->AddSubmenu (help_menu_sp);
+        
+        WindowSP menubar_window_sp = main_window_sp->CreateSubWindow("menubar", 1, main_window_sp->GetWidth(), 0, 0, false);
+        // Let the menubar get keys if the active window doesn't handle the
+        // keys that are typed so it can respond to menubar key presses.
+        menubar_window_sp->SetCanBeActive(false); // Don't let the menubar become the active window
+        menubar_window_sp->SetDelegate(menubar_sp);
+        init_pair (1, COLOR_WHITE   , COLOR_BLUE  );
+        init_pair (2, COLOR_BLACK   , COLOR_WHITE );
+        init_pair (3, COLOR_MAGENTA , COLOR_WHITE );
+        init_pair (4, COLOR_MAGENTA , COLOR_BLACK );
+        init_pair (5, COLOR_RED     , COLOR_BLACK );
+        
+        const int main_window_view_h = main_window_sp->GetHeight() - 1; // Subtract 1 for menubar
+        const int main_window_view_w = main_window_sp->GetWidth();
+        int source_window_height = (main_window_view_h / 3) * 2;
+        int locals_window_height = main_window_view_h - source_window_height;
+        WindowSP source_window_sp (main_window_sp->CreateSubWindow("source",
+                                                                   source_window_height,
+                                                                   main_window_view_w,
+                                                                   1,
+                                                                   0,
+                                                                   true));
+        WindowSP locals_window_sp (main_window_sp->CreateSubWindow("locals",
+                                                                   locals_window_height - 1,
+                                                                   main_window_view_w,
+                                                                   1 + source_window_height,
+                                                                   0,
+                                                                   false));
+        WindowSP status_window_sp (main_window_sp->CreateSubWindow("status",
+                                                                   1,
+                                                                   main_window_view_w,
+                                                                   source_window_height + locals_window_height,
+                                                                   0,
+                                                                   false));
+        status_window_sp->SetCanBeActive(false); // Don't let the status bar become the active window
+        main_window_sp->SetDelegate (std::static_pointer_cast<WindowDelegate>(app_delegate_sp));
+        source_window_sp->SetDelegate (WindowDelegateSP(new SourceFileWindowDelegate(m_debugger)));
+        locals_window_sp->SetDelegate (WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
+        status_window_sp->SetDelegate (WindowDelegateSP(new StatusBarWindowDelegate(m_debugger)));
+    }
+}
+
+void
+IOHandlerCursesGUI::Deactivate ()
+{
+    m_app_ap->Terminate();
+}
+
+void
+IOHandlerCursesGUI::Run ()
+{
+    m_app_ap->Run(m_debugger);
+    SetIsDone(true);
+}
+
+
+IOHandlerCursesGUI::~IOHandlerCursesGUI ()
+{
+    
+}
+
+void
+IOHandlerCursesGUI::Hide ()
+{
+}
+
+
+void
+IOHandlerCursesGUI::Refresh ()
+{
+}
+
+
+void
+IOHandlerCursesGUI::Interrupt ()
+{
+}
+
+
+void
+IOHandlerCursesGUI::GotEOF()
+{
+}
+

Removed: lldb/branches/iohandler/source/Core/InputReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Core/InputReader.cpp?rev=198365&view=auto
==============================================================================
--- lldb/branches/iohandler/source/Core/InputReader.cpp (original)
+++ lldb/branches/iohandler/source/Core/InputReader.cpp (removed)
@@ -1,387 +0,0 @@
-//===-- InputReader.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/lldb-python.h"
-
-#include <string>
-
-#include "lldb/Core/InputReader.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-InputReader::InputReader (Debugger &debugger) :
-    m_debugger (debugger),
-    m_callback (NULL),
-    m_callback_baton (NULL),
-    m_end_token (),
-    m_granularity (eInputReaderGranularityInvalid),
-    m_done (true),
-    m_echo (true),
-    m_active (false), 
-    m_reader_done (false),
-    m_user_input(),
-    m_save_user_input(false)
-{
-}
-
-InputReader::~InputReader ()
-{
-}
-
-Error
-InputReader::Initialize 
-(
-    Callback callback, 
-    void *baton,
-    lldb::InputReaderGranularity granularity,
-    const char *end_token,
-    const char *prompt,
-    bool echo
-)
-{
-    Error err;
-    m_callback = callback;
-    m_callback_baton = baton,
-    m_granularity = granularity;
-    if (end_token != NULL)
-        m_end_token = end_token;
-    if (prompt != NULL)
-        m_prompt = prompt;
-    m_done = true;
-    m_echo = echo;
-
-    if (m_granularity == eInputReaderGranularityInvalid)
-    {
-        err.SetErrorString ("Invalid read token size:  Reader must be initialized with a token size other than 'eInputReaderGranularityInvalid'.");
-    }
-    else
-    if (end_token != NULL && granularity != eInputReaderGranularityInvalid)
-    {
-        if (granularity == eInputReaderGranularityByte)
-        {
-            // Check to see if end_token is longer than one byte.
-            
-            if (strlen (end_token) > 1)
-            {
-                err.SetErrorString ("Invalid end token:  End token cannot be larger than specified token size (byte).");
-            }
-        }
-        else if (granularity == eInputReaderGranularityWord)
-        {
-            // Check to see if m_end_token contains any white space (i.e. is multiple words).
-            
-            const char *white_space = " \t\n";
-            size_t pos = m_end_token.find_first_of (white_space);
-            if (pos != std::string::npos)
-            {
-                err.SetErrorString ("Invalid end token:  End token cannot be larger than specified token size (word).");
-            }
-        }
-        else
-        {
-            // Check to see if m_end_token contains any newlines; cannot handle multi-line end tokens.
-            
-            size_t pos = m_end_token.find_first_of ('\n');
-            if (pos != std::string::npos)
-            {
-                err.SetErrorString ("Invalid end token:  End token cannot contain a newline.");
-            }
-        }
-    }
-    
-    m_done = err.Fail();
-
-    return err;
-}
-
-size_t
-InputReader::HandleRawBytes (const char *bytes, size_t bytes_len)
-{
-    const char *end_token = NULL;
-    
-    if (m_end_token.empty() == false)
-    {
-        end_token = ::strstr (bytes, m_end_token.c_str());
-        if (end_token >= bytes + bytes_len)
-            end_token = NULL;
-    }
-
-    const char *p = bytes;
-    const char *end = bytes + bytes_len;
-
-    switch (m_granularity)
-    {
-    case eInputReaderGranularityInvalid:
-        break;
-
-    case eInputReaderGranularityByte:
-        while (p < end)
-        {
-            if (end_token == p)
-            {
-                p += m_end_token.size();
-                SetIsDone(true);
-                break;
-            }
-
-            if (m_callback (m_callback_baton, *this, eInputReaderGotToken, p, 1) == 0)
-                break;
-            ++p;
-            if (IsDone())
-                break;
-        }
-        // Return how many bytes were handled.
-        return p - bytes;
-        break;
-
-
-    case eInputReaderGranularityWord:
-        {
-            char quote = '\0';
-            const char *word_start = NULL;
-            bool send_word = false;
-            for (; p < end; ++p, send_word = false)
-            {
-                if (end_token && end_token == p)
-                {
-                    m_end_token.size();
-                    SetIsDone(true);
-                    break;
-                }
-
-                const char ch = *p;
-                if (isspace(ch) && (!quote || (quote == ch && p[-1] != '\\')))
-                {
-                    // We have a space character or the terminating quote
-                    send_word = word_start != NULL;
-                    quote = '\0';
-                }
-                else if (quote)
-                {
-                    // We are in the middle of a quoted character
-                    continue;
-                }
-                else if (ch == '"' || ch == '\'' || ch == '`')
-                    quote = ch;
-                else if (word_start == NULL)
-                {
-                    // We have the first character in a word
-                    word_start = p;
-                }
-                
-                if (send_word)
-                {
-                    const size_t word_len = p - word_start;
-                    size_t bytes_handled = m_callback (m_callback_baton, 
-                                                       *this, 
-                                                       eInputReaderGotToken, 
-                                                       word_start,
-                                                       word_len);
-
-                    if (bytes_handled != word_len)
-                        return word_start - bytes + bytes_handled;
-                    
-                    if (IsDone())
-                        return p - bytes;
-                }
-            }
-        }
-        break;
-
-
-    case eInputReaderGranularityLine:
-        {
-            const char *line_start = bytes;
-            const char *end_line = NULL;
-            while (p < end)
-            {
-                const char ch = *p;
-                if (ch == '\n' || ch == '\r')
-                {
-                    size_t line_length = p - line_start;
-                    // Now skip the newline character
-                    ++p; 
-                    // Skip a complete DOS newline if we run into one
-                    if (ch == 0xd && p < end && *p == 0xa)
-                        ++p;
-
-                    if (line_start <= end_token && end_token < line_start + line_length)
-                    {
-                        SetIsDone(true);
-                        m_callback (m_callback_baton, 
-                                    *this, 
-                                    eInputReaderGotToken, 
-                                    line_start, 
-                                    end_token - line_start);
-                        
-                        return p - bytes;
-                    }
-
-                    size_t bytes_handled = m_callback (m_callback_baton, 
-                                                       *this, 
-                                                       eInputReaderGotToken, 
-                                                       line_start, 
-                                                       line_length);
-
-                    end_line = p;
-
-                    if (bytes_handled != line_length)
-                    {
-                        // The input reader wasn't able to handle all the data
-                        return line_start - bytes + bytes_handled;
-                    }
-
-
-                    if (IsDone())
-                        return p - bytes;
-
-                    line_start = p;
-                }
-                else
-                {
-                    ++p;
-                }                
-            }
-            
-            if (end_line)
-                return end_line - bytes;
-        }
-        break;
-
-    
-    case eInputReaderGranularityAll:
-        {
-            // Nothing should be handle unless we see our end token
-            if (end_token)
-            {
-                size_t length = end_token - bytes;
-                size_t bytes_handled = m_callback (m_callback_baton, 
-                                                   *this, 
-                                                   eInputReaderGotToken, 
-                                                   bytes, 
-                                                   length);
-                m_done = true;
-
-                p += bytes_handled + m_end_token.size();
-
-                // Consume any white space, such as newlines, beyond the end token
-
-                while (p < end && isspace(*p))
-                    ++p;
-
-                if (bytes_handled != length)
-                    return bytes_handled;
-                else
-                {
-                    return p - bytes;
-                    //return bytes_handled + m_end_token.size();
-                }
-            }
-            return 0;
-        }
-        break;
-    }
-    return 0;
-}
-
-const char *
-InputReader::GetPrompt () const
-{
-    if (!m_prompt.empty())
-        return m_prompt.c_str();
-    else
-        return NULL;
-}
-
-void
-InputReader::RefreshPrompt ()
-{
-	if (m_debugger.GetCommandInterpreter().GetBatchCommandMode())
-        return;
-    
-    if (!m_prompt.empty())
-    {
-        File &out_file = m_debugger.GetOutputFile();
-        if (out_file.IsValid())
-        {
-            out_file.Printf ("%s", m_prompt.c_str());
-            out_file.Flush();
-        }
-    }
-}
-
-void
-InputReader::Notify (InputReaderAction notification)
-{
-    switch (notification)
-    {
-    case eInputReaderActivate:
-    case eInputReaderReactivate:
-        m_active = true;
-        m_reader_done.SetValue(false, eBroadcastAlways);
-        break;
-
-    case eInputReaderDeactivate:
-    case eInputReaderDone:
-        m_active = false;
-        break;
-    
-    case eInputReaderAsynchronousOutputWritten:
-        break;
-        
-    case eInputReaderInterrupt:
-    case eInputReaderEndOfFile:
-        break;
-    
-    case eInputReaderGotToken:
-        return; // We don't notify the tokens here, it is done in HandleRawBytes
-    }
-    if (m_callback)
-        m_callback (m_callback_baton, *this, notification, NULL, 0);
-    if (notification == eInputReaderDone)
-        m_reader_done.SetValue(true, eBroadcastAlways);
-}
-
-void 
-InputReader::WaitOnReaderIsDone ()
-{
-    m_reader_done.WaitForValueEqualTo (true);
-}
-
-const char *
-InputReader::GranularityAsCString (lldb::InputReaderGranularity granularity)
-{
-    switch (granularity)
-    {
-    case eInputReaderGranularityInvalid:  return "invalid";
-    case eInputReaderGranularityByte:     return "byte";
-    case eInputReaderGranularityWord:     return "word";
-    case eInputReaderGranularityLine:     return "line";
-    case eInputReaderGranularityAll:      return "all";
-    }
-
-    static char unknown_state_string[64];
-    snprintf(unknown_state_string, sizeof (unknown_state_string), "InputReaderGranularity = %i", granularity);
-    return unknown_state_string;
-}
-
-bool
-InputReader::HandlerData::GetBatchMode()
-{
-    return reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-}
-
-lldb::StreamSP
-InputReader::HandlerData::GetOutStream()
-{
-    return reader.GetDebugger().GetAsyncOutputStream();
-}

Removed: lldb/branches/iohandler/source/Core/InputReaderEZ.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Core/InputReaderEZ.cpp?rev=198365&view=auto
==============================================================================
--- lldb/branches/iohandler/source/Core/InputReaderEZ.cpp (original)
+++ lldb/branches/iohandler/source/Core/InputReaderEZ.cpp (removed)
@@ -1,91 +0,0 @@
-//===-- InputReaderEZ.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/InputReaderEZ.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-size_t
-InputReaderEZ::Callback_Impl(void *baton, 
-                             InputReader &reader, 
-                             lldb::InputReaderAction notification,
-                             const char *bytes, 
-                             size_t bytes_len)
-
-{
-    HandlerData hand_data(reader,
-                          bytes,
-                          bytes_len,
-                          baton);
-    
-    switch (notification)
-    {
-        case eInputReaderActivate:
-            reader.ActivateHandler(hand_data);
-            break;
-        case eInputReaderDeactivate:
-            reader.DeactivateHandler(hand_data);
-            break;
-        case eInputReaderReactivate:
-            reader.ReactivateHandler(hand_data);
-            break;
-        case eInputReaderAsynchronousOutputWritten:
-            reader.AsynchronousOutputWrittenHandler(hand_data);
-            break;
-        case eInputReaderGotToken:
-        {
-            if (reader.GetSaveUserInput())
-                reader.GetUserInput().AppendString(bytes, bytes_len);            
-            reader.GotTokenHandler(hand_data);
-        }
-            break;
-        case eInputReaderInterrupt:
-            reader.InterruptHandler(hand_data);
-            break;
-        case eInputReaderEndOfFile:
-            reader.EOFHandler(hand_data);
-            break;
-        case eInputReaderDone:
-            reader.DoneHandler(hand_data);
-            break;
-    }
-    return bytes_len;
-}
-
-Error
-InputReaderEZ::Initialize(void* baton,
-                          lldb::InputReaderGranularity token_size,
-                          const char* end_token,
-                          const char *prompt,
-                          bool echo)
-{
-    return InputReader::Initialize(Callback_Impl,
-                                   baton,
-                                   token_size,
-                                   end_token,
-                                   prompt,
-                                   echo);
-}
-
-Error
-InputReaderEZ::Initialize(InitializationParameters& params)
-{
-    Error ret =  Initialize(params.m_baton,
-                            params.m_token_size,
-                            params.m_end_token,
-                            params.m_prompt,
-                            params.m_echo);
-    m_save_user_input = params.m_save_user_input;
-    return ret;
-}
-
-InputReaderEZ::~InputReaderEZ ()
-{
-}

Removed: lldb/branches/iohandler/source/Core/InputReaderStack.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Core/InputReaderStack.cpp?rev=198365&view=auto
==============================================================================
--- lldb/branches/iohandler/source/Core/InputReaderStack.cpp (original)
+++ lldb/branches/iohandler/source/Core/InputReaderStack.cpp (removed)
@@ -1,80 +0,0 @@
-//===-- InputReaderStack.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/InputReaderStack.h"
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-
-
-using namespace lldb;
-using namespace lldb_private;
-
-InputReaderStack::InputReaderStack () :
-    m_input_readers (),
-    m_input_readers_mutex (Mutex::eMutexTypeRecursive)
-{
-}
-
-InputReaderStack::~InputReaderStack ()
-{
-}
-
-size_t
-InputReaderStack::GetSize () const
-{
-    Mutex::Locker locker (m_input_readers_mutex);
-    return m_input_readers.size();
-}
-    
-void
-InputReaderStack::Push (const lldb::InputReaderSP& reader_sp)
-{
-    if (reader_sp)
-    {
-        Mutex::Locker locker (m_input_readers_mutex);
-        m_input_readers.push (reader_sp);
-    }
-}
-    
-bool
-InputReaderStack::IsEmpty () const
-{
-    Mutex::Locker locker (m_input_readers_mutex);
-    return m_input_readers.empty();
-}
-    
-InputReaderSP
-InputReaderStack::Top ()
-{
-    InputReaderSP input_reader_sp;
-    {
-        Mutex::Locker locker (m_input_readers_mutex);
-        if (!m_input_readers.empty())
-            input_reader_sp = m_input_readers.top();
-    }
-        
-    return input_reader_sp;
-}
-    
-void
-InputReaderStack::Pop ()
-{
-    Mutex::Locker locker (m_input_readers_mutex);
-    if (!m_input_readers.empty())
-        m_input_readers.pop();
-}
-    
-Mutex &
-InputReaderStack::GetStackMutex ()
-{
-    return m_input_readers_mutex;
-}

Modified: lldb/branches/iohandler/source/Core/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Core/SourceManager.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Core/SourceManager.cpp (original)
+++ lldb/branches/iohandler/source/Core/SourceManager.cpp Thu Jan  2 16:40:14 2014
@@ -432,6 +432,56 @@ SourceManager::File::GetLineOffset (uint
     return UINT32_MAX;
 }
 
+uint32_t
+SourceManager::File::GetNumLines ()
+{
+    CalculateLineOffsets();
+    return m_offsets.size();
+}
+
+const char *
+SourceManager::File::PeekLineData (uint32_t line)
+{
+    if (!LineIsValid(line))
+        return NULL;
+    
+    size_t line_offset = GetLineOffset (line);
+    if (line_offset < m_data_sp->GetByteSize())
+        return (const char *)m_data_sp->GetBytes() + line_offset;
+    return NULL;
+}
+
+uint32_t
+SourceManager::File::GetLineLength (uint32_t line, bool include_newline_chars)
+{
+    if (!LineIsValid(line))
+        return false;
+    
+    size_t start_offset = GetLineOffset (line);
+    size_t end_offset = GetLineOffset (line + 1);
+    if (end_offset == UINT32_MAX)
+        end_offset = m_data_sp->GetByteSize();
+    
+    if (end_offset > start_offset)
+    {
+        uint32_t length = end_offset - start_offset;
+        if (include_newline_chars == false)
+        {
+            const char *line_start = (const char *)m_data_sp->GetBytes() + start_offset;
+            while (length > 0)
+            {
+                const char last_char = line_start[length-1];
+                if ((last_char == '\r') || (last_char == '\n'))
+                    --length;
+                else
+                    break;
+            }
+        }
+        return length;
+    }
+    return 0;
+}
+
 bool
 SourceManager::File::LineIsValid (uint32_t line)
 {

Modified: lldb/branches/iohandler/source/Core/StreamAsynchronousIO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Core/StreamAsynchronousIO.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Core/StreamAsynchronousIO.cpp (original)
+++ lldb/branches/iohandler/source/Core/StreamAsynchronousIO.cpp Thu Jan  2 16:40:14 2014
@@ -28,25 +28,26 @@ StreamAsynchronousIO::StreamAsynchronous
 
 StreamAsynchronousIO::~StreamAsynchronousIO ()
 {
+    // Flush when we destroy to make sure we display the data
+    Flush();
 }
 
 void
 StreamAsynchronousIO::Flush ()
 {
-    if (m_accumulated_data.GetSize() > 0)
+    if (!m_accumulated_data.empty())
     {
         std::unique_ptr<EventDataBytes> data_bytes_ap (new EventDataBytes);
         // Let's swap the bytes to avoid LARGE string copies.
-        data_bytes_ap->SwapBytes (m_accumulated_data.GetString());
+        data_bytes_ap->SwapBytes (m_accumulated_data);
         EventSP new_event_sp (new Event (m_broadcast_event_type, data_bytes_ap.release()));
         m_broadcaster.BroadcastEvent (new_event_sp);
-        m_accumulated_data.Clear();
     }
 }
 
 size_t
 StreamAsynchronousIO::Write (const void *s, size_t length)
 {
-    m_accumulated_data.Write (s, length);
+    m_accumulated_data.append ((const char *)s, length);
     return length;
 }

Modified: lldb/branches/iohandler/source/Core/StringList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Core/StringList.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Core/StringList.cpp (original)
+++ lldb/branches/iohandler/source/Core/StringList.cpp Thu Jan  2 16:40:14 2014
@@ -56,6 +56,12 @@ StringList::AppendString (const std::str
 }
 
 void
+StringList::AppendString (std::string &&s)
+{
+    m_strings.push_back (s);
+}
+
+void
 StringList::AppendString (const char *str, size_t str_len)
 {
     if (str)
@@ -126,37 +132,39 @@ StringList::Clear ()
 void
 StringList::LongestCommonPrefix (std::string &common_prefix)
 {
-    //arg_sstr_collection::iterator pos, end = m_args.end();
-    size_t pos = 0;
-    size_t end = m_strings.size();
+    const size_t num_strings = m_strings.size();
 
-    if (pos == end)
+    if (num_strings == 0)
+    {
         common_prefix.clear();
+    }
     else
-        common_prefix = m_strings[pos];
-
-    for (++pos; pos != end; ++pos)
     {
-        size_t new_size = strlen (m_strings[pos].c_str());
+        common_prefix = m_strings.front();
 
-        // First trim common_prefix if it is longer than the current element:
-        if (common_prefix.size() > new_size)
-            common_prefix.erase (new_size);
+        for (size_t idx = 1; idx < num_strings; ++idx)
+        {
+            std::string &curr_string = m_strings[idx];
+            size_t new_size = curr_string.size();
 
-        // Then trim it at the first disparity:
+            // First trim common_prefix if it is longer than the current element:
+            if (common_prefix.size() > new_size)
+                common_prefix.erase (new_size);
 
-        for (size_t i = 0; i < common_prefix.size(); i++)
-        {
-            if (m_strings[pos][i]  != common_prefix[i])
+            // Then trim it at the first disparity:
+            for (size_t i = 0; i < common_prefix.size(); i++)
             {
-                common_prefix.erase(i);
-                break;
+                if (curr_string[i] != common_prefix[i])
+                {
+                    common_prefix.erase(i);
+                    break;
+                }
             }
-        }
 
-        // If we've emptied the common prefix, we're done.
-        if (common_prefix.empty())
-            break;
+            // If we've emptied the common prefix, we're done.
+            if (common_prefix.empty())
+                break;
+        }
     }
 }
 
@@ -173,6 +181,24 @@ StringList::InsertStringAtIndex (size_t
 }
 
 void
+StringList::InsertStringAtIndex (size_t idx, const std::string &str)
+{
+    if (idx < m_strings.size())
+        m_strings.insert (m_strings.begin() + idx, str);
+    else
+        m_strings.push_back (str);
+}
+
+void
+StringList::InsertStringAtIndex (size_t idx, std::string &&str)
+{
+    if (idx < m_strings.size())
+        m_strings.insert (m_strings.begin() + idx, str);
+    else
+        m_strings.push_back (str);
+}
+
+void
 StringList::DeleteStringAtIndex (size_t idx)
 {
     if (idx < m_strings.size())
@@ -180,6 +206,12 @@ StringList::DeleteStringAtIndex (size_t
 }
 
 size_t
+StringList::SplitIntoLines (const std::string &lines)
+{
+    return SplitIntoLines (lines.c_str(), lines.size());
+}
+
+size_t
 StringList::SplitIntoLines (const char *lines, size_t len)
 {
     const size_t orig_size = m_strings.size();
@@ -231,8 +263,7 @@ StringList::RemoveBlankLines ()
 }
 
 std::string
-StringList::CopyList(const char* item_preamble,
-                     const char* items_sep)
+StringList::CopyList(const char* item_preamble, const char* items_sep) const
 {
     StreamString strm;
     for (size_t i = 0; i < GetSize(); i++)

Modified: lldb/branches/iohandler/source/Expression/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Expression/ClangExpressionParser.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Expression/ClangExpressionParser.cpp (original)
+++ lldb/branches/iohandler/source/Expression/ClangExpressionParser.cpp Thu Jan  2 16:40:14 2014
@@ -16,6 +16,7 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Disassembler.h"
 #include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Expression/ClangASTSource.h"
 #include "lldb/Expression/ClangExpression.h"
@@ -505,7 +506,7 @@ ClangExpressionParser::PrepareForExecuti
         Stream *error_stream = NULL;
         Target *target = exe_ctx.GetTargetPtr();
         if (target)
-            error_stream = &target->GetDebugger().GetErrorStream();
+            error_stream = target->GetDebugger().GetErrorFile().get();
     
         IRForTarget ir_for_target(decl_map,
                                   m_expr.NeedsVariableResolution(),

Added: lldb/branches/iohandler/source/Host/common/Editline.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Host/common/Editline.cpp?rev=198366&view=auto
==============================================================================
--- lldb/branches/iohandler/source/Host/common/Editline.cpp (added)
+++ lldb/branches/iohandler/source/Host/common/Editline.cpp Thu Jan  2 16:40:14 2014
@@ -0,0 +1,667 @@
+//===-- Editline.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/Host/Editline.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Host/Host.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static const char k_prompt_escape_char = '\1';
+
+Editline::Editline (const char *prog,       // prog can't be NULL
+                    const char *prompt,     // can be NULL for no prompt
+                    FILE *fin,
+                    FILE *fout,
+                    FILE *ferr) :
+    m_editline (NULL),
+    m_history (NULL),
+    m_history_event (),
+    m_program (),
+    m_prompt (),
+    m_lines_prompt (),
+    m_getc_buffer (),
+    m_getc_mutex (Mutex::eMutexTypeNormal),
+    m_getc_cond (),
+//    m_gets_mutex (Mutex::eMutexTypeNormal),
+    m_completion_callback (NULL),
+    m_completion_callback_baton (NULL),
+    m_line_complete_callback (NULL),
+    m_line_complete_callback_baton (NULL),
+    m_lines_command (Command::None),
+    m_lines_curr_line (0),
+    m_lines_max_line (0),
+    m_prompt_with_line_numbers (false),
+    m_getting_line (false),
+    m_got_eof (false),
+    m_interrupted (false)
+{
+    if (prog && prog[0])
+    {
+        m_program = prog;
+        m_editline = ::el_init(prog, fin, fout, ferr);
+        m_history = ::history_init();
+    }
+    else
+    {
+        m_editline = ::el_init("lldb-tmp", fin, fout, ferr);
+    }
+    if (prompt && prompt[0])
+        SetPrompt (prompt);
+
+    //::el_set (m_editline, EL_BIND, "^[[A", NULL); // Print binding for up arrow key
+    //::el_set (m_editline, EL_BIND, "^[[B", NULL); // Print binding for up down key
+
+    assert (m_editline);
+    ::el_set (m_editline, EL_CLIENTDATA, this);
+    ::el_set (m_editline, EL_PROMPT_ESC, GetPromptCallback, k_prompt_escape_char);
+    ::el_set (m_editline, EL_EDITOR, "emacs");
+    if (m_history)
+    {
+        ::el_set (m_editline, EL_HIST, history, m_history);
+    }
+    ::el_set (m_editline, EL_ADDFN, "lldb-complete", "Editline completion function", Editline::CallbackComplete);
+    ::el_set (m_editline, EL_ADDFN, "lldb-edit-prev-line", "Editline edit prev line", Editline::CallbackEditPrevLine);
+    ::el_set (m_editline, EL_ADDFN, "lldb-edit-next-line", "Editline edit next line", Editline::CallbackEditNextLine);
+
+    ::el_set (m_editline, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string
+    ::el_set (m_editline, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does.
+    ::el_set (m_editline, EL_BIND, "\033[3~", "ed-delete-next-char", NULL); // Fix the delete key.
+    ::el_set (m_editline, EL_BIND, "\t", "lldb-complete", NULL); // Bind TAB to be autocompelte
+    
+    // Source $PWD/.editrc then $HOME/.editrc
+    ::el_source (m_editline, NULL);
+ 
+    if (m_history)
+    {
+        ::history (m_history, &m_history_event, H_SETSIZE, 800);
+        ::history (m_history, &m_history_event, H_SETUNIQUE, 1);
+    }
+
+    // Always read through our callback function so we don't read
+    // stuff we aren't supposed to. This also stops the extra echoing
+    // that can happen when you have more input than editline can handle
+    // at once.
+    SetGetCharCallback(GetCharFromInputFileCallback);
+
+    LoadHistory();
+}
+
+Editline::~Editline()
+{
+    SaveHistory();
+
+    // Disable edit mode to stop the terminal from flushing all input
+    // during the call to el_end() since we expect to have multiple editline
+    // instances in this program.
+    ::el_set (m_editline, EL_EDITMODE, 0);
+
+    ::el_end(m_editline);
+    m_editline = NULL;
+    if (m_history)
+    {
+        ::history_end (m_history);
+        m_history = NULL;
+    }
+}
+
+void
+Editline::SetGetCharCallback (GetCharCallbackType callback)
+{
+    ::el_set (m_editline, EL_GETCFN, callback);
+}
+
+FileSpec
+Editline::GetHistoryFile()
+{
+    char history_path[PATH_MAX];
+    ::snprintf (history_path, sizeof(history_path), "~/.%s-history", m_program.c_str());
+    return FileSpec(history_path, true);
+}
+
+bool
+Editline::LoadHistory ()
+{
+    if (m_history)
+    {
+        FileSpec history_file(GetHistoryFile());
+        if (history_file.Exists())
+            ::history (m_history, &m_history_event, H_LOAD, history_file.GetPath().c_str());
+        return true;
+    }
+    return false;
+}
+
+bool
+Editline::SaveHistory ()
+{
+    if (m_history)
+    {
+        ::history (m_history, &m_history_event, H_SAVE, GetHistoryFile().GetPath().c_str());
+        return true;
+    }
+    return false;
+}
+
+
+Error
+Editline::PrivateGetLine(std::string &line)
+{
+    Error error;
+    if (m_interrupted)
+    {
+        error.SetErrorString("interrupted");
+        return error;
+    }
+    
+    line.clear();
+    if (m_editline != NULL)
+    {
+        int line_len = 0;
+        const char *line_cstr = NULL;
+        // Call el_gets to prompt the user and read the user's input.
+//        {
+//            // Make sure we know when we are in el_gets() by using a mutex
+//            Mutex::Locker locker (m_gets_mutex);
+            line_cstr = ::el_gets (m_editline, &line_len);
+//        }
+        
+        static int save_errno = (line_len < 0) ? errno : 0;
+        
+        if (save_errno != 0)
+        {
+            error.SetError(save_errno, eErrorTypePOSIX);
+        }
+        else if (line_cstr)
+        {
+            // Decrement the length so we don't have newline characters in "line" for when
+            // we assign the cstr into the std::string
+            while (line_len > 0 &&
+                   (line_cstr[line_len - 1] == '\n' ||
+                    line_cstr[line_len - 1] == '\r'))
+                --line_len;
+            
+            if (line_len > 0)
+            {
+                // We didn't strip the newlines, we just adjusted the length, and
+                // we want to add the history item with the newlines
+                if (m_history)
+                    ::history (m_history, &m_history_event, H_ENTER, line_cstr);
+                
+                // Copy the part of the c string that we want (removing the newline chars)
+                line.assign(line_cstr, line_len);
+            }
+        }
+    }
+    else
+    {
+        error.SetErrorString("the EditLine instance has been deleted");
+    }
+    return error;
+}
+
+
+Error
+Editline::GetLine(std::string &line)
+{
+    Error error;
+    line.clear();
+
+    // Set arrow key bindings for up and down arrows for single line
+    // mode where up and down arrows do prev/next history
+    ::el_set (m_editline, EL_BIND, "^[[A", "ed-prev-history", NULL); // Map up arrow
+    ::el_set (m_editline, EL_BIND, "^[[B", "ed-next-history", NULL); // Map down arrow
+    m_interrupted = false;
+
+    if (!m_got_eof)
+    {
+        if (m_getting_line)
+        {
+            error.SetErrorString("already getting a line");
+            return error;
+        }
+        if (m_lines_curr_line > 0)
+        {
+            error.SetErrorString("already getting lines");
+            return error;
+        }
+        m_getting_line = true;
+        error = PrivateGetLine(line);
+        m_getting_line = false;
+    }
+
+    if (m_got_eof && line.empty())
+    {
+        // Only set the error if we didn't get an error back from PrivateGetLine()
+        if (error.Success())
+            error.SetErrorString("end of file");
+    }
+
+    return error;
+}
+
+size_t
+Editline::Push (const char *bytes, size_t len)
+{
+    if (m_editline)
+    {
+        // Must NULL terminate the string for el_push() so we stick it
+        // into a std::string first
+        ::el_push(m_editline, std::string (bytes, len).c_str());
+        return len;
+    }
+    return 0;
+}
+
+
+Error
+Editline::GetLines(const std::string &end_line, StringList &lines)
+{
+    Error error;
+    if (m_getting_line)
+    {
+        error.SetErrorString("already getting a line");
+        return error;
+    }
+    if (m_lines_curr_line > 0)
+    {
+        error.SetErrorString("already getting lines");
+        return error;
+    }
+    
+    // Set arrow key bindings for up and down arrows for multiple line
+    // mode where up and down arrows do edit prev/next line
+    ::el_set (m_editline, EL_BIND, "^[[A", "lldb-edit-prev-line", NULL); // Map up arrow
+    ::el_set (m_editline, EL_BIND, "^[[B", "lldb-edit-next-line", NULL); // Map down arrow
+    ::el_set (m_editline, EL_BIND, "^b", "ed-prev-history", NULL);
+    ::el_set (m_editline, EL_BIND, "^n", "ed-next-history", NULL);
+    m_interrupted = false;
+
+    LineStatus line_status = LineStatus::Success;
+
+    lines.Clear();
+
+    FILE *out_file = GetOutputFile();
+    FILE *err_file = GetErrorFile();
+    m_lines_curr_line = 1;
+    while (line_status != LineStatus::Done)
+    {
+        const uint32_t line_idx = m_lines_curr_line-1;
+        if (line_idx >= lines.GetSize())
+            lines.SetSize(m_lines_curr_line);
+        m_lines_max_line = lines.GetSize();
+        m_lines_command = Command::None;
+        assert(line_idx < m_lines_max_line);
+        std::string &line = lines[line_idx];
+        error = PrivateGetLine(line);
+        if (error.Fail())
+        {
+            line_status = LineStatus::Error;
+        }
+        else
+        {
+            switch (m_lines_command)
+            {
+                case Command::None:
+                    if (m_line_complete_callback)
+                    {
+                        line_status = m_line_complete_callback (this,
+                                                                lines,
+                                                                line_idx,
+                                                                error,
+                                                                m_line_complete_callback_baton);
+                    }
+                    else if (line == end_line)
+                    {
+                        line_status = LineStatus::Done;
+                    }
+
+                    if (line_status == LineStatus::Success)
+                    {
+                        ++m_lines_curr_line;
+                        // If we already have content for the next line because
+                        // we were editing previous lines, then populate the line
+                        // with the appropriate contents
+                        if (line_idx+1 < lines.GetSize() && !lines[line_idx+1].empty())
+                            ::el_push (m_editline, lines[line_idx+1].c_str());
+                    }
+                    else if (line_status == LineStatus::Error)
+                    {
+                        // Clear to end of line ("ESC[K"), then print the error,
+                        // then go to the next line ("\n") and then move cursor up
+                        // two lines ("ESC[2A").
+                        fprintf (err_file, "\033[Kerror: %s\n\033[2A", error.AsCString());
+                    }
+                    break;
+                case Command::EditPrevLine:
+                    if (m_lines_curr_line > 1)
+                    {
+                        //::fprintf (out_file, "\033[1A\033[%uD\033[2K", (uint32_t)(m_lines_prompt.size() + lines[line_idx].size())); // Make cursor go up a line and clear that line
+                        ::fprintf (out_file, "\033[1A\033[1000D\033[2K");
+                        if (!lines[line_idx-1].empty())
+                            ::el_push (m_editline, lines[line_idx-1].c_str());
+                        --m_lines_curr_line;
+                    }
+                    break;
+                case Command::EditNextLine:
+                    // Allow the down arrow to create a new line
+                    ++m_lines_curr_line;
+                    //::fprintf (out_file, "\033[1B\033[%uD\033[2K", (uint32_t)(m_lines_prompt.size() + lines[line_idx].size()));
+                    ::fprintf (out_file, "\033[1B\033[1000D\033[2K");
+                    if (line_idx+1 < lines.GetSize() && !lines[line_idx+1].empty())
+                        ::el_push (m_editline, lines[line_idx+1].c_str());
+                    break;
+            }
+        }
+    }
+    m_lines_curr_line = 0;
+    m_lines_command = Command::None;
+
+    // If we have a callback, call it one more time to let the
+    // user know the lines are complete
+    if (m_line_complete_callback)
+        m_line_complete_callback (this,
+                                  lines,
+                                  UINT32_MAX,
+                                  error,
+                                  m_line_complete_callback_baton);
+
+    return error;
+}
+
+unsigned char
+Editline::HandleCompletion (int ch)
+{
+    if (m_completion_callback == NULL)
+        return CC_ERROR;
+
+    const LineInfo *line_info  = ::el_line(m_editline);
+    StringList completions;
+    int page_size = 40;
+        
+    const int num_completions = m_completion_callback (line_info->buffer,
+                                                       line_info->cursor,
+                                                       line_info->lastchar,
+                                                       0,     // Don't skip any matches (start at match zero)
+                                                       -1,    // Get all the matches
+                                                       completions,
+                                                       m_completion_callback_baton);
+    
+    FILE *out_file = GetOutputFile();
+
+//    if (num_completions == -1)
+//    {
+//        ::el_insertstr (m_editline, m_completion_key);
+//        return CC_REDISPLAY;
+//    }
+//    else
+    if (num_completions == -2)
+    {
+        // Replace the entire line with the first string...
+        ::el_deletestr (m_editline, line_info->cursor - line_info->buffer);
+        ::el_insertstr (m_editline, completions.GetStringAtIndex(0));
+        return CC_REDISPLAY;
+    }
+    
+    // If we get a longer match display that first.
+    const char *completion_str = completions.GetStringAtIndex(0);
+    if (completion_str != NULL && *completion_str != '\0')
+    {
+        el_insertstr (m_editline, completion_str);
+        return CC_REDISPLAY;
+    }
+    
+    if (num_completions > 1)
+    {
+        int num_elements = num_completions + 1;
+        ::fprintf (out_file, "\nAvailable completions:");
+        if (num_completions < page_size)
+        {
+            for (int i = 1; i < num_elements; i++)
+            {
+                completion_str = completions.GetStringAtIndex(i);
+                ::fprintf (out_file, "\n\t%s", completion_str);
+            }
+            ::fprintf (out_file, "\n");
+        }
+        else
+        {
+            int cur_pos = 1;
+            char reply;
+            int got_char;
+            while (cur_pos < num_elements)
+            {
+                int endpoint = cur_pos + page_size;
+                if (endpoint > num_elements)
+                    endpoint = num_elements;
+                for (; cur_pos < endpoint; cur_pos++)
+                {
+                    completion_str = completions.GetStringAtIndex(cur_pos);
+                    ::fprintf (out_file, "\n\t%s", completion_str);
+                }
+                
+                if (cur_pos >= num_elements)
+                {
+                    ::fprintf (out_file, "\n");
+                    break;
+                }
+                
+                ::fprintf (out_file, "\nMore (Y/n/a): ");
+                reply = 'n';
+                got_char = el_getc(m_editline, &reply);
+                if (got_char == -1 || reply == 'n')
+                    break;
+                if (reply == 'a')
+                    page_size = num_elements - cur_pos;
+            }
+        }
+        
+    }
+    
+    if (num_completions == 0)
+        return CC_REFRESH_BEEP;
+    else
+        return CC_REDISPLAY;
+}
+
+Editline *
+Editline::GetClientData (::EditLine *e)
+{
+    Editline *editline = NULL;
+    if (e && ::el_get(e, EL_CLIENTDATA, &editline) == 0)
+        return editline;
+    return NULL;
+}
+
+FILE *
+Editline::GetInputFile ()
+{
+    return GetFilePointer (m_editline, 0);
+}
+
+FILE *
+Editline::GetOutputFile ()
+{
+    return GetFilePointer (m_editline, 1);
+}
+
+FILE *
+Editline::GetErrorFile ()
+{
+    return GetFilePointer (m_editline, 2);
+}
+
+const char *
+Editline::GetPrompt()
+{
+    if (m_prompt_with_line_numbers && m_lines_curr_line > 0)
+    {
+        StreamString strm;
+        strm.Printf("%3u: ", m_lines_curr_line);
+        m_lines_prompt = std::move(strm.GetString());
+        return m_lines_prompt.c_str();
+    }
+    else
+    {
+        return m_prompt.c_str();
+    }
+}
+
+void
+Editline::SetPrompt (const char *p)
+{
+    if (p && p[0])
+        m_prompt = p;
+    else
+        m_prompt.clear();
+    size_t start_pos = 0;
+    size_t escape_pos;
+    while ((escape_pos = m_prompt.find('\033', start_pos)) != std::string::npos)
+    {
+        m_prompt.insert(escape_pos, 1, k_prompt_escape_char);
+        start_pos += 2;
+    }
+}
+
+FILE *
+Editline::GetFilePointer (::EditLine *e, int fd)
+{
+    FILE *file_ptr = NULL;
+    if (e && ::el_get(e, EL_GETFP, fd, &file_ptr) == 0)
+        return file_ptr;
+    return NULL;
+}
+
+unsigned char
+Editline::CallbackEditPrevLine (::EditLine *e, int ch)
+{
+    Editline *editline = GetClientData (e);
+    if (editline->m_lines_curr_line > 1)
+    {
+        editline->m_lines_command = Command::EditPrevLine;
+        return CC_NEWLINE;
+    }
+    return CC_ERROR;
+}
+unsigned char
+Editline::CallbackEditNextLine (::EditLine *e, int ch)
+{
+    Editline *editline = GetClientData (e);
+    if (editline->m_lines_curr_line < editline->m_lines_max_line)
+    {
+        editline->m_lines_command = Command::EditNextLine;
+        return CC_NEWLINE;
+    }
+    return CC_ERROR;
+}
+
+unsigned char
+Editline::CallbackComplete (::EditLine *e, int ch)
+{
+    Editline *editline = GetClientData (e);
+    if (editline)
+        return editline->HandleCompletion (ch);
+    return CC_ERROR;
+}
+
+const char *
+Editline::GetPromptCallback (::EditLine *e)
+{
+    Editline *editline = GetClientData (e);
+    if (editline)
+        return editline->GetPrompt();
+    return "";
+}
+
+size_t
+Editline::SetInputBuffer (const char *c, size_t len)
+{
+    if (c && len > 0)
+    {
+        Mutex::Locker locker(m_getc_mutex);
+        SetGetCharCallback(GetCharInputBufferCallback);
+        m_getc_buffer.append(c, len);
+        m_getc_cond.Broadcast();
+    }
+    return len;
+}
+
+int
+Editline::GetChar (char *c)
+{
+    Mutex::Locker locker(m_getc_mutex);
+    if (m_getc_buffer.empty())
+        m_getc_cond.Wait(m_getc_mutex);
+    if (m_getc_buffer.empty())
+        return 0;
+    *c = m_getc_buffer[0];
+    m_getc_buffer.erase(0,1);
+    return 1;
+}
+
+int
+Editline::GetCharInputBufferCallback (EditLine *e, char *c)
+{
+    Editline *editline = GetClientData (e);
+    if (editline)
+        return editline->GetChar(c);
+    return 0;
+}
+
+int
+Editline::GetCharFromInputFileCallback (EditLine *e, char *c)
+{
+    Editline *editline = GetClientData (e);
+    if (editline && editline->m_got_eof == false)
+    {
+        char ch = ::fgetc(editline->GetInputFile());
+        if (ch == '\x04' || ch == EOF)
+        {
+            editline->m_got_eof = true;
+        }
+        else
+        {
+            *c = ch;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+void
+Editline::Hide ()
+{
+    FILE *out_file = GetOutputFile();
+    if (out_file)
+    {
+        const LineInfo *line_info  = ::el_line(m_editline);
+        if (line_info)
+            ::fprintf (out_file, "\033[%uD\033[K", (uint32_t)(strlen(GetPrompt()) + line_info->cursor - line_info->buffer));
+    }
+}
+
+
+void
+Editline::Refresh()
+{
+    ::el_set (m_editline, EL_REFRESH);
+}
+
+void
+Editline::Interrupt ()
+{
+    m_interrupted = true;
+    if (m_getting_line || m_lines_curr_line > 0)
+        el_insertstr(m_editline, "\n"); // True to force the line to complete itself so we get exit from el_gets()
+}

Modified: lldb/branches/iohandler/source/Host/common/File.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Host/common/File.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Host/common/File.cpp (original)
+++ lldb/branches/iohandler/source/Host/common/File.cpp Thu Jan  2 16:40:14 2014
@@ -76,7 +76,7 @@ FILE * File::kInvalidStream = NULL;
 File::File(const char *path, uint32_t options, uint32_t permissions) :
     m_descriptor (kInvalidDescriptor),
     m_stream (kInvalidStream),
-    m_options (0),
+    m_options (),
     m_owned (false)
 {
     Open (path, options, permissions);
@@ -272,7 +272,10 @@ File::Open (const char *path, uint32_t o
     if (!DescriptorIsValid())
         error.SetErrorToErrno();
     else
+    {
         m_owned = true;
+        m_options = options;
+    }
     
     return error;
 }

Modified: lldb/branches/iohandler/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Interpreter/CommandInterpreter.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/branches/iohandler/source/Interpreter/CommandInterpreter.cpp Thu Jan  2 16:40:14 2014
@@ -22,6 +22,7 @@
 #include "../Commands/CommandObjectDisassemble.h"
 #include "../Commands/CommandObjectExpression.h"
 #include "../Commands/CommandObjectFrame.h"
+#include "../Commands/CommandObjectGUI.h"
 #include "../Commands/CommandObjectHelp.h"
 #include "../Commands/CommandObjectLog.h"
 #include "../Commands/CommandObjectMemory.h"
@@ -42,11 +43,12 @@
 
 
 #include "lldb/Core/Debugger.h"
-#include "lldb/Core/InputReader.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/Core/Timer.h"
 
+#include "lldb/Host/Editline.h"
 #include "lldb/Host/Host.h"
 
 #include "lldb/Interpreter/Args.h"
@@ -99,11 +101,13 @@ CommandInterpreter::CommandInterpreter
 ) :
     Broadcaster (&debugger, "lldb.command-interpreter"),
     Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
+    IOHandlerDelegate (IOHandlerDelegate::Completion::LLDBCommand),
     m_debugger (debugger),
     m_synchronous_execution (synchronous_execution),
     m_skip_lldbinit_files (false),
     m_skip_app_init_files (false),
     m_script_interpreter_ap (),
+    m_command_io_handler_sp (),
     m_comment_char ('#'),
     m_batch_command_mode (false),
     m_truncation_warning(eNoTruncation),
@@ -376,6 +380,7 @@ CommandInterpreter::LoadCommandDictionar
     m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
     m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
     m_command_dict["frame"]     = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
+    m_command_dict["gui"]       = CommandObjectSP (new CommandObjectGUI (*this));
     m_command_dict["help"]      = CommandObjectSP (new CommandObjectHelp (*this));
     m_command_dict["log"]       = CommandObjectSP (new CommandObjectLog (*this));
     m_command_dict["memory"]    = CommandObjectSP (new CommandObjectMemory (*this));
@@ -2093,96 +2098,15 @@ CommandInterpreter::~CommandInterpreter
 {
 }
 
-const char *
-CommandInterpreter::GetPrompt ()
-{
-    return m_debugger.GetPrompt();
-}
-
 void
-CommandInterpreter::SetPrompt (const char *new_prompt)
+CommandInterpreter::UpdatePrompt (const char *new_prompt)
 {
-    m_debugger.SetPrompt (new_prompt);
+    EventSP prompt_change_event_sp (new Event(eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));;
+    BroadcastEvent (prompt_change_event_sp);
+    if (m_command_io_handler_sp)
+        m_command_io_handler_sp->SetPrompt(new_prompt);
 }
 
-size_t
-CommandInterpreter::GetConfirmationInputReaderCallback 
-(
-    void *baton,
-    InputReader &reader,
-    lldb::InputReaderAction action,
-    const char *bytes,
-    size_t bytes_len
-)
-{
-    File &out_file = reader.GetDebugger().GetOutputFile();
-    bool *response_ptr = (bool *) baton;
-    
-    switch (action)
-    {
-    case eInputReaderActivate:
-        if (out_file.IsValid())
-        {
-            if (reader.GetPrompt())
-            {
-                out_file.Printf ("%s", reader.GetPrompt());
-                out_file.Flush ();
-            }
-        }
-        break;
-
-    case eInputReaderDeactivate:
-        break;
-
-    case eInputReaderReactivate:
-        if (out_file.IsValid() && reader.GetPrompt())
-        {
-            out_file.Printf ("%s", reader.GetPrompt());
-            out_file.Flush ();
-        }
-        break;
-        
-    case eInputReaderAsynchronousOutputWritten:
-        break;
-        
-    case eInputReaderGotToken:
-        if (bytes_len == 0)
-        {
-            reader.SetIsDone(true);
-        }
-        else if (bytes[0] == 'y' || bytes[0] == 'Y')
-        {
-            *response_ptr = true;
-            reader.SetIsDone(true);
-        }
-        else if (bytes[0] == 'n' || bytes[0] == 'N')
-        {
-            *response_ptr = false;
-            reader.SetIsDone(true);
-        }
-        else
-        {
-            if (out_file.IsValid() && !reader.IsDone() && reader.GetPrompt())
-            {
-                out_file.Printf ("Please answer \"y\" or \"n\".\n%s", reader.GetPrompt());
-                out_file.Flush ();
-            }
-        }
-        break;
-        
-    case eInputReaderInterrupt:
-    case eInputReaderEndOfFile:
-        *response_ptr = false;  // Assume ^C or ^D means cancel the proposed action
-        reader.SetIsDone (true);
-        break;
-        
-    case eInputReaderDone:
-        break;
-    }
-
-    return bytes_len;
-
-}
 
 bool 
 CommandInterpreter::Confirm (const char *message, bool default_answer)
@@ -2190,31 +2114,13 @@ CommandInterpreter::Confirm (const char
     // Check AutoConfirm first:
     if (m_debugger.GetAutoConfirm())
         return default_answer;
-        
-    InputReaderSP reader_sp (new InputReader(GetDebugger()));
-    bool response = default_answer;
-    if (reader_sp)
-    {
-        std::string prompt(message);
-        prompt.append(": [");
-        if (default_answer)
-            prompt.append ("Y/n] ");
-        else
-            prompt.append ("y/N] ");
-            
-        Error err (reader_sp->Initialize (CommandInterpreter::GetConfirmationInputReaderCallback,
-                                          &response,                    // baton
-                                          eInputReaderGranularityLine,  // token size, to pass to callback function
-                                          NULL,                         // end token
-                                          prompt.c_str(),               // prompt
-                                          true));                       // echo input
-        if (err.Success())
-        {
-            GetDebugger().PushInputReader (reader_sp);
-        }
-        reader_sp->WaitOnReaderIsDone();
-    }
-    return response;        
+    
+    IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger,
+                                                     message,
+                                                     default_answer);
+    IOHandlerSP io_handler_sp (confirm);
+    m_debugger.RunIOHandler (io_handler_sp);
+    return confirm->GetResponse();
 }
     
 OptionArgVectorSP
@@ -2490,7 +2396,9 @@ CommandInterpreter::SourceInitFile (bool
         bool echo_commands    = false;
         bool print_results    = false;
         
+        const bool saved_batch = SetBatchCommandMode (true);
         HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, eLazyBoolNo, result);
+        SetBatchCommandMode (saved_batch);
     }
     else
     {
@@ -2553,8 +2461,8 @@ CommandInterpreter::HandleCommands (cons
         if (echo_commands)
         {
             result.AppendMessageWithFormat ("%s %s\n", 
-                                             GetPrompt(), 
-                                             cmd);
+                                            m_debugger.GetPrompt(),
+                                            cmd);
         }
 
         CommandReturnObject tmp_result;
@@ -2650,6 +2558,33 @@ CommandInterpreter::HandleCommandsFromFi
 {
     if (cmd_file.Exists())
     {
+        StreamFileSP input_file_sp (new StreamFile());
+        
+        std::string cmd_file_path = cmd_file.GetPath();
+        Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), File::eOpenOptionRead);
+        
+        if (error.Success())
+        {
+            Debugger &debugger = GetDebugger();
+
+            IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
+                                                              input_file_sp,
+                                                              debugger.GetOutputFile(),
+                                                              debugger.GetErrorFile(),
+                                                              NULL, // Pass in NULL for "editline_name" so no history is saved, or written
+                                                              m_debugger.GetPrompt(),
+                                                              false, // Not multi-line
+                                                              *this));
+            m_debugger.RunIOHandler(io_handler_sp);
+            result.SetStatus (eReturnStatusSuccessFinishNoResult);
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString());
+            result.SetStatus (eReturnStatusFailed);
+        }
+        
+#if 0
         bool success;
         StringList commands;
         success = commands.ReadFileLines(cmd_file);
@@ -2662,6 +2597,7 @@ CommandInterpreter::HandleCommandsFromFi
         m_command_source_depth++;
         HandleCommands (commands, context, stop_on_continue, stop_on_error, echo_command, print_result, add_to_history, result);
         m_command_source_depth--;
+#endif
     }
     else
     {
@@ -2901,7 +2837,6 @@ CommandInterpreter::FindCommandsForAprop
     }
 }
 
-
 void
 CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
 {
@@ -2915,3 +2850,145 @@ CommandInterpreter::UpdateExecutionConte
         m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
     }
 }
+
+
+size_t
+CommandInterpreter::GetProcessOutput ()
+{
+    //  The process has stuff waiting for stderr; get it and write it out to the appropriate place.
+    char stdio_buffer[1024];
+    size_t len;
+    size_t total_bytes = 0;
+    Error error;
+    TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
+    if (target_sp)
+    {
+        ProcessSP process_sp (target_sp->GetProcessSP());
+        if (process_sp)
+        {
+            while ((len = process_sp->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
+            {
+                size_t bytes_written = len;
+                m_debugger.GetOutputFile()->Write (stdio_buffer, bytes_written);
+                total_bytes += len;
+            }
+            while ((len = process_sp->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
+            {
+                size_t bytes_written = len;
+                m_debugger.GetErrorFile()->Write (stdio_buffer, bytes_written);
+                total_bytes += len;
+            }
+        }
+    }
+    return total_bytes;
+}
+
+void
+CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+{
+    lldb_private::CommandReturnObject result;
+    HandleCommand(line.c_str(), eLazyBoolCalculate, result);
+    
+    // Display any STDOUT/STDERR _prior_ to emitting the command result text
+    GetProcessOutput ();
+    
+    // Now emit the command output text from the command we just executed
+    const char *output = result.GetOutputData();
+    if (output && output[0])
+        io_handler.GetOutputStreamFile()->PutCString(output);
+    
+    // Now emit the command error text from the command we just executed
+    const char *error = result.GetErrorData();
+    if (error && error[0])
+        io_handler.GetErrorStreamFile()->PutCString(error);
+    
+    switch (result.GetStatus())
+    {
+        case eReturnStatusInvalid:
+        case eReturnStatusSuccessFinishNoResult:
+        case eReturnStatusSuccessFinishResult:
+        case eReturnStatusSuccessContinuingNoResult:
+        case eReturnStatusSuccessContinuingResult:
+        case eReturnStatusStarted:
+        case eReturnStatusFailed:
+            break;
+            
+        case eReturnStatusQuit:
+            io_handler.SetIsDone(true);
+            break;
+    }
+}
+
+void
+CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt,
+                                                  IOHandlerDelegate &delegate,
+                                                  bool asynchronously,
+                                                  void *baton)
+{
+    Debugger &debugger = GetDebugger();
+    IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
+                                                      "lldb",       // Name of input reader for history
+                                                      prompt,       // Prompt
+                                                      true,         // Get multiple lines
+                                                      delegate));   // IOHandlerDelegate
+    
+    if (io_handler_sp)
+    {
+        io_handler_sp->SetUserData (baton);
+        if (asynchronously)
+            debugger.PushIOHandler(io_handler_sp);
+        else
+            debugger.RunIOHandler(io_handler_sp);
+    }
+    
+}
+
+
+void
+CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt,
+                                                    IOHandlerDelegate &delegate,
+                                                    bool asynchronously,
+                                                    void *baton)
+{
+    Debugger &debugger = GetDebugger();
+    IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
+                                                      "lldb-python",    // Name of input reader for history
+                                                      prompt,           // Prompt
+                                                      true,             // Get multiple lines
+                                                      delegate));       // IOHandlerDelegate
+    
+    if (io_handler_sp)
+    {
+        io_handler_sp->SetUserData (baton);
+        if (asynchronously)
+            debugger.PushIOHandler(io_handler_sp);
+        else
+            debugger.RunIOHandler(io_handler_sp);
+    }
+
+}
+void
+CommandInterpreter::RunCommandInterpreter(bool auto_handle_events)
+{
+    const bool multiple_lines = false; // Only get one line at a time
+    if (!m_command_io_handler_sp)
+        m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger,
+                                                             m_debugger.GetInputFile(),
+                                                             m_debugger.GetOutputFile(),
+                                                             m_debugger.GetErrorFile(),
+                                                             "lldb",
+                                                             m_debugger.GetPrompt(),
+                                                             multiple_lines,
+                                                             *this));
+    m_debugger.PushIOHandler(m_command_io_handler_sp);
+    
+    if (auto_handle_events)
+        m_debugger.StartEventHandlerThread();
+    
+    m_debugger.ExecuteIOHanders();
+    
+    if (auto_handle_events)
+        m_debugger.StopEventHandlerThread();
+
+}
+

Modified: lldb/branches/iohandler/source/Interpreter/PythonDataObjects.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Interpreter/PythonDataObjects.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Interpreter/PythonDataObjects.cpp (original)
+++ lldb/branches/iohandler/source/Interpreter/PythonDataObjects.cpp Thu Jan  2 16:40:14 2014
@@ -97,7 +97,7 @@ PythonString::PythonString (PyObject *py
 PythonString::PythonString (const PythonObject &object) :
     PythonObject()
 {
-    Reset(object.GetPythonObject()); // Use "Reset()" to ensure that py_obj is a string
+    Reset(object.get()); // Use "Reset()" to ensure that py_obj is a string
 }
 
 PythonString::PythonString (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
@@ -166,7 +166,7 @@ PythonInteger::PythonInteger (PyObject *
 PythonInteger::PythonInteger (const PythonObject &object) :
     PythonObject()
 {
-    Reset(object.GetPythonObject()); // Use "Reset()" to ensure that py_obj is a integer type
+    Reset(object.get()); // Use "Reset()" to ensure that py_obj is a integer type
 }
 
 PythonInteger::PythonInteger (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
@@ -223,8 +223,8 @@ PythonInteger::SetInteger (int64_t value
 // PythonList
 //----------------------------------------------------------------------
 
-PythonList::PythonList () :
-    PythonObject(PyList_New(0))
+PythonList::PythonList (bool create_empty) :
+    PythonObject(create_empty ? PyList_New(0) : NULL)
 {
 }
 
@@ -243,7 +243,7 @@ PythonList::PythonList (PyObject *py_obj
 PythonList::PythonList (const PythonObject &object) :
     PythonObject()
 {
-    Reset(object.GetPythonObject()); // Use "Reset()" to ensure that py_obj is a list
+    Reset(object.get()); // Use "Reset()" to ensure that py_obj is a list
 }
 
 PythonList::PythonList (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
@@ -280,29 +280,29 @@ PythonList::GetItemAtIndex (uint32_t ind
 {
     if (m_py_obj)
         return PythonObject(PyList_GetItem(m_py_obj, index));
-    return NULL;
+    return PythonObject();
 }
 
 void
 PythonList::SetItemAtIndex (uint32_t index, const PythonObject & object)
 {
     if (m_py_obj && object)
-        PyList_SetItem(m_py_obj, index, object.GetPythonObject());
+        PyList_SetItem(m_py_obj, index, object.get());
 }
 
 void
 PythonList::AppendItem (const PythonObject &object)
 {
     if (m_py_obj && object)
-        PyList_Append(m_py_obj, object.GetPythonObject());
+        PyList_Append(m_py_obj, object.get());
 }
 
 //----------------------------------------------------------------------
 // PythonDictionary
 //----------------------------------------------------------------------
 
-PythonDictionary::PythonDictionary () :
-    PythonObject(PyDict_New())
+PythonDictionary::PythonDictionary (bool create_empty) :
+PythonObject(create_empty ? PyDict_New() : NULL)
 {
 }
 
@@ -316,7 +316,7 @@ PythonDictionary::PythonDictionary (PyOb
 PythonDictionary::PythonDictionary (const PythonObject &object) :
     PythonObject()
 {
-    Reset(object.GetPythonObject()); // Use "Reset()" to ensure that py_obj is a dictionary
+    Reset(object.get()); // Use "Reset()" to ensure that py_obj is a dictionary
 }
 
 PythonDictionary::PythonDictionary (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
@@ -356,7 +356,7 @@ PythonDictionary::GetItemForKey (const c
         PythonString python_key(key);
         return GetItemForKey(python_key);
     }
-    return NULL;
+    return PythonObject();
 }
 
 
@@ -364,7 +364,7 @@ PythonObject
 PythonDictionary::GetItemForKey (const PythonString &key) const
 {
     if (m_py_obj && key)
-        return PythonObject(PyDict_GetItem(m_py_obj, key.GetPythonObject()));
+        return PythonObject(PyDict_GetItem(m_py_obj, key.get()));
     return PythonObject();
 }
 
@@ -374,7 +374,7 @@ PythonDictionary::GetItemForKeyAsString
 {
     if (m_py_obj && key)
     {
-        PyObject *py_obj = PyDict_GetItem(m_py_obj, key.GetPythonObject());
+        PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get());
         if (py_obj && PyString_Check(py_obj))
             return PyString_AsString(py_obj);
     }
@@ -386,7 +386,7 @@ PythonDictionary::GetItemForKeyAsInteger
 {
     if (m_py_obj && key)
     {
-        PyObject *py_obj = PyDict_GetItem(m_py_obj, key.GetPythonObject());
+        PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get());
         if (py_obj)
         {
             if (PyInt_Check(py_obj))
@@ -404,7 +404,7 @@ PythonDictionary::GetKeys () const
 {
     if (m_py_obj)
         return PythonList(PyDict_Keys(m_py_obj));
-    return PythonList();
+    return PythonList(true);
 }
 
 PythonString
@@ -431,7 +431,7 @@ PythonDictionary::GetValueAtPosition (ui
     Py_ssize_t pos_iter = 0;
     
     if (!m_py_obj)
-        return NULL;
+        return PythonObject();
     
     while (PyDict_Next(m_py_obj, &pos_iter, &key, &value)) {
         if (pos-- == 0)
@@ -441,10 +441,17 @@ PythonDictionary::GetValueAtPosition (ui
 }
 
 void
+PythonDictionary::SetItemForKey (const PythonString &key, PyObject *value)
+{
+    if (m_py_obj && key && value)
+        PyDict_SetItem(m_py_obj, key.get(), value);
+}
+
+void
 PythonDictionary::SetItemForKey (const PythonString &key, const PythonObject &value)
 {
     if (m_py_obj && key && value)
-        PyDict_SetItem(m_py_obj, key.GetPythonObject(), value.GetPythonObject());
+        PyDict_SetItem(m_py_obj, key.get(), value.get());
 }
 
 #endif

Modified: lldb/branches/iohandler/source/Interpreter/ScriptInterpreterNone.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Interpreter/ScriptInterpreterNone.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Interpreter/ScriptInterpreterNone.cpp (original)
+++ lldb/branches/iohandler/source/Interpreter/ScriptInterpreterNone.cpp Thu Jan  2 16:40:14 2014
@@ -11,6 +11,7 @@
 
 #include "lldb/Interpreter/ScriptInterpreterNone.h"
 #include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/Core/StringList.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
@@ -30,14 +31,14 @@ ScriptInterpreterNone::~ScriptInterprete
 bool
 ScriptInterpreterNone::ExecuteOneLine (const char *command, CommandReturnObject *, const ExecuteScriptOptions&)
 {
-    m_interpreter.GetDebugger().GetErrorStream().PutCString ("error: there is no embedded script interpreter in this mode.\n");
+    m_interpreter.GetDebugger().GetErrorFile()->PutCString ("error: there is no embedded script interpreter in this mode.\n");
     return false;
 }
 
 void
 ScriptInterpreterNone::ExecuteInterpreterLoop ()
 {
-    m_interpreter.GetDebugger().GetErrorStream().PutCString ("error: there is no embedded script interpreter in this mode.\n");
+    m_interpreter.GetDebugger().GetErrorFile()->PutCString ("error: there is no embedded script interpreter in this mode.\n");
 }
 
 

Modified: lldb/branches/iohandler/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Interpreter/ScriptInterpreterPython.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/branches/iohandler/source/Interpreter/ScriptInterpreterPython.cpp Thu Jan  2 16:40:14 2014
@@ -32,6 +32,7 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/PythonDataObjects.h"
 #include "lldb/Target/Thread.h"
 
 using namespace lldb;
@@ -69,19 +70,17 @@ _check_and_flush (FILE *stream)
 ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter,
                                          uint16_t on_entry,
                                          uint16_t on_leave,
-                                         FILE* wait_msg_handle) :
+                                         FILE *in,
+                                         FILE *out,
+                                         FILE *err) :
     ScriptInterpreterLocker (),
     m_teardown_session( (on_leave & TearDownSession) == TearDownSession ),
-    m_python_interpreter(py_interpreter),
-    m_tmp_fh(wait_msg_handle)
+    m_python_interpreter(py_interpreter)
 {
-    if (m_python_interpreter && !m_tmp_fh)
-        m_tmp_fh = (m_python_interpreter->m_dbg_stdout ? m_python_interpreter->m_dbg_stdout : stdout);
-
     DoAcquireLock();
     if ((on_entry & InitSession) == InitSession)
     {
-        if (DoInitSession((on_entry & InitGlobals) == InitGlobals) == false)
+        if (DoInitSession((on_entry & InitGlobals) == InitGlobals, in, out, err) == false)
         {
             // Don't teardown the session if we didn't init it.
             m_teardown_session = false;
@@ -100,11 +99,11 @@ ScriptInterpreterPython::Locker::DoAcqui
 }
 
 bool
-ScriptInterpreterPython::Locker::DoInitSession(bool init_lldb_globals)
+ScriptInterpreterPython::Locker::DoInitSession(bool init_lldb_globals, FILE *in, FILE *out, FILE *err)
 {
     if (!m_python_interpreter)
         return false;
-    return m_python_interpreter->EnterSession (init_lldb_globals);
+    return m_python_interpreter->EnterSession (init_lldb_globals, in, out, err);
 }
 
 bool
@@ -133,257 +132,24 @@ ScriptInterpreterPython::Locker::~Locker
     DoFreeLock();
 }
 
-ScriptInterpreterPython::PythonInputReaderManager::PythonInputReaderManager (ScriptInterpreterPython *interpreter) :
-m_interpreter(interpreter),
-m_debugger_sp(),
-m_reader_sp(),
-m_error(false)
-{
-    if (m_interpreter == NULL)
-    {
-        m_error = true;
-        return;
-    }
-    
-    m_debugger_sp = m_interpreter->GetCommandInterpreter().GetDebugger().shared_from_this();
-    
-    if (!m_debugger_sp)
-    {
-        m_error = true;
-        return;
-    }
-
-    m_reader_sp = InputReaderSP(new InputReader(*m_debugger_sp.get()));
-    
-    if (!m_reader_sp)
-    {
-        m_error = true;
-        return;
-    }
-    
-    Error error (m_reader_sp->Initialize (ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback,
-                                          m_interpreter,                // baton
-                                          eInputReaderGranularityLine,  // token size, to pass to callback function
-                                          NULL,                         // end token
-                                          NULL,                         // prompt
-                                          true));                       // echo input
-    if (error.Fail())
-        m_error = true;
-    else
-    {
-        m_debugger_sp->PushInputReader (m_reader_sp);
-        m_interpreter->m_embedded_thread_input_reader_sp = m_reader_sp;
-    }
-}
-
-ScriptInterpreterPython::PythonInputReaderManager::~PythonInputReaderManager()
-{
-    // Nothing to do if either m_interpreter or m_reader_sp is invalid.
-    if (!m_interpreter || !m_reader_sp)
-        return;
-
-    m_reader_sp->SetIsDone (true);
-    if (m_debugger_sp)
-        m_debugger_sp->PopInputReader(m_reader_sp);
-
-    // Only mess with m_interpreter's counterpart if, indeed, they are the same object.
-    if (m_reader_sp.get() == m_interpreter->m_embedded_thread_input_reader_sp.get())
-    {
-        m_interpreter->m_embedded_thread_pty.CloseSlaveFileDescriptor();
-        m_interpreter->m_embedded_thread_input_reader_sp.reset();
-    }
-}
-
-size_t
-ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback (void *baton,
-                                                                        InputReader &reader,
-                                                                        InputReaderAction notification,
-                                                                        const char *bytes, 
-                                                                        size_t bytes_len)
-{
-    lldb::thread_t embedded_interpreter_thread;
-    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
-    
-    if (baton == NULL)
-        return 0;
-    
-    ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
-    
-    if (script_interpreter->m_script_lang != eScriptLanguagePython)
-        return 0;
-    
-    switch (notification)
-    {
-        case eInputReaderActivate:
-        {
-            // Save terminal settings if we can
-            int input_fd = reader.GetDebugger().GetInputFile().GetDescriptor();
-            if (input_fd == File::kInvalidDescriptor)
-                input_fd = STDIN_FILENO;
-            
-            script_interpreter->SaveTerminalState(input_fd);
-
-            char error_str[1024];
-            if (script_interpreter->m_embedded_thread_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, 
-                                                                                    sizeof(error_str)))
-            {
-                if (log)
-                    log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, succeeded in opening master pty (fd = %d).",
-                                 script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor());
-                {
-                    StreamString run_string;
-                    char error_str[1024];
-                    const char *pty_slave_name = script_interpreter->m_embedded_thread_pty.GetSlaveName (error_str, sizeof (error_str));
-                    if (pty_slave_name != NULL && PyThreadState_GetDict() != NULL)
-                    {
-                        ScriptInterpreterPython::Locker locker(script_interpreter,
-                                                               ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
-                                                               ScriptInterpreterPython::Locker::FreeAcquiredLock);
-                        run_string.Printf ("run_one_line (%s, 'save_stderr = sys.stderr')", script_interpreter->m_dictionary_name.c_str());
-                        PyRun_SimpleString (run_string.GetData());
-                        run_string.Clear ();
-                        
-                        run_string.Printf ("run_one_line (%s, 'sys.stderr = sys.stdout')", script_interpreter->m_dictionary_name.c_str());
-                        PyRun_SimpleString (run_string.GetData());
-                        run_string.Clear ();
-                        
-                        run_string.Printf ("run_one_line (%s, 'save_stdin = sys.stdin')", script_interpreter->m_dictionary_name.c_str());
-                        PyRun_SimpleString (run_string.GetData());
-                        run_string.Clear ();
-                        
-                        run_string.Printf ("run_one_line (%s, \"sys.stdin = open ('%s', 'r')\")", script_interpreter->m_dictionary_name.c_str(),
-                                           pty_slave_name);
-                        PyRun_SimpleString (run_string.GetData());
-                        run_string.Clear ();
-                    }
-                }
-                embedded_interpreter_thread = Host::ThreadCreate ("<lldb.script-interpreter.noninteractive-python>",
-                                                                  ScriptInterpreterPython::PythonInputReaderManager::RunPythonInputReader,
-                                                                  script_interpreter, NULL);
-                if (IS_VALID_LLDB_HOST_THREAD(embedded_interpreter_thread))
-                {
-                    if (log)
-                        log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, succeeded in creating thread (thread_t = %p)", (void *)embedded_interpreter_thread);
-                    Error detach_error;
-                    Host::ThreadDetach (embedded_interpreter_thread, &detach_error);
-                }
-                else
-                {
-                    if (log)
-                        log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, failed in creating thread");
-                    reader.SetIsDone (true);
-                }
-            }
-            else
-            {
-                if (log)
-                    log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, failed to open master pty ");
-                reader.SetIsDone (true);
-            }
-        }
-            break;
-            
-        case eInputReaderDeactivate:
-			// When another input reader is pushed, don't leave the session...
-            //script_interpreter->LeaveSession ();
-            break;
-            
-        case eInputReaderReactivate:
-//        {
-//            ScriptInterpreterPython::Locker locker(script_interpreter,
-//                                                   ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
-//                                                   ScriptInterpreterPython::Locker::FreeAcquiredLock);
-//        }
-            break;
-            
-        case eInputReaderAsynchronousOutputWritten:
-            break;
-            
-        case eInputReaderInterrupt:
-            {
-                PyThreadState* state = _PyThreadState_Current;
-                if (!state)
-                    state = script_interpreter->m_command_thread_state;
-                if (state)
-                {
-                    long tid = state->thread_id;
-                    _PyThreadState_Current = state;
-                    int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
-                    if (log)
-                        log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, tid = %ld, num_threads = %d, state = %p",
-                                    tid,num_threads,state);
-                }
-                else if (log)
-                    log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, state = NULL");
-            }
-            break;
-            
-        case eInputReaderEndOfFile:
-            reader.SetIsDone(true);
-            break;
-            
-        case eInputReaderGotToken:
-            if (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor() != -1)
-            {
-                if (log)
-                    log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, GotToken, bytes='%s', byte_len = %zu", bytes,
-                                 bytes_len);
-                if (bytes && bytes_len)
-                    ::write (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor(), bytes, bytes_len);
-                ::write (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor(), "\n", 1);
-            }
-            else
-            {
-                if (log)
-                    log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, GotToken, bytes='%s', byte_len = %zu, Master File Descriptor is bad.", 
-                                 bytes,
-                                 bytes_len);
-                reader.SetIsDone (true);
-            }
-            break;
-            
-        case eInputReaderDone:
-            {
-                StreamString run_string;
-                char error_str[1024];
-                const char *pty_slave_name = script_interpreter->m_embedded_thread_pty.GetSlaveName (error_str, sizeof (error_str));
-                if (pty_slave_name != NULL && PyThreadState_GetDict() != NULL)
-                {
-                    ScriptInterpreterPython::Locker locker(script_interpreter,
-                                                           ScriptInterpreterPython::Locker::AcquireLock,
-                                                           ScriptInterpreterPython::Locker::FreeAcquiredLock);
-                    run_string.Printf ("run_one_line (%s, 'sys.stdin = save_stdin; sys.stderr = save_stderr')", script_interpreter->m_dictionary_name.c_str());
-                    PyRun_SimpleString (run_string.GetData());
-                    run_string.Clear();
-                }
-                // Restore terminal settings if they were validly saved
-                if (log)
-                    log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Done, closing down input reader.");
-                
-                script_interpreter->RestoreTerminalState ();
-                
-                script_interpreter->m_embedded_thread_pty.CloseMasterFileDescriptor();
-            }            
-            break;
-    }
-    
-    return bytes_len;
-}
 
 ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) :
     ScriptInterpreter (interpreter, eScriptLanguagePython),
-    m_embedded_thread_pty (),
-    m_embedded_python_pty (),
-    m_embedded_thread_input_reader_sp (),
-    m_embedded_python_input_reader_sp (),
-    m_dbg_stdout (interpreter.GetDebugger().GetOutputFile().GetStream()),
-    m_new_sysout (NULL),
-    m_old_sysout (NULL),
-    m_old_syserr (NULL),
-    m_run_one_line (NULL),
+    IOHandlerDelegateMultiline("DONE"),
+    m_saved_stdin (),
+    m_saved_stdout (),
+    m_saved_stderr (),
+    m_main_module (),
+    m_lldb_module (),
+    m_session_dict (false),     // Don't create an empty dictionary, leave it invalid
+    m_sys_module_dict (false),  // Don't create an empty dictionary, leave it invalid
+    m_run_one_line_function (),
+    m_run_one_line_str_global (),
     m_dictionary_name (interpreter.GetDebugger().GetInstanceName().AsCString()),
     m_terminal_state (),
+    m_active_io_handler (eIOHandlerNone),
     m_session_is_active (false),
+    m_pty_slave_is_open (false),
     m_valid_session (true),
     m_command_thread_state (NULL)
 {
@@ -435,62 +201,116 @@ ScriptInterpreterPython::ScriptInterpret
     run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64 "; pydoc.pager = pydoc.plainpager')", m_dictionary_name.c_str(),
                        interpreter.GetDebugger().GetID());
     PyRun_SimpleString (run_string.GetData());
-    
-    if (m_dbg_stdout != NULL)
-    {
-        m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush);
-    }
-    
-    // get the output file handle from the debugger (if any)
-    File& out_file = interpreter.GetDebugger().GetOutputFile();
-    if (out_file.IsValid())
-        ResetOutputFileHandle(out_file.GetStream());
 }
 
 ScriptInterpreterPython::~ScriptInterpreterPython ()
 {
-    Debugger &debugger = GetCommandInterpreter().GetDebugger();
+}
 
-    if (m_embedded_thread_input_reader_sp.get() != NULL)
-    {
-        m_embedded_thread_input_reader_sp->SetIsDone (true);
-        m_embedded_thread_pty.CloseSlaveFileDescriptor();
-        const InputReaderSP reader_sp = m_embedded_thread_input_reader_sp;
-        debugger.PopInputReader (reader_sp);
-        m_embedded_thread_input_reader_sp.reset();
-    }
+void
+ScriptInterpreterPython::IOHandlerActivated (IOHandler &io_handler)
+{
+    const char *instructions = NULL;
     
-    if (m_embedded_python_input_reader_sp.get() != NULL)
+    switch (m_active_io_handler)
     {
-        m_embedded_python_input_reader_sp->SetIsDone (true);
-        m_embedded_python_pty.CloseSlaveFileDescriptor();
-        const InputReaderSP reader_sp = m_embedded_python_input_reader_sp;
-        debugger.PopInputReader (reader_sp);
-        m_embedded_python_input_reader_sp.reset();
+    case eIOHandlerNone:
+            break;
+    case eIOHandlerBreakpoint:
+            instructions = R"(Enter your Python command(s). Type 'DONE' to end.
+def function (frame, bp_loc, internal_dict):
+    """frame: the lldb.SBFrame for the location at which you stopped
+       bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information
+       internal_dict: an LLDB support object not to be used"""
+)";
+            break;
+    case eIOHandlerWatchpoint:
+            instructions = "Enter your Python command(s). Type 'DONE' to end.\n";
+            break;
     }
     
-    if (m_new_sysout)
+    if (instructions)
     {
-        Locker locker(this,
-                      ScriptInterpreterPython::Locker::AcquireLock,
-                      ScriptInterpreterPython::Locker::FreeLock);
-        Py_XDECREF ((PyObject*)m_new_sysout);
+        StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+        if (output_sp)
+        {
+            output_sp->PutCString(instructions);
+            output_sp->Flush();
+        }
     }
 }
 
 void
-ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh)
+ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
 {
-    if (fh == NULL)
-        return;
-        
-    m_dbg_stdout = fh;
+    io_handler.SetIsDone(true);
+    bool batch_mode = m_interpreter.GetBatchCommandMode();
+
+    switch (m_active_io_handler)
+    {
+    case eIOHandlerNone:
+        break;
+    case eIOHandlerBreakpoint:
+        {
+            BreakpointOptions *bp_options = (BreakpointOptions *)io_handler.GetUserData();
+            std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+            if (data_ap.get())
+            {
+                data_ap->user_source.SplitIntoLines(data);
+                
+                if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
+                {
+                    BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+                    bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
+                }
+                else if (!batch_mode)
+                {
+                    StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+                    if (error_sp)
+                    {
+                        error_sp->Printf ("Warning: No command attached to breakpoint.\n");
+                        error_sp->Flush();
+                    }
+                }
+            }
+            m_active_io_handler = eIOHandlerNone;
+        }
+        break;
+    case eIOHandlerWatchpoint:
+        {
+            WatchpointOptions *wp_options = (WatchpointOptions *)io_handler.GetUserData();
+            std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
+            if (data_ap.get())
+            {
+                data_ap->user_source.SplitIntoLines(data);
+                
+                if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
+                {
+                    BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
+                    wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp);
+                }
+                else if (!batch_mode)
+                {
+                    StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+                    if (error_sp)
+                    {
+                        error_sp->Printf ("Warning: No command attached to breakpoint.\n");
+                        error_sp->Flush();
+                    }
+                }
+            }
+            m_active_io_handler = eIOHandlerNone;
+        }
+        break;
+    }
 
-    Locker locker(this,
-                  ScriptInterpreterPython::Locker::AcquireLock,
-                  ScriptInterpreterPython::Locker::FreeAcquiredLock);
 
-    m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush);
+}
+
+
+void
+ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh)
+{
 }
 
 void
@@ -529,15 +349,15 @@ ScriptInterpreterPython::LeaveSession ()
     // When the current thread state is NULL, PyThreadState_Get() issues a fatal error.
     if (PyThreadState_GetDict())
     {
-        PyObject *sysmod = PyImport_AddModule ("sys");
-        PyObject *sysdict = PyModule_GetDict (sysmod);
-
-        if (m_new_sysout && sysmod && sysdict)
+        PythonDictionary &sys_module_dict = GetSysModuleDictionary ();
+        if (sys_module_dict)
         {
-            if (m_old_sysout)
-                PyDict_SetItemString (sysdict, "stdout", (PyObject*)m_old_sysout);
-            if (m_old_syserr)
-                PyDict_SetItemString (sysdict, "stderr", (PyObject*)m_old_syserr);
+            if (m_saved_stdin)
+                sys_module_dict.SetItemForKey("stdin", m_saved_stdin);
+            if (m_saved_stdout)
+                sys_module_dict.SetItemForKey("stdout", m_saved_stdout);
+            if (m_saved_stderr)
+                sys_module_dict.SetItemForKey("stderr", m_saved_stderr);
         }
     }
 
@@ -545,7 +365,10 @@ ScriptInterpreterPython::LeaveSession ()
 }
 
 bool
-ScriptInterpreterPython::EnterSession (bool init_lldb_globals)
+ScriptInterpreterPython::EnterSession (bool init_lldb_globals,
+                                       FILE *in,
+                                       FILE *out,
+                                       FILE *err)
 {
     // If we have already entered the session, without having officially 'left' it, then there is no need to 
     // 'enter' it again.
@@ -578,26 +401,40 @@ ScriptInterpreterPython::EnterSession (b
     else
     {
         // If we aren't initing the globals, we should still always set the debugger (since that is always unique.)
-        run_string.Printf (    "run_one_line (%s, \"lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
+        run_string.Printf (    "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
         run_string.Printf (    "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID());
-        run_string.PutCString ("\")");
+        run_string.PutCString ("')");
     }
 
     PyRun_SimpleString (run_string.GetData());
     run_string.Clear();
 
-    PyObject *sysmod = PyImport_AddModule ("sys");
-    PyObject *sysdict = PyModule_GetDict (sysmod);
-
-    if (m_new_sysout && sysmod && sysdict)
+    PythonDictionary &sys_module_dict = GetSysModuleDictionary ();
+    if (sys_module_dict)
     {
-        m_old_sysout = PyDict_GetItemString(sysdict, "stdout");
-        m_old_syserr = PyDict_GetItemString(sysdict, "stderr");
-        if (m_new_sysout)
+        if (in)
         {
-            PyDict_SetItemString (sysdict, "stdout", (PyObject*)m_new_sysout);
-            PyDict_SetItemString (sysdict, "stderr", (PyObject*)m_new_sysout);
+            m_saved_stdin.Reset(sys_module_dict.GetItemForKey("stdin"));
+            sys_module_dict.SetItemForKey ("stdin", PyFile_FromFile (in, (char *) "", (char *) "r", 0));
         }
+        else
+            m_saved_stdin.Reset();
+        
+        if (out)
+        {
+            m_saved_stdout.Reset(sys_module_dict.GetItemForKey("stdout"));
+            sys_module_dict.SetItemForKey ("stdout", PyFile_FromFile (out, (char *) "", (char *) "w", 0));
+        }
+        else
+            m_saved_stdout.Reset();
+        
+        if (err)
+        {
+            m_saved_stderr.Reset(sys_module_dict.GetItemForKey("stderr"));
+            sys_module_dict.SetItemForKey ("stderr", PyFile_FromFile (err, (char *) "", (char *) "w", 0));
+        }
+        else
+            m_saved_stdout.Reset();
     }
 
     if (PyErr_Occurred())
@@ -606,44 +443,42 @@ ScriptInterpreterPython::EnterSession (b
     return true;
 }
 
-static PyObject*
-FindSessionDictionary (const char* dict_name)
+PythonObject &
+ScriptInterpreterPython::GetMainModule ()
 {
-    static std::map<ConstString,PyObject*> g_dict_map;
-    
-    ConstString dict(dict_name);
-    
-    std::map<ConstString,PyObject*>::iterator iter = g_dict_map.find(dict);
-    
-    if (iter != g_dict_map.end())
-        return iter->second;
-    
-    PyObject *main_mod = PyImport_AddModule ("__main__");
-    if (main_mod != NULL)
+    if (!m_main_module)
+        m_main_module.Reset(PyImport_AddModule ("__main__"));
+    return m_main_module;
+}
+
+PythonDictionary &
+ScriptInterpreterPython::GetSessionDictionary ()
+{
+    if (!m_session_dict)
     {
-        PyObject *main_dict = PyModule_GetDict (main_mod);
-        if ((main_dict != NULL)
-            && PyDict_Check (main_dict))
+        PythonObject &main_module = GetMainModule ();
+        if (main_module)
         {
-            // Go through the main dictionary looking for the correct python script interpreter dictionary
-            PyObject *key, *value;
-            Py_ssize_t pos = 0;
-            
-            while (PyDict_Next (main_dict, &pos, &key, &value))
+            PythonDictionary main_dict(PyModule_GetDict (main_module.get()));
+            if (main_dict)
             {
-                // We have stolen references to the key and value objects in the dictionary; we need to increment 
-                // them now so that Python's garbage collector doesn't collect them out from under us.
-                Py_INCREF (key);
-                Py_INCREF (value);
-                if (strcmp (PyString_AsString (key), dict_name) == 0)
-                {
-                    g_dict_map[dict] = value;
-                    return value;
-                }
+                m_session_dict = main_dict.GetItemForKey(m_dictionary_name.c_str());
             }
         }
     }
-    return NULL;
+    return m_session_dict;
+}
+
+PythonDictionary &
+ScriptInterpreterPython::GetSysModuleDictionary ()
+{
+    if (!m_sys_module_dict)
+    {
+        PyObject *sys_module = PyImport_AddModule ("sys");
+        if (sys_module)
+            m_sys_module_dict.Reset(PyModule_GetDict (sys_module));
+    }
+    return m_sys_module_dict;
 }
 
 static std::string
@@ -665,80 +500,81 @@ GenerateUniqueName (const char* base_nam
 }
 
 bool
+ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects ()
+{
+    if (!m_run_one_line_function)
+    {
+        PyObject *module = PyImport_AddModule ("lldb.embedded_interpreter");
+        if (module != NULL)
+        {
+            PythonDictionary module_dict (PyModule_GetDict (module));
+            if (module_dict)
+            {
+                m_run_one_line_function = module_dict.GetItemForKey("run_one_line");
+                m_run_one_line_str_global = module_dict.GetItemForKey("g_run_one_line_str");
+            }
+        }
+    }
+    return (bool)m_run_one_line_function;
+}
+
+bool
 ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options)
 {
     if (!m_valid_session)
         return false;
-        
+    
     // We want to call run_one_line, passing in the dictionary and the command string.  We cannot do this through
     // PyRun_SimpleString here because the command string may contain escaped characters, and putting it inside
     // another string to pass to PyRun_SimpleString messes up the escaping.  So we use the following more complicated
     // method to pass the command string directly down to Python.
-
+    Debugger &debugger = m_interpreter.GetDebugger();
+    
     Locker locker(this,
-                  ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
-                  ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+                  ScriptInterpreterPython::Locker::AcquireLock |
+                  ScriptInterpreterPython::Locker::InitSession |
+                  (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
+                  ScriptInterpreterPython::Locker::FreeAcquiredLock |
+                  ScriptInterpreterPython::Locker::TearDownSession,
+                  debugger.GetInputFile()->GetFile().GetStream(),
+                  debugger.GetOutputFile()->GetFile().GetStream(),
+                  debugger.GetErrorFile()->GetFile().GetStream());
 
     bool success = false;
 
+
     if (command)
     {
         // Find the correct script interpreter dictionary in the main module.
-        PyObject *script_interpreter_dict = FindSessionDictionary(m_dictionary_name.c_str());
-        if (script_interpreter_dict != NULL)
+        PythonDictionary &session_dict = GetSessionDictionary ();
+        if (session_dict)
         {
-            PyObject *pfunc = (PyObject*)m_run_one_line;
-            PyObject *pmod = PyImport_AddModule ("lldb.embedded_interpreter");
-            if (pmod != NULL)
+            if (GetEmbeddedInterpreterModuleObjects ())
             {
-                PyObject *pmod_dict = PyModule_GetDict (pmod);
-                if ((pmod_dict != NULL)
-                    && PyDict_Check (pmod_dict))
+                PyObject *pfunc = m_run_one_line_function.get();
+                
+                if (pfunc && PyCallable_Check (pfunc))
                 {
-                    if (!pfunc)
+                    PythonObject pargs (Py_BuildValue("(Os)", session_dict.get(), command));
+                    if (pargs)
                     {
-                        PyObject *key, *value;
-                        Py_ssize_t pos = 0;
-                        
-                        while (PyDict_Next (pmod_dict, &pos, &key, &value))
+                        PythonObject return_value;
+                        { // scope for PythonInputReaderManager
+                            //PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
+                            return_value.Reset(PyObject_CallObject (pfunc, pargs.get()));
+                        }
+                        if (return_value)
                         {
-                            Py_INCREF (key);
-                            Py_INCREF (value);
-                            if (strcmp (PyString_AsString (key), "run_one_line") == 0)
-                            {
-                                pfunc = value;
-                                break;
-                            }
+                            success = true;
                         }
-                        m_run_one_line = pfunc;
-                    }
-                    
-                    if (pfunc && PyCallable_Check (pfunc))
-                    {
-                        PyObject *pargs = Py_BuildValue("(Os)",script_interpreter_dict,command);
-                        if (pargs != NULL)
+                        else if (options.GetMaskoutErrors() && PyErr_Occurred ())
                         {
-                            PyObject *pvalue = NULL;
-                            { // scope for PythonInputReaderManager
-                                PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
-                                pvalue = PyObject_CallObject (pfunc, pargs);
-                            }
-                            Py_XDECREF (pargs);
-                            if (pvalue != NULL)
-                            {
-                                Py_XDECREF (pvalue);
-                                success = true;
-                            }
-                            else if (options.GetMaskoutErrors() && PyErr_Occurred ())
-                            {
-                                PyErr_Print();
-                                PyErr_Clear();
-                            }
+                            PyErr_Print();
+                            PyErr_Clear();
                         }
                     }
                 }
             }
-            Py_INCREF (script_interpreter_dict);
         }
 
         if (success)
@@ -755,155 +591,98 @@ ScriptInterpreterPython::ExecuteOneLine
     return false;
 }
 
-size_t
-ScriptInterpreterPython::InputReaderCallback
-(
-    void *baton, 
-    InputReader &reader, 
-    InputReaderAction notification,
-    const char *bytes, 
-    size_t bytes_len
-)
-{
-    lldb::thread_t embedded_interpreter_thread;
-    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
 
-    if (baton == NULL)
-        return 0;
-        
-    ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
+class IOHandlerPythonInterpreter :
+    public IOHandler
+{
+public:
     
-    if (script_interpreter->m_script_lang != eScriptLanguagePython)
-        return 0;
+    IOHandlerPythonInterpreter (Debugger &debugger,
+                                ScriptInterpreterPython *python) :
+        IOHandler (debugger),
+        m_python(python)
+    {
+        
+    }
     
-    switch (notification)
+    virtual
+    ~IOHandlerPythonInterpreter()
     {
-    case eInputReaderActivate:
+        
+    }
+    virtual void
+    Run ()
+    {
+        if (m_python)
         {
-            StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-            bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-            if (!batch_mode)
-            {
-                out_stream->Printf ("Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.\n");
-                out_stream->Flush();
-            }
-
-            // Save terminal settings if we can
-            int input_fd = reader.GetDebugger().GetInputFile().GetDescriptor();
-            if (input_fd == File::kInvalidDescriptor)
-                input_fd = STDIN_FILENO;
-
-            script_interpreter->SaveTerminalState(input_fd);
-
+            int stdin_fd = GetInputFD();
+            if (stdin_fd >= 0)
             {
-                ScriptInterpreterPython::Locker locker(script_interpreter,
-                                                       ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
-                                                       ScriptInterpreterPython::Locker::FreeAcquiredLock);
-            }
-
-            char error_str[1024];
-            if (script_interpreter->m_embedded_python_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, 
-                                                                                    sizeof(error_str)))
-            {
-                if (log)
-                    log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, succeeded in opening master pty (fd = %d).",
-                                  script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor());
-                embedded_interpreter_thread = Host::ThreadCreate ("<lldb.script-interpreter.embedded-python-loop>",
-                                                                  ScriptInterpreterPython::RunEmbeddedPythonInterpreter,
-                                                                  script_interpreter, NULL);
-                if (IS_VALID_LLDB_HOST_THREAD(embedded_interpreter_thread))
-                {
-                    if (log)
-                        log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, succeeded in creating thread (thread_t = %p)", (void *)embedded_interpreter_thread);
-                    Error detach_error;
-                    Host::ThreadDetach (embedded_interpreter_thread, &detach_error);
-                }
-                else
-                {
-                    if (log)
-                        log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, failed in creating thread");
-                    reader.SetIsDone (true);
+                Terminal terminal(stdin_fd);
+                TerminalState terminal_state;
+                const bool is_a_tty = terminal.IsATerminal();
+                
+                if (is_a_tty)
+                {
+                    terminal_state.Save (stdin_fd, false);
+                    terminal.SetCanonical(false);
+                    terminal.SetEcho(true);
                 }
-            }
-            else
-            {
-                if (log)
-                    log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, failed to open master pty ");
-                reader.SetIsDone (true);
+                
+                ScriptInterpreterPython::Locker locker (m_python,
+                                                        ScriptInterpreterPython::Locker::AcquireLock |
+                                                        ScriptInterpreterPython::Locker::InitSession |
+                                                        ScriptInterpreterPython::Locker::InitGlobals,
+                                                        ScriptInterpreterPython::Locker::FreeAcquiredLock |
+                                                        ScriptInterpreterPython::Locker::TearDownSession);
+
+                // The following call drops into the embedded interpreter loop and stays there until the
+                // user chooses to exit from the Python interpreter.
+                // This embedded interpreter will, as any Python code that performs I/O, unlock the GIL before
+                // a system call that can hang, and lock it when the syscall has returned.
+                
+                // We need to surround the call to the embedded interpreter with calls to PyGILState_Ensure and
+                // PyGILState_Release (using the Locker above). This is because Python has a global lock which must be held whenever we want
+                // to touch any Python objects. Otherwise, if the user calls Python code, the interpreter state will be off,
+                // and things could hang (it's happened before).
+                
+                StreamString run_string;
+                run_string.Printf ("run_python_interpreter (%s)", m_python->GetDictionaryName ());
+                PyRun_SimpleString (run_string.GetData());
+                
+                if (is_a_tty)
+                    terminal_state.Restore();
             }
         }
-        break;
-
-    case eInputReaderDeactivate:
-			// When another input reader is pushed, don't leave the session...
-            //script_interpreter->LeaveSession ();
-        break;
+        SetIsDone(true);
+    }
 
-    case eInputReaderReactivate:
-        {
-            ScriptInterpreterPython::Locker locker (script_interpreter,
-                                                    ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
-                                                    ScriptInterpreterPython::Locker::FreeAcquiredLock);
-        }
-        break;
+    virtual void
+    Hide ()
+    {
         
-    case eInputReaderAsynchronousOutputWritten:
-        break;
+    }
+    
+    virtual void
+    Refresh ()
+    {
         
-    case eInputReaderInterrupt:
-        ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "raise KeyboardInterrupt\n", 24);
-        break;
+    }
+    
+    virtual void
+    Interrupt ()
+    {
         
-    case eInputReaderEndOfFile:
-        ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "quit()\n", 7);
-        break;
-
-    case eInputReaderGotToken:
-        if (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor() != -1)
-        {
-            if (log)
-                log->Printf ("ScriptInterpreterPython::InputReaderCallback, GotToken, bytes='%s', byte_len = %zu", bytes,
-                             bytes_len);
-            if (bytes && bytes_len)
-            {
-                if ((int) bytes[0] == 4)
-                    ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "quit()", 6);
-                else
-                    ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), bytes, bytes_len);
-            }
-            ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "\n", 1);
-        }
-        else
-        {
-            if (log)
-                log->Printf ("ScriptInterpreterPython::InputReaderCallback, GotToken, bytes='%s', byte_len = %zu, Master File Descriptor is bad.", 
-                             bytes,
-                             bytes_len);
-            reader.SetIsDone (true);
-        }
-
-        break;
+    }
+    
+    virtual void
+    GotEOF()
+    {
         
-    case eInputReaderDone:
-        {
-            Locker locker(script_interpreter,
-                          ScriptInterpreterPython::Locker::AcquireLock,
-                          ScriptInterpreterPython::Locker::FreeAcquiredLock);
-            script_interpreter->LeaveSession ();
-        }
-
-        // Restore terminal settings if they were validly saved
-        if (log)
-            log->Printf ("ScriptInterpreterPython::InputReaderCallback, Done, closing down input reader.");
-            
-        script_interpreter->RestoreTerminalState ();
-
-        script_interpreter->m_embedded_python_pty.CloseMasterFileDescriptor();
-        break;
     }
-
-    return bytes_len;
-}
+protected:
+    ScriptInterpreterPython *m_python;
+};
 
 
 void
@@ -918,24 +697,13 @@ ScriptInterpreterPython::ExecuteInterpre
     // try to embed a running interpreter loop inside the already running Python interpreter loop, so we won't
     // do it.
 
-    if (!debugger.GetInputFile().IsValid())
+    if (!debugger.GetInputFile()->GetFile().IsValid())
         return;
 
-    InputReaderSP reader_sp (new InputReader(debugger));
-    if (reader_sp)
+    IOHandlerSP io_handler_sp (new IOHandlerPythonInterpreter (debugger, this));
+    if (io_handler_sp)
     {
-        Error error (reader_sp->Initialize (ScriptInterpreterPython::InputReaderCallback,
-                                            this,                         // baton
-                                            eInputReaderGranularityLine,  // token size, to pass to callback function
-                                            NULL,                         // end token
-                                            NULL,                         // prompt
-                                            true));                       // echo input
-     
-        if (error.Success())
-        {
-            debugger.PushInputReader (reader_sp);
-            m_embedded_python_input_reader_sp = reader_sp;
-        }
+        debugger.PushIOHandler(io_handler_sp);
     }
 }
 
@@ -951,27 +719,21 @@ ScriptInterpreterPython::ExecuteOneLineW
                   ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
 
     PyObject *py_return = NULL;
-    PyObject *mainmod = PyImport_AddModule ("__main__");
-    PyObject *globals = PyModule_GetDict (mainmod);
-    PyObject *locals = NULL;
+    PythonObject &main_module = GetMainModule ();
+    PythonDictionary globals (PyModule_GetDict(main_module.get()));
     PyObject *py_error = NULL;
     bool ret_success = false;
-    bool should_decrement_locals = false;
     int success;
     
-    locals = FindSessionDictionary(m_dictionary_name.c_str());
+    PythonDictionary locals = GetSessionDictionary ();
     
-    if (locals == NULL)
+    if (!locals)
     {
-        locals = PyObject_GetAttrString (globals, m_dictionary_name.c_str());
-        should_decrement_locals = true;
+        locals = PyObject_GetAttrString (globals.get(), m_dictionary_name.c_str());
     }
         
-    if (locals == NULL)
-    {
+    if (!locals)
         locals = globals;
-        should_decrement_locals = false;
-    }
 
     py_error = PyErr_Occurred();
     if (py_error != NULL)
@@ -980,22 +742,18 @@ ScriptInterpreterPython::ExecuteOneLineW
     if (in_string != NULL)
     {
         { // scope for PythonInputReaderManager
-            PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
-            py_return = PyRun_String (in_string, Py_eval_input, globals, locals);
+            //PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
+            py_return = PyRun_String (in_string, Py_eval_input, globals.get(), locals.get());
             if (py_return == NULL)
             { 
                 py_error = PyErr_Occurred ();
                 if (py_error != NULL)
                     PyErr_Clear ();
 
-                py_return = PyRun_String (in_string, Py_single_input, globals, locals);
+                py_return = PyRun_String (in_string, Py_single_input, globals.get(), locals.get());
             }
         }
 
-        if (locals != NULL
-            && should_decrement_locals)
-            Py_XDECREF (locals);
-
         if (py_return != NULL)
         {
             switch (return_type)
@@ -1125,25 +883,21 @@ ScriptInterpreterPython::ExecuteMultiple
                   ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
 
     bool success = false;
-    PyObject *py_return = NULL;
-    PyObject *mainmod = PyImport_AddModule ("__main__");
-    PyObject *globals = PyModule_GetDict (mainmod);
-    PyObject *locals = NULL;
+    PythonObject return_value;
+    PythonObject &main_module = GetMainModule ();
+    PythonDictionary globals (PyModule_GetDict(main_module.get()));
     PyObject *py_error = NULL;
-    bool should_decrement_locals = false;
 
-    locals = FindSessionDictionary(m_dictionary_name.c_str());
+    PythonDictionary locals = GetSessionDictionary ();
     
-    if (locals == NULL)
+    if (!locals)
     {
-        locals = PyObject_GetAttrString (globals, m_dictionary_name.c_str());
-        should_decrement_locals = true;
+        locals = PyObject_GetAttrString (globals.get(), m_dictionary_name.c_str());
     }
 
-    if (locals == NULL)
+    if (!locals)
     {
         locals = globals;
-        should_decrement_locals = false;
     }
 
     py_error = PyErr_Occurred();
@@ -1159,16 +913,11 @@ ScriptInterpreterPython::ExecuteMultiple
             if (compiled_code)
             {
                 { // scope for PythonInputReaderManager
-                    PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
-                    py_return = PyEval_EvalCode (compiled_code, globals, locals);
+                    //PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
+                    return_value.Reset(PyEval_EvalCode (compiled_code, globals.get(), locals.get()));
                 }
-                if (py_return != NULL)
-                {
+                if (return_value)
                     success = true;
-                    Py_XDECREF (py_return);
-                }
-                if (locals && should_decrement_locals)
-                    Py_XDECREF (locals);
             }
         }
     }
@@ -1176,6 +925,9 @@ ScriptInterpreterPython::ExecuteMultiple
     py_error = PyErr_Occurred ();
     if (py_error != NULL)
     {
+        puts(in_string);
+        _PyObject_Dump (py_error);
+        PyErr_Print();
         success = false;
         if (options.GetMaskoutErrors())
         {
@@ -1188,312 +940,21 @@ ScriptInterpreterPython::ExecuteMultiple
     return success;
 }
 
-static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.";
-
-static const char *g_bkpt_command_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
-                                                        "def function(frame,bp_loc,internal_dict):\n"
-                                                        "    \"\"\"frame: the SBFrame for the location at which you stopped\n"
-                                                        "       bp_loc: an SBBreakpointLocation for the breakpoint location information\n"
-                                                        "       internal_dict: an LLDB support object not to be used\"\"\"";
-
-size_t
-ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback
-(
-    void *baton, 
-    InputReader &reader, 
-    InputReaderAction notification,
-    const char *bytes, 
-    size_t bytes_len
-)
-{
-    static StringList commands_in_progress;
-    
-    switch (notification)
-    {
-    case eInputReaderActivate:
-        {
-            
-            StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-            bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-            commands_in_progress.Clear();
-            if (!batch_mode)
-            {
-                out_stream->Printf ("%s\n", g_bkpt_command_reader_instructions);
-                if (reader.GetPrompt())
-                    out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush ();
-            }
-        }
-        break;
-
-    case eInputReaderDeactivate:
-        break;
-
-    case eInputReaderReactivate:
-        {
-            StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-            bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-            if (reader.GetPrompt() && !batch_mode)
-            {
-                out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush ();
-            }
-        }
-        break;
-
-    case eInputReaderAsynchronousOutputWritten:
-        break;
-        
-    case eInputReaderGotToken:
-        {
-            StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-            bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-            std::string temp_string (bytes, bytes_len);
-            commands_in_progress.AppendString (temp_string.c_str());
-            if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
-            {
-                out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush ();
-            }
-        }
-        break;
-
-    case eInputReaderEndOfFile:
-    case eInputReaderInterrupt:
-        // Control-c (SIGINT) & control-d both mean finish & exit.
-        reader.SetIsDone(true);
-        
-        // Control-c (SIGINT) ALSO means cancel; do NOT create a breakpoint command.
-        if (notification == eInputReaderInterrupt)
-            commands_in_progress.Clear();  
-        
-        // Fall through here...
-
-    case eInputReaderDone:
-        {
-            bool batch_mode = notification == eInputReaderDone ? 
-                reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode() :
-                true;
-            BreakpointOptions *bp_options = (BreakpointOptions *)baton;
-            std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
-            data_ap->user_source.AppendList (commands_in_progress);
-            if (data_ap.get())
-            {
-                ScriptInterpreter *interpreter = reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
-                if (interpreter)
-                {
-                    if (interpreter->GenerateBreakpointCommandCallbackData (data_ap->user_source, 
-                                                                            data_ap->script_source))
-                    {
-                        BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
-                        bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
-                    }
-                    else if (!batch_mode)
-                    {
-                        StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-                        out_stream->Printf ("Warning: No command attached to breakpoint.\n");
-                        out_stream->Flush();
-                    }
-                }
-                else
-                {
-		            if (!batch_mode)
-                    {
-                        StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-                        out_stream->Printf ("Warning:  Unable to find script intepreter; no command attached to breakpoint.\n");
-                        out_stream->Flush();
-                    }
-                }
-            }
-        }
-        break;
-        
-    }
-
-    return bytes_len;
-}
-
-size_t
-ScriptInterpreterPython::GenerateWatchpointOptionsCommandCallback
-(
-    void *baton, 
-    InputReader &reader, 
-    InputReaderAction notification,
-    const char *bytes, 
-    size_t bytes_len
-)
-{
-    static StringList commands_in_progress;
-    
-    switch (notification)
-    {
-    case eInputReaderActivate:
-        {
-            StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-            bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-            
-            commands_in_progress.Clear();
-            if (!batch_mode)
-            {
-                out_stream->Printf ("%s\n", g_reader_instructions);
-                if (reader.GetPrompt())
-                    out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush ();
-            }
-        }
-        break;
-
-    case eInputReaderDeactivate:
-        break;
-
-    case eInputReaderReactivate:
-        {
-            StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-            bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-            if (reader.GetPrompt() && !batch_mode)
-            {
-                out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush ();
-            }
-        }
-        break;
-
-    case eInputReaderAsynchronousOutputWritten:
-        break;
-        
-    case eInputReaderGotToken:
-        {
-            StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-            bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-            std::string temp_string (bytes, bytes_len);
-            commands_in_progress.AppendString (temp_string.c_str());
-            if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
-            {
-                out_stream->Printf ("%s", reader.GetPrompt());
-                out_stream->Flush ();
-            }
-        }
-        break;
-
-    case eInputReaderEndOfFile:
-    case eInputReaderInterrupt:
-        // Control-c (SIGINT) & control-d both mean finish & exit.
-        reader.SetIsDone(true);
-        
-        // Control-c (SIGINT) ALSO means cancel; do NOT create a breakpoint command.
-        if (notification == eInputReaderInterrupt)
-            commands_in_progress.Clear();  
-        
-        // Fall through here...
-
-    case eInputReaderDone:
-        {
-            bool batch_mode = notification == eInputReaderDone ?
-                reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode() :
-                true;
-            WatchpointOptions *wp_options = (WatchpointOptions *)baton;
-            std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
-            data_ap->user_source.AppendList (commands_in_progress);
-            if (data_ap.get())
-            {
-                ScriptInterpreter *interpreter = reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
-                if (interpreter)
-                {
-                    if (interpreter->GenerateWatchpointCommandCallbackData (data_ap->user_source, 
-                                                                            data_ap->script_source))
-                    {
-                        BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
-                        wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp);
-                    }
-                    else if (!batch_mode)
-                    {
-                        StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-                        out_stream->Printf ("Warning: No command attached to breakpoint.\n");
-                        out_stream->Flush();
-                    }
-                }
-                else
-                {
-		            if (!batch_mode)
-                    {
-                        StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-                        out_stream->Printf ("Warning:  Unable to find script intepreter; no command attached to breakpoint.\n");
-                        out_stream->Flush();
-                    }
-                }
-            }
-        }
-        break;
-        
-    }
-
-    return bytes_len;
-}
 
 void
 ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
                                                                   CommandReturnObject &result)
 {
-    Debugger &debugger = GetCommandInterpreter().GetDebugger();
-    
-    InputReaderSP reader_sp (new InputReader (debugger));
-
-    if (reader_sp)
-    {
-        Error err = reader_sp->Initialize (
-                ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback,
-                bp_options,                 // baton
-                eInputReaderGranularityLine, // token size, for feeding data to callback function
-                "DONE",                     // end token
-                "    ",                     // prompt
-                true);                      // echo input
-    
-        if (err.Success())
-            debugger.PushInputReader (reader_sp);
-        else
-        {
-            result.AppendError (err.AsCString());
-            result.SetStatus (eReturnStatusFailed);
-        }
-    }
-    else
-    {
-        result.AppendError("out of memory");
-        result.SetStatus (eReturnStatusFailed);
-    }
+    m_active_io_handler = eIOHandlerBreakpoint;
+    m_interpreter.GetPythonCommandsFromIOHandler ("    ", *this, true, bp_options);
 }
 
 void
 ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
                                                                   CommandReturnObject &result)
 {
-    Debugger &debugger = GetCommandInterpreter().GetDebugger();
-    
-    InputReaderSP reader_sp (new InputReader (debugger));
-
-    if (reader_sp)
-    {
-        Error err = reader_sp->Initialize (
-                ScriptInterpreterPython::GenerateWatchpointOptionsCommandCallback,
-                wp_options,                 // baton
-                eInputReaderGranularityLine, // token size, for feeding data to callback function
-                "DONE",                     // end token
-                "> ",                       // prompt
-                true);                      // echo input
-    
-        if (err.Success())
-            debugger.PushInputReader (reader_sp);
-        else
-        {
-            result.AppendError (err.AsCString());
-            result.SetStatus (eReturnStatusFailed);
-        }
-    }
-    else
-    {
-        result.AppendError("out of memory");
-        result.SetStatus (eReturnStatusFailed);
-    }
+    m_active_io_handler = eIOHandlerWatchpoint;
+    m_interpreter.GetPythonCommandsFromIOHandler ("    ", *this, true, wp_options);
 }
 
 // Set a Python one-liner as the callback for the breakpoint.
@@ -2140,7 +1601,7 @@ ScriptInterpreterPython::GetScriptedSumm
             {
             Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback");
             ret_val = g_swig_typescript_callback (python_function_name,
-                                                  FindSessionDictionary(m_dictionary_name.c_str()),
+                                                  GetSessionDictionary().get(),
                                                   valobj,
                                                   &new_callee,
                                                   retval);
@@ -2188,8 +1649,7 @@ ScriptInterpreterPython::BreakpointCallb
     if (!script_interpreter)
         return true;
     
-    if (python_function_name != NULL 
-        && python_function_name[0] != '\0')
+    if (python_function_name && python_function_name[0])
     {
         const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP());
         BreakpointSP breakpoint_sp = target->GetBreakpointByID (break_id);
@@ -2243,8 +1703,7 @@ ScriptInterpreterPython::WatchpointCallb
     if (!script_interpreter)
         return true;
     
-    if (python_function_name != NULL 
-        && python_function_name[0] != '\0')
+    if (python_function_name && python_function_name[0])
     {
         const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP());
         WatchpointSP wp_sp = target->GetWatchpointList().FindByID (watch_id);
@@ -2269,106 +1728,6 @@ ScriptInterpreterPython::WatchpointCallb
     return true;
 }
 
-lldb::thread_result_t
-ScriptInterpreterPython::RunEmbeddedPythonInterpreter (lldb::thread_arg_t baton)
-{
-    ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
-    
-    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
-    
-    if (log)
-        log->Printf ("%p ScriptInterpreterPython::RunEmbeddedPythonInterpreter () thread starting...", baton);
-    
-    char error_str[1024];
-    const char *pty_slave_name = script_interpreter->m_embedded_python_pty.GetSlaveName (error_str, sizeof (error_str));
-
-    if (pty_slave_name != NULL)
-    {
-        StreamString run_string;
-
-        // Ensure we have the GIL before running any Python code.
-        // Since we're only running a few one-liners and then dropping to the interpreter (which will release the GIL when needed),
-        // we can just release the GIL after finishing our work.
-        // If finer-grained locking is desirable, we can lock and unlock the GIL only when calling a python function.
-        Locker locker(script_interpreter,
-                      ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
-                      ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
-
-        run_string.Printf ("run_one_line (%s, 'save_stderr = sys.stderr')", script_interpreter->m_dictionary_name.c_str());
-        PyRun_SimpleString (run_string.GetData());
-        run_string.Clear ();
-        
-        run_string.Printf ("run_one_line (%s, 'sys.stderr = sys.stdout')", script_interpreter->m_dictionary_name.c_str());
-        PyRun_SimpleString (run_string.GetData());
-        run_string.Clear ();
-        
-        run_string.Printf ("run_one_line (%s, 'save_stdin = sys.stdin')", script_interpreter->m_dictionary_name.c_str());
-        PyRun_SimpleString (run_string.GetData());
-        run_string.Clear ();
-        
-        run_string.Printf ("run_one_line (%s, \"sys.stdin = open ('%s', 'r')\")", script_interpreter->m_dictionary_name.c_str(),
-                           pty_slave_name);
-        PyRun_SimpleString (run_string.GetData());
-        run_string.Clear ();
-
-        // The following call drops into the embedded interpreter loop and stays there until the
-        // user chooses to exit from the Python interpreter.
-        // This embedded interpreter will, as any Python code that performs I/O, unlock the GIL before
-        // a system call that can hang, and lock it when the syscall has returned.
-
-        // We need to surround the call to the embedded interpreter with calls to PyGILState_Ensure and 
-        // PyGILState_Release (using the Locker above). This is because Python has a global lock which must be held whenever we want
-        // to touch any Python objects. Otherwise, if the user calls Python code, the interpreter state will be off,
-        // and things could hang (it's happened before).
-
-        run_string.Printf ("run_python_interpreter (%s)", script_interpreter->m_dictionary_name.c_str());
-        PyRun_SimpleString (run_string.GetData());
-        run_string.Clear ();
-
-        run_string.Printf ("run_one_line (%s, 'sys.stdin = save_stdin')", script_interpreter->m_dictionary_name.c_str());
-        PyRun_SimpleString (run_string.GetData());
-        run_string.Clear();
-
-        run_string.Printf ("run_one_line (%s, 'sys.stderr = save_stderr')", script_interpreter->m_dictionary_name.c_str());
-        PyRun_SimpleString (run_string.GetData());
-        run_string.Clear();
-    }
-    
-    if (script_interpreter->m_embedded_python_input_reader_sp)
-        script_interpreter->m_embedded_python_input_reader_sp->SetIsDone (true);
-    
-    script_interpreter->m_embedded_python_pty.CloseSlaveFileDescriptor();
-
-    log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT);
-    if (log)
-        log->Printf ("%p ScriptInterpreterPython::RunEmbeddedPythonInterpreter () thread exiting...", baton);
-    
-
-    // Clean up the input reader and make the debugger pop it off the stack.
-    Debugger &debugger = script_interpreter->GetCommandInterpreter().GetDebugger();
-    const InputReaderSP reader_sp = script_interpreter->m_embedded_python_input_reader_sp;
-    if (reader_sp)
-    {
-        debugger.PopInputReader (reader_sp);
-        script_interpreter->m_embedded_python_input_reader_sp.reset();
-    }
-    
-    return NULL;
-}
-
-lldb::thread_result_t
-ScriptInterpreterPython::PythonInputReaderManager::RunPythonInputReader (lldb::thread_arg_t baton)
-{
-    ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
-
-    const InputReaderSP reader_sp = script_interpreter->m_embedded_thread_input_reader_sp;
-    
-    if (reader_sp)
-        reader_sp->WaitOnReaderIsDone();
-    
-    return NULL;
-}
-
 size_t
 ScriptInterpreterPython::CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor_sp)
 {
@@ -2954,7 +2313,7 @@ ScriptInterpreterPython::RunScriptBasedC
         // to set the asynchronous exception - not a desirable situation
         m_command_thread_state = _PyThreadState_Current;
         
-        PythonInputReaderManager py_input(this);
+        //PythonInputReaderManager py_input(this);
         
         ret_val = g_swig_call_command       (impl_function,
                                              m_dictionary_name.c_str(),

Modified: lldb/branches/iohandler/source/Interpreter/embedded_interpreter.py
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Interpreter/embedded_interpreter.py?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Interpreter/embedded_interpreter.py (original)
+++ lldb/branches/iohandler/source/Interpreter/embedded_interpreter.py Thu Jan  2 16:40:14 2014
@@ -1,88 +1,59 @@
-import readline
+import __builtin__
 import code
+import lldb
 import sys
 import traceback
 
-class SimpleREPL(code.InteractiveConsole):
-   def __init__(self, prompt, dict):
-       code.InteractiveConsole.__init__(self,dict)
-       self.prompt = prompt
-       self.loop_exit = False
-       self.dict = dict
-
-   def interact(self):
-       try:
-           sys.ps1
-       except AttributeError:
-           sys.ps1 = ">>> "
-       try:
-           sys.ps2
-       except AttributeError:
-           sys.ps2 = "... "
-
-       while not self.loop_exit:
-           try:
-               self.read_py_command()
-           except (SystemExit, EOFError):
-               # EOF while in Python just breaks out to top level.
-               self.write('\n')
-               self.loop_exit = True
-               break
-           except KeyboardInterrupt:
-               self.write("\nKeyboardInterrupt\n")
-               self.resetbuffer()
-               more = 0
-           except:
-               traceback.print_exc()
-
-   def process_input (self, in_str):
-      # Canonicalize the format of the input string
-      temp_str = in_str
-      temp_str.strip(' \t')
-      words = temp_str.split()
-      temp_str = ('').join(words)
-
-      # Check the input string to see if it was the quit
-      # command.  If so, intercept it, so that it doesn't
-      # close stdin on us!
-      if (temp_str.lower() == "quit()" or temp_str.lower() == "exit()"):
-         self.loop_exit = True
-         in_str = "raise SystemExit "
-      return in_str
-
-   def my_raw_input (self, prompt):
-      stream = sys.stdout
-      stream.write (prompt)
-      stream.flush ()
-      try:
-         line = sys.stdin.readline()
-      except KeyboardInterrupt:
-         line = " \n"
-      except (SystemExit, EOFError):
-         line = "quit()\n"
-      if not line:
-         raise EOFError
-      if line[-1] == '\n':
-         line = line[:-1]
-      return line
-
-   def read_py_command(self):
-       # Read off a complete Python command.
-       more = 0
-       while 1:
-           if more:
-               prompt = sys.ps2
-           else:
-               prompt = sys.ps1
-           line = self.my_raw_input(prompt)
-           # Can be None if sys.stdin was redefined
-           encoding = getattr(sys.stdin, "encoding", None)
-           if encoding and not isinstance(line, unicode):
-               line = line.decode(encoding)
-           line = self.process_input (line)
-           more = self.push(line)
-           if not more:
-               break
+try:
+    import readline
+    import rlcompleter
+except ImportError:
+    have_readline = False
+else:
+    have_readline = True
+    if 'libedit' in readline.__doc__:
+        readline.parse_and_bind('bind ^I rl_complete')
+    else:
+        readline.parse_and_bind('tab: complete')
+
+g_builtin_override_called = False
+
+class LLDBQuitter(object):
+    def __init__(self, name):
+        self.name = name
+    def __repr__(self):
+        self()
+    def __call__(self, code=None):
+        global g_builtin_override_called
+        g_builtin_override_called = True
+        raise SystemExit(-1)
+
+def setquit():
+    '''Redefine builtin functions 'quit()' and 'exit()' to print a message and raise an EOFError exception.'''
+    # This function will be called prior to each interactive
+    # interpreter loop or each single line, so we set the global
+    # g_builtin_override_called to False so we know if a SystemExit
+    # is thrown, we can catch it and tell the difference between
+    # a call to "quit()" or "exit()" and something like
+    # "sys.exit(123)"
+    global g_builtin_override_called
+    g_builtin_override_called = False
+    __builtin__.quit = LLDBQuitter('quit')
+    __builtin__.exit = LLDBQuitter('exit')
+
+def run_python_interpreter (dict):
+    global g_builtin_override_called
+    setquit()
+    try:
+        code.interact ("Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", None, dict)
+    except SystemExit as e:
+        if not g_builtin_override_called:
+            print 'Script exited with %s' %(e)
+
+# When running one line, we might place the string to run in this string
+# in case it would be hard to correctly escape a string's contents
+
+g_run_one_line_str = None
 
    def one_line (self, input):
       line = self.process_input (input)
@@ -98,6 +69,16 @@ def run_python_interpreter (dict):
    repl.interact()
 
 def run_one_line (dict, input_string):
-   repl = SimpleREPL ('', dict)
-   repl.one_line (input_string)
-
+    global g_builtin_override_called
+    global g_run_one_line_str
+    setquit()
+    try:
+        repl = code.InteractiveConsole(dict);
+        if input_string:
+            repl.runsource (input_string)
+        elif g_run_one_line_str:
+            repl.runsource (g_run_one_line_str)
+
+    except SystemExit as e:
+        if not g_builtin_override_called:
+            print 'Script exited with %s' %(e)

Modified: lldb/branches/iohandler/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp (original)
+++ lldb/branches/iohandler/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp Thu Jan  2 16:40:14 2014
@@ -19,6 +19,7 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Core/State.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/Host/Symbols.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/RegisterContext.h"
@@ -717,7 +718,7 @@ DynamicLoaderDarwinKernel::KextImageInfo
             {
                 if (m_uuid != exe_module->GetUUID())
                 {
-                    Stream *s = &process->GetTarget().GetDebugger().GetOutputStream();
+                    Stream *s = process->GetTarget().GetDebugger().GetOutputFile().get();
                     if (s)
                     {
                         s->Printf ("warning: Host-side kernel file has Mach-O UUID of %s but remote kernel has a UUID of %s -- a mismatched kernel file will result in a poor debugger experience.\n", 
@@ -765,7 +766,7 @@ DynamicLoaderDarwinKernel::KextImageInfo
 
     if (IsKernel() && uuid_is_valid && m_memory_module_sp.get())
     {
-        Stream *s = &target.GetDebugger().GetOutputStream();
+        Stream *s = target.GetDebugger().GetOutputFile().get();
         if (s)
         {
             s->Printf ("Kernel UUID: %s\n", m_memory_module_sp->GetUUID().GetAsString().c_str());
@@ -834,7 +835,7 @@ DynamicLoaderDarwinKernel::KextImageInfo
 
             if (IsKernel() && !m_module_sp)
             {
-                Stream *s = &target.GetDebugger().GetOutputStream();
+                Stream *s = target.GetDebugger().GetOutputFile().get();
                 if (s)
                 {
                     s->Printf ("WARNING: Unable to locate kernel binary on the debugger system.\n");
@@ -867,7 +868,7 @@ DynamicLoaderDarwinKernel::KextImageInfo
     
     if (!m_module_sp && !IsKernel() && m_uuid.IsValid() && !m_name.empty())
     {
-        Stream *s = &target.GetDebugger().GetOutputStream();
+        Stream *s = target.GetDebugger().GetOutputFile().get();
         if (s)
         {
             s->Printf ("warning: Can't find binary/dSYM for %s (%s)\n", 
@@ -945,7 +946,7 @@ DynamicLoaderDarwinKernel::KextImageInfo
     
     if (is_loaded && m_module_sp && IsKernel())
     {
-        Stream *s = &target.GetDebugger().GetOutputStream();
+        Stream *s = target.GetDebugger().GetOutputFile().get();
         if (s)
         {
             ObjectFile *kernel_object_file = m_module_sp->GetObjectFile();
@@ -1248,7 +1249,7 @@ DynamicLoaderDarwinKernel::ParseKextSumm
     if (number_of_new_kexts_being_added == 0 && number_of_old_kexts_being_removed == 0)
         return true;
 
-    Stream *s = &m_process->GetTarget().GetDebugger().GetOutputStream();
+    Stream *s = m_process->GetTarget().GetDebugger().GetOutputFile().get();
     if (s && load_kexts)
     {
         if (number_of_new_kexts_being_added > 0 && number_of_old_kexts_being_removed > 0)

Modified: lldb/branches/iohandler/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp (original)
+++ lldb/branches/iohandler/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp Thu Jan  2 16:40:14 2014
@@ -22,6 +22,7 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Expression/ClangExpression.h"
 #include "lldb/Expression/ClangFunction.h"
@@ -664,7 +665,7 @@ AppleObjCTrampolineHandler::AppleObjCTra
         // step through any method dispatches.  Warn to that effect and get out of here.
         if (process_sp->CanJIT())
         {
-            process_sp->GetTarget().GetDebugger().GetErrorStream().Printf("Could not find implementation lookup function \"%s\""
+            process_sp->GetTarget().GetDebugger().GetErrorFile()->Printf ("Could not find implementation lookup function \"%s\""
                                                                           " step in through ObjC method dispatch will not work.\n",
                                                                           get_impl_name.AsCString());
         }

Modified: lldb/branches/iohandler/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp (original)
+++ lldb/branches/iohandler/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp Thu Jan  2 16:40:14 2014
@@ -812,7 +812,12 @@ PlatformDarwin::Attach (ProcessAttachInf
             process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName(), NULL);
             
             if (process_sp)
+            {
+                ListenerSP listener_sp (new Listener("lldb.PlatformDarwin.attach.hijack"));
+                attach_info.SetHijackListener(listener_sp);
+                process_sp->HijackProcessEvents(listener_sp.get());
                 error = process_sp->Attach (attach_info);
+            }
         }
     }
     else

Modified: lldb/branches/iohandler/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h (original)
+++ lldb/branches/iohandler/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h Thu Jan  2 16:40:14 2014
@@ -21,7 +21,6 @@
 #include "lldb/Core/Broadcaster.h"
 #include "lldb/Core/ConstString.h"
 #include "lldb/Core/Error.h"
-#include "lldb/Core/InputReader.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/StringList.h"
 #include "lldb/Core/ThreadSafeValue.h"

Modified: lldb/branches/iohandler/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/branches/iohandler/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Thu Jan  2 16:40:14 2014
@@ -34,7 +34,6 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/ConnectionFileDescriptor.h"
 #include "lldb/Host/FileSpec.h"
-#include "lldb/Core/InputReader.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
@@ -1041,27 +1040,6 @@ ProcessGDBRemote::DoAttachToProcessWithI
     return error;
 }
 
-size_t
-ProcessGDBRemote::AttachInputReaderCallback
-(
-    void *baton, 
-    InputReader *reader, 
-    lldb::InputReaderAction notification,
-    const char *bytes, 
-    size_t bytes_len
-)
-{
-    if (notification == eInputReaderGotToken)
-    {
-        ProcessGDBRemote *gdb_process = (ProcessGDBRemote *)baton;
-        if (gdb_process->m_waiting_for_attach)
-            gdb_process->m_waiting_for_attach = false;
-        reader->SetIsDone(true);
-        return 1;
-    }
-    return 0;
-}
-
 Error
 ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const ProcessAttachInfo &attach_info)
 {

Modified: lldb/branches/iohandler/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/branches/iohandler/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Thu Jan  2 16:40:14 2014
@@ -21,7 +21,6 @@
 #include "lldb/Core/Broadcaster.h"
 #include "lldb/Core/ConstString.h"
 #include "lldb/Core/Error.h"
-#include "lldb/Core/InputReader.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/StringList.h"
 #include "lldb/Core/ThreadSafeValue.h"
@@ -378,13 +377,6 @@ protected:
     GetDispatchQueueNameForThread (lldb::addr_t thread_dispatch_qaddr,
                                    std::string &dispatch_queue_name);
 
-    static size_t
-    AttachInputReaderCallback (void *baton, 
-                               lldb_private::InputReader *reader, 
-                               lldb::InputReaderAction notification,
-                               const char *bytes, 
-                               size_t bytes_len);
-
     lldb_private::DynamicLoader *
     GetDynamicLoader ();
 

Modified: lldb/branches/iohandler/source/Symbol/ClangASTType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Symbol/ClangASTType.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Symbol/ClangASTType.cpp (original)
+++ lldb/branches/iohandler/source/Symbol/ClangASTType.cpp Thu Jan  2 16:40:14 2014
@@ -38,6 +38,7 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Scalar.h"
 #include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/ClangExternalASTSourceCommon.h"

Modified: lldb/branches/iohandler/source/Target/ExecutionContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Target/ExecutionContext.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Target/ExecutionContext.cpp (original)
+++ lldb/branches/iohandler/source/Target/ExecutionContext.cpp Thu Jan  2 16:40:14 2014
@@ -127,7 +127,7 @@ ExecutionContext::ExecutionContext (Targ
     if (t && fill_current_process_thread_frame)
     {
         m_process_sp = t->GetProcessSP();
-        if (m_process_sp)
+        if (m_process_sp && StateIsStoppedState(m_process_sp->GetState(), true))
         {
             m_thread_sp = m_process_sp->GetThreadList().GetSelectedThread();
             if (m_thread_sp)
@@ -149,9 +149,14 @@ ExecutionContext::ExecutionContext(Proce
 ExecutionContext::ExecutionContext (const ExecutionContextRef &exe_ctx_ref) :
     m_target_sp (exe_ctx_ref.GetTargetSP()),
     m_process_sp (exe_ctx_ref.GetProcessSP()),
-    m_thread_sp (exe_ctx_ref.GetThreadSP()),
-    m_frame_sp (exe_ctx_ref.GetFrameSP())
+    m_thread_sp (),
+    m_frame_sp ()
 {
+    if (m_process_sp && StateIsStoppedState(m_process_sp->GetState(), true))
+    {
+        m_thread_sp = exe_ctx_ref.GetThreadSP();
+        m_frame_sp = exe_ctx_ref.GetFrameSP();
+    }
 }
 
 ExecutionContext::ExecutionContext (const ExecutionContextRef *exe_ctx_ref_ptr) :
@@ -164,8 +169,11 @@ ExecutionContext::ExecutionContext (cons
     {
         m_target_sp  = exe_ctx_ref_ptr->GetTargetSP();
         m_process_sp = exe_ctx_ref_ptr->GetProcessSP();
-        m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
-        m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
+        if (m_process_sp && StateIsStoppedState(m_process_sp->GetState(), true))
+        {
+            m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
+            m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
+        }
     }
 }
 
@@ -182,8 +190,11 @@ ExecutionContext::ExecutionContext (cons
         {
             locker.Lock(m_target_sp->GetAPIMutex());
             m_process_sp = exe_ctx_ref_ptr->GetProcessSP();
-            m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
-            m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
+            if (m_process_sp && StateIsStoppedState(m_process_sp->GetState(), true))
+            {
+                m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
+                m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
+            }
         }
     }
 }
@@ -198,8 +209,11 @@ ExecutionContext::ExecutionContext (cons
     {
         locker.Lock(m_target_sp->GetAPIMutex());
         m_process_sp = exe_ctx_ref.GetProcessSP();
-        m_thread_sp  = exe_ctx_ref.GetThreadSP();
-        m_frame_sp   = exe_ctx_ref.GetFrameSP();
+        if (m_process_sp && StateIsStoppedState(m_process_sp->GetState(), true))
+        {
+            m_thread_sp  = exe_ctx_ref.GetThreadSP();
+            m_frame_sp   = exe_ctx_ref.GetFrameSP();
+        }
     }
 }
 

Modified: lldb/branches/iohandler/source/Target/Platform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Target/Platform.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Target/Platform.cpp (original)
+++ lldb/branches/iohandler/source/Target/Platform.cpp Thu Jan  2 16:40:14 2014
@@ -1039,6 +1039,8 @@ Platform::DebugProcess (ProcessLaunchInf
             process_sp = Attach (attach_info, debugger, target, listener, error);
             if (process_sp)
             {
+                launch_info.SetHijackListener(attach_info.GetHijackListener());
+                
                 // Since we attached to the process, it will think it needs to detach
                 // if the process object just goes away without an explicit call to
                 // Process::Kill() or Process::Detach(), so let it know to kill the 

Modified: lldb/branches/iohandler/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Target/Process.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Target/Process.cpp (original)
+++ lldb/branches/iohandler/source/Target/Process.cpp Thu Jan  2 16:40:14 2014
@@ -18,14 +18,15 @@
 #include "lldb/Core/Event.h"
 #include "lldb/Core/ConnectionFileDescriptor.h"
 #include "lldb/Core/Debugger.h"
-#include "lldb/Core/InputReader.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/State.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/Expression/ClangUserExpression.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Host/Terminal.h"
 #include "lldb/Target/ABI.h"
 #include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/OperatingSystem.h"
@@ -1241,7 +1242,7 @@ Process::GetNextEvent (EventSP &event_sp
 
 
 StateType
-Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr, bool wait_always)
+Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr, bool wait_always, Listener *hijack_listener)
 {
     // We can't just wait for a "stopped" event, because the stopped event may have restarted the target.
     // We have to actually check each event, and in the case of a stopped event check the restarted flag
@@ -1270,7 +1271,7 @@ Process::WaitForProcessToStop (const Tim
     while (state != eStateInvalid)
     {
         EventSP event_sp;
-        state = WaitForStateChangedEvents (timeout, event_sp);
+        state = WaitForStateChangedEvents (timeout, event_sp, hijack_listener);
         if (event_sp_ptr && event_sp)
             *event_sp_ptr = event_sp;
 
@@ -1280,12 +1281,22 @@ Process::WaitForProcessToStop (const Tim
         case eStateDetached:
         case eStateExited:
         case eStateUnloaded:
+            // We need to toggle the run lock as this won't get done in
+            // SetPublicState() if the process is hijacked.
+            if (hijack_listener)
+                m_public_run_lock.SetStopped();
             return state;
         case eStateStopped:
             if (Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
                 continue;
             else
+            {
+                // We need to toggle the run lock as this won't get done in
+                // SetPublicState() if the process is hijacked.
+                if (hijack_listener)
+                    m_public_run_lock.SetStopped();
                 return state;
+            }
         default:
             continue;
         }
@@ -1298,7 +1309,8 @@ StateType
 Process::WaitForState
 (
     const TimeValue *timeout,
-    const StateType *match_states, const uint32_t num_match_states
+    const StateType *match_states,
+    const uint32_t num_match_states
 )
 {
     EventSP event_sp;
@@ -1311,7 +1323,7 @@ Process::WaitForState
         if (state == eStateDetached || state == eStateExited)
             return state;
 
-        state = WaitForStateChangedEvents (timeout, event_sp);
+        state = WaitForStateChangedEvents (timeout, event_sp, NULL);
 
         for (i=0; i<num_match_states; ++i)
         {
@@ -1357,18 +1369,22 @@ Process::RestorePrivateProcessEvents ()
 }
 
 StateType
-Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp)
+Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp, Listener *hijack_listener)
 {
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
 
     if (log)
         log->Printf ("Process::%s (timeout = %p, event_sp)...", __FUNCTION__, timeout);
 
+    Listener *listener = hijack_listener;
+    if (listener == NULL)
+        listener = &m_listener;
+    
     StateType state = eStateInvalid;
-    if (m_listener.WaitForEventForBroadcasterWithType (timeout,
-                                                       this,
-                                                       eBroadcastBitStateChanged | eBroadcastBitInterrupt,
-                                                       event_sp))
+    if (listener->WaitForEventForBroadcasterWithType (timeout,
+                                                      this,
+                                                      eBroadcastBitStateChanged | eBroadcastBitInterrupt,
+                                                      event_sp))
     {
         if (event_sp && event_sp->GetType() == eBroadcastBitStateChanged)
             state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
@@ -1506,6 +1522,7 @@ Process::SetExitStatus (int status, cons
     DidExit ();
 
     SetPrivateState (eStateExited);
+    CancelWatchForSTDIN (true);
     return true;
 }
 
@@ -2197,11 +2214,11 @@ Process::CreateBreakpointSite (const Bre
                     if (show_error)
                     {
                         // Report error for setting breakpoint...
-                        m_target.GetDebugger().GetErrorFile().Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
-                                                                      load_addr,
-                                                                      owner->GetBreakpoint().GetID(),
-                                                                      owner->GetID(),
-                                                                      error.AsCString() ? error.AsCString() : "unkown error");
+                        m_target.GetDebugger().GetErrorFile()->Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
+                                                                       load_addr,
+                                                                       owner->GetBreakpoint().GetID(),
+                                                                       owner->GetID(),
+                                                                       error.AsCString() ? error.AsCString() : "unkown error");
                     }
                 }
             }
@@ -3722,8 +3739,6 @@ Process::Destroy ()
         }
         m_stdio_communication.StopReadThread();
         m_stdio_communication.Disconnect();
-        if (m_process_input_reader && m_process_input_reader->IsActive())
-            m_target.GetDebugger().PopInputReader (m_process_input_reader);
         if (m_process_input_reader)
             m_process_input_reader.reset();
         
@@ -4105,9 +4120,14 @@ Process::HandlePrivateEvent (EventSP &ev
         }
         Process::ProcessEventData::SetUpdateStateOnRemoval(event_sp.get());
         if (StateIsRunningState (new_state))
-            PushProcessInputReader ();
+        {
+            // Only push the input handler if we aren't fowarding events,
+            // as this means the curses GUI is in use...
+            if (!GetTarget().GetDebugger().IsForwardingEvents())
+                PushProcessIOHandler ();
+        }
         else if (!Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
-            PopProcessInputReader ();
+            PopProcessIOHandler ();
 
         BroadcastEvent (event_sp);
     }
@@ -4653,64 +4673,187 @@ Process::STDIOReadThreadBytesReceived (v
     process->AppendSTDOUT (static_cast<const char *>(src), src_len);
 }
 
-size_t
-Process::ProcessInputReaderCallback (void *baton,
-                                     InputReader &reader,
-                                     lldb::InputReaderAction notification,
-                                     const char *bytes,
-                                     size_t bytes_len)
+void
+Process::ResetProcessIOHandler ()
+{   
+    m_process_input_reader.reset();
+}
+
+
+class IOHandlerProcessSTDIO :
+    public IOHandler
 {
-    Process *process = (Process *) baton;
-    
-    switch (notification)
+public:
+    IOHandlerProcessSTDIO (Process *process,
+                           int write_fd) :
+        IOHandler(process->GetTarget().GetDebugger()),
+        m_process (process),
+        m_read_file (),
+        m_write_file (write_fd, false),
+        m_pipe_read(),
+        m_pipe_write()
+    {
+        m_read_file.SetDescriptor(GetInputFD(), false);
+    }
+
+    virtual
+    ~IOHandlerProcessSTDIO ()
     {
-    case eInputReaderActivate:
-        break;
-        
-    case eInputReaderDeactivate:
-        break;
-        
-    case eInputReaderReactivate:
-        break;
-        
-    case eInputReaderAsynchronousOutputWritten:
-        break;
         
-    case eInputReaderGotToken:
+    }
+    
+    bool
+    OpenPipes ()
+    {
+        if (m_pipe_read.IsValid() && m_pipe_write.IsValid())
+            return true;
+
+        int fds[2];
+        int err = pipe(fds);
+        if (err == 0)
         {
-            Error error;
-            process->PutSTDIN (bytes, bytes_len, error);
+            m_pipe_read.SetDescriptor(fds[0], true);
+            m_pipe_write.SetDescriptor(fds[1], true);
+            return true;
         }
-        break;
+        return false;
+    }
+
+    void
+    ClosePipes()
+    {
+        m_pipe_read.Close();
+        m_pipe_write.Close();
+    }
+    
+    // Each IOHandler gets to run until it is done. It should read data
+    // from the "in" and place output into "out" and "err and return
+    // when done.
+    virtual void
+    Run ()
+    {
+        if (m_read_file.IsValid() && m_write_file.IsValid())
+        {
+            SetIsDone(false);
+            if (OpenPipes())
+            {
+                const int read_fd = m_read_file.GetDescriptor();
+                const int pipe_read_fd = m_pipe_read.GetDescriptor();
+                TerminalState terminal_state;
+                terminal_state.Save (read_fd, false);
+                Terminal terminal(read_fd);
+                terminal.SetCanonical(false);
+                terminal.SetEcho(false);
+                while (!GetIsDone())
+                {
+                    fd_set read_fdset;
+                    FD_ZERO (&read_fdset);
+                    FD_SET (read_fd, &read_fdset);
+                    FD_SET (pipe_read_fd, &read_fdset);
+                    const int nfds = std::max<int>(read_fd, pipe_read_fd) + 1;
+                    int num_set_fds = select (nfds, &read_fdset, NULL, NULL, NULL);
+                    if (num_set_fds < 0)
+                    {
+                        const int select_errno = errno;
+                        
+                        if (select_errno != EINTR)
+                            SetIsDone(true);
+                    }
+                    else if (num_set_fds > 0)
+                    {
+                        char ch = 0;
+                        size_t n;
+                        if (FD_ISSET (read_fd, &read_fdset))
+                        {
+                            n = 1;
+                            if (m_read_file.Read(&ch, n).Success() && n == 1)
+                            {
+                                if (m_write_file.Write(&ch, n).Fail() || n != 1)
+                                    SetIsDone(true);
+                            }
+                            else
+                                SetIsDone(true);
+                        }
+                        if (FD_ISSET (pipe_read_fd, &read_fdset))
+                        {
+                            // Consume the interrupt byte
+                            n = 1;
+                            m_pipe_read.Read (&ch, n);
+                            SetIsDone(true);
+                        }
+                    }
+                }
+                terminal_state.Restore();
+
+            }
+            else
+                SetIsDone(true);
+        }
+        else
+            SetIsDone(true);
+    }
+    
+    // Hide any characters that have been displayed so far so async
+    // output can be displayed. Refresh() will be called after the
+    // output has been displayed.
+    virtual void
+    Hide ()
+    {
         
-    case eInputReaderInterrupt:
-        process->SendAsyncInterrupt();
-        break;
-            
-    case eInputReaderEndOfFile:
-        process->AppendSTDOUT ("^D", 2);
-        break;
+    }
+    // Called when the async output has been received in order to update
+    // the input reader (refresh the prompt and redisplay any current
+    // line(s) that are being edited
+    virtual void
+    Refresh ()
+    {
         
-    case eInputReaderDone:
-        break;
+    }
+    virtual void
+    Interrupt ()
+    {
+        size_t n = 1;
+        char ch = 'q';
+        m_pipe_write.Write (&ch, n);
+    }
+    
+    virtual void
+    GotEOF()
+    {
         
     }
     
-    return bytes_len;
+protected:
+    Process *m_process;
+    File m_read_file;   // Read from this file (usually actual STDIN for LLDB
+    File m_write_file;  // Write to this file (usually the master pty for getting io to debuggee)
+    File m_pipe_read;
+    File m_pipe_write;
+
+};
+
+void
+Process::WatchForSTDIN (IOHandler &io_handler)
+{
 }
 
 void
-Process::ResetProcessInputReader ()
-{   
-    m_process_input_reader.reset();
+Process::CancelWatchForSTDIN (bool exited)
+{
+    if (m_process_input_reader)
+    {
+        if (exited)
+            m_process_input_reader->SetIsDone(true);
+        m_process_input_reader->Interrupt();
+    }
 }
 
 void
-Process::SetSTDIOFileDescriptor (int file_descriptor)
+Process::SetSTDIOFileDescriptor (int fd)
 {
     // First set up the Read Thread for reading/handling process I/O
     
-    std::unique_ptr<ConnectionFileDescriptor> conn_ap (new ConnectionFileDescriptor (file_descriptor, true));
+    std::unique_ptr<ConnectionFileDescriptor> conn_ap (new ConnectionFileDescriptor (fd, true));
     
     if (conn_ap.get())
     {
@@ -4723,70 +4866,37 @@ Process::SetSTDIOFileDescriptor (int fil
             // Now read thread is set up, set up input reader.
             
             if (!m_process_input_reader.get())
-            {
-                m_process_input_reader.reset (new InputReader(m_target.GetDebugger()));
-                Error err (m_process_input_reader->Initialize (Process::ProcessInputReaderCallback,
-                                                               this,
-                                                               eInputReaderGranularityByte,
-                                                               NULL,
-                                                               NULL,
-                                                               false));
-                
-                if  (err.Fail())
-                    m_process_input_reader.reset();
-            }
+                m_process_input_reader.reset (new IOHandlerProcessSTDIO (this, fd));
         }
     }
 }
 
 void
-Process::PushProcessInputReader ()
+Process::PushProcessIOHandler ()
 {
-    if (m_process_input_reader && !m_process_input_reader->IsActive())
-        m_target.GetDebugger().PushInputReader (m_process_input_reader);
+    IOHandlerSP io_handler_sp (m_process_input_reader);
+    if (io_handler_sp)
+    {
+        io_handler_sp->SetIsDone(false);
+        m_target.GetDebugger().PushIOHandler (io_handler_sp);
+    }
 }
 
 void
-Process::PopProcessInputReader ()
+Process::PopProcessIOHandler ()
 {
-    if (m_process_input_reader && m_process_input_reader->IsActive())
-        m_target.GetDebugger().PopInputReader (m_process_input_reader);
+    IOHandlerSP io_handler_sp (m_process_input_reader);
+    if (io_handler_sp && io_handler_sp->IsActive())
+    {
+        io_handler_sp->Interrupt();
+        m_target.GetDebugger().PopIOHandler (io_handler_sp);
+    }
 }
 
 // The process needs to know about installed plug-ins
 void
 Process::SettingsInitialize ()
 {
-//    static std::vector<OptionEnumValueElement> g_plugins;
-//    
-//    int i=0; 
-//    const char *name;
-//    OptionEnumValueElement option_enum;
-//    while ((name = PluginManager::GetProcessPluginNameAtIndex (i)) != NULL)
-//    {
-//        if (name)
-//        {
-//            option_enum.value = i;
-//            option_enum.string_value = name;
-//            option_enum.usage = PluginManager::GetProcessPluginDescriptionAtIndex (i);
-//            g_plugins.push_back (option_enum);
-//        }
-//        ++i;
-//    }
-//    option_enum.value = 0;
-//    option_enum.string_value = NULL;
-//    option_enum.usage = NULL;
-//    g_plugins.push_back (option_enum);
-//    
-//    for (i=0; (name = SettingsController::instance_settings_table[i].var_name); ++i)
-//    {
-//        if (::strcmp (name, "plugin") == 0)
-//        {
-//            SettingsController::instance_settings_table[i].enum_values = &g_plugins[0];
-//            break;
-//        }
-//    }
-//                                                          
     Thread::SettingsInitialize ();
 }
 

Modified: lldb/branches/iohandler/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Target/Target.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Target/Target.cpp (original)
+++ lldb/branches/iohandler/source/Target/Target.cpp Thu Jan  2 16:40:14 2014
@@ -29,6 +29,7 @@
 #include "lldb/Core/Section.h"
 #include "lldb/Core/SourceManager.h"
 #include "lldb/Core/State.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/Timer.h"
 #include "lldb/Core/ValueObject.h"
@@ -1006,11 +1007,11 @@ LoadScriptingResourceForModule (const Mo
     if (module_sp && !module_sp->LoadScriptingResourceInTarget(target, error, &feedback_stream))
     {
         if (error.AsCString())
-            target->GetDebugger().GetErrorStream().Printf("unable to load scripting data for module %s - error reported was %s\n",
+            target->GetDebugger().GetErrorFile()->Printf("unable to load scripting data for module %s - error reported was %s\n",
                                                            module_sp->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
                                                            error.AsCString());
         if (feedback_stream.GetSize())
-            target->GetDebugger().GetOutputStream().Printf("%s\n",
+            target->GetDebugger().GetErrorFile()->Printf("%s\n",
                                                            feedback_stream.GetData());
     }
 }
@@ -1998,13 +1999,13 @@ Target::GetSourceManager ()
 }
 
 
-lldb::user_id_t
-Target::AddStopHook (Target::StopHookSP &new_hook_sp)
+Target::StopHookSP
+Target::CreateStopHook ()
 {
     lldb::user_id_t new_uid = ++m_stop_hook_next_id;
-    new_hook_sp.reset (new StopHook(shared_from_this(), new_uid));
-    m_stop_hooks[new_uid] = new_hook_sp;
-    return new_uid;
+    Target::StopHookSP stop_hook_sp (new StopHook(shared_from_this(), new_uid));
+    m_stop_hooks[new_uid] = stop_hook_sp;
+    return stop_hook_sp;
 }
 
 bool
@@ -2323,7 +2324,6 @@ Error
 Target::Launch (Listener &listener, ProcessLaunchInfo &launch_info)
 {
     Error error;
-    Error error2;
     
     StateType state = eStateInvalid;
     
@@ -2399,40 +2399,49 @@ Target::Launch (Listener &listener, Proc
     {
         if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
         {
-            StateType state = m_process_sp->WaitForProcessToStop (NULL, NULL, false);
+            ListenerSP hijack_listener_sp (launch_info.GetHijackListener());
+            
+            StateType state = m_process_sp->WaitForProcessToStop (NULL, NULL, false, hijack_listener_sp.get());
             
             if (state == eStateStopped)
             {
-                error = m_process_sp->Resume();
+                if (!synchronous_execution)
+                    m_process_sp->RestoreProcessEvents ();
+
+                error = m_process_sp->PrivateResume();
+    
                 if (error.Success())
                 {
                     if (synchronous_execution)
                     {
-                        state = m_process_sp->WaitForProcessToStop (NULL);
+                        state = m_process_sp->WaitForProcessToStop (NULL, NULL, true, hijack_listener_sp.get());
                         const bool must_be_alive = false; // eStateExited is ok, so this must be false
                         if (!StateIsStoppedState(state, must_be_alive))
                         {
-                            error2.SetErrorStringWithFormat("process isn't stopped: %s", StateAsCString(state));
-                            return error2;
+                            error.SetErrorStringWithFormat("process isn't stopped: %s", StateAsCString(state));
                         }
                     }
                 }
                 else
                 {
+                    Error error2;
                     error2.SetErrorStringWithFormat("process resume at entry point failed: %s", error.AsCString());
-                    return error2;
+                    error = error2;
                 }
             }
             else
             {
                 error.SetErrorStringWithFormat ("initial process state wasn't stopped: %s", StateAsCString(state));
             }
+            
+            m_process_sp->RestoreProcessEvents ();
         }
     }
     else
     {
+        Error error2;
         error2.SetErrorStringWithFormat ("process launch failed: %s", error.AsCString());
-        return error2;
+        error = error2;
     }
     return error;
 }

Modified: lldb/branches/iohandler/source/Target/ThreadPlanTracer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/source/Target/ThreadPlanTracer.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/source/Target/ThreadPlanTracer.cpp (original)
+++ lldb/branches/iohandler/source/Target/ThreadPlanTracer.cpp Thu Jan  2 16:40:14 2014
@@ -23,6 +23,7 @@
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/State.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Symbol/TypeList.h"
 #include "lldb/Target/RegisterContext.h"
@@ -62,7 +63,7 @@ ThreadPlanTracer::GetLogStream ()
     {
         TargetSP target_sp (m_thread.CalculateTarget());
         if (target_sp)
-            return &target_sp->GetDebugger().GetOutputStream();
+            return target_sp->GetDebugger().GetOutputFile().get();
     }
     return NULL;
 }

Modified: lldb/branches/iohandler/tools/driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/tools/driver/Driver.cpp?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/tools/driver/Driver.cpp (original)
+++ lldb/branches/iohandler/tools/driver/Driver.cpp Thu Jan  2 16:40:14 2014
@@ -18,7 +18,6 @@
 #include <string>
 
 #include <thread>
-#include "IOChannel.h"
 #include "lldb/API/SBBreakpoint.h"
 #include "lldb/API/SBCommandInterpreter.h"
 #include "lldb/API/SBCommandReturnObject.h"
@@ -121,14 +120,7 @@ static const uint32_t last_option_set_wi
 Driver::Driver () :
     SBBroadcaster ("Driver"),
     m_debugger (SBDebugger::Create(false)),
-    m_editline_pty (),
-    m_editline_slave_fh (NULL),
-    m_editline_reader (),
-    m_io_channel_ap (),
-    m_option_data (),
-    m_executing_user_command (false),
-    m_waiting_for_command (false),
-    m_done(false)
+    m_option_data ()
 {
     // We want to be able to handle CTRL+D in the terminal to have it terminate
     // certain input
@@ -145,24 +137,6 @@ Driver::~Driver ()
     g_debugger_name = NULL;
 }
 
-void
-Driver::CloseIOChannelFile ()
-{
-    // Write an End of File sequence to the file descriptor to ensure any
-    // read functions can exit.
-    char eof_str[] = "\x04";
-    int mfd = m_editline_pty.GetMasterFileDescriptor();
-    if (mfd != -1)
-        ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
-
-    m_editline_pty.CloseMasterFileDescriptor();
-
-    if (m_editline_slave_fh)
-    {
-        ::fclose (m_editline_slave_fh);
-        m_editline_slave_fh = NULL;
-    }
-}
 
 // This function takes INDENT, which tells how many spaces to output at the front
 // of each line; TEXT, which is the text that is to be output. It outputs the 
@@ -530,23 +504,27 @@ Driver::ExecuteInitialCommands (bool bef
         {
             const size_t output_size = result.GetOutputSize();
             if (output_size > 0)
-                m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
+            {
+                const char *cstr = result.GetOutput(dump_stream_only_if_no_immediate);
+                if (cstr)
+                    printf ("%s", cstr);
+            }
             const size_t error_size = result.GetErrorSize();
             if (error_size > 0)
-                m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
+            {
+                const char *cstr = result.GetError(dump_stream_only_if_no_immediate);
+                if (cstr)
+                    printf ("%s", cstr);
+            }
         }
         
         if (result.Succeeded() == false)
         {
-            char error_buffer[1024];
-            size_t error_size;
             const char *type = before_file ? "before file" : "after_file";
             if (is_file)
-                error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command file: '%s' failed.\n", type, command);
+                ::fprintf(stderr, "Aborting %s command execution, command file: '%s' failed.\n", type, command);
             else
-                error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command: '%s' failed.\n", type, command);
-            
-            m_io_channel_ap->OutWrite(error_buffer, error_size, NO_ASYNC);
+                ::fprintf(stderr, "Aborting %s command execution, command: '%s' failed.\n", type, command);
             break;
         }
         result.Clear();
@@ -861,524 +839,9 @@ Driver::ParseArgs (int argc, const char
     return error;
 }
 
-size_t
-Driver::GetProcessSTDOUT ()
-{
-    //  The process has stuff waiting for stdout; get it and write it out to the appropriate place.
-    char stdio_buffer[1024];
-    size_t len;
-    size_t total_bytes = 0;
-    while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
-    {
-        m_io_channel_ap->OutWrite (stdio_buffer, len, NO_ASYNC);
-        total_bytes += len;
-    }
-    return total_bytes;
-}
-
-size_t
-Driver::GetProcessSTDERR ()
-{
-    //  The process has stuff waiting for stderr; get it and write it out to the appropriate place.
-    char stdio_buffer[1024];
-    size_t len;
-    size_t total_bytes = 0;
-    while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
-    {
-        m_io_channel_ap->ErrWrite (stdio_buffer, len, NO_ASYNC);
-        total_bytes += len;
-    }
-    return total_bytes;
-}
-
-void
-Driver::UpdateSelectedThread ()
-{
-    using namespace lldb;
-    SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
-    if (process.IsValid())
-    {
-        SBThread curr_thread (process.GetSelectedThread());
-        SBThread thread;
-        StopReason curr_thread_stop_reason = eStopReasonInvalid;
-        curr_thread_stop_reason = curr_thread.GetStopReason();
-
-        if (!curr_thread.IsValid() ||
-            curr_thread_stop_reason == eStopReasonInvalid ||
-            curr_thread_stop_reason == eStopReasonNone)
-        {
-            // Prefer a thread that has just completed its plan over another thread as current thread.
-            SBThread plan_thread;
-            SBThread other_thread;
-            const size_t num_threads = process.GetNumThreads();
-            size_t i;
-            for (i = 0; i < num_threads; ++i)
-            {
-                thread = process.GetThreadAtIndex(i);
-                StopReason thread_stop_reason = thread.GetStopReason();
-                switch (thread_stop_reason)
-                {
-                case eStopReasonInvalid:
-                case eStopReasonNone:
-                    break;
-
-                case eStopReasonTrace:
-                case eStopReasonBreakpoint:
-                case eStopReasonWatchpoint:
-                case eStopReasonSignal:
-                case eStopReasonException:
-                case eStopReasonExec:
-                case eStopReasonThreadExiting:
-                    if (!other_thread.IsValid())
-                        other_thread = thread;
-                    break;
-                case eStopReasonPlanComplete:
-                    if (!plan_thread.IsValid())
-                        plan_thread = thread;
-                    break;
-                }
-            }
-            if (plan_thread.IsValid())
-                process.SetSelectedThread (plan_thread);
-            else if (other_thread.IsValid())
-                process.SetSelectedThread (other_thread);
-            else
-            {
-                if (curr_thread.IsValid())
-                    thread = curr_thread;
-                else
-                    thread = process.GetThreadAtIndex(0);
-
-                if (thread.IsValid())
-                    process.SetSelectedThread (thread);
-            }
-        }
-    }
-}
-
-// This function handles events that were broadcast by the process.
-void
-Driver::HandleBreakpointEvent (const SBEvent &event)
-{
-    using namespace lldb;
-    const uint32_t event_type = SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
-    
-    if (event_type & eBreakpointEventTypeAdded
-        || event_type & eBreakpointEventTypeRemoved
-        || event_type & eBreakpointEventTypeEnabled
-        || event_type & eBreakpointEventTypeDisabled
-        || event_type & eBreakpointEventTypeCommandChanged
-        || event_type & eBreakpointEventTypeConditionChanged
-        || event_type & eBreakpointEventTypeIgnoreChanged
-        || event_type & eBreakpointEventTypeLocationsResolved)
-    {
-        // Don't do anything about these events, since the breakpoint commands already echo these actions.
-    }              
-    else if (event_type & eBreakpointEventTypeLocationsAdded)
-    {
-        char message[256];
-        uint32_t num_new_locations = SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
-        if (num_new_locations > 0)
-        {
-            SBBreakpoint breakpoint = SBBreakpoint::GetBreakpointFromEvent(event);
-            int message_len = ::snprintf (message, sizeof(message), "%d location%s added to breakpoint %d\n", 
-                                          num_new_locations,
-                                          num_new_locations == 1 ? "" : "s",
-                                          breakpoint.GetID());
-            m_io_channel_ap->OutWrite(message, message_len, ASYNC);
-        }
-    }
-    else if (event_type & eBreakpointEventTypeLocationsRemoved)
-    {
-       // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
-    }
-    else if (event_type & eBreakpointEventTypeLocationsResolved)
-    {
-       // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
-    }
-}
-
-// This function handles events that were broadcast by the process.
-void
-Driver::HandleProcessEvent (const SBEvent &event)
-{
-    using namespace lldb;
-    const uint32_t event_type = event.GetType();
-
-    if (event_type & SBProcess::eBroadcastBitSTDOUT)
-    {
-        // The process has stdout available, get it and write it out to the
-        // appropriate place.
-        GetProcessSTDOUT ();
-    }
-    else if (event_type & SBProcess::eBroadcastBitSTDERR)
-    {
-        // The process has stderr available, get it and write it out to the
-        // appropriate place.
-        GetProcessSTDERR ();
-    }
-    else if (event_type & SBProcess::eBroadcastBitStateChanged)
-    {
-        // Drain all stout and stderr so we don't see any output come after
-        // we print our prompts
-        GetProcessSTDOUT ();
-        GetProcessSTDERR ();
-        // Something changed in the process;  get the event and report the process's current status and location to
-        // the user.
-        StateType event_state = SBProcess::GetStateFromEvent (event);
-        if (event_state == eStateInvalid)
-            return;
-
-        SBProcess process (SBProcess::GetProcessFromEvent (event));
-        assert (process.IsValid());
-
-        switch (event_state)
-        {
-        case eStateInvalid:
-        case eStateUnloaded:
-        case eStateConnected:
-        case eStateAttaching:
-        case eStateLaunching:
-        case eStateStepping:
-        case eStateDetached:
-            {
-                char message[1024];
-                int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " %s\n", process.GetProcessID(),
-                                              m_debugger.StateAsCString (event_state));
-                m_io_channel_ap->OutWrite(message, message_len, ASYNC);
-            }
-            break;
-
-        case eStateRunning:
-            // Don't be chatty when we run...
-            break;
-
-        case eStateExited:
-            {
-                SBCommandReturnObject result;
-                m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
-                m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
-                m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
-            }
-            break;
-
-        case eStateStopped:
-        case eStateCrashed:
-        case eStateSuspended:
-            // Make sure the program hasn't been auto-restarted:
-            if (SBProcess::GetRestartedFromEvent (event))
-            {
-                size_t num_reasons = SBProcess::GetNumRestartedReasonsFromEvent(event);
-                if (num_reasons > 0)
-                {
-                // FIXME: Do we want to report this, or would that just be annoyingly chatty?
-                    if (num_reasons == 1)
-                    {
-                        char message[1024];
-                        const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, 0);
-                        int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted: %s\n",
-                                              process.GetProcessID(), reason ? reason : "<UNKNOWN REASON>");
-                        m_io_channel_ap->OutWrite(message, message_len, ASYNC);
-                    }
-                    else
-                    {
-                        char message[1024];
-                        int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted, reasons:\n",
-                                              process.GetProcessID());
-                        m_io_channel_ap->OutWrite(message, message_len, ASYNC);
-                        for (size_t i = 0; i < num_reasons; i++)
-                        {
-                            const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, i);
-                            int message_len = ::snprintf(message, sizeof(message), "\t%s\n", reason ? reason : "<UNKNOWN REASON>");
-                            m_io_channel_ap->OutWrite(message, message_len, ASYNC);
-                        }
-                    }
-                }
-            }
-            else
-            {
-                if (GetDebugger().GetSelectedTarget() == process.GetTarget())
-                {
-                    SBCommandReturnObject result;
-                    UpdateSelectedThread ();
-                    m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
-                    m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
-                    m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
-                }
-                else
-                {
-                    SBStream out_stream;
-                    uint32_t target_idx = GetDebugger().GetIndexOfTarget(process.GetTarget());
-                    if (target_idx != UINT32_MAX)
-                        out_stream.Printf ("Target %d: (", target_idx);
-                    else
-                        out_stream.Printf ("Target <unknown index>: (");
-                    process.GetTarget().GetDescription (out_stream, eDescriptionLevelBrief);
-                    out_stream.Printf (") stopped.\n");
-                    m_io_channel_ap->OutWrite (out_stream.GetData(), out_stream.GetSize(), ASYNC);
-                }
-            }
-            break;
-        }
-    }
-}
-
-void
-Driver::HandleThreadEvent (const SBEvent &event)
-{
-    // At present the only thread event we handle is the Frame Changed event, and all we do for that is just
-    // reprint the thread status for that thread.
-    using namespace lldb;
-    const uint32_t event_type = event.GetType();
-    if (event_type == SBThread::eBroadcastBitStackChanged
-        || event_type == SBThread::eBroadcastBitThreadSelected)
-    {
-        SBThread thread = SBThread::GetThreadFromEvent (event);
-        if (thread.IsValid())
-        {
-            SBStream out_stream;
-            thread.GetStatus(out_stream);
-            m_io_channel_ap->OutWrite (out_stream.GetData (), out_stream.GetSize (), ASYNC);
-        }
-    }
-}
-
-//  This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
-
-bool
-Driver::HandleIOEvent (const SBEvent &event)
-{
-    bool quit = false;
-
-    const uint32_t event_type = event.GetType();
-
-    if (event_type & IOChannel::eBroadcastBitHasUserInput)
-    {
-        // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
-        // handling.
-
-        const char *command_string = SBEvent::GetCStringFromEvent(event);
-        if (command_string == NULL)
-            command_string = "";
-        SBCommandReturnObject result;
-        
-        // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
-        // output orderings and problems with the prompt.
-        
-        // Note that we are in the process of executing a command
-        m_executing_user_command = true;
-
-        m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
-
-        // Note that we are back from executing a user command
-        m_executing_user_command = false;
-
-        // Display any STDOUT/STDERR _prior_ to emitting the command result text
-        GetProcessSTDOUT ();
-        GetProcessSTDERR ();
-
-        const bool only_if_no_immediate = true;
-
-        // Now emit the command output text from the command we just executed
-        const size_t output_size = result.GetOutputSize();
-        if (output_size > 0)
-            m_io_channel_ap->OutWrite (result.GetOutput(only_if_no_immediate), output_size, NO_ASYNC);
-
-        // Now emit the command error text from the command we just executed
-        const size_t error_size = result.GetErrorSize();
-        if (error_size > 0)
-            m_io_channel_ap->OutWrite (result.GetError(only_if_no_immediate), error_size, NO_ASYNC);
-
-        // We are done getting and running our command, we can now clear the
-        // m_waiting_for_command so we can get another one.
-        m_waiting_for_command = false;
-
-        // If our editline input reader is active, it means another input reader
-        // got pushed onto the input reader and caused us to become deactivated.
-        // When the input reader above us gets popped, we will get re-activated
-        // and our prompt will refresh in our callback
-        if (m_editline_reader.IsActive())
-        {
-            ReadyForCommand ();
-        }
-    }
-    else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
-    {
-        // This is here to handle control-c interrupts from the user.  It has not yet really been implemented.
-        // TO BE DONE:  PROPERLY HANDLE CONTROL-C FROM USER
-        //m_io_channel_ap->CancelInput();
-        // Anything else?  Send Interrupt to process?
-    }
-    else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
-             (event_type & IOChannel::eBroadcastBitThreadDidExit))
-    {
-        // If the IOChannel thread is trying to go away, then it is definitely
-        // time to end the debugging session.
-        quit = true;
-    }
-
-    return quit;
-}
-
-void
-Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
-{
-    Driver *driver = (Driver*)baton;
-    driver->GetFromMaster ((const char *)src, src_len);
-}
-
-void
-Driver::GetFromMaster (const char *src, size_t src_len)
-{
-    // Echo the characters back to the Debugger's stdout, that way if you
-    // type characters while a command is running, you'll see what you've typed.
-    FILE *out_fh = m_debugger.GetOutputFileHandle();
-    if (out_fh)
-        ::fwrite (src, 1, src_len, out_fh);
-}
-
-size_t
-Driver::EditLineInputReaderCallback 
-(
-    void *baton, 
-    SBInputReader *reader, 
-    InputReaderAction notification,
-    const char *bytes, 
-    size_t bytes_len
-)
-{
-    Driver *driver = (Driver *)baton;
-
-    switch (notification)
-    {
-    case eInputReaderActivate:
-        break;
-
-    case eInputReaderReactivate:
-        if (driver->m_executing_user_command == false)
-            driver->ReadyForCommand();
-        break;
-
-    case eInputReaderDeactivate:
-        break;
-        
-    case eInputReaderAsynchronousOutputWritten:
-        if (driver->m_io_channel_ap.get() != NULL)
-            driver->m_io_channel_ap->RefreshPrompt();
-        break;
-
-    case eInputReaderInterrupt:
-        if (driver->m_io_channel_ap.get() != NULL)
-        {
-            SBProcess process(driver->GetDebugger().GetSelectedTarget().GetProcess());
-            if (!driver->m_io_channel_ap->EditLineHasCharacters()
-                &&  process.IsValid()
-                && (process.GetState() == lldb::eStateRunning || process.GetState() == lldb::eStateAttaching))
-            {
-                process.SendAsyncInterrupt ();
-            }
-            else
-            {
-                driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
-                // I wish I could erase the entire input line, but there's no public API for that.
-                driver->m_io_channel_ap->EraseCharsBeforeCursor();
-                driver->m_io_channel_ap->RefreshPrompt();
-            }
-        }
-        break;
-        
-    case eInputReaderEndOfFile:
-        if (driver->m_io_channel_ap.get() != NULL)
-        {
-            driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
-            driver->m_io_channel_ap->RefreshPrompt ();
-        }
-        write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
-        break;
-
-    case eInputReaderGotToken:
-        write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
-        break;
-        
-    case eInputReaderDone:
-        break;
-    }
-    return bytes_len;
-}
-
 void
 Driver::MainLoop ()
 {
-#if defined(_MSC_VER)
-    m_editline_slave_fh = stdin;
-    FILE *editline_output_slave_fh = stdout;
-    lldb_utility::PseudoTerminal editline_output_pty;
-#else
-
-    char error_str[1024];
-    if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
-    {
-        ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
-        exit(1);
-    }
-    else
-    {
-        const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
-        if (driver_slave_name == NULL)
-        {
-            ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
-            exit(2);
-        }
-        else
-        {
-            m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
-            if (m_editline_slave_fh == NULL)
-            {
-                SBError error;
-                error.SetErrorToErrno();
-                ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
-                           error.GetCString());
-                exit(3);
-            }
-
-            ::setbuf (m_editline_slave_fh, NULL);
-        }
-    }
-
-    lldb_utility::PseudoTerminal editline_output_pty;
-    FILE *editline_output_slave_fh = NULL;
-    
-    if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
-    {
-        ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
-        exit(1);
-    }
-    else
-    {
-        const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
-        if (output_slave_name == NULL)
-        {
-            ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
-            exit(2);
-        }
-        else
-        {
-            editline_output_slave_fh = ::fopen (output_slave_name, "r+");
-            if (editline_output_slave_fh == NULL)
-            {
-                SBError error;
-                error.SetErrorToErrno();
-                ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
-                           error.GetCString());
-                exit(3);
-            }
-            ::setbuf (editline_output_slave_fh, NULL);
-        }
-    }
-#endif
-
-   // struct termios stdin_termios;
-
     if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
     {
         g_old_stdin_termios_is_valid = true;
@@ -1394,43 +857,6 @@ Driver::MainLoop ()
     
     m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
 
-    // You have to drain anything that comes to the master side of the PTY.  master_out_comm is
-    // for that purpose.  The reason you need to do this is a curious reason...  editline will echo
-    // characters to the PTY when it gets characters while el_gets is not running, and then when
-    // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
-    // if there are unconsumed characters in the out buffer.
-    // However, you don't need to do anything with the characters, since editline will dump these
-    // unconsumed characters after printing the prompt again in el_gets.
-
-    SBCommunication master_out_comm("driver.editline");
-    master_out_comm.SetCloseOnEOF (false);
-    master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
-    master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
-
-    if (master_out_comm.ReadThreadStart () == false)
-    {
-        ::fprintf (stderr, "error: failed to start master out read thread");
-        exit(5);
-    }
-
-    SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
-
-    m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
-
-#if !defined (_MSC_VER)
-    SBCommunication out_comm_2("driver.editline_output");
-    out_comm_2.SetCloseOnEOF (false);
-    out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
-    out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
-
-    if (out_comm_2.ReadThreadStart () == false)
-    {
-        ::fprintf (stderr, "error: failed to start libedit output read thread");
-        exit (5);
-    }
-#endif
-
-
     struct winsize window_size;
     if (isatty (STDIN_FILENO)
         && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
@@ -1439,286 +865,93 @@ Driver::MainLoop ()
             m_debugger.SetTerminalWidth (window_size.ws_col);
     }
 
-    // Since input can be redirected by the debugger, we must insert our editline
-    // input reader in the queue so we know when our reader should be active
-    // and so we can receive bytes only when we are supposed to.
-    SBError err (m_editline_reader.Initialize (m_debugger, 
-                                               Driver::EditLineInputReaderCallback, // callback
-                                               this,                              // baton
-                                               eInputReaderGranularityByte,       // token_size
-                                               NULL,                              // end token - NULL means never done
-                                               NULL,                              // prompt - taken care of elsewhere
-                                               false));                           // echo input - don't need Debugger 
-                                                                                  // to do this, we handle it elsewhere
+    SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
     
-    if (err.Fail())
+    // Before we handle any options from the command line, we parse the
+    // .lldbinit file in the user's home directory.
+    SBCommandReturnObject result;
+    sb_interpreter.SourceInitFileInHomeDirectory(result);
+    if (GetDebugMode())
     {
-        ::fprintf (stderr, "error: %s", err.GetCString());
-        exit (6);
+        result.PutError (m_debugger.GetErrorFileHandle());
+        result.PutOutput (m_debugger.GetOutputFileHandle());
     }
-    
-    m_debugger.PushInputReader (m_editline_reader);
-
-    SBListener listener(m_debugger.GetListener());
-    if (listener.IsValid())
-    {
-
-        listener.StartListeningForEventClass(m_debugger, 
-                                         SBTarget::GetBroadcasterClassName(), 
-                                         SBTarget::eBroadcastBitBreakpointChanged);
-        listener.StartListeningForEventClass(m_debugger, 
-                                         SBThread::GetBroadcasterClassName(),
-                                         SBThread::eBroadcastBitStackChanged |
-                                         SBThread::eBroadcastBitThreadSelected);
-        listener.StartListeningForEvents (*m_io_channel_ap,
-                                          IOChannel::eBroadcastBitHasUserInput |
-                                          IOChannel::eBroadcastBitUserInterrupt |
-                                          IOChannel::eBroadcastBitThreadShouldExit |
-                                          IOChannel::eBroadcastBitThreadDidStart |
-                                          IOChannel::eBroadcastBitThreadDidExit);
 
-        if (m_io_channel_ap->Start ())
+    // Now we handle options we got from the command line
+    // First source in the commands specified to be run before the file arguments are processed.
+    ExecuteInitialCommands(true);
+    
+    // Was there a core file specified?
+    std::string core_file_spec("");
+    if (!m_option_data.m_core_file.empty())
+        core_file_spec.append("--core ").append(m_option_data.m_core_file);
+    
+    char command_string[PATH_MAX * 2];
+    const size_t num_args = m_option_data.m_args.size();
+    if (num_args > 0)
+    {
+        char arch_name[64];
+        if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
+            ::snprintf (command_string,
+                        sizeof (command_string),
+                        "target create --arch=%s %s \"%s\"",
+                        arch_name,
+                        core_file_spec.c_str(),
+                        m_option_data.m_args[0].c_str());
+        else
+            ::snprintf (command_string,
+                        sizeof(command_string),
+                        "target create %s \"%s\"",
+                        core_file_spec.c_str(),
+                        m_option_data.m_args[0].c_str());
+        
+        m_debugger.HandleCommand (command_string);
+        
+        if (num_args > 1)
         {
-            bool iochannel_thread_exited = false;
-
-            listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
-                                              SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
-                                              SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
-                                              SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
-
-            // Before we handle any options from the command line, we parse the
-            // .lldbinit file in the user's home directory.
-            SBCommandReturnObject result;
-            sb_interpreter.SourceInitFileInHomeDirectory(result);
-            if (GetDebugMode())
+            m_debugger.HandleCommand ("settings clear target.run-args");
+            char arg_cstr[1024];
+            for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
             {
-                result.PutError (m_debugger.GetErrorFileHandle());
-                result.PutOutput (m_debugger.GetOutputFileHandle());
+                ::snprintf (arg_cstr,
+                            sizeof(arg_cstr),
+                            "settings append target.run-args \"%s\"",
+                            m_option_data.m_args[arg_idx].c_str());
+                m_debugger.HandleCommand (arg_cstr);
             }
-
-            // Now we handle options we got from the command line
-            // First source in the commands specified to be run before the file arguments are processed.
-            ExecuteInitialCommands(true);
-            
-            // Was there a core file specified?
-            std::string core_file_spec("");
-            if (!m_option_data.m_core_file.empty())
-                core_file_spec.append("--core ").append(m_option_data.m_core_file);
-
-            char command_string[PATH_MAX * 2];
-            const size_t num_args = m_option_data.m_args.size();
-            if (num_args > 0)
-            {
-                char arch_name[64];
-                if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
-                    ::snprintf (command_string, 
-                                sizeof (command_string), 
-                                "target create --arch=%s %s \"%s\"", 
-                                arch_name,
-                                core_file_spec.c_str(),
-                                m_option_data.m_args[0].c_str());
-                else
-                    ::snprintf (command_string, 
-                                sizeof(command_string), 
-                                "target create %s \"%s\"", 
-                                core_file_spec.c_str(),
-                                m_option_data.m_args[0].c_str());
-
-                m_debugger.HandleCommand (command_string);
-                
-                if (num_args > 1)
-                {
-                    m_debugger.HandleCommand ("settings clear target.run-args");
-                    char arg_cstr[1024];
-                    for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
-                    {
-                        ::snprintf (arg_cstr, 
-                                    sizeof(arg_cstr), 
-                                    "settings append target.run-args \"%s\"", 
-                                    m_option_data.m_args[arg_idx].c_str());
-                        m_debugger.HandleCommand (arg_cstr);
-                    }
-                }
-            }
-            else if (!core_file_spec.empty())
-            {
-                ::snprintf (command_string, 
-                            sizeof(command_string), 
-                            "target create %s", 
-                            core_file_spec.c_str());
-                m_debugger.HandleCommand (command_string);;
-            }
-
-            // Now that all option parsing is done, we try and parse the .lldbinit
-            // file in the current working directory
-            sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
-            if (GetDebugMode())
-            {
-                result.PutError(m_debugger.GetErrorFileHandle());
-                result.PutOutput(m_debugger.GetOutputFileHandle());
-            }
-            
-            // Now execute the commands specified for after the file arguments are processed.
-            ExecuteInitialCommands(false);
-
-            SBEvent event;
-
-            // Make sure the IO channel is started up before we try to tell it we
-            // are ready for input
-            listener.WaitForEventForBroadcasterWithType (UINT32_MAX, 
-                                                         *m_io_channel_ap,
-                                                         IOChannel::eBroadcastBitThreadDidStart, 
-                                                         event);
-            // If we were asked to attach, then do that here:
-            // I'm going to use the command string rather than directly
-            // calling the API's because then I don't have to recode the
-            // event handling here.
-            if (!m_option_data.m_process_name.empty()
-                || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
-            {
-                std::string command_str("process attach ");
-                if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
-                {
-                    command_str.append("-p ");
-                    char pid_buffer[32];
-                    ::snprintf (pid_buffer, sizeof(pid_buffer), "%" PRIu64, m_option_data.m_process_pid);
-                    command_str.append(pid_buffer);
-                }
-                else 
-                {
-                    command_str.append("-n \"");
-                    command_str.append(m_option_data.m_process_name);
-                    command_str.push_back('\"');
-                    if (m_option_data.m_wait_for)
-                        command_str.append(" -w");
-                }
-                
-                if (m_debugger.GetOutputFileHandle())
-                    ::fprintf (m_debugger.GetOutputFileHandle(), 
-                               "Attaching to process with:\n    %s\n", 
-                               command_str.c_str());
-                                               
-                // Force the attach to be synchronous:
-                bool orig_async = m_debugger.GetAsync();
-                m_debugger.SetAsync(true);
-                m_debugger.HandleCommand(command_str.c_str());
-                m_debugger.SetAsync(orig_async);                
-            }
-                        
-            ReadyForCommand ();
-
-            while (!GetIsDone())
-            {
-                listener.WaitForEvent (UINT32_MAX, event);
-                if (event.IsValid())
-                {
-                    if (event.GetBroadcaster().IsValid())
-                    {
-                        uint32_t event_type = event.GetType();
-                        if (event.BroadcasterMatchesRef (*m_io_channel_ap))
-                        {
-                            if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
-                                (event_type & IOChannel::eBroadcastBitThreadDidExit))
-                            {
-                                SetIsDone();
-                                if (event_type & IOChannel::eBroadcastBitThreadDidExit)
-                                    iochannel_thread_exited = true;
-                            }
-                            else
-                            {
-                                if (HandleIOEvent (event))
-                                    SetIsDone();
-                            }
-                        }
-                        else if (SBProcess::EventIsProcessEvent (event))
-                        {
-                            HandleProcessEvent (event);
-                        }
-                        else if (SBBreakpoint::EventIsBreakpointEvent (event))
-                        {
-                            HandleBreakpointEvent (event);
-                        }
-                        else if (SBThread::EventIsThreadEvent (event))
-                        {
-                            HandleThreadEvent (event);
-                        }
-                        else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
-                        {
-                            // TODO: deprecate the eBroadcastBitQuitCommandReceived event
-                            // now that we have SBCommandInterpreter::SetCommandOverrideCallback()
-                            // that can take over a command
-                            if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
-                            {
-                                SetIsDone();
-                            }
-                            else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
-                            {
-                                const char *data = SBEvent::GetCStringFromEvent (event);
-                                m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
-                            }
-                            else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
-                            {
-                                const char *data = SBEvent::GetCStringFromEvent (event);
-                                m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
-                            }
-                        }
-                    }
-                }
-            }
-
-            master_out_comm.SetReadThreadBytesReceivedCallback(NULL, NULL);
-            master_out_comm.Disconnect();
-            master_out_comm.ReadThreadStop();
-
-#if !defined(_MSC_VER)
-            out_comm_2.SetReadThreadBytesReceivedCallback(NULL, NULL);
-            out_comm_2.Disconnect();
-            out_comm_2.ReadThreadStop();
-#endif
-
-            editline_output_pty.CloseMasterFileDescriptor();
-            reset_stdin_termios();
-            fclose (stdin);
-
-            CloseIOChannelFile ();
-
-            if (!iochannel_thread_exited)
-            {
-                event.Clear();
-                listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
-                                                             IOChannel::eBroadcastBitThreadDidExit,
-                                                             event);
-                if (!event.IsValid())
-                {
-                    // Send end EOF to the driver file descriptor
-                    m_io_channel_ap->Stop();
-                }
-            }
-
-            SBDebugger::Destroy (m_debugger);
         }
     }
-}
-
+    else if (!core_file_spec.empty())
+    {
+        ::snprintf (command_string,
+                    sizeof(command_string),
+                    "target create %s",
+                    core_file_spec.c_str());
+        m_debugger.HandleCommand (command_string);;
+    }
 
-void
-Driver::ReadyForCommand ()
-{
-    if (m_waiting_for_command == false)
+    // Now that all option parsing is done, we try and parse the .lldbinit
+    // file in the current working directory
+    sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
+    if (GetDebugMode())
     {
-        m_waiting_for_command = true;
-        BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
+        result.PutError(m_debugger.GetErrorFileHandle());
+        result.PutOutput(m_debugger.GetOutputFileHandle());
     }
+        
+    m_debugger.RunCommandInterpreter(true);
+    
+    reset_stdin_termios();
+    fclose (stdin);
+    
+    SBDebugger::Destroy (m_debugger);
 }
 
+
 void
 Driver::ResizeWindow (unsigned short col)
 {
     GetDebugger().SetTerminalWidth (col);
-    if (m_io_channel_ap.get() != NULL)
-    {
-        m_io_channel_ap->ElResize();
-    }
 }
 
 void

Modified: lldb/branches/iohandler/tools/driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/tools/driver/Driver.h?rev=198366&r1=198365&r2=198366&view=diff
==============================================================================
--- lldb/branches/iohandler/tools/driver/Driver.h (original)
+++ lldb/branches/iohandler/tools/driver/Driver.h Thu Jan  2 16:40:14 2014
@@ -22,27 +22,15 @@
 #include "lldb/API/SBBroadcaster.h"
 #include "lldb/API/SBDebugger.h"
 #include "lldb/API/SBError.h"
-#include "lldb/API/SBInputReader.h"
 
 #define ASYNC true
 #define NO_ASYNC false
 
 class IOChannel;
 
-namespace lldb
-{
-    class SBInputReader;
-}
-
-
 class Driver : public lldb::SBBroadcaster
 {
 public:
-    enum {
-        eBroadcastBitReadyForInput    = (1 << 0),
-        eBroadcastBitThreadShouldExit = (1 << 1)
-    };
-
     Driver ();
 
     virtual
@@ -51,24 +39,6 @@ public:
     void
     MainLoop ();
 
-    void
-    PutSTDIN (const char *src, size_t src_len);
-
-    void
-    GetFromMaster (const char *src, size_t src_len);
-
-    bool
-    HandleIOEvent (const lldb::SBEvent &event);
-
-    void
-    HandleProcessEvent (const lldb::SBEvent &event);
-
-    void
-    HandleBreakpointEvent (const lldb::SBEvent &event);
-
-    void
-    HandleThreadEvent (const lldb::SBEvent &event);
-
     lldb::SBError
     ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &do_exit);
 
@@ -137,66 +107,16 @@ public:
         return m_debugger;
     }
     
-    bool
-    EditlineReaderIsTop ()
-    {
-        return m_debugger.InputReaderIsTopReader (m_editline_reader);
-    }
-
-    bool
-    GetIsDone () const
-    {
-        return m_done;
-    }
-
-    void
-    SetIsDone ()
-    {
-        m_done = true;
-    }
-    
     void
     ResizeWindow (unsigned short col);
 
 private:
     lldb::SBDebugger m_debugger;
-    lldb_utility::PseudoTerminal m_editline_pty;
-    FILE *m_editline_slave_fh;
-    lldb::SBInputReader m_editline_reader;
-    std::unique_ptr<IOChannel> m_io_channel_ap;
     OptionData m_option_data;
-    bool m_executing_user_command;
-    bool m_waiting_for_command;
-    bool m_done;
 
     void
     ResetOptionValues ();
 
-    size_t
-    GetProcessSTDOUT ();
-
-    size_t
-    GetProcessSTDERR ();
-
-    void
-    UpdateSelectedThread ();
-
-    void
-    CloseIOChannelFile ();
-
-    static size_t
-    EditLineInputReaderCallback (void *baton, 
-                                 lldb::SBInputReader *reader, 
-                                 lldb::InputReaderAction notification,
-                                 const char *bytes, 
-                                 size_t bytes_len);
-
-    static void
-    ReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
-
-    static void
-    MasterThreadBytesReceived (void *baton, const void *src, size_t src_len);
-    
     void
     ReadyForCommand ();
 };

Removed: lldb/branches/iohandler/tools/driver/IOChannel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/tools/driver/IOChannel.cpp?rev=198365&view=auto
==============================================================================
--- lldb/branches/iohandler/tools/driver/IOChannel.cpp (original)
+++ lldb/branches/iohandler/tools/driver/IOChannel.cpp (removed)
@@ -1,656 +0,0 @@
-//===-- IOChannel.cpp -------------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Platform.h"
-#include "IOChannel.h"
-
-#include <map>
-
-#include "lldb/API/SBCommandInterpreter.h"
-#include "lldb/API/SBDebugger.h"
-#include "lldb/API/SBError.h"
-#include "lldb/API/SBEvent.h"
-#include "lldb/API/SBFileSpec.h"
-#include "lldb/API/SBHostOS.h"
-#include "lldb/API/SBListener.h"
-#include "lldb/API/SBStringList.h"
-
-#include <string.h>
-#include <limits.h>
-
-using namespace lldb;
-
-typedef std::map<EditLine *, std::string> PromptMap;
-const char *g_default_prompt = "(lldb) ";
-PromptMap g_prompt_map;
-
-// Printing the following string causes libedit to back up to the beginning of the line & blank it out.
-const char undo_prompt_string[4] = { (char) 13, (char) 27, (char) 91, (char) 75};
-
-static const char*
-el_prompt(EditLine *el)
-{
-    PromptMap::const_iterator pos = g_prompt_map.find (el);
-    if (pos == g_prompt_map.end())
-        return g_default_prompt;
-    return pos->second.c_str();
-}
-
-const char *
-IOChannel::GetPrompt ()
-{
-    PromptMap::const_iterator pos = g_prompt_map.find (m_edit_line);
-    if (pos == g_prompt_map.end())
-        return g_default_prompt;
-    return pos->second.c_str();
-}
-
-bool
-IOChannel::EditLineHasCharacters ()
-{
-    const LineInfo *line_info  = el_line(m_edit_line);
-    if (line_info)
-    {
-        // Sometimes we get called after the user has submitted the line, but before editline has
-        // cleared the buffer.  In that case the cursor will be pointing at the newline.  That's
-        // equivalent to having no characters on the line, since it has already been submitted.
-        if (*line_info->cursor == '\n')
-            return false;
-        else
-            return line_info->cursor != line_info->buffer;
-    }
-    else
-        return false;
-}
-
-
-void
-IOChannel::EraseCharsBeforeCursor ()
-{
-    const LineInfo *line_info  = el_line(m_edit_line);
-    if (line_info != NULL)
-        el_deletestr(m_edit_line, line_info->cursor - line_info->buffer);
-}
-
-unsigned char
-IOChannel::ElCompletionFn (EditLine *e, int ch)
-{
-    IOChannel *io_channel;
-    if (el_get(e, EL_CLIENTDATA, &io_channel) == 0)
-    {
-        return io_channel->HandleCompletion (e, ch);
-    }
-    else
-    {
-        return CC_ERROR;
-    }
-}
-
-void
-IOChannel::ElResize()
-{
-    el_resize(m_edit_line);
-}
-
-unsigned char
-IOChannel::HandleCompletion (EditLine *e, int ch)
-{
-    assert (e == m_edit_line);
-
-    const LineInfo *line_info  = el_line(m_edit_line);
-    SBStringList completions;
-    int page_size = 40;
-
-    int num_completions = m_driver->GetDebugger().GetCommandInterpreter().HandleCompletion (line_info->buffer,
-                                                                                            line_info->cursor,
-                                                                                            line_info->lastchar,
-                                                                                            0,
-                                                                                            -1,
-                                                                                            completions);
-    
-    if (num_completions == -1)
-    {
-        el_insertstr (m_edit_line, m_completion_key);
-        return CC_REDISPLAY;
-    }
-    else if (num_completions == -2)
-    {
-        el_deletestr (m_edit_line, line_info->cursor - line_info->buffer);
-        el_insertstr (m_edit_line, completions.GetStringAtIndex(0));
-        return CC_REDISPLAY;
-    }
-
-    // If we get a longer match display that first.
-    const char *completion_str = completions.GetStringAtIndex(0);
-    if (completion_str != NULL && *completion_str != '\0')
-    {
-        el_insertstr (m_edit_line, completion_str);
-        return CC_REDISPLAY;
-    }
-
-    if (num_completions > 1)
-    {
-        const char *comment = "\nAvailable completions:";
-
-        int num_elements = num_completions + 1;
-        OutWrite(comment,  strlen (comment), NO_ASYNC);
-        if (num_completions < page_size)
-        {
-            for (int i = 1; i < num_elements; i++)
-            {
-                completion_str = completions.GetStringAtIndex(i);
-                OutWrite("\n\t", 2, NO_ASYNC);
-                OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
-            }
-            OutWrite ("\n", 1, NO_ASYNC);
-        }
-        else
-        {
-            int cur_pos = 1;
-            char reply;
-            int got_char;
-            while (cur_pos < num_elements)
-            {
-                int endpoint = cur_pos + page_size;
-                if (endpoint > num_elements)
-                    endpoint = num_elements;
-                for (; cur_pos < endpoint; cur_pos++)
-                {
-                    completion_str = completions.GetStringAtIndex(cur_pos);
-                    OutWrite("\n\t", 2, NO_ASYNC);
-                    OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
-                }
-
-                if (cur_pos >= num_elements)
-                {
-                    OutWrite("\n", 1, NO_ASYNC);
-                    break;
-                }
-
-                OutWrite("\nMore (Y/n/a): ", strlen ("\nMore (Y/n/a): "), NO_ASYNC);
-                reply = 'n';
-                got_char = el_getc(m_edit_line, &reply);
-                if (got_char == -1 || reply == 'n')
-                    break;
-                if (reply == 'a')
-                    page_size = num_elements - cur_pos;
-            }
-        }
-
-    }
-
-    if (num_completions == 0)
-        return CC_REFRESH_BEEP;
-    else
-        return CC_REDISPLAY;
-}
-
-IOChannel::IOChannel
-(
-    FILE *editline_in,
-    FILE *editline_out,
-    FILE *out,  
-    FILE *err,
-    Driver *driver
-) :
-    SBBroadcaster ("IOChannel"),
-    m_output_mutex (),
-    m_enter_elgets_time (),
-    m_driver (driver),
-    m_read_thread (LLDB_INVALID_HOST_THREAD),
-    m_read_thread_should_exit (false),
-    m_out_file (out),
-    m_err_file (err),
-    m_editline_out (editline_out),
-    m_command_queue (),
-    m_completion_key ("\t"),
-    m_edit_line (::el_init (SBHostOS::GetProgramFileSpec().GetFilename(), editline_in, editline_out,  editline_out)),
-    m_history (history_init()),
-    m_history_event(),
-    m_getting_command (false),
-    m_expecting_prompt (false),
-    m_prompt_str (),
-    m_refresh_request_pending (false)
-{
-    assert (m_edit_line);
-    el_set (m_edit_line, EL_PROMPT, el_prompt);
-    el_set (m_edit_line, EL_EDITOR, "emacs");
-    el_set (m_edit_line, EL_HIST, history, m_history);
-    el_set (m_edit_line, EL_ADDFN, "lldb_complete", "LLDB completion function", IOChannel::ElCompletionFn);
-    el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL);
-    el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL);  // Cycle through backwards search, entering string
-    el_set (m_edit_line, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does.
-    el_set (m_edit_line, EL_BIND, "\033[3~", "ed-delete-next-char", NULL); // Fix the delete key.
-    el_set (m_edit_line, EL_CLIENTDATA, this);
-
-    // Source $PWD/.editrc then $HOME/.editrc
-    el_source (m_edit_line, NULL);
-
-    assert (m_history);
-    history (m_history, &m_history_event, H_SETSIZE, 800);
-    history (m_history, &m_history_event, H_SETUNIQUE, 1);
-    // Load history
-    HistorySaveLoad (false);
-
-    // Initialize time that ::el_gets was last called.
-    m_enter_elgets_time.tv_sec = 0;
-    m_enter_elgets_time.tv_usec = 0;
-
-    // set the initial state to non flushed
-    m_output_flushed = false;
-}
-
-IOChannel::~IOChannel ()
-{
-    // Save history
-    HistorySaveLoad (true);
-
-    if (m_history != NULL)
-    {
-        ::history_end (m_history);
-        m_history = NULL;
-    }
-
-    if (m_edit_line != NULL)
-    {
-        ::el_end (m_edit_line);
-        m_edit_line = NULL;
-    }
-}
-
-void
-IOChannel::HistorySaveLoad (bool save)
-{
-    if (m_history != NULL)
-    {
-        char history_path[PATH_MAX];
-        ::snprintf (history_path, sizeof(history_path), "~/.%s-history", SBHostOS::GetProgramFileSpec().GetFilename());
-        if ((size_t)SBFileSpec::ResolvePath (history_path, history_path, sizeof(history_path)) < sizeof(history_path) - 1)
-        {
-            const char *path_ptr = history_path;
-            if (save)
-                ::history (m_history, &m_history_event, H_SAVE, path_ptr);
-            else
-                ::history (m_history, &m_history_event, H_LOAD, path_ptr);
-        }
-    }
-}
-
-void
-IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len)
-{
-    IOChannel *io_channel = (IOChannel *) baton;
-    std::lock_guard<std::recursive_mutex> locker(io_channel->m_output_mutex);
-    const char *bytes = (const char *) src;
-
-    bool flush = false;
-
-    // See if we have a 'flush' synchronization point in there.
-    // this is performed from 'fputc ('\0', m_editline_out);' in LibeditGetInput()
-    if (src_len > 0 && bytes[src_len-1] == '\0')
-    {
-        src_len--;
-        flush = true;
-    }
-
-    if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt)
-    {
-        io_channel->m_prompt_str.append (bytes, src_len);
-        // Log this to make sure the prompt is really what you think it is.
-        if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0)
-        {
-            io_channel->m_expecting_prompt = false;
-            io_channel->m_refresh_request_pending = false;
-            io_channel->OutWrite (io_channel->m_prompt_str.c_str(), 
-                                  io_channel->m_prompt_str.size(), NO_ASYNC);
-            io_channel->m_prompt_str.clear();
-        }
-    }
-    else
-    {
-        if (io_channel->m_prompt_str.size() > 0)
-            io_channel->m_prompt_str.clear();
-        std::string tmp_str (bytes, src_len);
-        if (tmp_str.find (el_prompt (io_channel->m_edit_line)) == 0)
-            io_channel->m_refresh_request_pending = false;
-        io_channel->OutWrite (bytes, src_len, NO_ASYNC);
-    }
-
-#if !defined (_MSC_VER)
-    if (flush)
-    {
-        io_channel->m_output_flushed = true;
-        io_channel->m_output_cond.notify_all();
-    }
-#endif
-
-}
-
-IOChannel::LibeditGetInputResult
-IOChannel::LibeditGetInput (std::string &new_line)
-{
-    IOChannel::LibeditGetInputResult retval = IOChannel::eLibeditGetInputResultUnknown;
-    if (m_edit_line != NULL)
-    {
-        int line_len = 0;
-
-        // Set boolean indicating whether or not el_gets is trying to get input (i.e. whether or not to attempt
-        // to refresh the prompt after writing data).
-        SetGettingCommand (true);
-        m_expecting_prompt = true;
-
-        // Call el_gets to prompt the user and read the user's input.
-        const char *line = ::el_gets (m_edit_line, &line_len);
-
-#if !defined (_MSC_VER)
-        // Force the piped output from el_gets to finish processing.
-        // el_gets does an fflush internally, which is not sufficient here; it only
-        // writes the data into m_editline_out, but doesn't affect whether our worker
-        // thread will read that data yet. So we block here manually.
-        {
-            std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
-            m_output_flushed = false;
-
-            // Write a synchronization point into the stream, so we can guarantee
-            // LibeditOutputBytesReceived has processed everything up till that mark.
-            fputc ('\0', m_editline_out);
-
-            while (!m_output_flushed)
-            {
-                // wait until the condition variable is signaled
-                m_output_cond.wait(m_output_mutex);
-            }
-        }
-#endif
-
-        // Re-set the boolean indicating whether or not el_gets is trying to get input.
-        SetGettingCommand (false);
-
-        if (line)
-        {
-            retval = IOChannel::eLibeditGetInputValid;
-            // strip any newlines off the end of the string...
-            while (line_len > 0 && (line[line_len - 1] == '\n' || line[line_len - 1] == '\r'))
-                --line_len;
-            if (line_len > 0)
-            {
-                ::history (m_history, &m_history_event, H_ENTER, line);
-                new_line.assign (line, line_len);   // Omit the newline
-            }
-            else
-            {
-                retval = IOChannel::eLibeditGetInputEmpty;
-                // Someone just hit ENTER, return the empty string
-                new_line.clear();
-            }
-            // Return true to indicate success even if a string is empty
-            return retval;
-        }
-        else
-        {
-            retval = (line_len == 0 ? IOChannel::eLibeditGetInputEOF : IOChannel::eLibeditGetInputResultError);
-        }
-    }
-    // Return false to indicate failure. This can happen when the file handle
-    // is closed (EOF).
-    new_line.clear();
-    return retval;
-}
-
-thread_result_t
-IOChannel::IOReadThread (void *ptr)
-{
-    IOChannel *myself = static_cast<IOChannel *> (ptr);
-    myself->Run();
-    return NULL;
-}
-
-void
-IOChannel::Run ()
-{
-    SBListener listener("IOChannel::Run");
-    std::string new_line;
-
-    SBBroadcaster interpreter_broadcaster (m_driver->GetDebugger().GetCommandInterpreter().GetBroadcaster());
-    listener.StartListeningForEvents (interpreter_broadcaster,
-                                      SBCommandInterpreter::eBroadcastBitResetPrompt |
-                                      SBCommandInterpreter::eBroadcastBitThreadShouldExit |
-                                      SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
-
-    listener.StartListeningForEvents (*this,
-                                      IOChannel::eBroadcastBitThreadShouldExit);
-
-    listener.StartListeningForEvents (*m_driver,
-                                      Driver::eBroadcastBitReadyForInput |
-                                      Driver::eBroadcastBitThreadShouldExit);
-
-    // Let anyone know that the IO channel is up and listening and ready for events
-    BroadcastEventByType (eBroadcastBitThreadDidStart);
-    bool done = false;
-    while (!done)
-    {
-        SBEvent event;
-
-        listener.WaitForEvent (UINT32_MAX, event);
-        if (!event.IsValid())
-            continue;
-
-        const uint32_t event_type = event.GetType();
-
-        if (event.GetBroadcaster().IsValid())
-        {
-            if (event.BroadcasterMatchesPtr (m_driver))
-            {
-                if (event_type & Driver::eBroadcastBitReadyForInput)
-                {
-                    std::string line;
-
-                    if (CommandQueueIsEmpty())
-                    {
-                        IOChannel::LibeditGetInputResult getline_result = LibeditGetInput(line);
-                        if (getline_result == IOChannel::eLibeditGetInputEOF)
-                        {
-                            // EOF occurred
-                            // pretend that a quit was typed so the user gets a potential
-                            // chance to confirm
-                            line.assign("quit");
-                        }
-                        else if (getline_result == IOChannel::eLibeditGetInputResultError || getline_result == IOChannel::eLibeditGetInputResultUnknown)
-                        {
-                            // some random error occurred, exit and don't ask because the state might be corrupt
-                            done = true;
-                            continue;
-                        }
-                    }
-                    else
-                    {
-                        GetCommandFromQueue (line);
-                    }
-
-                    // TO BE DONE: FIGURE OUT WHICH COMMANDS SHOULD NOT BE REPEATED IF USER PRESSES PLAIN 'RETURN'
-                    // AND TAKE CARE OF THAT HERE.
-
-                    SBEvent line_event(IOChannel::eBroadcastBitHasUserInput,
-                             line.c_str(),
-                             line.size());
-                    BroadcastEvent (line_event);
-                }
-                else if (event_type & Driver::eBroadcastBitThreadShouldExit)
-                {
-                    done = true;
-                    continue;
-                }
-            }
-            else if (event.BroadcasterMatchesRef (interpreter_broadcaster))
-            {
-                switch (event_type)
-                {
-                case SBCommandInterpreter::eBroadcastBitResetPrompt:
-                    {
-                        const char *new_prompt = SBEvent::GetCStringFromEvent (event);
-                        if (new_prompt)
-                            g_prompt_map[m_edit_line] = new_prompt;
-                    }
-                    break;
-
-                case SBCommandInterpreter::eBroadcastBitThreadShouldExit:
-                case SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
-                    done = true;
-                    break;
-                }
-            }
-            else if (event.BroadcasterMatchesPtr (this))
-            {
-                if (event_type & IOChannel::eBroadcastBitThreadShouldExit)
-                {
-                    done = true;
-                    continue;
-                }
-            }
-        }
-    }
-    BroadcastEventByType (IOChannel::eBroadcastBitThreadDidExit);
-    m_driver = NULL;
-    m_read_thread = 0;
-}
-
-bool
-IOChannel::Start ()
-{
-    if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
-        return true;
-
-    m_read_thread = SBHostOS::ThreadCreate("<lldb.driver.commandline_io>", (lldb::thread_func_t) IOChannel::IOReadThread, this, NULL);
-
-    return (IS_VALID_LLDB_HOST_THREAD(m_read_thread));
-}
-
-bool
-IOChannel::Stop ()
-{
-    if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
-        return true;
-
-    BroadcastEventByType (eBroadcastBitThreadShouldExit);
-
-    // Don't call Host::ThreadCancel since el_gets won't respond to this
-    // function call -- the thread will just die and all local variables in
-    // IOChannel::Run() won't get destructed down which is bad since there is
-    // a local listener holding onto broadcasters... To ensure proper shutdown,
-    // a ^D (control-D) sequence (0x04) should be written to other end of the
-    // the "in" file handle that was passed into the contructor as closing the
-    // file handle doesn't seem to make el_gets() exit....
-    return SBHostOS::ThreadJoin (m_read_thread, NULL, NULL);
-}
-
-void
-IOChannel::RefreshPrompt ()
-{
-    // If we are not in the middle of getting input from the user, there is no need to 
-    // refresh the prompt.
-    std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
-    if (! IsGettingCommand())
-        return;
-
-    // If we haven't finished writing the prompt, there's no need to refresh it.
-    if (m_expecting_prompt)
-        return;
-
-    if (m_refresh_request_pending)
-        return;
-
-    ::el_set (m_edit_line, EL_REFRESH);
-    m_refresh_request_pending = true;    
-}
-
-void
-IOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous)
-{
-    if (len == 0 || buffer == NULL)
-        return;
-
-    // We're in the process of exiting -- IOChannel::Run() has already completed
-    // and set m_driver to NULL - it is time for us to leave now.  We might not
-    // print the final ^D to stdout in this case.  We need to do some re-work on
-    // how the I/O streams are managed at some point.
-    if (m_driver == NULL)
-    {
-        return;
-    }
-
-    // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
-    std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
-    if (m_driver->EditlineReaderIsTop() && asynchronous)
-        ::fwrite (undo_prompt_string, 1, 4, m_out_file);
-    ::fwrite (buffer, 1, len, m_out_file);
-    if (asynchronous)
-        m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
-}
-
-void
-IOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous)
-{
-    if (len == 0 || buffer == NULL)
-        return;
-
-    // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
-    std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
-    if (asynchronous)
-        ::fwrite (undo_prompt_string, 1, 4, m_err_file);
-    ::fwrite (buffer, 1, len, m_err_file);
-    if (asynchronous)
-        m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
-}
-
-void
-IOChannel::AddCommandToQueue (const char *command)
-{
-    m_command_queue.push (std::string(command));
-}
-
-bool
-IOChannel::GetCommandFromQueue (std::string &cmd)
-{
-    if (m_command_queue.empty())
-        return false;
-    cmd.swap(m_command_queue.front());
-    m_command_queue.pop ();
-    return true;
-}
-
-int
-IOChannel::CommandQueueSize () const
-{
-    return m_command_queue.size();
-}
-
-void
-IOChannel::ClearCommandQueue ()
-{
-    while (!m_command_queue.empty())
-        m_command_queue.pop();
-}
-
-bool
-IOChannel::CommandQueueIsEmpty () const
-{
-    return m_command_queue.empty();
-}
-
-bool
-IOChannel::IsGettingCommand () const
-{
-    return m_getting_command;
-}
-
-void
-IOChannel::SetGettingCommand (bool new_value)
-{
-    m_getting_command = new_value;
-}

Removed: lldb/branches/iohandler/tools/driver/IOChannel.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/iohandler/tools/driver/IOChannel.h?rev=198365&view=auto
==============================================================================
--- lldb/branches/iohandler/tools/driver/IOChannel.h (original)
+++ lldb/branches/iohandler/tools/driver/IOChannel.h (removed)
@@ -1,154 +0,0 @@
-//===-- IOChannel.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_IOChannel_h_
-#define lldb_IOChannel_h_
-
-#include <thread>
-#include <mutex>
-#include <atomic>
-#include <condition_variable>
-
-#include <string>
-#include <queue>
-#include "Driver.h"
-
-class IOChannel : public lldb::SBBroadcaster
-{
-public:
-    enum {
-        eBroadcastBitHasUserInput     = (1 << 0),
-        eBroadcastBitUserInterrupt    = (1 << 1),
-        eBroadcastBitThreadShouldExit = (1 << 2),
-        eBroadcastBitThreadDidExit    = (1 << 3),
-        eBroadcastBitThreadDidStart   = (1 << 4),
-        eBroadcastBitsSTDOUT          = (1 << 5),
-        eBroadcastBitsSTDERR          = (1 << 6),
-        eBroadcastBitsSTDIN           = (1 << 7),
-        eAllEventBits                 = 0xffffffff
-    };
-    
-    enum LibeditGetInputResult
-    {
-        eLibeditGetInputEOF = 0,
-        eLibeditGetInputValid = 1,
-        eLibeditGetInputEmpty = 2,
-        eLibeditGetInputResultError = 4,
-        eLibeditGetInputResultUnknown = 0xffffffff
-    };
-
-    IOChannel (FILE *editline_in,
-               FILE *editline_out,
-               FILE *out,
-               FILE *err,
-               Driver *driver = NULL);
-
-    virtual
-    ~IOChannel ();
-
-    bool
-    Start ();
-
-    bool
-    Stop ();
-
-    static lldb::thread_result_t
-    IOReadThread (void *);
-
-    void
-    Run ();
-
-    void
-    OutWrite (const char *buffer, size_t len, bool asynchronous);
-
-    void
-    ErrWrite (const char *buffer, size_t len, bool asynchronous);
-
-    LibeditGetInputResult
-    LibeditGetInput (std::string &);
-    
-    static void
-    LibeditOutputBytesReceived (void *baton, const void *src,size_t src_len);
-
-    void
-    SetPrompt ();
-
-    void
-    RefreshPrompt ();
-
-    void
-    AddCommandToQueue (const char *command);
-
-    bool
-    GetCommandFromQueue (std::string &cmd);
-
-    int
-    CommandQueueSize () const;
-
-    void
-    ClearCommandQueue ();
-
-    bool
-    CommandQueueIsEmpty () const;
-
-    const char *
-    GetPrompt ();
-
-    bool
-    EditLineHasCharacters ();
-    
-    void
-    EraseCharsBeforeCursor ();
-
-    static unsigned char 
-    ElCompletionFn (EditLine *e, int ch);
-    
-    void
-    ElResize();
-
-protected:
-
-    bool
-    IsGettingCommand () const;
-
-    void
-    SetGettingCommand (bool new_value);
-
-private:
-
-    std::recursive_mutex m_output_mutex;
-    std::condition_variable_any m_output_cond;
-    struct timeval m_enter_elgets_time;
-
-    Driver *m_driver;
-    lldb::thread_t m_read_thread;
-    bool m_read_thread_should_exit;
-    FILE *m_out_file;
-    FILE *m_err_file;
-    FILE *m_editline_out;
-    std::queue<std::string> m_command_queue;
-    const char *m_completion_key;
-
-    EditLine *m_edit_line;
-    History *m_history;
-    HistEvent m_history_event;
-    bool m_getting_command;
-    bool m_expecting_prompt;
-    bool m_output_flushed;
-    std::string m_prompt_str;  // for accumlating the prompt as it gets written out by editline
-    bool m_refresh_request_pending;
-
-    void
-    HistorySaveLoad (bool save);
-
-    unsigned char
-    HandleCompletion (EditLine *e, int ch);
-};
-
-#endif  // lldb_IOChannel_h_





More information about the llvm-branch-commits mailing list