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



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@119837 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp
index 0dc4a34..86a635a 100644
--- a/source/Interpreter/CommandInterpreter.cpp
+++ b/source/Interpreter/CommandInterpreter.cpp
@@ -860,6 +860,12 @@
         }
         break;
         
+    case eInputReaderInterrupt:
+    case eInputReaderEndOfFile:
+        *response_ptr = false;  // Assume ^C or ^D means cancel the proposed action
+        reader.SetIsDone (true);
+        break;
+        
     case eInputReaderDone:
         break;
     }
diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
index 1927531..1e3a308 100644
--- a/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/source/Interpreter/ScriptInterpreterPython.cpp
@@ -272,11 +272,6 @@
         PyRun_SimpleString (run_string.GetData());
         PyRun_SimpleString ("sys.stdin = new_stdin");
 
-        PyRun_SimpleString ("new_mode = tcgetattr(new_stdin)");
-        PyRun_SimpleString ("new_mode[3] = new_mode[3] | ECHO | ICANON");
-        PyRun_SimpleString ("new_mode[6][VEOF] = 255");
-        PyRun_SimpleString ("tcsetattr (new_stdin, TCSANOW, new_mode)");
-
         run_string.Clear();
         run_string.Printf ("lldb.debugger_unique_id = %d", interpreter.GetDebugger().GetID());
         PyRun_SimpleString (run_string.GetData());
@@ -302,26 +297,10 @@
     {
         int success;
 
-
-        // Save the current input file handle state before executing the command.
-        int input_fd;
-        struct termios tmp_termios;
-        bool valid_termios = false;
-        FILE *input_fh = m_interpreter.GetDebugger().GetInputFileHandle();
-        if (input_fh != NULL)
-        {
-            input_fd = ::fileno (input_fh);
-            valid_termios = ::tcgetattr (input_fd, &tmp_termios) == 0;
-        }
-
         success = PyRun_SimpleString (command);
         if (success == 0)
             return true;
 
-        // Restore the input file handle state after executing the command.
-        if (valid_termios)
-            ::tcsetattr (input_fd, TCSANOW, &tmp_termios);
-
         // The one-liner failed.  Append the error message.
         if (result)
             result->AppendErrorWithFormat ("python failed attempting to evaluate '%s'\n", command);
@@ -366,12 +345,6 @@
 
             script_interpreter->m_termios_valid = ::tcgetattr (input_fd, &script_interpreter->m_termios) == 0;
             
-            if (script_interpreter->m_termios_valid)
-            {
-                struct termios tmp_termios = script_interpreter->m_termios;
-                tmp_termios.c_cc[VEOF] = _POSIX_VDISABLE;
-                ::tcsetattr (input_fd, TCSANOW, &tmp_termios);
-            }
             char error_str[1024];
             if (script_interpreter->m_embedded_python_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, 
                                                                                     sizeof(error_str)))
@@ -411,6 +384,14 @@
 
     case eInputReaderReactivate:
         break;
+        
+    case eInputReaderInterrupt:
+        ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "raise KeyboardInterrupt\n", 24);
+        break;
+        
+    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)
@@ -724,6 +705,17 @@
         }
         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:
         {
             BreakpointOptions *bp_options = (BreakpointOptions *)baton;
@@ -843,6 +835,10 @@
     int num_lines = user_input.GetSize ();
     StreamString sstr;
 
+    // Check to see if we have any data; if not, just return.
+    if (user_input.GetSize() == 0)
+        return false;
+
     // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the
     // frame and breakpoint location as parameters to the function.
 
@@ -933,10 +929,6 @@
         PyRun_SimpleString ("save_stdin = sys.stdin");
         run_string.Printf ("sys.stdin = open ('%s', 'r')", pty_slave_name);
         PyRun_SimpleString (run_string.GetData());
-        PyRun_SimpleString ("new_mode = tcgetattr(sys.stdin)");
-        PyRun_SimpleString ("new_mode[3] = new_mode[3] | ECHO | ICANON");
-        PyRun_SimpleString ("new_mode[6][VEOF] = 255");
-        PyRun_SimpleString ("tcsetattr (sys.stdin, TCSANOW, new_mode)");
         
 	    // The following call drops into the embedded interpreter loop and stays there until the
 	    // user chooses to exit from the Python interpreter.