Add the ability to catch and do the right thing with Interrupts (often control-c)
and end-of-file (often control-d).

llvm-svn: 119837
diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp
index 1bc3148..29b50f0 100644
--- a/lldb/tools/driver/Driver.cpp
+++ b/lldb/tools/driver/Driver.cpp
@@ -40,6 +40,7 @@
 static struct termios g_old_stdin_termios;
 
 static char *g_debugger_name =  (char *) "";
+static Driver *g_driver = NULL;
 
 // In the Driver::MainLoop, we change the terminal settings.  This function is
 // added as an atexit handler to make sure we clean them up.
@@ -98,10 +99,13 @@
     g_debugger_name = (char *) m_debugger.GetInstanceName();
     if (g_debugger_name == NULL)
         g_debugger_name = (char *) "";
+    g_driver = this;
 }
 
 Driver::~Driver ()
 {
+    g_driver = NULL;
+    g_debugger_name = NULL;
 }
 
 void
@@ -1091,6 +1095,23 @@
     case eInputReaderDeactivate:
         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->RefreshPrompt();
+        }
+        break;
+        
+    case eInputReaderEndOfFile:
+        if (driver->m_io_channel_ap.get() != NULL)
+        {
+            driver->m_io_channel_ap->OutWrite ("^D\n", 3);
+            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;
@@ -1370,6 +1391,24 @@
     }
 }
 
+void
+sigint_handler (int signo)
+{
+	static bool g_interrupt_sent = false;
+    if (g_driver)
+	{
+		if (!g_interrupt_sent)
+		{
+			g_interrupt_sent = true;
+        	g_driver->GetDebugger().DispatchInputInterrupt();
+			g_interrupt_sent = false;
+			return;
+		}
+	}
+    
+	exit (signo);
+}
+
 int
 main (int argc, char const *argv[])
 {
@@ -1379,6 +1418,7 @@
 
     signal (SIGPIPE, SIG_IGN);
     signal (SIGWINCH, sigwinch_handler);
+    signal (SIGINT, sigint_handler);
 
     // Create a scope for driver so that the driver object will destroy itself
     // before SBDebugger::Terminate() is called.
diff --git a/lldb/tools/driver/IOChannel.cpp b/lldb/tools/driver/IOChannel.cpp
index 004e1da..bf7891a 100644
--- a/lldb/tools/driver/IOChannel.cpp
+++ b/lldb/tools/driver/IOChannel.cpp
@@ -448,12 +448,12 @@
     if (! IsGettingCommand())
         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.
+    // 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() < 10000000)
-        usleep (10000);
+    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.