[Lldb-commits] [lldb] r130721 - in /lldb/trunk: include/lldb/ include/lldb/API/ include/lldb/Core/ include/lldb/Interpreter/ lldb.xcodeproj/ source/API/ source/Commands/ source/Core/ source/Interpreter/ source/Target/ tools/driver/

Caroline Tice ctice at apple.com
Mon May 2 13:41:46 PDT 2011


Author: ctice
Date: Mon May  2 15:41:46 2011
New Revision: 130721

URL: http://llvm.org/viewvc/llvm-project?rev=130721&view=rev
Log:

This patch captures and serializes all output being written by the
command line driver, including the lldb prompt being output by
editline, the asynchronous process output & error messages, and
asynchronous messages written by target stop-hooks.

As part of this it introduces a new Stream class,
StreamAsynchronousIO.  A StreamAsynchronousIO object is created with a
broadcaster, who will eventually broadcast the stream's data for a
listener to handle, and an event type indicating what type of event
the broadcaster will broadcast.  When the Write method is called on a
StreamAsynchronousIO object, the data is appended to an internal
string.  When the Flush method is called on a StreamAsynchronousIO
object, it broadcasts it's data string and clears the string.

Anything in lldb-core that needs to generate asynchronous output for
the end-user should use the StreamAsynchronousIO objects.

I have also added a new notification type for InputReaders, to let
them know that a asynchronous output has been written. This is to
allow the input readers to, for example, refresh their prompts and
lines, if desired.  I added the case statements to all the input
readers to catch this notification, but I haven't added any code for
handling them yet (except to the IOChannel input reader).


Added:
    lldb/trunk/include/lldb/Core/StreamAsynchronousIO.h
    lldb/trunk/source/Core/StreamAsynchronousIO.cpp
Modified:
    lldb/trunk/include/lldb/API/SBCommandInterpreter.h
    lldb/trunk/include/lldb/API/SBDebugger.h
    lldb/trunk/include/lldb/Core/Debugger.h
    lldb/trunk/include/lldb/Core/Event.h
    lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
    lldb/trunk/include/lldb/lldb-enumerations.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/API/SBDebugger.cpp
    lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
    lldb/trunk/source/Commands/CommandObjectCommands.cpp
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Commands/CommandObjectTarget.cpp
    lldb/trunk/source/Core/Debugger.cpp
    lldb/trunk/source/Core/Event.cpp
    lldb/trunk/source/Core/InputReader.cpp
    lldb/trunk/source/Interpreter/CommandInterpreter.cpp
    lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
    lldb/trunk/source/Target/Process.cpp
    lldb/trunk/source/Target/Target.cpp
    lldb/trunk/tools/driver/Driver.cpp
    lldb/trunk/tools/driver/Driver.h
    lldb/trunk/tools/driver/IOChannel.cpp
    lldb/trunk/tools/driver/IOChannel.h

Modified: lldb/trunk/include/lldb/API/SBCommandInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBCommandInterpreter.h?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBCommandInterpreter.h (original)
+++ lldb/trunk/include/lldb/API/SBCommandInterpreter.h Mon May  2 15:41:46 2011
@@ -21,7 +21,9 @@
     {
         eBroadcastBitThreadShouldExit       = (1 << 0),
         eBroadcastBitResetPrompt            = (1 << 1),
-        eBroadcastBitQuitCommandReceived    = (1 << 2)   // User entered quit
+        eBroadcastBitQuitCommandReceived    = (1 << 2),           // User entered quit 
+        eBroadcastBitAsynchronousOutputData = (1 << 3),
+        eBroadcastBitAsynchronousErrorData  = (1 << 4)
     };
 
     SBCommandInterpreter (const lldb::SBCommandInterpreter &rhs);

Modified: lldb/trunk/include/lldb/API/SBDebugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBDebugger.h?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBDebugger.h (original)
+++ lldb/trunk/include/lldb/API/SBDebugger.h Mon May  2 15:41:46 2011
@@ -163,6 +163,9 @@
     void
     PushInputReader (lldb::SBInputReader &reader);
 
+    void
+    NotifyTopInputReader (lldb::InputReaderAction notification);
+
     const char *
     GetInstanceName  ();
 

