summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lldb/source/Interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Interpreter')
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp506
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/Options.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp49
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp1627
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py183
7 files changed, 1041 insertions, 1339 deletions
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp
index a7c892d..fb0fc7f 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -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::LoadCommandDictionary ()
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));
@@ -1929,12 +1934,19 @@ CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
&& matches.GetStringAtIndex(0) != NULL
&& strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
{
- look_for_subcommand = true;
- num_command_matches = 0;
- matches.DeleteStringAtIndex(0);
- parsed_line.AppendArgument ("");
- cursor_index++;
- cursor_char_position = 0;
+ if (parsed_line.GetArgumentCount() == 1)
+ {
+ word_complete = true;
+ }
+ else
+ {
+ look_for_subcommand = true;
+ num_command_matches = 0;
+ matches.DeleteStringAtIndex(0);
+ parsed_line.AppendArgument ("");
+ cursor_index++;
+ cursor_char_position = 0;
+ }
}
}
@@ -2023,7 +2035,7 @@ CommandInterpreter::HandleCompletion (const char *current_line,
const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
{
- parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '"');
+ parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0');
cursor_index++;
cursor_char_position = 0;
}
@@ -2086,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)
@@ -2183,31 +2114,13 @@ CommandInterpreter::Confirm (const char *message, bool default_answer)
// 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
@@ -2477,13 +2390,16 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
if (init_file.Exists())
{
- ExecutionContext *exe_ctx = NULL; // We don't have any context yet.
- bool stop_on_continue = true;
- bool stop_on_error = false;
- bool echo_commands = false;
- bool print_results = false;
-
- HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, eLazyBoolNo, result);
+ const bool saved_batch = SetBatchCommandMode (true);
+ HandleCommandsFromFile (init_file,
+ NULL, // Execution context
+ eLazyBoolYes, // Stop on continue
+ eLazyBoolNo, // Stop on error
+ eLazyBoolNo, // Don't echo commands
+ eLazyBoolNo, // Don't print command output
+ eLazyBoolNo, // Don't add the commands that are sourced into the history buffer
+ result);
+ SetBatchCommandMode (saved_batch);
}
else
{
@@ -2546,8 +2462,8 @@ CommandInterpreter::HandleCommands (const StringList &commands,
if (echo_commands)
{
result.AppendMessageWithFormat ("%s %s\n",
- GetPrompt(),
- cmd);
+ m_debugger.GetPrompt(),
+ cmd);
}
CommandReturnObject tmp_result;
@@ -2631,30 +2547,145 @@ CommandInterpreter::HandleCommands (const StringList &commands,
return;
}
+// Make flags that we can pass into the IOHandler so our delegates can do the right thing
+enum {
+ eHandleCommandFlagStopOnContinue = (1u << 0),
+ eHandleCommandFlagStopOnError = (1u << 1),
+ eHandleCommandFlagEchoCommand = (1u << 2),
+ eHandleCommandFlagPrintResult = (1u << 3)
+};
+
void
CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
ExecutionContext *context,
- bool stop_on_continue,
- bool stop_on_error,
- bool echo_command,
- bool print_result,
+ LazyBool stop_on_continue,
+ LazyBool stop_on_error,
+ LazyBool echo_command,
+ LazyBool print_result,
LazyBool add_to_history,
CommandReturnObject &result)
{
if (cmd_file.Exists())
{
- bool success;
- StringList commands;
- success = commands.ReadFileLines(cmd_file);
- if (!success)
+ 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())
{
- result.AppendErrorWithFormat ("Error reading commands from file: %s.\n", cmd_file.GetFilename().AsCString());
+ Debugger &debugger = GetDebugger();
+
+ uint32_t flags = 0;
+
+ if (stop_on_continue == eLazyBoolCalculate)
+ {
+ if (m_command_source_flags.empty())
+ {
+ // Stop on continue by default
+ flags |= eHandleCommandFlagStopOnContinue;
+ }
+ else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue)
+ {
+ flags |= eHandleCommandFlagStopOnContinue;
+ }
+ }
+ else if (stop_on_continue == eLazyBoolYes)
+ {
+ flags |= eHandleCommandFlagStopOnContinue;
+ }
+
+ if (stop_on_error == eLazyBoolCalculate)
+ {
+ if (m_command_source_flags.empty())
+ {
+ if (GetStopCmdSourceOnError())
+ flags |= eHandleCommandFlagStopOnError;
+ }
+ else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError)
+ {
+ flags |= eHandleCommandFlagStopOnError;
+ }
+ }
+ else if (stop_on_error == eLazyBoolYes)
+ {
+ flags |= eHandleCommandFlagStopOnError;
+ }
+
+ if (echo_command == eLazyBoolCalculate)
+ {
+ if (m_command_source_flags.empty())
+ {
+ // Echo command by default
+ flags |= eHandleCommandFlagEchoCommand;
+ }
+ else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand)
+ {
+ flags |= eHandleCommandFlagEchoCommand;
+ }
+ }
+ else if (echo_command == eLazyBoolYes)
+ {
+ flags |= eHandleCommandFlagEchoCommand;
+ }
+
+ if (print_result == eLazyBoolCalculate)
+ {
+ if (m_command_source_flags.empty())
+ {
+ // Print output by default
+ flags |= eHandleCommandFlagPrintResult;
+ }
+ else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult)
+ {
+ flags |= eHandleCommandFlagPrintResult;
+ }
+ }
+ else if (print_result == eLazyBoolYes)
+ {
+ flags |= eHandleCommandFlagPrintResult;
+ }
+
+ if (flags & eHandleCommandFlagPrintResult)
+ {
+ debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", cmd_file_path.c_str());
+ }
+
+ // Used for inheriting the right settings when "command source" might have
+ // nested "command source" commands
+ lldb::StreamFileSP empty_stream_sp;
+ m_command_source_flags.push_back(flags);
+ IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
+ input_file_sp,
+ empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream
+ empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream
+ flags,
+ NULL, // Pass in NULL for "editline_name" so no history is saved, or written
+ debugger.GetPrompt(),
+ false, // Not multi-line
+ *this));
+ const bool old_async_execution = debugger.GetAsyncExecution();
+
+ // Set synchronous execution if we not stopping when we continue
+ if ((flags & eHandleCommandFlagStopOnContinue) == 0)
+ debugger.SetAsyncExecution (false);
+
+ m_command_source_depth++;
+
+ debugger.RunIOHandler(io_handler_sp);
+ if (!m_command_source_flags.empty())
+ m_command_source_flags.pop_back();
+ m_command_source_depth--;
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ debugger.SetAsyncExecution (old_async_execution);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString());
result.SetStatus (eReturnStatusFailed);
- return;
}
- 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--;
+
+
}
else
{
@@ -2894,7 +2925,6 @@ CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList
}
}
-
void
CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
{
@@ -2908,3 +2938,195 @@ CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
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)
+{
+ const bool is_interactive = io_handler.GetIsInteractive();
+ if (is_interactive == false)
+ {
+ // When we are not interactive, don't execute blank lines. This will happen
+ // sourcing a commands file. We don't want blank lines to repeat the previous
+ // command and cause any errors to occur (like redefining an alias, get an error
+ // and stop parsing the commands file).
+ if (line.empty())
+ return;
+
+ // When using a non-interactive file handle (like when sourcing commands from a file)
+ // we need to echo the command out so we don't just see the command output and no
+ // command...
+ if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand))
+ io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
+ }
+
+ lldb_private::CommandReturnObject result;
+ HandleCommand(line.c_str(), eLazyBoolCalculate, result);
+
+ // Now emit the command output text from the command we just executed
+ if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult))
+ {
+ // Display any STDOUT/STDERR _prior_ to emitting the command result text
+ GetProcessOutput ();
+
+ if (!result.GetImmediateOutputStream())
+ {
+ 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
+ if (!result.GetImmediateErrorStream())
+ {
+ const char *error = result.GetErrorData();
+ if (error && error[0])
+ io_handler.GetErrorStreamFile()->PutCString(error);
+ }
+ }
+
+ switch (result.GetStatus())
+ {
+ case eReturnStatusInvalid:
+ case eReturnStatusSuccessFinishNoResult:
+ case eReturnStatusSuccessFinishResult:
+ case eReturnStatusStarted:
+ break;
+
+ case eReturnStatusSuccessContinuingNoResult:
+ case eReturnStatusSuccessContinuingResult:
+ if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue))
+ io_handler.SetIsDone(true);
+ break;
+
+ case eReturnStatusFailed:
+ if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError))
+ io_handler.SetIsDone(true);
+ 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);
+ }
+
+}
+
+bool
+CommandInterpreter::IsActive ()
+{
+ return m_debugger.IsTopIOHandler (m_command_io_handler_sp);
+}
+
+void
+CommandInterpreter::RunCommandInterpreter(bool auto_handle_events,
+ bool spawn_thread)
+{
+ 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(),
+ eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult,
+ "lldb",
+ m_debugger.GetPrompt(),
+ multiple_lines,
+ *this));
+ m_debugger.PushIOHandler(m_command_io_handler_sp);
+
+ if (auto_handle_events)
+ m_debugger.StartEventHandlerThread();
+
+ if (spawn_thread)
+ {
+ m_debugger.StartIOHandlerThread();
+ }
+ else
+ {
+ m_debugger.ExecuteIOHanders();
+
+ if (auto_handle_events)
+ m_debugger.StopEventHandlerThread();
+ }
+
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp
index c71ca28..c699536 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp
@@ -261,13 +261,7 @@ CommandObject::CheckRequirements (CommandReturnObject &result)
{
Target *target = m_exe_ctx.GetTargetPtr();
if (target)
- {
- if (m_api_locker.TryLock (target->GetAPIMutex(), NULL) == false)
- {
- result.AppendError ("failed to get API lock");
- return false;
- }
- }
+ m_api_locker.Lock (target->GetAPIMutex());
}
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/Options.cpp b/contrib/llvm/tools/lldb/source/Interpreter/Options.cpp
index 8d245cc..c6c66d8 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/Options.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/Options.cpp
@@ -952,7 +952,7 @@ Options::HandleOptionArgumentCompletion
// If this is the "shlib" option and there was an argument provided,
// restrict it to that shared library.
- if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
+ if (cur_opt_name && strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
{
const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
if (module_name)
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp b/contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp
index 1e2bd23..053ff34 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp
@@ -84,6 +84,12 @@ PythonObject::Str ()
return PythonString(str);
}
+bool
+PythonObject::IsNULLOrNone () const
+{
+ return ((m_py_obj == nullptr) || (m_py_obj == Py_None));
+}
+
//----------------------------------------------------------------------
// PythonString
//----------------------------------------------------------------------
@@ -97,7 +103,7 @@ PythonString::PythonString (PyObject *py_obj) :
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 +172,7 @@ PythonInteger::PythonInteger (PyObject *py_obj) :
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 +229,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 +249,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 +286,29 @@ PythonList::GetItemAtIndex (uint32_t index)
{
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 +322,7 @@ PythonDictionary::PythonDictionary (PyObject *py_obj) :
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 +362,7 @@ PythonDictionary::GetItemForKey (const char *key) const
PythonString python_key(key);
return GetItemForKey(python_key);
}
- return NULL;
+ return PythonObject();
}
@@ -364,7 +370,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 +380,7 @@ PythonDictionary::GetItemForKeyAsString (const PythonString &key, const char *fa
{
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 +392,7 @@ PythonDictionary::GetItemForKeyAsInteger (const PythonString &key, int64_t fail_
{
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 +410,7 @@ PythonDictionary::GetKeys () const
{
if (m_py_obj)
return PythonList(PyDict_Keys(m_py_obj));
- return PythonList();
+ return PythonList(true);
}
PythonString
@@ -431,7 +437,7 @@ PythonDictionary::GetValueAtPosition (uint32_t pos) const
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 +447,17 @@ PythonDictionary::GetValueAtPosition (uint32_t pos) const
}
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
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp
index 6a44114..e33480d 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp
@@ -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::~ScriptInterpreterNone ()
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");
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp
index fb60fed..c1d28e8 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp
@@ -27,11 +27,14 @@
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/WatchpointOptions.h"
+#include "lldb/Core/Communication.h"
+#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Timer.h"
#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;
@@ -66,22 +69,23 @@ _check_and_flush (FILE *stream)
return fflush (stream) || prev_fail ? EOF : 0;
}
+static std::string
+ReadPythonBacktrace (PyObject* py_backtrace);
+
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, in, out, err) == false)
{
// Don't teardown the session if we didn't init it.
m_teardown_session = false;
@@ -100,11 +104,11 @@ ScriptInterpreterPython::Locker::DoAcquireLock()
}
bool
-ScriptInterpreterPython::Locker::DoInitSession(bool init_lldb_globals)
+ScriptInterpreterPython::Locker::DoInitSession(uint16_t on_entry_flags, 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 (on_entry_flags, in, out, err);
}
bool
@@ -133,268 +137,29 @@ 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)
{
- static int g_initialized = false;
-
- if (!g_initialized)
- {
- g_initialized = true;
- ScriptInterpreterPython::InitializePrivate ();
- }
+ ScriptInterpreterPython::InitializePrivate ();
m_dictionary_name.append("_dict");
StreamString run_string;
@@ -425,72 +190,130 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete
run_string.Clear();
run_string.Printf ("run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
+ run_string.Clear();
int new_count = Debugger::TestDebuggerRefCount();
if (new_count > old_count)
Debugger::Terminate();
+ run_string.Printf ("run_one_line (%s, 'import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line')", m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
run_string.Clear();
+
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 +352,24 @@ 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);
+ m_saved_stdin.Reset ();
+ }
+ if (m_saved_stdout)
+ {
+ sys_module_dict.SetItemForKey("stdout", m_saved_stdout);
+ m_saved_stdout.Reset ();
+ }
+ if (m_saved_stderr)
+ {
+ sys_module_dict.SetItemForKey("stderr", m_saved_stderr);
+ m_saved_stderr.Reset ();
+ }
}
}
@@ -545,7 +377,10 @@ ScriptInterpreterPython::LeaveSession ()
}
bool
-ScriptInterpreterPython::EnterSession (bool init_lldb_globals)
+ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags,
+ 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.
@@ -553,19 +388,19 @@ ScriptInterpreterPython::EnterSession (bool init_lldb_globals)
if (m_session_is_active)
{
if (log)
- log->Printf("ScriptInterpreterPython::EnterSession(init_lldb_globals=%i) session is already active, returning without doing anything", init_lldb_globals);
+ log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ") session is already active, returning without doing anything", on_entry_flags);
return false;
}
if (log)
- log->Printf("ScriptInterpreterPython::EnterSession(init_lldb_globals=%i)", init_lldb_globals);
+ log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ")", on_entry_flags);
m_session_is_active = true;
StreamString run_string;
- if (init_lldb_globals)
+ if (on_entry_flags & Locker::InitGlobals)
{
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());
@@ -578,26 +413,61 @@ ScriptInterpreterPython::EnterSession (bool init_lldb_globals)
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)
+ lldb::StreamFileSP in_sp;
+ lldb::StreamFileSP out_sp;
+ lldb::StreamFileSP err_sp;
+ if (in == NULL || out == NULL || err == NULL)
+ m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp);
+
+ if (in == NULL && in_sp && (on_entry_flags & Locker::NoSTDIN) == 0)
+ in = in_sp->GetFile().GetStream();
+ 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"));
+
+ PyObject *new_file = PyFile_FromFile (in, (char *) "", (char *) "r", 0);
+ sys_module_dict.SetItemForKey ("stdin", new_file);
+ Py_DECREF (new_file);
}
+ else
+ m_saved_stdin.Reset();
+
+ if (out == NULL && out_sp)
+ out = out_sp->GetFile().GetStream();
+ if (out)
+ {
+ m_saved_stdout.Reset(sys_module_dict.GetItemForKey("stdout"));
+
+ PyObject *new_file = PyFile_FromFile (out, (char *) "", (char *) "w", 0);
+ sys_module_dict.SetItemForKey ("stdout", new_file);
+ Py_DECREF (new_file);
+ }
+ else
+ m_saved_stdout.Reset();
+
+ if (err == NULL && err_sp)
+ err = err_sp->GetFile().GetStream();
+ if (err)
+ {
+ m_saved_stderr.Reset(sys_module_dict.GetItemForKey("stderr"));
+
+ PyObject *new_file = PyFile_FromFile (err, (char *) "", (char *) "w", 0);
+ sys_module_dict.SetItemForKey ("stderr", new_file);
+ Py_DECREF (new_file);
+ }
+ else
+ m_saved_stderr.Reset();
}
if (PyErr_Occurred())
@@ -606,44 +476,42 @@ ScriptInterpreterPython::EnterSession (bool init_lldb_globals)
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,82 +533,154 @@ GenerateUniqueName (const char* base_name_wanted,
}
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;
+}
+
+static void
+ReadThreadBytesReceived(void *baton, const void *src, size_t src_len)
+{
+ if (src && src_len)
+ {
+ Stream *strm = (Stream *)baton;
+ strm->Write(src, src_len);
+ strm->Flush();
+ }
+}
+
+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.
-
- Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
- ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
-
- bool success = false;
-
- if (command)
+
+ if (command && command[0])
{
- // 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)
+ // 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();
+
+ StreamFileSP input_file_sp;
+ StreamFileSP output_file_sp;
+ StreamFileSP error_file_sp;
+ Communication output_comm ("lldb.ScriptInterpreterPython.ExecuteOneLine.comm");
+ int pipe_fds[2] = { -1, -1 };
+
+ if (options.GetEnableIO())
{
- PyObject *pfunc = (PyObject*)m_run_one_line;
- PyObject *pmod = PyImport_AddModule ("lldb.embedded_interpreter");
- if (pmod != NULL)
+ if (result)
{
- PyObject *pmod_dict = PyModule_GetDict (pmod);
- if ((pmod_dict != NULL)
- && PyDict_Check (pmod_dict))
+ input_file_sp = debugger.GetInputFile();
+ // Set output to a temporary file so we can forward the results on to the result object
+
+ int err = pipe(pipe_fds);
+ if (err == 0)
{
- if (!pfunc)
+ std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe_fds[0], true));
+ if (conn_ap->IsConnected())
{
- PyObject *key, *value;
- Py_ssize_t pos = 0;
+ output_comm.SetConnection(conn_ap.release());
+ output_comm.SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived, &result->GetOutputStream());
+ output_comm.StartReadThread();
+ FILE *outfile_handle = fdopen (pipe_fds[1], "w");
+ output_file_sp.reset(new StreamFile(outfile_handle, true));
+ error_file_sp = output_file_sp;
+ if (outfile_handle)
+ ::setbuf (outfile_handle, NULL);
- while (PyDict_Next (pmod_dict, &pos, &key, &value))
- {
- Py_INCREF (key);
- Py_INCREF (value);
- if (strcmp (PyString_AsString (key), "run_one_line") == 0)
- {
- pfunc = value;
- break;
- }
- }
- m_run_one_line = pfunc;
+ result->SetImmediateOutputFile(debugger.GetOutputFile()->GetFile().GetStream());
+ result->SetImmediateErrorFile(debugger.GetErrorFile()->GetFile().GetStream());
}
-
- if (pfunc && PyCallable_Check (pfunc))
+ }
+ }
+ if (!input_file_sp || !output_file_sp || !error_file_sp)
+ debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp, error_file_sp);
+ }
+ else
+ {
+ input_file_sp.reset (new StreamFile ());
+ input_file_sp->GetFile().Open("/dev/null", File::eOpenOptionRead);
+ output_file_sp.reset (new StreamFile ());
+ output_file_sp->GetFile().Open("/dev/null", File::eOpenOptionWrite);
+ error_file_sp = output_file_sp;
+ }
+
+ FILE *in_file = input_file_sp->GetFile().GetStream();
+ FILE *out_file = output_file_sp->GetFile().GetStream();
+ FILE *err_file = error_file_sp->GetFile().GetStream();
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock |
+ ScriptInterpreterPython::Locker::InitSession |
+ (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
+ ScriptInterpreterPython::Locker::FreeAcquiredLock |
+ ScriptInterpreterPython::Locker::TearDownSession,
+ in_file,
+ out_file,
+ err_file);
+
+ bool success = false;
+
+ // Find the correct script interpreter dictionary in the main module.
+ PythonDictionary &session_dict = GetSessionDictionary ();
+ if (session_dict)
+ {
+ if (GetEmbeddedInterpreterModuleObjects ())
+ {
+ PyObject *pfunc = m_run_one_line_function.get();
+
+ if (pfunc && PyCallable_Check (pfunc))
+ {
+ PythonObject pargs (Py_BuildValue("(Os)", session_dict.get(), command));
+ if (pargs)
{
- PyObject *pargs = Py_BuildValue("(Os)",script_interpreter_dict,command);
- if (pargs != NULL)
+ PythonObject return_value(PyObject_CallObject (pfunc, pargs.get()));
+ if (return_value)
+ success = true;
+ 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);
}
+ // Flush our output and error file handles
+ ::fflush (out_file);
+ if (out_file != err_file)
+ ::fflush (err_file);
+
+ if (pipe_fds[0] != -1)
+ {
+ // Close the write end of the pipe since we are done with our
+ // one line script. This should cause the read thread that
+ // output_comm is using to exit
+ output_file_sp->GetFile().Close();
+ // The close above should cause this thread to exit when it gets
+ // to the end of file, so let it get all its data
+ output_comm.JoinReadThread();
+ // Now we can close the read end of the pipe
+ output_comm.Disconnect();
+ }
+
+
if (success)
return true;
@@ -755,155 +695,113 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec
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;
+class IOHandlerPythonInterpreter :
+ public IOHandler
+{
+public:
+
+ IOHandlerPythonInterpreter (Debugger &debugger,
+ ScriptInterpreterPython *python) :
+ IOHandler (debugger),
+ m_python(python)
+ {
- ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
+ }
- if (script_interpreter->m_script_lang != eScriptLanguagePython)
- return 0;
+ virtual
+ ~IOHandlerPythonInterpreter()
+ {
+
+ }
- switch (notification)
+ virtual ConstString
+ GetControlSequence (char ch)
{
- case eInputReaderActivate:
- {
- 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);
-
- {
- ScriptInterpreterPython::Locker locker(script_interpreter,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
- ScriptInterpreterPython::Locker::FreeAcquiredLock);
- }
+ if (ch == 'd')
+ return ConstString("quit()\n");
+ return ConstString();
+ }
- char error_str[1024];
- if (script_interpreter->m_embedded_python_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str,
- sizeof(error_str)))
+ virtual void
+ Run ()
+ {
+ if (m_python)
+ {
+ int stdin_fd = GetInputFD();
+ if (stdin_fd >= 0)
{
- 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
+ Terminal terminal(stdin_fd);
+ TerminalState terminal_state;
+ const bool is_a_tty = terminal.IsATerminal();
+
+ if (is_a_tty)
{
- if (log)
- log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, failed in creating thread");
- reader.SetIsDone (true);
+ 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;
-
- case eInputReaderAsynchronousOutputWritten:
- break;
+ virtual void
+ Hide ()
+ {
- case eInputReaderInterrupt:
- ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "raise KeyboardInterrupt\n", 24);
- break;
+ }
+
+ virtual void
+ Refresh ()
+ {
- 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
+ Cancel ()
+ {
- 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;
-}
+ virtual void
+ Interrupt ()
+ {
+
+ }
+
+ virtual void
+ GotEOF()
+ {
+
+ }
+protected:
+ ScriptInterpreterPython *m_python;
+};
void
@@ -918,24 +816,13 @@ ScriptInterpreterPython::ExecuteInterpreterLoop ()
// 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)
- {
- 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;
- }
+ IOHandlerSP io_handler_sp (new IOHandlerPythonInterpreter (debugger, this));
+ if (io_handler_sp)
+ {
+ debugger.PushIOHandler(io_handler_sp);
}
}
@@ -951,27 +838,21 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
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 +861,18 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
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)
@@ -1115,35 +992,31 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
return ret_success;
}
-bool
+Error
ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const ExecuteScriptOptions &options)
{
-
+ Error error;
Locker locker(this,
ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
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 +1032,11 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec
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,324 +1044,50 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec
py_error = PyErr_Occurred ();
if (py_error != NULL)
{
- success = false;
- if (options.GetMaskoutErrors())
- {
- if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
- PyErr_Print ();
- PyErr_Clear();
- }
- }
-
- 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;
+// puts(in_string);
+// _PyObject_Dump (py_error);
+// PyErr_Print();
+// success = false;
- 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);
+ PyObject *type = NULL;
+ PyObject *value = NULL;
+ PyObject *traceback = NULL;
+ PyErr_Fetch (&type,&value,&traceback);
- // Control-c (SIGINT) ALSO means cancel; do NOT create a breakpoint command.
- if (notification == eInputReaderInterrupt)
- commands_in_progress.Clear();
+ // get the backtrace
+ std::string bt = ReadPythonBacktrace(traceback);
- // Fall through here...
-
- case eInputReaderDone:
+ if (value && value != Py_None)
+ error.SetErrorStringWithFormat("%s\n%s", PyString_AsString(PyObject_Str(value)),bt.c_str());
+ else
+ error.SetErrorStringWithFormat("%s",bt.c_str());
+ Py_XDECREF(type);
+ Py_XDECREF(value);
+ Py_XDECREF(traceback);
+ if (options.GetMaskoutErrors())
{
- 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();
- }
- }
- }
+ PyErr_Clear();
}
- break;
-
}
- return bytes_len;
+ return error;
}
-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.
@@ -1548,7 +1142,7 @@ ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &func
// Convert StringList to one long, newline delimited, const char *.
std::string function_def_string(function_def.CopyList());
- return ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
+ return ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)).Success();
}
bool
@@ -1700,7 +1294,9 @@ ScriptInterpreterPython::OSPlugin_CreatePluginObject (const char *class_name, ll
void* ret_val;
{
- Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+ Locker py_lock (this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
ret_val = g_swig_create_os_plugin (class_name,
m_dictionary_name.c_str(),
process_sp);
@@ -1712,7 +1308,9 @@ ScriptInterpreterPython::OSPlugin_CreatePluginObject (const char *class_name, ll
lldb::ScriptInterpreterObjectSP
ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp)
{
- Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
static char callee_name[] = "get_register_info";
@@ -1771,7 +1369,9 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP
lldb::ScriptInterpreterObjectSP
ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp)
{
- Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+ Locker py_lock (this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
static char callee_name[] = "get_thread_info";
@@ -1857,7 +1457,9 @@ lldb::ScriptInterpreterObjectSP
ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp,
lldb::tid_t tid)
{
- Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+ Locker py_lock (this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
static char callee_name[] = "get_register_data";
static char *param_format = const_cast<char *>(GetPythonValueFormatString(tid));
@@ -1919,7 +1521,9 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP
lldb::tid_t tid,
lldb::addr_t context)
{
- Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
static char callee_name[] = "create_thread";
std::string param_format;
@@ -2011,7 +1615,7 @@ ScriptInterpreterPython::GetDynamicSettings (lldb::ScriptInterpreterObjectSP plu
PyObject *reply_pyobj = nullptr;
{
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
TargetSP target_sp(target->shared_from_this());
reply_pyobj = (PyObject*)g_swig_plugin_get(plugin_module_sp->GetObject(),setting_name,target_sp);
}
@@ -2045,7 +1649,7 @@ ScriptInterpreterPython::CreateSyntheticScriptedProvider (const char *class_name
void* ret_val;
{
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_synthetic_script (class_name,
python_interpreter->m_dictionary_name.c_str(),
valobj);
@@ -2136,14 +1740,14 @@ ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name,
&& *python_function_name)
{
{
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
{
- 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()),
- valobj,
- &new_callee,
- retval);
+ Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback");
+ ret_val = g_swig_typescript_callback (python_function_name,
+ GetSessionDictionary().get(),
+ valobj,
+ &new_callee,
+ retval);
}
}
}
@@ -2188,8 +1792,7 @@ ScriptInterpreterPython::BreakpointCallbackFunction
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);
@@ -2201,8 +1804,8 @@ ScriptInterpreterPython::BreakpointCallbackFunction
{
bool ret_val = true;
{
- Locker py_lock(python_interpreter);
- ret_val = g_swig_breakpoint_callback (python_function_name,
+ Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_breakpoint_callback (python_function_name,
python_interpreter->m_dictionary_name.c_str(),
stop_frame_sp,
bp_loc_sp);
@@ -2243,8 +1846,7 @@ ScriptInterpreterPython::WatchpointCallbackFunction
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);
@@ -2254,8 +1856,8 @@ ScriptInterpreterPython::WatchpointCallbackFunction
{
bool ret_val = true;
{
- Locker py_lock(python_interpreter);
- ret_val = g_swig_watchpoint_callback (python_function_name,
+ Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_watchpoint_callback (python_function_name,
python_interpreter->m_dictionary_name.c_str(),
stop_frame_sp,
wp_sp);
@@ -2269,106 +1871,6 @@ ScriptInterpreterPython::WatchpointCallbackFunction
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)
{
@@ -2386,7 +1888,7 @@ ScriptInterpreterPython::CalculateNumChildren (const lldb::ScriptInterpreterObje
uint32_t ret_val = 0;
{
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_calc_children (implementor);
}
@@ -2410,7 +1912,7 @@ ScriptInterpreterPython::GetChildAtIndex (const lldb::ScriptInterpreterObjectSP&
lldb::ValueObjectSP ret_val;
{
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
void* child_ptr = g_swig_get_child_index (implementor,idx);
if (child_ptr != NULL && child_ptr != Py_None)
{
@@ -2446,7 +1948,7 @@ ScriptInterpreterPython::GetIndexOfChildWithName (const lldb::ScriptInterpreterO
int ret_val = UINT32_MAX;
{
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_get_index_child (implementor, child_name);
}
@@ -2470,7 +1972,7 @@ ScriptInterpreterPython::UpdateSynthProviderInstance (const lldb::ScriptInterpre
return ret_val;
{
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_update_provider (implementor);
}
@@ -2494,7 +1996,7 @@ ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance (const lldb::Scr
return ret_val;
{
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_mighthavechildren_provider (implementor);
}
@@ -2582,7 +2084,7 @@ ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
}
{
ProcessSP process_sp(process->shared_from_this());
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_run_script_keyword_process (impl_function, m_dictionary_name.c_str(), process_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
@@ -2614,7 +2116,7 @@ ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
}
{
ThreadSP thread_sp(thread->shared_from_this());
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_run_script_keyword_thread (impl_function, m_dictionary_name.c_str(), thread_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
@@ -2646,7 +2148,7 @@ ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
}
{
TargetSP target_sp(target->shared_from_this());
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_run_script_keyword_target (impl_function, m_dictionary_name.c_str(), target_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
@@ -2678,7 +2180,7 @@ ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
}
{
StackFrameSP frame_sp(frame->shared_from_this());
- Locker py_lock(this);
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_run_script_keyword_frame (impl_function, m_dictionary_name.c_str(), frame_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
@@ -2728,7 +2230,7 @@ ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
// Before executing Pyton code, lock the GIL.
Locker py_lock (this,
- Locker::AcquireLock | (init_session ? Locker::InitSession : 0),
+ Locker::AcquireLock | (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN,
Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0));
if (target_file.GetFileType() == FileSpec::eFileTypeInvalid ||
@@ -2755,7 +2257,7 @@ ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
command_stream.Printf("if not (sys.path.__contains__('%s')):\n sys.path.insert(1,'%s');\n\n",
directory.c_str(),
directory.c_str());
- bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false));
+ bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)).Success();
if (!syspath_retval)
{
error.SetErrorString("Python sys.path handling failed");
@@ -2782,7 +2284,6 @@ ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
command_stream.Clear();
command_stream.Printf("sys.modules.__contains__('%s')",basename.c_str());
bool does_contain = false;
- int refcount = 0;
// this call will succeed if the module was ever imported in any Debugger in the lifetime of the process
// in which this LLDB framework is living
bool was_imported_globally = (ExecuteOneLineWithReturn(command_stream.GetData(),
@@ -2792,10 +2293,7 @@ ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
// this call will fail if the module was not imported in this Debugger before
command_stream.Clear();
command_stream.Printf("sys.getrefcount(%s)",basename.c_str());
- bool was_imported_locally = (ExecuteOneLineWithReturn(command_stream.GetData(),
- ScriptInterpreterPython::eScriptReturnTypeInt,
- &refcount,
- ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && refcount > 0);
+ bool was_imported_locally = !(GetSessionDictionary().GetItemForKey(basename.c_str()).IsNULLOrNone());
bool was_imported = (was_imported_globally || was_imported_locally);
@@ -2818,47 +2316,9 @@ ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
else
command_stream.Printf("import %s",basename.c_str());
- bool import_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false).SetMaskoutErrors(false));
- PyObject* py_error = PyErr_Occurred(); // per Python docs: "you do not need to Py_DECREF()" the return of this function
-
- if (py_error || !import_retval) // check for failure of the import
- {
- if (py_error) // if we have a Python error..
- {
- PyObject *type = NULL,*value = NULL,*traceback = NULL;
- PyErr_Fetch (&type,&value,&traceback);
-
- if (PyErr_GivenExceptionMatches (py_error, PyExc_ImportError)) // and it is an ImportError
- {
- if (value && value != Py_None)
- error.SetErrorString(PyString_AsString(PyObject_Str(value)));
- else
- error.SetErrorString("ImportError raised by imported module");
- }
- else // any other error
- {
- // get the backtrace
- std::string bt = ReadPythonBacktrace(traceback);
-
- if (value && value != Py_None)
- error.SetErrorStringWithFormat("Python error raised while importing module: %s - traceback: %s", PyString_AsString(PyObject_Str(value)),bt.c_str());
- else
- error.SetErrorStringWithFormat("Python raised an error while importing module - traceback: %s",bt.c_str());
- }
-
- Py_XDECREF(type);
- Py_XDECREF(value);
- Py_XDECREF(traceback);
- }
- else // we failed but have no error to explain why
- {
- error.SetErrorString("unknown error while importing module");
- }
-
- // anyway, clear the error indicator and return false
- PyErr_Clear();
+ error = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false));
+ if (error.Fail())
return false;
- }
// if we are here, everything worked
// call __lldb_init_module(debugger,dict)
@@ -2954,7 +2414,7 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function,
// 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(),
@@ -3007,8 +2467,8 @@ std::unique_ptr<ScriptInterpreterLocker>
ScriptInterpreterPython::AcquireInterpreterLock ()
{
std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(this,
- Locker::AcquireLock | Locker::InitSession,
- Locker::FreeLock | Locker::TearDownSession));
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
+ Locker::FreeLock | Locker::TearDownSession));
return py_lock;
}
@@ -3059,6 +2519,13 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb
void
ScriptInterpreterPython::InitializePrivate ()
{
+ static int g_initialized = false;
+
+ if (g_initialized)
+ return;
+
+ g_initialized = true;
+
Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
// Python will muck with STDIN terminal state, so save off any current TTY
@@ -3081,8 +2548,8 @@ ScriptInterpreterPython::InitializePrivate ()
Py_InitializeEx (0);
// Initialize SWIG after setting up python
- assert (g_swig_init_callback != NULL);
- g_swig_init_callback ();
+ if (g_swig_init_callback)
+ g_swig_init_callback ();
// Update the path python uses to search for modules to include the current directory.
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py b/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py
index 0e57c1e..bc0dd6d 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py
+++ b/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py
@@ -1,103 +1,108 @@
-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
+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')
- def interact(self):
- try:
- sys.ps1
- except AttributeError:
- sys.ps1 = ">>> "
- try:
- sys.ps2
- except AttributeError:
- sys.ps2 = "... "
+g_builtin_override_called = False
- 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()
+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 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)
+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')
- # 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
+# 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
- 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
+g_run_one_line_str = None
- 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
- def one_line (self, input):
- line = self.process_input (input)
- more = self.push(line)
- if more:
- self.write ("Input not a complete line.")
- self.resetbuffer()
- more = 0
+def get_terminal_size(fd):
+ try:
+ import fcntl, termios, struct
+ hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
+ except:
+ hw = (0,0)
+ return hw
-def run_python_interpreter (dict):
- # Pass in the dictionary, for continuity from one session to the next.
- repl = SimpleREPL('>>> ', dict)
- repl.interact()
+def readfunc_stdio(prompt):
+ sys.stdout.write(prompt)
+ return sys.stdin.readline()
-def run_one_line (dict, input_string):
- repl = SimpleREPL ('', dict)
- repl.one_line (input_string)
+def run_python_interpreter (local_dict):
+ # Pass in the dictionary, for continuity from one session to the next.
+ setquit()
+ try:
+ fd = sys.stdin.fileno();
+ interacted = False
+ if get_terminal_size(fd)[1] == 0:
+ try:
+ import termios
+ old = termios.tcgetattr(fd)
+ if old[3] & termios.ECHO:
+ # Need to turn off echoing and restore
+ new = termios.tcgetattr(fd)
+ new[3] = new[3] & ~termios.ECHO
+ try:
+ termios.tcsetattr(fd, termios.TCSADRAIN, new)
+ interacted = True
+ code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.", readfunc=readfunc_stdio, local=local_dict)
+ finally:
+ termios.tcsetattr(fd, termios.TCSADRAIN, old)
+ except:
+ pass
+ # Don't need to turn off echoing
+ if not interacted:
+ code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", readfunc=readfunc_stdio, local=local_dict)
+ else:
+ # We have a real interactive terminal
+ code.interact(banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", local=local_dict)
+ except SystemExit as e:
+ global g_builtin_override_called
+ if not g_builtin_override_called:
+ print 'Script exited with %s' %(e)
+def run_one_line (local_dict, input_string):
+ global g_run_one_line_str
+ setquit()
+ try:
+ repl = code.InteractiveConsole(local_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:
+ global g_builtin_override_called
+ if not g_builtin_override_called:
+ print 'Script exited with %s' %(e)
OpenPOWER on IntegriCloud