summaryrefslogtreecommitdiffstats
path: root/lldb/source/Interpreter/ScriptInterpreterPython.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-06-08 16:52:24 +0000
committerChris Lattner <sabre@nondot.org>2010-06-08 16:52:24 +0000
commit30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c (patch)
treef70013106f6a461a14abcd71c65f48a95a2979a6 /lldb/source/Interpreter/ScriptInterpreterPython.cpp
parent312c4c799da215b337f790fda330f70c4aa757cf (diff)
downloadbcm5719-llvm-30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c.tar.gz
bcm5719-llvm-30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c.zip
Initial checkin of lldb code from internal Apple repo.
llvm-svn: 105619
Diffstat (limited to 'lldb/source/Interpreter/ScriptInterpreterPython.cpp')
-rw-r--r--lldb/source/Interpreter/ScriptInterpreterPython.cpp830
1 files changed, 830 insertions, 0 deletions
diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
new file mode 100644
index 00000000000..6b2e3b2e7ad
--- /dev/null
+++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
@@ -0,0 +1,830 @@
+//===-- ScriptInterpreterPython.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// In order to guarantee correct working with Python, Python.h *MUST* be
+// the *FIRST* header file included:
+
+#include <Python.h>
+
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
+
+
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <string>
+
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+
+extern "C" void init_lldb (void);
+
+using namespace lldb;
+using namespace lldb_private;
+
+const char embedded_interpreter_string[] =
+"import readline\n\
+import code\n\
+import sys\n\
+import traceback\n\
+\n\
+class SimpleREPL(code.InteractiveConsole):\n\
+ def __init__(self, prompt, dict):\n\
+ code.InteractiveConsole.__init__(self,dict)\n\
+ self.prompt = prompt\n\
+ self.loop_exit = False\n\
+ self.dict = dict\n\
+\n\
+ def interact(self):\n\
+ try:\n\
+ sys.ps1\n\
+ except AttributeError:\n\
+ sys.ps1 = \">>> \"\n\
+ try:\n\
+ sys.ps2\n\
+ except AttributeError:\n\
+ sys.ps2 = \"... \"\n\
+\n\
+ while not self.loop_exit:\n\
+ try:\n\
+ self.read_py_command()\n\
+ except (SystemExit, EOFError):\n\
+ # EOF while in Python just breaks out to top level.\n\
+ self.write('\\n')\n\
+ self.loop_exit = True\n\
+ break\n\
+ except KeyboardInterrupt:\n\
+ self.write(\"\\nKeyboardInterrupt\\n\")\n\
+ self.resetbuffer()\n\
+ more = 0\n\
+ except:\n\
+ traceback.print_exc()\n\
+\n\
+ def process_input (self, in_str):\n\
+ # Canonicalize the format of the input string\n\
+ temp_str = in_str\n\
+ temp_str.strip(' \t')\n\
+ words = temp_str.split()\n\
+ temp_str = ('').join(words)\n\
+\n\
+ # Check the input string to see if it was the quit\n\
+ # command. If so, intercept it, so that it doesn't\n\
+ # close stdin on us!\n\
+ if (temp_str.lower() == \"quit()\"):\n\
+ self.loop_exit = True\n\
+ in_str = \"raise SystemExit \"\n\
+ return in_str\n\
+\n\
+ def my_raw_input (self, prompt):\n\
+ stream = sys.stdout\n\
+ stream.write (prompt)\n\
+ stream.flush ()\n\
+ try:\n\
+ line = sys.stdin.readline()\n\
+ except KeyboardInterrupt:\n\
+ line = \" \\n\"\n\
+ except (SystemExit, EOFError):\n\
+ line = \"quit()\\n\"\n\
+ if not line:\n\
+ raise EOFError\n\
+ if line[-1] == '\\n':\n\
+ line = line[:-1]\n\
+ return line\n\
+\n\
+ def read_py_command(self):\n\
+ # Read off a complete Python command.\n\
+ more = 0\n\
+ while 1:\n\
+ if more:\n\
+ prompt = sys.ps2\n\
+ else:\n\
+ prompt = sys.ps1\n\
+ line = self.my_raw_input(prompt)\n\
+ # Can be None if sys.stdin was redefined\n\
+ encoding = getattr(sys.stdin, \"encoding\", None)\n\
+ if encoding and not isinstance(line, unicode):\n\
+ line = line.decode(encoding)\n\
+ line = self.process_input (line)\n\
+ more = self.push(line)\n\
+ if not more:\n\
+ break\n\
+\n\
+def run_python_interpreter (dict):\n\
+ # Pass in the dictionary, for continuity from one session to the next.\n\
+ repl = SimpleREPL('>>> ', dict)\n\
+ repl.interact()\n";
+
+static int
+_check_and_flush (FILE *stream)
+{
+ int prev_fail = ferror (stream);
+ return fflush (stream) || prev_fail ? EOF : 0;
+}
+
+ScriptInterpreterPython::ScriptInterpreterPython () :
+ ScriptInterpreter (eScriptLanguagePython),
+ m_compiled_module (NULL),
+ m_termios_valid (false)
+{
+
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+ // Find the module that owns this code and use that path we get to
+ // set the PYTHONPATH appropriately.
+
+ FileSpec this_module (Host::GetModuleFileSpecForHostAddress ((void *)init_lldb));
+ std::string python_path;
+
+ if (this_module.GetDirectory())
+ {
+ // Append the directory that the module that loaded this code
+ // belongs to
+ python_path += this_module.GetDirectory().AsCString("");
+
+#if defined (__APPLE__)
+ // If we are running on MacOSX we might be in a framework and should
+ // add an appropriate path so Resource can be found in a bundle
+
+ if (::strstr(this_module.GetDirectory().AsCString(""), ".framework"))
+ {
+ python_path.append(1, ':');
+ python_path.append(this_module.GetDirectory().AsCString(""));
+ python_path.append("/Resources/Python");
+ }
+#endif
+ // The the PYTHONPATH environment variable so that Python can find
+ // our lldb.py module and our _lldb.so.
+ ::setenv ("PYTHONPATH", python_path.c_str(), 1);
+ }
+
+ Py_Initialize ();
+
+ PyObject *compiled_module = Py_CompileString (embedded_interpreter_string, "embedded_interpreter.py",
+ Py_file_input);
+
+ m_compiled_module = compiled_module;
+
+ init_lldb ();
+
+ // Update the path python uses to search for modules to include the current directory.
+
+ int success = PyRun_SimpleString ("import sys");
+ success = PyRun_SimpleString ("sys.path.append ('.')");
+ if (success == 0)
+ {
+ // Import the Script Bridge module.
+ success = PyRun_SimpleString ("from lldb import *");
+ }
+
+ const char *pty_slave_name = GetScriptInterpreterPtyName ();
+ FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+
+ PyObject *pmod = PyImport_ExecCodeModule((char *)"embedded_interpreter", m_compiled_module);
+ if (pmod != NULL)
+ {
+ PyRun_SimpleString ("ConsoleDict = locals()");
+ PyRun_SimpleString ("from embedded_interpreter import run_python_interpreter");
+ PyRun_SimpleString ("import sys");
+ PyRun_SimpleString ("from termios import *");
+ PyRun_SimpleString ("old_stdin = sys.stdin");
+
+ StreamString run_string;
+ run_string.Printf ("new_stdin = open('%s', 'r')", pty_slave_name);
+ PyRun_SimpleString (run_string.GetData());
+ PyRun_SimpleString ("sys.stdin = new_stdin");
+
+ PyRun_SimpleString ("old_stdout = sys.stdout");
+
+ if (out_fh != NULL)
+ {
+ PyObject *new_sysout = PyFile_FromFile (out_fh, (char *) "", (char *) "w",
+ _check_and_flush);
+ PyObject *sysmod = PyImport_AddModule ("sys");
+ PyObject *sysdict = PyModule_GetDict (sysmod);
+
+ if ((new_sysout != NULL)
+ && (sysmod != NULL)
+ && (sysdict != NULL))
+ {
+ PyDict_SetItemString (sysdict, "stdout", new_sysout);
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ }
+
+ PyRun_SimpleString ("new_mode = tcgetattr(new_stdin)");
+ PyRun_SimpleString ("new_mode[3] = new_mode[3] | ECHO | ICANON");
+ PyRun_SimpleString ("new_mode[6][VEOF] = 255");
+ PyRun_SimpleString ("tcsetattr (new_stdin, TCSANOW, new_mode)");
+ }
+
+
+}
+
+ScriptInterpreterPython::~ScriptInterpreterPython ()
+{
+ PyRun_SimpleString ("sys.stdin = old_stdin");
+ PyRun_SimpleString ("sys.stdout = old_stdout");
+ Py_Finalize ();
+}
+
+void
+ScriptInterpreterPython::ExecuteOneLine (const std::string& line, FILE *out, FILE *err)
+{
+ int success;
+
+ success = PyRun_SimpleString (line.c_str());
+ if (success != 0)
+ {
+ fprintf (err, "error: python failed attempting to evaluate '%s'\n", line.c_str());
+ }
+}
+
+
+
+size_t
+ScriptInterpreterPython::InputReaderCallback
+(
+ void *baton,
+ InputReader *reader,
+ lldb::InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len
+)
+{
+ if (baton == NULL)
+ return 0;
+
+ ScriptInterpreterPython *interpreter = (ScriptInterpreterPython *) baton;
+ switch (notification)
+ {
+ case eInputReaderActivate:
+ {
+ // Save terminal settings if we can
+ interpreter->m_termios_valid = ::tcgetattr (::fileno (reader->GetInputFileHandle()),
+ &interpreter->m_termios) == 0;
+ struct termios tmp_termios;
+ if (::tcgetattr (::fileno (reader->GetInputFileHandle()), &tmp_termios) == 0)
+ {
+ tmp_termios.c_cc[VEOF] = _POSIX_VDISABLE;
+ ::tcsetattr (::fileno (reader->GetInputFileHandle()), TCSANOW, &tmp_termios);
+ }
+ }
+ break;
+
+ case eInputReaderDeactivate:
+ break;
+
+ case eInputReaderReactivate:
+ break;
+
+ case eInputReaderGotToken:
+ if (bytes && bytes_len)
+ {
+ if ((int) bytes[0] == 4)
+ ::write (interpreter->GetMasterFileDescriptor(), "quit()", 6);
+ else
+ ::write (interpreter->GetMasterFileDescriptor(), bytes, bytes_len);
+ }
+ ::write (interpreter->GetMasterFileDescriptor(), "\n", 1);
+ break;
+
+ case eInputReaderDone:
+ // Send a control D to the script interpreter
+ //::write (interpreter->GetMasterFileDescriptor(), "\nquit()\n", strlen("\nquit()\n"));
+ // Write a newline out to the reader output
+ //::fwrite ("\n", 1, 1, out_fh);
+ // Restore terminal settings if they were validly saved
+ if (interpreter->m_termios_valid)
+ {
+ ::tcsetattr (::fileno (reader->GetInputFileHandle()),
+ TCSANOW,
+ &interpreter->m_termios);
+ }
+ break;
+ }
+
+ return bytes_len;
+}
+
+
+void
+ScriptInterpreterPython::ExecuteInterpreterLoop (FILE *out, FILE *err)
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ InputReaderSP reader_sp (new InputReader());
+ 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::GetSharedInstance().PushInputReader (reader_sp);
+ ExecuteOneLine ("run_python_interpreter(ConsoleDict)", out, err);
+ Debugger::GetSharedInstance().PopInputReader (reader_sp);
+ }
+ }
+}
+
+bool
+ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
+ ScriptInterpreter::ReturnType return_type,
+ void *ret_value)
+{
+ PyObject *py_return = NULL;
+ PyObject *mainmod = PyImport_AddModule ("__main__");
+ PyObject *globals = PyModule_GetDict (mainmod);
+ PyObject *locals = globals;
+ PyObject *py_error = NULL;
+ bool ret_success;
+ int success;
+
+ if (in_string != NULL)
+ {
+ py_return = PyRun_String (in_string, Py_eval_input, globals, locals);
+ 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);
+ }
+
+ if (py_return != NULL)
+ {
+ switch (return_type)
+ {
+ case eCharPtr: // "char *"
+ {
+ const char format[3] = "s#";
+ success = PyArg_Parse (py_return, format, (char **) &ret_value);
+ break;
+ }
+ case eBool:
+ {
+ const char format[2] = "b";
+ success = PyArg_Parse (py_return, format, (bool *) ret_value);
+ break;
+ }
+ case eShortInt:
+ {
+ const char format[2] = "h";
+ success = PyArg_Parse (py_return, format, (short *) ret_value);
+ break;
+ }
+ case eShortIntUnsigned:
+ {
+ const char format[2] = "H";
+ success = PyArg_Parse (py_return, format, (unsigned short *) ret_value);
+ break;
+ }
+ case eInt:
+ {
+ const char format[2] = "i";
+ success = PyArg_Parse (py_return, format, (int *) ret_value);
+ break;
+ }
+ case eIntUnsigned:
+ {
+ const char format[2] = "I";
+ success = PyArg_Parse (py_return, format, (unsigned int *) ret_value);
+ break;
+ }
+ case eLongInt:
+ {
+ const char format[2] = "l";
+ success = PyArg_Parse (py_return, format, (long *) ret_value);
+ break;
+ }
+ case eLongIntUnsigned:
+ {
+ const char format[2] = "k";
+ success = PyArg_Parse (py_return, format, (unsigned long *) ret_value);
+ break;
+ }
+ case eLongLong:
+ {
+ const char format[2] = "L";
+ success = PyArg_Parse (py_return, format, (long long *) ret_value);
+ break;
+ }
+ case eLongLongUnsigned:
+ {
+ const char format[2] = "K";
+ success = PyArg_Parse (py_return, format, (unsigned long long *) ret_value);
+ break;
+ }
+ case eFloat:
+ {
+ const char format[2] = "f";
+ success = PyArg_Parse (py_return, format, (float *) ret_value);
+ break;
+ }
+ case eDouble:
+ {
+ const char format[2] = "d";
+ success = PyArg_Parse (py_return, format, (double *) ret_value);
+ break;
+ }
+ case eChar:
+ {
+ const char format[2] = "c";
+ success = PyArg_Parse (py_return, format, (char *) ret_value);
+ break;
+ }
+ default:
+ {}
+ }
+ Py_DECREF (py_return);
+ if (success)
+ ret_success = true;
+ else
+ ret_success = false;
+ }
+ }
+
+ py_error = PyErr_Occurred();
+ if (py_error != NULL)
+ {
+ if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
+ PyErr_Print ();
+ PyErr_Clear();
+ ret_success = false;
+ }
+
+ return ret_success;
+}
+
+bool
+ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string)
+{
+ bool success = false;
+ PyObject *py_return = NULL;
+ PyObject *mainmod = PyImport_AddModule ("__main__");
+ PyObject *globals = PyModule_GetDict (mainmod);
+ PyObject *locals = globals;
+ PyObject *py_error = NULL;
+
+ if (in_string != NULL)
+ {
+ struct _node *compiled_node = PyParser_SimpleParseString (in_string, Py_file_input);
+ if (compiled_node)
+ {
+ PyCodeObject *compiled_code = PyNode_Compile (compiled_node, "temp.py");
+ if (compiled_code)
+ {
+ py_return = PyEval_EvalCode (compiled_code, globals, locals);
+ if (py_return != NULL)
+ {
+ success = true;
+ Py_DECREF (py_return);
+ }
+ }
+ }
+ }
+
+ py_error = PyErr_Occurred ();
+ if (py_error != NULL)
+ {
+ if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
+ PyErr_Print ();
+ PyErr_Clear();
+ success = false;
+ }
+
+ return success;
+}
+
+static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.";
+
+size_t
+ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback
+(
+ void *baton,
+ InputReader *reader,
+ lldb::InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len
+)
+{
+ static StringList commands_in_progress;
+
+ FILE *out_fh = reader->GetOutputFileHandle();
+ switch (notification)
+ {
+ case eInputReaderActivate:
+ {
+ commands_in_progress.Clear();
+ if (out_fh)
+ {
+ ::fprintf (out_fh, "%s\n", g_reader_instructions);
+ if (reader->GetPrompt())
+ ::fprintf (out_fh, "%s", reader->GetPrompt());
+ }
+ }
+ break;
+
+ case eInputReaderDeactivate:
+ break;
+
+ case eInputReaderReactivate:
+ if (reader->GetPrompt() && out_fh)
+ ::fprintf (out_fh, "%s", reader->GetPrompt());
+ break;
+
+ case eInputReaderGotToken:
+ {
+ std::string temp_string (bytes, bytes_len);
+ commands_in_progress.AppendString (temp_string.c_str());
+ if (out_fh && !reader->IsDone() && reader->GetPrompt())
+ ::fprintf (out_fh, "%s", reader->GetPrompt());
+ }
+ break;
+
+ case eInputReaderDone:
+ {
+ BreakpointOptions *bp_options = (BreakpointOptions *)baton;
+ std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+ data_ap->user_source.AppendList (commands_in_progress);
+ if (data_ap.get())
+ {
+ ScriptInterpreter *interpreter = Debugger::GetSharedInstance().GetCommandInterpreter().GetScriptInterpreter();
+ if (interpreter)
+ {
+ if (interpreter->GenerateBreakpointCommandCallbackData (data_ap->user_source,
+ data_ap->script_source))
+ {
+ if (data_ap->script_source.GetSize() == 1)
+ {
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
+ }
+ }
+ }
+ else
+ {
+ // FIXME: Error processing.
+ }
+ }
+ }
+ break;
+
+ }
+
+ return bytes_len;
+}
+
+void
+ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
+ CommandReturnObject &result)
+{
+ InputReaderSP reader_sp (new InputReader ());
+
+ 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::GetSharedInstance().PushInputReader (reader_sp);
+ else
+ {
+ result.AppendError (err.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError("out of memory");
+ result.SetStatus (eReturnStatusFailed);
+ }
+}
+
+bool
+ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def)
+{
+ // Convert StringList to one long, newline delimited, const char *.
+ std::string function_def_string;
+
+ int num_lines = function_def.GetSize();
+
+ for (int i = 0; i < num_lines; ++i)
+ {
+ function_def_string.append (function_def.GetStringAtIndex(i));
+ if (function_def_string.at (function_def_string.length() - 1) != '\n')
+ function_def_string.append ("\n");
+
+ }
+
+ return ExecuteMultipleLines (function_def_string.c_str());
+}
+
+bool
+ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, StringList &callback_data)
+{
+ static int num_created_functions = 0;
+
+ user_input.RemoveBlankLines ();
+ int num_lines = user_input.GetSize();
+ std::string last_function_call;
+
+ // Go through lines of input looking for any function definitions. For each function definition found,
+ // export the function definition to Python, create a potential function call for the function, and
+ // mark the lines of the function to be removed from the user input.
+
+ for (int i = 0; i < num_lines; ++i)
+ {
+ int function_start = i;
+ std::string current_str = user_input.GetStringAtIndex (i);
+ const char *current_line = current_str.c_str();
+ int len = 0;
+ if (current_line)
+ len = strlen (current_line);
+
+ // Check to see if the current line is the start of a Python function definition.
+ if (len > 4 && strncmp (current_line, "def ", 4) == 0)
+ {
+ // We've found the first line of a function. First, get the function name.
+
+ // Skip over the 'def '.
+ char *start = (char *) current_line + 4;
+
+ // Skip over white space.
+ while (start[0] == ' ' || start[0] == '\t')
+ ++start;
+
+ // Find the end of the function name.
+ char *end = start;
+ while (isalnum (end[0]) || end[0] == '_')
+ ++end;
+
+ int name_len = end - start;
+ std::string func_name = current_str.substr (4, name_len);
+
+ // Now to find the last line of the function. That will be the first line that does not begin with
+ // any white space (thanks to Python's indentation rules).
+ ++i;
+ bool found = false;
+ while (i < num_lines && !found)
+ {
+ std::string next_str = user_input.GetStringAtIndex (i);
+ const char *next_line = next_str.c_str();
+ if (next_line[0] != ' ' && next_line[0] != '\t')
+ found = true;
+ else
+ ++i;
+ }
+ if (found)
+ --i; // Make 'i' correspond to the last line of the function.
+ int function_end = i;
+
+ // Special case: All of user_input is one big function definition.
+ if ((function_start == 0) && (function_end == (num_lines - 1)))
+ {
+ ExportFunctionDefinitionToInterpreter (user_input);
+ last_function_call = func_name + " ()";
+ callback_data.AppendString (last_function_call.c_str());
+ return callback_data.GetSize() > 0;
+ }
+ else
+ {
+ // Make a copy of the function definition:
+ StringList new_function;
+ for (int k = function_start; k <= function_end; ++k)
+ {
+ new_function.AppendString (user_input.GetStringAtIndex (k));
+ // Mark the string to be deleted from user_input.
+ user_input.DeleteStringAtIndex (k);
+ user_input.InsertStringAtIndex (k, "<lldb_delete>");
+ }
+ ExportFunctionDefinitionToInterpreter (new_function);
+ last_function_call = func_name + " ()";
+ }
+ }
+ }
+
+ // Now instead of trying to really delete the marked lines from user_input, we will just copy all the
+ // unmarked lines into a new StringList.
+
+ StringList new_user_input;
+
+ for (int i = 0; i < num_lines; ++i)
+ {
+ std::string current_string = user_input.GetStringAtIndex (i);
+ if (current_string.compare (0, 13, "<lldb_delete>") == 0)
+ continue;
+
+ new_user_input.AppendString (current_string.c_str());
+ }
+
+ num_lines = new_user_input.GetSize();
+
+ if (num_lines > 0)
+ {
+ if (num_lines == 1
+ && strchr (new_user_input.GetStringAtIndex(0), '\n') == NULL)
+ {
+ // If there's only one line of input, and it doesn't contain any newline characters....
+ callback_data.AppendString (new_user_input.GetStringAtIndex (0));
+ }
+ else
+ {
+ // Create the new function name.
+ StreamString func_name;
+ func_name.Printf ("lldb_bp_callback_func_%d", num_created_functions);
+ //std::string func_name = "lldb_bp_callback_func_" + num_created_functions;
+ ++num_created_functions;
+
+ // Create the function call for the new function.
+ last_function_call = func_name.GetString() + " ()";
+
+ // Create the Python function definition line (which will have to be inserted at the beginning of
+ // the function).
+ std::string def_line = "def " + func_name.GetString() + " ():";
+
+
+ // Indent all lines an additional four spaces (as they are now being put inside a function definition).
+ for (int i = 0; i < num_lines; ++i)
+ {
+ const char *temp_cstring = new_user_input.GetStringAtIndex(i);
+ std::string temp2 = " ";
+ temp2.append(temp_cstring);
+ new_user_input.DeleteStringAtIndex (i);
+ new_user_input.InsertStringAtIndex (i, temp2.c_str());
+ }
+
+ // Insert the function definition line at the top of the new function.
+ new_user_input.InsertStringAtIndex (0, def_line.c_str());
+
+ ExportFunctionDefinitionToInterpreter (new_user_input);
+ callback_data.AppendString (last_function_call.c_str());
+ }
+ }
+ else
+ {
+ if (!last_function_call.empty())
+ callback_data.AppendString (last_function_call.c_str());
+ }
+
+ return callback_data.GetSize() > 0;
+}
+
+bool
+ScriptInterpreterPython::BreakpointCallbackFunction
+(
+ void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id
+)
+{
+ bool ret_value = true;
+ bool temp_bool;
+
+ BreakpointOptions::CommandData *bp_option_data = (BreakpointOptions::CommandData *) baton;
+
+ const char *python_string = bp_option_data->script_source.GetStringAtIndex(0);
+
+ if (python_string != NULL)
+ {
+ bool success =
+ Debugger::GetSharedInstance().GetCommandInterpreter().GetScriptInterpreter()->ExecuteOneLineWithReturn
+ (python_string,
+ ScriptInterpreter::eBool,
+ (void *) &temp_bool);
+ if (success)
+ ret_value = temp_bool;
+ }
+
+ return ret_value;
+}
OpenPOWER on IntegriCloud