Modified: lldb/trunk/include/lldb/Core/Debugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Debugger.h (original)
+++ lldb/trunk/include/lldb/Core/Debugger.h Mon May  2 15:41:46 2011
@@ -388,6 +388,9 @@
     bool
     PopInputReader (const lldb::InputReaderSP& reader_sp);
 
+    void
+    NotifyTopInputReader (lldb::InputReaderAction notification);
+
     static lldb::DebuggerSP
     FindDebuggerWithID (lldb::user_id_t id);
     

Modified: lldb/trunk/include/lldb/Core/Event.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Event.h?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Event.h (original)
+++ lldb/trunk/include/lldb/Core/Event.h Mon May  2 15:41:46 2011
@@ -87,6 +87,9 @@
 
     void
     SetBytes (const void *src, size_t src_len);
+    
+    void
+    SwapBytes (std::string &new_bytes);
 
     void
     SetBytesFromCString (const char *cstr);

Added: lldb/trunk/include/lldb/Core/StreamAsynchronousIO.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/StreamAsynchronousIO.h?rev=130721&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Core/StreamAsynchronousIO.h (added)
+++ lldb/trunk/include/lldb/Core/StreamAsynchronousIO.h Mon May  2 15:41:46 2011
@@ -0,0 +1,42 @@
+//===-- StreamAsynchronousIO.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_StreamAsynchronousIO_h_
+#define liblldb_StreamAsynchronousIO_h_
+
+#include <string>
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+
+namespace lldb_private {
+
+class StreamAsynchronousIO : 
+    public Stream
+{
+public:
+    StreamAsynchronousIO (Broadcaster &broadcaster, uint32_t broadcast_event_type);
+    
+    virtual ~StreamAsynchronousIO ();
+    
+    virtual void
+    Flush ();
+    
+    virtual int
+    Write (const void *src, size_t src_len);
+    
+    
+private:
+    Broadcaster &m_broadcaster;
+    uint32_t m_broadcast_event_type;
+    StreamString m_accumulated_data;
+};
+
+} // namespace lldb_private
+#endif // #ifndef liblldb_StreamAsynchronousIO_h

Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h Mon May  2 15:41:46 2011
@@ -35,7 +35,9 @@
     {
         eBroadcastBitThreadShouldExit       = (1 << 0),
         eBroadcastBitResetPrompt            = (1 << 1),
-        eBroadcastBitQuitCommandReceived    = (1 << 2)   // User entered quit
+        eBroadcastBitQuitCommandReceived    = (1 << 2),   // User entered quit
+        eBroadcastBitAsynchronousOutputData = (1 << 3),
+        eBroadcastBitAsynchronousErrorData  = (1 << 4)
     };
 
     void

Modified: lldb/trunk/include/lldb/lldb-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-enumerations.h Mon May  2 15:41:46 2011
@@ -265,6 +265,7 @@
     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)

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Mon May  2 15:41:46 2011
@@ -433,6 +433,8 @@
 		9A357673116E7B6400E8ED2F /* SBStringList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A357672116E7B6400E8ED2F /* SBStringList.cpp */; };
 		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 */; };
+		9A4F35121368A54100823F52 /* StreamAsynchronousIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A4F35111368A54100823F52 /* StreamAsynchronousIO.h */; };
 		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 */; };
@@ -1192,6 +1194,8 @@
 		9A4633DA11F65D8600955CE1 /* UserSettingsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserSettingsController.h; path = include/lldb/Core/UserSettingsController.h; sourceTree = "<group>"; };
 		9A4633DC11F65D9A00955CE1 /* UserSettingsController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UserSettingsController.cpp; path = source/Core/UserSettingsController.cpp; sourceTree = "<group>"; };
 		9A48A3A7124AAA5A00922451 /* python-extensions.swig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "python-extensions.swig"; sourceTree = "<group>"; };
+		9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StreamAsynchronousIO.cpp; path = source/Core/StreamAsynchronousIO.cpp; sourceTree = "<group>"; };
+		9A4F35111368A54100823F52 /* StreamAsynchronousIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StreamAsynchronousIO.h; path = include/lldb/Core/StreamAsynchronousIO.h; sourceTree = "<group>"; };
 		9A633FE7112DCE3C001A7E43 /* SBFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBFrame.cpp; path = source/API/SBFrame.cpp; sourceTree = "<group>"; };
 		9A633FE8112DCE3C001A7E43 /* SBFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBFrame.h; path = include/lldb/API/SBFrame.h; sourceTree = "<group>"; };
 		9A82010B10FFB49800182560 /* ScriptInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ScriptInterpreter.cpp; path = source/Interpreter/ScriptInterpreter.cpp; sourceTree = "<group>"; };
@@ -1327,7 +1331,6 @@
 				26BC7E7510F1B85900F91463 /* lldb-log.cpp */,
 				26BC7C2A10F1B3BC00F91463 /* lldb-private.h */,
 				26217932133BCB850083B112 /* lldb-private-enumerations.h */,
