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).

llvm-svn: 130721
diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp
index 84b13ab..04f15cb 100644
--- a/lldb/source/API/SBDebugger.cpp
+++ b/lldb/source/API/SBDebugger.cpp
@@ -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;
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
index a188bae..1646648 100644
--- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -466,6 +466,9 @@
         }
         break;
 
+    case eInputReaderAsynchronousOutputWritten:
+        break;
+        
     case eInputReaderGotToken:
         if (bytes && bytes_len && baton)
         {
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp
index 142f29d..9d31cf7 100644
--- a/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/lldb/source/Commands/CommandObjectCommands.cpp
@@ -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;
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index ed7824b..fa578f4 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -205,6 +205,9 @@
     case eInputReaderDeactivate:
         break;
 
+    case eInputReaderAsynchronousOutputWritten:
+        break;
+        
     case eInputReaderGotToken:
         ++cmd_object_expr->m_expr_line_count;
         if (bytes && bytes_len)
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 958aa2c..f7f873c 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -1032,6 +1032,9 @@
             }
             break;
 
+        case eInputReaderAsynchronousOutputWritten:
+            break;
+            
         case eInputReaderGotToken:
             if (bytes && bytes_len && baton)
             {
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index f1a64b9..f328c62 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -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)
diff --git a/lldb/source/Core/Event.cpp b/lldb/source/Core/Event.cpp
index 8b0ac16..ac12285 100644
--- a/lldb/source/Core/Event.cpp
+++ b/lldb/source/Core/Event.cpp
@@ -198,3 +198,10 @@
     return NULL;
 }
 
+void
+EventDataBytes::SwapBytes (std::string &new_bytes)
+{
+    m_bytes.swap (new_bytes);
+}
+
+
diff --git a/lldb/source/Core/InputReader.cpp b/lldb/source/Core/InputReader.cpp
index fc94bed..26f7f84 100644
--- a/lldb/source/Core/InputReader.cpp
+++ b/lldb/source/Core/InputReader.cpp
@@ -327,6 +327,9 @@
         m_active = false;
         break;
     
+    case eInputReaderAsynchronousOutputWritten:
+        break;
+        
     case eInputReaderInterrupt:
     case eInputReaderEndOfFile:
         break;
diff --git a/lldb/source/Core/StreamAsynchronousIO.cpp b/lldb/source/Core/StreamAsynchronousIO.cpp
new file mode 100644
index 0000000..84659c6
--- /dev/null
+++ b/lldb/source/Core/StreamAsynchronousIO.cpp
@@ -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;
+}
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index a36d9c2..16e5f3b 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -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.
diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
index 10b9792..47302be 100644
--- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
@@ -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);
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 8e96c71..7bdccda 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -3183,6 +3183,9 @@
     case eInputReaderReactivate:
         break;
         
+    case eInputReaderAsynchronousOutputWritten:
+        break;
+        
     case eInputReaderGotToken:
         {
             Error error;
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 1180479..a023bf5 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -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();
 }
 
 //--------------------------------------------------------------