-				26BC7C2810F1B3BC00F91463 /* lldb-private-interfaces.h */,
 				26BC7D5D10F1B77400F91463 /* lldb-private-log.h */,
 				26217930133BC8640083B112 /* lldb-private-types.h */,
 				262D3190111B4341004E6F88 /* API */,
@@ -1977,6 +1980,8 @@
 				26BC7D7810F1B77400F91463 /* STLUtils.h */,
 				26BC7D7910F1B77400F91463 /* Stream.h */,
 				26BC7E9110F1B85900F91463 /* Stream.cpp */,
+				9A4F35111368A54100823F52 /* StreamAsynchronousIO.h */,
+				9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */,
 				26BC7D7A10F1B77400F91463 /* StreamFile.h */,
 				26BC7E9210F1B85900F91463 /* StreamFile.cpp */,
 				26BC7D7B10F1B77400F91463 /* StreamString.h */,
@@ -2176,6 +2181,7 @@
 		26BC7DBE10F1B78200F91463 /* Expression */ = {
 			isa = PBXGroup;
 			children = (
+				26BC7C2810F1B3BC00F91463 /* lldb-private-interfaces.h */,
 				49D7072611B5AD03001AD875 /* ClangASTSource.h */,
 				49D7072811B5AD11001AD875 /* ClangASTSource.cpp */,
 				26BC7DC010F1B79500F91463 /* ClangExpression.h */,
@@ -2677,6 +2683,7 @@
 				2671A0CE134825F6003A87BB /* ConnectionMachPort.h in Headers */,
 				4CABA9DD134A8BA800539BDD /* ValueObjectMemory.h in Headers */,
 				4CD0BD0D134BFAB600CB44D4 /* ValueObjectDynamicValue.h in Headers */,
+				9A4F35121368A54100823F52 /* StreamAsynchronousIO.h in Headers */,
 				4C2FAE2F135E3A70001EDE44 /* SharedCluster.h in Headers */,
 				2692BA16136610C100F9E14D /* UnwindAssemblyInstEmulation.h in Headers */,
 			);
@@ -3246,6 +3253,7 @@
 				26A7A035135E6E4200FB369E /* NamedOptionValue.cpp in Sources */,
 				9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */,
 				9A22A163135E30370024DDC3 /* EmulationStateARM.cpp in Sources */,
+				9A4F35101368A51A00823F52 /* StreamAsynchronousIO.cpp in Sources */,
 				2630BFAF1365F3220070C534 /* ArchDefaultUnwindPlan.cpp in Sources */,
 				2630BFB01365F3220070C534 /* ArchVolatileRegs.cpp in Sources */,
 				2692BA15136610C100F9E14D /* UnwindAssemblyInstEmulation.cpp in Sources */,
@@ -3336,7 +3344,7 @@
 					__STDC_LIMIT_MACROS,
 					LLDB_CONFIGURATION_DEBUG,
 				);
-				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_VERSION = 4.2;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;

Modified: lldb/trunk/source/API/SBDebugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBDebugger.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/API/SBDebugger.cpp (original)
+++ lldb/trunk/source/API/SBDebugger.cpp Mon May  2 15:41:46 2011
@@ -640,6 +640,18 @@
 }
 
 void
+SBDebugger::NotifyTopInputReader (InputReaderAction notification)
+{
+    LogSP 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);
+}
+
+void
 SBDebugger::reset (const DebuggerSP &debugger_sp)
 {
     m_opaque_sp = debugger_sp;

Modified: lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp Mon May  2 15:41:46 2011
@@ -466,6 +466,9 @@
         }
         break;
 
+    case eInputReaderAsynchronousOutputWritten:
+        break;
+        
     case eInputReaderGotToken:
         if (bytes && bytes_len && baton)
         {

Modified: lldb/trunk/source/Commands/CommandObjectCommands.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectCommands.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectCommands.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectCommands.cpp Mon May  2 15:41:46 2011
@@ -975,7 +975,10 @@
             
         case eInputReaderDeactivate:
             break;
-            
+        
+        case eInputReaderAsynchronousOutputWritten:
+            break;
+                    
         case eInputReaderGotToken:
             while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
                 --bytes_len;

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Mon May  2 15:41:46 2011
@@ -205,6 +205,9 @@
     case eInputReaderDeactivate:
         break;
 
+    case eInputReaderAsynchronousOutputWritten:
+        break;
+        
     case eInputReaderGotToken:
         ++cmd_object_expr->m_expr_line_count;
         if (bytes && bytes_len)

Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Mon May  2 15:41:46 2011
@@ -1032,6 +1032,9 @@
             }
             break;
 
+        case eInputReaderAsynchronousOutputWritten:
+            break;
+            
         case eInputReaderGotToken:
             if (bytes && bytes_len && baton)
             {

Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Mon May  2 15:41:46 2011
@@ -423,6 +423,20 @@
 }
 
 void
+Debugger::NotifyTopInputReader (InputReaderAction notification)
+{
+    InputReaderSP reader_sp (GetCurrentInputReader());
+    if (reader_sp)
+	{
+        reader_sp->Notify (notification);
+
+        // Flush out any input readers that are done.
+        while (CheckIfTopInputReaderIsDone ())
+            /* Do nothing. */;
+    }
+}
+
+void
 Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len)
 {
     if (bytes && bytes_len)

Modified: lldb/trunk/source/Core/Event.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Event.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/Core/Event.cpp (original)
+++ lldb/trunk/source/Core/Event.cpp Mon May  2 15:41:46 2011
@@ -198,3 +198,10 @@
     return NULL;
 }
 
+void
+EventDataBytes::SwapBytes (std::string &new_bytes)
+{
+    m_bytes.swap (new_bytes);
+}
+
+

Modified: lldb/trunk/source/Core/InputReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/InputReader.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/Core/InputReader.cpp (original)
+++ lldb/trunk/source/Core/InputReader.cpp Mon May  2 15:41:46 2011
@@ -327,6 +327,9 @@
         m_active = false;
         break;
     
+    case eInputReaderAsynchronousOutputWritten:
+        break;
+        
     case eInputReaderInterrupt:
     case eInputReaderEndOfFile:
         break;

Added: lldb/trunk/source/Core/StreamAsynchronousIO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/StreamAsynchronousIO.cpp?rev=130721&view=auto
==============================================================================
--- lldb/trunk/source/Core/StreamAsynchronousIO.cpp (added)
+++ lldb/trunk/source/Core/StreamAsynchronousIO.cpp Mon May  2 15:41:46 2011
@@ -0,0 +1,52 @@
+//===-- StreamBroadcast.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Event.h"
+#include "lldb/Core/StreamAsynchronousIO.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+StreamAsynchronousIO::StreamAsynchronousIO (Broadcaster &broadcaster, uint32_t broadcast_event_type) :
+    Stream (0, 4, eByteOrderBig),
+    m_broadcaster (broadcaster),
+    m_broadcast_event_type (broadcast_event_type),
+    m_accumulated_data ()
+{
+}
+
+StreamAsynchronousIO::~StreamAsynchronousIO ()
+{
+}
+
+void
+StreamAsynchronousIO::Flush ()
+{
+    if (m_accumulated_data.GetSize() > 0)
+    {
+        std::auto_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());
+        EventSP new_event_sp (new Event (m_broadcast_event_type, data_bytes_ap.release()));
+        m_broadcaster.BroadcastEvent (new_event_sp);
+        m_accumulated_data.Clear();
+    }
+}
+
+int
+StreamAsynchronousIO::Write (const void *s, size_t length)
+{
+    m_accumulated_data.Write (s, length);
+    return length;
+}

Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Mon May  2 15:41:46 2011
@@ -1226,7 +1226,10 @@
             out_file.Flush ();
         }
         break;
-
+        
+    case eInputReaderAsynchronousOutputWritten:
+        break;
+        
     case eInputReaderGotToken:
         if (bytes_len == 0)
         {
@@ -1642,6 +1645,12 @@
             }
         }
         
+        if (result.GetImmediateOutputStream())
+            result.GetImmediateOutputStream()->Flush();
+        
+        if (result.GetImmediateErrorStream())
+            result.GetImmediateErrorStream()->Flush();
+        
         // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
         // could be running (for instance in Breakpoint Commands.
         // So we check the return value to see if it is has running in it.

Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Mon May  2 15:41:46 2011
@@ -639,6 +639,9 @@
             script_interpreter->EnterSession ();
         break;
         
+    case eInputReaderAsynchronousOutputWritten:
+        break;
+        
     case eInputReaderInterrupt:
         ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "raise KeyboardInterrupt\n", 24);
         break;
@@ -1047,6 +1050,9 @@
         }
         break;
 
+    case eInputReaderAsynchronousOutputWritten:
+        break;
+        
     case eInputReaderGotToken:
         {
             std::string temp_string (bytes, bytes_len);

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Mon May  2 15:41:46 2011
@@ -3183,6 +3183,9 @@
     case eInputReaderReactivate:
         break;
         
+    case eInputReaderAsynchronousOutputWritten:
+        break;
+        
     case eInputReaderGotToken:
         {
             Error error;

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Mon May  2 15:41:46 2011
@@ -20,6 +20,7 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Event.h"
 #include "lldb/Core/Log.h"
+#include "lldb/Core/StreamAsynchronousIO.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/Timer.h"
 #include "lldb/Core/ValueObject.h"
@@ -1104,8 +1105,12 @@
     if (num_exe_ctx == 0)
         return;
     
-    result.SetImmediateOutputFile (m_debugger.GetOutputFile().GetStream());
-    result.SetImmediateErrorFile (m_debugger.GetErrorFile().GetStream());
+    StreamSP output_stream (new StreamAsynchronousIO (m_debugger.GetCommandInterpreter(),
+                                                      CommandInterpreter::eBroadcastBitAsynchronousOutputData));
+    StreamSP error_stream (new StreamAsynchronousIO (m_debugger.GetCommandInterpreter(),
+                                                     CommandInterpreter::eBroadcastBitAsynchronousErrorData));
+    result.SetImmediateOutputStream (output_stream);
+    result.SetImmediateErrorStream (error_stream);
     
     bool keep_going = true;
     bool hooks_ran = false;
@@ -1176,6 +1181,9 @@
     }
     if (hooks_ran)
         result.AppendMessage ("\n** End Stop Hooks **\n");
+        
+    result.GetImmediateOutputStream()->Flush();
+    result.GetImmediateErrorStream()->Flush();
 }
 
 //--------------------------------------------------------------

Modified: lldb/trunk/tools/driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.cpp (original)
+++ lldb/trunk/tools/driver/Driver.cpp Mon May  2 15:41:46 2011
@@ -658,7 +658,7 @@
     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);
+        m_io_channel_ap->OutWrite (stdio_buffer, len, ASYNC);
         total_bytes += len;
     }
     return total_bytes;
@@ -673,7 +673,7 @@
     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);
+        m_io_channel_ap->ErrWrite (stdio_buffer, len, ASYNC);
         total_bytes += len;
     }
     return total_bytes;
@@ -755,24 +755,20 @@
     {
         // The process has stdout available, get it and write it out to the
         // appropriate place.
-        if (GetProcessSTDOUT ())
-            m_io_channel_ap->RefreshPrompt();
+        GetProcessSTDOUT ();
     }
     else if (event_type & SBProcess::eBroadcastBitSTDERR)
     {
         // The process has stderr available, get it and write it out to the
         // appropriate place.
-        if (GetProcessSTDERR ())
-            m_io_channel_ap->RefreshPrompt();
+        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
-        if (GetProcessSTDOUT ()
-            || GetProcessSTDERR ())
-            m_io_channel_ap->RefreshPrompt();
-
+        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);
@@ -795,7 +791,7 @@
                 char message[1024];
                 int message_len = ::snprintf (message, sizeof(message), "Process %d %s\n", process.GetProcessID(),
                                               m_debugger.StateAsCString (event_state));
-                m_io_channel_ap->OutWrite(message, message_len);
+                m_io_channel_ap->OutWrite(message, message_len, ASYNC);
             }
             break;
 
@@ -807,9 +803,8 @@
             {
                 SBCommandReturnObject result;
                 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
-                m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
-                m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
-                m_io_channel_ap->RefreshPrompt();
+                m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
+                m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
             }
             break;
 
@@ -823,17 +818,15 @@
                 char message[1024];
                 int message_len = ::snprintf (message, sizeof(message), "Process %d stopped and was programmatically restarted.\n",
                                               process.GetProcessID());
-                m_io_channel_ap->OutWrite(message, message_len);
-                m_io_channel_ap->RefreshPrompt ();
+                m_io_channel_ap->OutWrite(message, message_len, ASYNC);
             }
             else
             {
                 SBCommandReturnObject result;
                 UpdateSelectedThread ();
                 m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
-                m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize());
-                m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize());
-                m_io_channel_ap->RefreshPrompt ();
+                m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
+                m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
             }
             break;
         }
@@ -935,11 +928,16 @@
 
     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)
         {
-            driver->m_io_channel_ap->OutWrite ("^C\n", 3);
+            driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
             driver->m_io_channel_ap->RefreshPrompt();
         }
         break;
@@ -947,7 +945,7 @@
     case eInputReaderEndOfFile:
         if (driver->m_io_channel_ap.get() != NULL)
         {
-            driver->m_io_channel_ap->OutWrite ("^D\n", 3);
+            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);
@@ -996,6 +994,36 @@
         }
     }
 
+    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);
+        }
+    }
 
    // struct termios stdin_termios;
 
@@ -1038,7 +1066,19 @@
 //
     SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
 
-    m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, stdout, stderr, this));
+    m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
+
+    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);
+    }
+
 
     struct winsize window_size;
     if (isatty (STDIN_FILENO)

Modified: lldb/trunk/tools/driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.h?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.h (original)
+++ lldb/trunk/tools/driver/Driver.h Mon May  2 15:41:46 2011
@@ -23,6 +23,8 @@
 #include "lldb/API/SBError.h"
 #include "lldb/API/SBInputReader.h"
 
+#define ASYNC true
+#define NO_ASYNC false
 
 class IOChannel;
 

Modified: lldb/trunk/tools/driver/IOChannel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/IOChannel.cpp?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/tools/driver/IOChannel.cpp (original)
+++ lldb/trunk/tools/driver/IOChannel.cpp Mon May  2 15:41:46 2011
@@ -29,10 +29,6 @@
 const char *g_default_prompt = "(lldb) ";
 PromptMap g_prompt_map;
 
-#define NSEC_PER_USEC   1000ull
-#define USEC_PER_SEC    1000000ull
-#define NSEC_PER_SEC    1000000000ull
-
 static const char*
 el_prompt(EditLine *el)
 {
@@ -100,16 +96,16 @@
         const char *comment = "\nAvailable completions:";
 
         int num_elements = num_completions + 1;
-        OutWrite(comment,  strlen (comment));
+        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);
-                OutWrite(completion_str, strlen (completion_str));
+                OutWrite("\n\t", 2, NO_ASYNC);
+                OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
             }
-            OutWrite ("\n", 1);
+            OutWrite ("\n", 1, NO_ASYNC);
         }
         else
         {
@@ -124,17 +120,17 @@
                 for (; cur_pos < endpoint; cur_pos++)
                 {
                     completion_str = completions.GetStringAtIndex(cur_pos);
-                    OutWrite("\n\t", 2);
-                    OutWrite(completion_str, strlen (completion_str));
+                    OutWrite("\n\t", 2, NO_ASYNC);
+                    OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
                 }
 
                 if (cur_pos >= num_elements)
                 {
-                    OutWrite("\n", 1);
+                    OutWrite("\n", 1, NO_ASYNC);
                     break;
                 }
 
-                OutWrite("\nMore (Y/n/a): ", strlen ("\nMore (Y/n/a): "));
+                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')
@@ -154,8 +150,9 @@
 
 IOChannel::IOChannel
 (
-    FILE *in,
-    FILE *out,
+    FILE *editline_in,
+    FILE *editline_out,
+    FILE *out,  
     FILE *err,
     Driver *driver
 ) :
@@ -169,10 +166,12 @@
     m_err_file (err),
     m_command_queue (),
     m_completion_key ("\t"),
-    m_edit_line (::el_init (SBHostOS::GetProgramFileSpec().GetFilename(), in, out, err)),
+    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_getting_command (false),
+    m_expecting_prompt (false),
+	m_prompt_str ()
 {
     assert (m_edit_line);
     ::el_set (m_edit_line, EL_PROMPT, el_prompt);
@@ -252,6 +251,36 @@
     }
 }
 
+void
+IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len)
+{
+	// Make this a member variable.
+    // static std::string prompt_str;
+    IOChannel *io_channel = (IOChannel *) baton;
+    const char *bytes = (const char *) src;
+
+    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->OutWrite (io_channel->m_prompt_str.c_str(), 
+                                  io_channel->m_prompt_str.size(), NO_ASYNC);
+            io_channel->m_prompt_str.clear();
+        }
+		else 
+			assert (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == std::string::npos);
+    }
+    else
+    {
+        if (io_channel->m_prompt_str.size() > 0)
+            io_channel->m_prompt_str.clear();
+        io_channel->OutWrite (bytes, src_len, NO_ASYNC);
+    }
+}
+
 bool
 IOChannel::LibeditGetInput (std::string &new_line)
 {
@@ -262,12 +291,7 @@
         // 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);
-        
-        // Get the current time just before calling el_gets; this is used by OutWrite, ErrWrite, and RefreshPrompt
-        // to make sure they have given el_gets enough time to write the prompt before they attempt to write
-        // anything.
-
-        ::gettimeofday (&m_enter_elgets_time, NULL);
+        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);
@@ -318,7 +342,9 @@
     listener.StartListeningForEvents (interpreter_broadcaster,
                                       SBCommandInterpreter::eBroadcastBitResetPrompt |
                                       SBCommandInterpreter::eBroadcastBitThreadShouldExit |
-                                      SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
+                                      SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
+                                      SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
+                                      SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
 
     listener.StartListeningForEvents (*this,
                                       IOChannel::eBroadcastBitThreadShouldExit);
@@ -392,6 +418,18 @@
                 case SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
                     done = true;
                     break;
+                case SBCommandInterpreter::eBroadcastBitAsynchronousErrorData:
+                    {
+                        const char *data = SBEvent::GetCStringFromEvent (event);
+                        ErrWrite (data, strlen(data), ASYNC);
+                    }
+                    break;
+                case SBCommandInterpreter::eBroadcastBitAsynchronousOutputData:
+                    {
+                        const char *data = SBEvent::GetCStringFromEvent (event);
+                        OutWrite (data, strlen(data), ASYNC);
+                    }
+                    break;
                 }
             }
             else if (event.BroadcasterMatchesPtr (this))
@@ -448,60 +486,41 @@
     if (! IsGettingCommand())
         return;
 
-    // Compare the current time versus the last time el_gets was called.  If less than 40 milliseconds
-    // (40,0000 microseconds or 40,000,0000 nanoseconds) have elapsed, wait 40,0000 microseconds, to ensure el_gets had
-    // time to finish writing the prompt before we start writing here.
-
-    if (ElapsedNanoSecondsSinceEnteringElGets() < (40 * 1000 * 1000))
-        usleep (40 * 1000);
-
-    // Use the mutex to make sure OutWrite, ErrWrite and Refresh prompt do not interfere with
-    // each other's output.
+	// If we haven't finished writing the prompt, there's no need to refresh it.
+    if (m_expecting_prompt)
+        return;
 
-    IOLocker locker (m_output_mutex);
     ::el_set (m_edit_line, EL_REFRESH);
 }
 
 void
-IOChannel::OutWrite (const char *buffer, size_t len)
+IOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous)
 {
     if (len == 0)
         return;
 
-    // Compare the current time versus the last time el_gets was called.  If less than
-    // 10000 microseconds (10000000 nanoseconds) have elapsed, wait 10000 microseconds, to ensure el_gets had time
-    // to finish writing the prompt before we start writing here.
-
-    if (ElapsedNanoSecondsSinceEnteringElGets() < 10000000)
-        usleep (10000);
-
-    {
-        // Use the mutex to make sure OutWrite, ErrWrite and Refresh prompt do not interfere with
-        // each other's output.
-        IOLocker locker (m_output_mutex);
-        ::fwrite (buffer, 1, len, m_out_file);
-    }
+    // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
+    IOLocker locker (m_output_mutex);
+    if (asynchronous)
+        ::fwrite ("\n", 1, 1, 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)
+IOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous)
 {
     if (len == 0)
         return;
 
-    // Compare the current time versus the last time el_gets was called.  If less than
-    // 10000 microseconds (10000000 nanoseconds) have elapsed, wait 10000 microseconds, to ensure el_gets had time
-    // to finish writing the prompt before we start writing here.
-
-    if (ElapsedNanoSecondsSinceEnteringElGets() < 10000000)
-        usleep (10000);
-
-    {
-        // Use the mutex to make sure OutWrite, ErrWrite and Refresh prompt do not interfere with
-        // each other's output.
-        IOLocker locker (m_output_mutex);
-        ::fwrite (buffer, 1, len, m_err_file);
-    }
+    // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
+    IOLocker locker (m_output_mutex);
+    if (asynchronous)
+        ::fwrite ("\n", 1, 1, m_err_file);
+    ::fwrite (buffer, 1, len, m_err_file);
+    if (asynchronous)
+        m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
 }
 
 void
@@ -551,25 +570,6 @@
     m_getting_command = new_value;
 }
 
-uint64_t
-IOChannel::Nanoseconds (const struct timeval &time_val) const
-{
-    uint64_t nanoseconds = time_val.tv_sec * NSEC_PER_SEC + time_val.tv_usec * NSEC_PER_USEC;
-
-    return nanoseconds;
-}
-
-uint64_t
-IOChannel::ElapsedNanoSecondsSinceEnteringElGets ()
-{
-    if (! IsGettingCommand())
-        return 0;
-
-    struct timeval current_time;
-    ::gettimeofday (&current_time, NULL);
-    return (Nanoseconds (current_time) - Nanoseconds (m_enter_elgets_time));
-}
-
 IOLocker::IOLocker (pthread_mutex_t &mutex) :
     m_mutex_ptr (&mutex)
 {

Modified: lldb/trunk/tools/driver/IOChannel.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/IOChannel.h?rev=130721&r1=130720&r2=130721&view=diff
==============================================================================
--- lldb/trunk/tools/driver/IOChannel.h (original)
+++ lldb/trunk/tools/driver/IOChannel.h Mon May  2 15:41:46 2011
@@ -35,7 +35,8 @@
         eAllEventBits                 = 0xffffffff
     };
 
-    IOChannel (FILE *in,
+    IOChannel (FILE *editline_in,
+               FILE *editline_out,
                FILE *out,
                FILE *err,
                Driver *driver = NULL);
@@ -56,13 +57,16 @@
     Run ();
 
     void
-    OutWrite (const char *buffer, size_t len);
+    OutWrite (const char *buffer, size_t len, bool asynchronous);
 
     void
-    ErrWrite (const char *buffer, size_t len);
+    ErrWrite (const char *buffer, size_t len, bool asynchronous);
 
     bool
     LibeditGetInput (std::string &);
+    
+    static void
+    LibeditOutputBytesReceived (void *baton, const void *src,size_t src_len);
 
     void
     SetPrompt ();
@@ -99,12 +103,6 @@
     void
     SetGettingCommand (bool new_value);
 
-    uint64_t
-    Nanoseconds (const struct timeval &time_val) const;
-
-    uint64_t
-    ElapsedNanoSecondsSinceEnteringElGets ();
-    
 private:
 
     pthread_mutex_t m_output_mutex;
@@ -122,6 +120,8 @@
     History *m_history;
     HistEvent m_history_event;
     bool m_getting_command;
+    bool m_expecting_prompt;
+	std::string m_prompt_str;  // for accumlating the prompt as it gets written out by editline
 
     void
     HistorySaveLoad (bool save);





More information about the lldb-commits mailing list