diff options
18 files changed, 508 insertions, 47 deletions
diff --git a/lldb/include/lldb/Host/FileSpec.h b/lldb/include/lldb/Host/FileSpec.h index 057b5a45dd9..b1d25256ee2 100644 --- a/lldb/include/lldb/Host/FileSpec.h +++ b/lldb/include/lldb/Host/FileSpec.h @@ -357,6 +357,34 @@ public: size_t GetPath (char *path, size_t max_path_length) const; + //------------------------------------------------------------------ + /// Extract the extension of the file. + /// + /// Returns a ConstString that represents the extension of the filename + /// for this FileSpec object. If this object does not represent a file, + /// or the filename has no extension, ConstString(NULL) is returned. + /// The dot ('.') character is not returned as part of the extension + /// + /// @return + /// Returns the extension of the file as a ConstString object. + //------------------------------------------------------------------ + ConstString + GetFileNameExtension () const; + + //------------------------------------------------------------------ + /// Return the filename without the extension part + /// + /// Returns a ConstString that represents the filename of this object + /// without the extension part (e.g. for a file named "foo.bar", "foo" + /// is returned) + /// + /// @return + /// Returns the filename without extension + /// as a ConstString object. + //------------------------------------------------------------------ + ConstString + GetFileNameStrippingExtension () const; + FileType GetFileType () const; diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 91b2b6dc010..94c2161683c 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -11,7 +11,10 @@ #define liblldb_ScriptInterpreter_h_ #include "lldb/lldb-private.h" + #include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Error.h" + #include "lldb/Utility/PseudoTerminal.h" @@ -48,24 +51,28 @@ public: const char* args, std::string& err_msg, lldb_private::CommandReturnObject& cmd_retobj); + + typedef bool (*SWIGPythonCallModuleInit) (const std::string python_module_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger); typedef enum { - eCharPtr, - eBool, - eShortInt, - eShortIntUnsigned, - eInt, - eIntUnsigned, - eLongInt, - eLongIntUnsigned, - eLongLong, - eLongLongUnsigned, - eFloat, - eDouble, - eChar, - eCharStrOrNone - } ReturnType; + eScriptReturnTypeCharPtr, + eScriptReturnTypeBool, + eScriptReturnTypeShortInt, + eScriptReturnTypeShortIntUnsigned, + eScriptReturnTypeInt, + eScriptReturnTypeIntUnsigned, + eScriptReturnTypeLongInt, + eScriptReturnTypeLongIntUnsigned, + eScriptReturnTypeLongLong, + eScriptReturnTypeLongLongUnsigned, + eScriptReturnTypeFloat, + eScriptReturnTypeDouble, + eScriptReturnTypeChar, + eScriptReturnTypeCharStrOrNone + } ScriptReturnType; ScriptInterpreter (CommandInterpreter &interpreter, lldb::ScriptLanguage script_lang); @@ -79,7 +86,7 @@ public: ExecuteInterpreterLoop () = 0; virtual bool - ExecuteOneLineWithReturn (const char *in_string, ReturnType return_type, void *ret_value) + ExecuteOneLineWithReturn (const char *in_string, ScriptReturnType return_type, void *ret_value) { return true; } @@ -176,20 +183,28 @@ public: } virtual bool - RunScriptBasedCommand(const char* impl_function, - const char* args, - lldb_private::CommandReturnObject& cmd_retobj, - Error& error) + RunScriptBasedCommand (const char* impl_function, + const char* args, + lldb_private::CommandReturnObject& cmd_retobj, + Error& error) { return false; } virtual std::string - GetDocumentationForItem(const char* item) + GetDocumentationForItem (const char* item) { return std::string(""); } + virtual bool + LoadScriptingModule (const char* filename, + lldb_private::Error& error) + { + error.SetErrorString("loading unimplemented"); + return false; + } + const char * GetScriptInterpreterPtyName (); @@ -212,7 +227,8 @@ public: SWIGPythonGetIndexOfChildWithName python_swig_get_index_child, SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue, SWIGPythonUpdateSynthProviderInstance python_swig_update_provider, - SWIGPythonCallCommand python_swig_call_command); + SWIGPythonCallCommand python_swig_call_command, + SWIGPythonCallModuleInit python_swig_call_mod_init); static void TerminateInterpreter (); diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h index e90e7cdb86a..0ddaa7ff84f 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -40,7 +40,7 @@ public: bool ExecuteOneLineWithReturn (const char *in_string, - ScriptInterpreter::ReturnType return_type, + ScriptInterpreter::ScriptReturnType return_type, void *ret_value); bool @@ -108,7 +108,11 @@ public: lldb::ValueObjectSP valobj); virtual std::string - GetDocumentationForItem(const char* item); + GetDocumentationForItem (const char* item); + + virtual bool + LoadScriptingModule (const char* filename, + lldb_private::Error& error); void CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, @@ -141,7 +145,8 @@ public: SWIGPythonGetIndexOfChildWithName python_swig_get_index_child, SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue, SWIGPythonUpdateSynthProviderInstance python_swig_update_provider, - SWIGPythonCallCommand python_swig_call_command); + SWIGPythonCallCommand python_swig_call_command, + SWIGPythonCallModuleInit python_swig_call_mod_init); protected: diff --git a/lldb/scripts/Python/python-wrapper.swig b/lldb/scripts/Python/python-wrapper.swig index 3417c71ab35..d68c1b9260c 100644 --- a/lldb/scripts/Python/python-wrapper.swig +++ b/lldb/scripts/Python/python-wrapper.swig @@ -676,7 +676,89 @@ LLDBSwigPythonCallCommand PyErr_Print(); PyErr_Clear (); } -return retval; + return retval; +} + +SWIGEXPORT bool +LLDBSwigPythonCallModuleInit +( + const std::string python_module_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger +) +{ + + lldb::SBDebugger debugger_sb(debugger); + + bool retval = false; + + PyObject *DebuggerObj_PyObj = SWIG_NewPointerObj((void *) &debugger_sb, SWIGTYPE_p_lldb__SBDebugger, 0); + + if (DebuggerObj_PyObj == NULL) + return retval; + + if (!(python_module_name.length()) || !session_dictionary_name) + return retval; + + PyObject *session_dict, *pfunc; + PyObject *pargs, *pvalue; + + session_dict = FindSessionDictionary (session_dictionary_name); + + std::string python_function_name_string = python_module_name + (".__lldb_init_module"); + const char* python_function_name = python_function_name_string.c_str(); + + if (session_dict != NULL) + { + pfunc = ResolvePythonName (python_function_name, session_dict); + + if (PyErr_Occurred()) // this might not exist.. let's make sure we handle that + { + PyErr_Clear(); + return true; + } + + if (pfunc == NULL) + return true; + else + { + // Set up the arguments and call the function. + + if (PyCallable_Check (pfunc)) + { + pargs = PyTuple_New (2); + if (pargs == NULL) + { + if (PyErr_Occurred()) + PyErr_Clear(); + return retval; + } + + PyTuple_SetItem (pargs, 0, DebuggerObj_PyObj); // This "steals" a reference to DebuggerObj_PyObj + PyTuple_SetItem (pargs, 1, session_dict); // This "steals" a reference to session_dict + pvalue = PyObject_CallObject (pfunc, pargs); + Py_DECREF (pargs); + + if (PyErr_Occurred ()) + { + PyErr_Print(); + PyErr_Clear(); + } + else + { + retval = true; + Py_XDECREF (pvalue); + } + Py_INCREF (session_dict); + } + else if (PyErr_Occurred()) + { + PyErr_Print(); + PyErr_Clear(); + } + } + } + return retval; } %} diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index 8a15423c324..ec2653d909e 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -358,6 +358,13 @@ extern "C" bool LLDBSwigPythonCallCommand lldb_private::CommandReturnObject& cmd_retobj ); +extern "C" bool LLDBSwigPythonCallModuleInit +( + const std::string python_module_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger +); + extern "C" void init_lldb(void); @@ -377,6 +384,7 @@ SBCommandInterpreter::InitializeSWIG () LLDBSwigPython_GetIndexOfChildWithName, LLDBSWIGPython_CastPyObjectToSBValue, LLDBSwigPython_UpdateSynthProviderInstance, - LLDBSwigPythonCallCommand); + LLDBSwigPythonCallCommand, + LLDBSwigPythonCallModuleInit); } } diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index da0af986247..ba81f28ef2e 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -1220,6 +1220,78 @@ public: }; +//------------------------------------------------------------------------- +// CommandObjectCommandsScriptImport +//------------------------------------------------------------------------- + +class CommandObjectCommandsScriptImport : public CommandObject +{ +public: + CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) : + CommandObject (interpreter, + "command script import", + "Import a scripting module in LLDB.", + NULL) + { + CommandArgumentEntry arg1; + CommandArgumentData cmd_arg; + + // Define the first (and only) variant of this arg. + cmd_arg.arg_type = eArgTypePath; + cmd_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the argument entry. + arg1.push_back (cmd_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg1); + } + + ~CommandObjectCommandsScriptImport () + { + } + + bool + Execute + ( + Args& args, + CommandReturnObject &result + ) + { + + if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) + { + result.AppendError ("only scripting language supported for module importing is currently Python"); + result.SetStatus (eReturnStatusFailed); + return false; + } + + size_t argc = args.GetArgumentCount(); + + if (argc != 1) + { + result.AppendError ("'command script import' requires one argument"); + result.SetStatus (eReturnStatusFailed); + return false; + } + + std::string path = args.GetArgumentAtIndex(0); + Error error; + + if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(), + error)) + { + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendErrorWithFormat("module importing failed: %s", error.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + + return result.Succeeded(); + } +}; //------------------------------------------------------------------------- // CommandObjectCommandsScriptAdd @@ -1684,6 +1756,7 @@ public: LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter))); LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter))); LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter))); + LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter))); } ~CommandObjectMultiwordCommandsScript () diff --git a/lldb/source/Host/common/FileSpec.cpp b/lldb/source/Host/common/FileSpec.cpp index 5e034db6571..35e12ebdb57 100644 --- a/lldb/source/Host/common/FileSpec.cpp +++ b/lldb/source/Host/common/FileSpec.cpp @@ -699,10 +699,39 @@ FileSpec::GetPath(char *path, size_t path_max_len) const return ::snprintf (path, path_max_len, "%s", filename); } } - path[0] = '\0'; + if (path) + path[0] = '\0'; return 0; } +ConstString +FileSpec::GetFileNameExtension () const +{ + const char *filename = m_filename.GetCString(); + if (filename == NULL) + return ConstString(); + + char* dot_pos = strrchr(filename, '.'); + if (dot_pos == NULL) + return ConstString(); + + return ConstString(dot_pos+1); +} + +ConstString +FileSpec::GetFileNameStrippingExtension () const +{ + const char *filename = m_filename.GetCString(); + if (filename == NULL) + return ConstString(); + + char* dot_pos = strrchr(filename, '.'); + if (dot_pos == NULL) + return m_filename; + + return ConstString(filename, dot_pos-filename); +} + //------------------------------------------------------------------ // Returns a shared pointer to a data buffer that contains all or // part of the contents of a file. The data is memory mapped and diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp index 27bbb67605e..e125d657c33 100644 --- a/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -100,7 +100,8 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call SWIGPythonGetIndexOfChildWithName python_swig_get_index_child, SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue, SWIGPythonUpdateSynthProviderInstance python_swig_update_provider, - SWIGPythonCallCommand python_swig_call_command) + SWIGPythonCallCommand python_swig_call_command, + SWIGPythonCallModuleInit python_swig_call_mod_init) { ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback, python_swig_breakpoint_callback, @@ -111,7 +112,8 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call python_swig_get_index_child, python_swig_cast_to_sbvalue, python_swig_update_provider, - python_swig_call_command); + python_swig_call_command, + python_swig_call_mod_init); } void diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 634f76d60f6..f1f4a3255a3 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -42,6 +42,7 @@ static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_chi static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = NULL; static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = NULL; static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = NULL; +static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = NULL; static int _check_and_flush (FILE *stream) @@ -199,6 +200,10 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete PyRun_SimpleString (run_string.GetData()); run_string.Clear(); + run_string.Printf ("run_one_line (%s, 'import os')", m_dictionary_name.c_str()); + PyRun_SimpleString (run_string.GetData()); + + run_string.Clear(); run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %d')", m_dictionary_name.c_str(), interpreter.GetDebugger().GetID()); PyRun_SimpleString (run_string.GetData()); @@ -702,7 +707,7 @@ ScriptInterpreterPython::ExecuteInterpreterLoop () bool ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, - ScriptInterpreter::ReturnType return_type, + ScriptInterpreter::ScriptReturnType return_type, void *ret_value) { @@ -783,85 +788,85 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, { switch (return_type) { - case eCharPtr: // "char *" + case eScriptReturnTypeCharPtr: // "char *" { const char format[3] = "s#"; success = PyArg_Parse (py_return, format, (char **) ret_value); break; } - case eCharStrOrNone: // char* or NULL if py_return == Py_None + case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == Py_None { const char format[3] = "z"; success = PyArg_Parse (py_return, format, (char **) ret_value); break; } - case eBool: + case eScriptReturnTypeBool: { const char format[2] = "b"; success = PyArg_Parse (py_return, format, (bool *) ret_value); break; } - case eShortInt: + case eScriptReturnTypeShortInt: { const char format[2] = "h"; success = PyArg_Parse (py_return, format, (short *) ret_value); break; } - case eShortIntUnsigned: + case eScriptReturnTypeShortIntUnsigned: { const char format[2] = "H"; success = PyArg_Parse (py_return, format, (unsigned short *) ret_value); break; } - case eInt: + case eScriptReturnTypeInt: { const char format[2] = "i"; success = PyArg_Parse (py_return, format, (int *) ret_value); break; } - case eIntUnsigned: + case eScriptReturnTypeIntUnsigned: { const char format[2] = "I"; success = PyArg_Parse (py_return, format, (unsigned int *) ret_value); break; } - case eLongInt: + case eScriptReturnTypeLongInt: { const char format[2] = "l"; success = PyArg_Parse (py_return, format, (long *) ret_value); break; } - case eLongIntUnsigned: + case eScriptReturnTypeLongIntUnsigned: { const char format[2] = "k"; success = PyArg_Parse (py_return, format, (unsigned long *) ret_value); break; } - case eLongLong: + case eScriptReturnTypeLongLong: { const char format[2] = "L"; success = PyArg_Parse (py_return, format, (long long *) ret_value); break; } - case eLongLongUnsigned: + case eScriptReturnTypeLongLongUnsigned: { const char format[2] = "K"; success = PyArg_Parse (py_return, format, (unsigned long long *) ret_value); break; } - case eFloat: + case eScriptReturnTypeFloat: { const char format[2] = "f"; success = PyArg_Parse (py_return, format, (float *) ret_value); break; } - case eDouble: + case eScriptReturnTypeDouble: { const char format[2] = "d"; success = PyArg_Parse (py_return, format, (double *) ret_value); break; } - case eChar: + case eScriptReturnTypeChar: { const char format[2] = "c"; success = PyArg_Parse (py_return, format, (char *) ret_value); @@ -1825,6 +1830,98 @@ ScriptInterpreterPython::UpdateSynthProviderInstance (void* implementor) } bool +ScriptInterpreterPython::LoadScriptingModule (const char* pathname, + lldb_private::Error& error) +{ + if (!pathname || !pathname[0]) + { + error.SetErrorString("invalid pathname"); + return false; + } + + if (!g_swig_call_module_init) + { + error.SetErrorString("internal helper function missing"); + return false; + } + + ScriptInterpreterPython *python_interpreter = this; + + lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().GetSP(); + + FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); + + { + Locker py_lock(python_interpreter, tmp_fh); + + FileSpec target_file(pathname, true); + + // TODO: would we want to reject any other value? + if (target_file.GetFileType() == FileSpec::eFileTypeInvalid || + target_file.GetFileType() == FileSpec::eFileTypeUnknown) + { + error.SetErrorString("invalid pathname"); + return false; + } + + const char* directory = target_file.GetDirectory().GetCString(); + std::string basename(target_file.GetFilename().GetCString()); + + // now make sure that Python has "directory" in the search path + StreamString command_stream; + command_stream.Printf("if not (sys.path.__contains__('%s')):\n sys.path.append('%s');\n\n", + directory, + directory); + bool syspath_retval = python_interpreter->ExecuteMultipleLines(command_stream.GetData()); + if (!syspath_retval) + { + error.SetErrorString("Python sys.path handling failed"); + return false; + } + + // strip .py or .pyc extension + ConstString extension = target_file.GetFileNameExtension(); + if (::strcmp(extension.GetCString(), "py") == 0) + basename.resize(basename.length()-3); + else if(::strcmp(extension.GetCString(), "pyc") == 0) + basename.resize(basename.length()-4); + + // check if the module is already import-ed + command_stream.Clear(); + command_stream.Printf("sys.getrefcount(%s)",basename.c_str()); + int refcount = 0; + // this call will fail if the module does not exist (because the parameter to it is not a string + // but an actual Python module object, which is non-existant if the module was not imported before) + if (python_interpreter->ExecuteOneLineWithReturn(command_stream.GetData(), + ScriptInterpreterPython::eScriptReturnTypeInt, &refcount) && refcount > 0) + { + error.SetErrorString("module already imported"); + return false; + } + + // now actually do the import + command_stream.Clear(); + command_stream.Printf("import %s",basename.c_str()); + bool import_retval = python_interpreter->ExecuteOneLine(command_stream.GetData(), NULL); + if (!import_retval) + { + error.SetErrorString("Python import statement failed"); + return false; + } + + // call __lldb_module_init(debugger,dict) + if (!g_swig_call_module_init (basename, + python_interpreter->m_dictionary_name.c_str(), + debugger_sp)) + { + error.SetErrorString("calling __lldb_module_init failed"); + return false; + } + return true; + } +} + +bool ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, const char* args, lldb_private::CommandReturnObject& cmd_retobj, @@ -1886,7 +1983,7 @@ ScriptInterpreterPython::GetDocumentationForItem(const char* item) char* result_ptr = NULL; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully if (ExecuteOneLineWithReturn (command.c_str(), - ScriptInterpreter::eCharStrOrNone, + ScriptInterpreter::eScriptReturnTypeCharStrOrNone, &result_ptr) && result_ptr) { return std::string(result_ptr); @@ -1905,7 +2002,8 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_ini SWIGPythonGetIndexOfChildWithName python_swig_get_index_child, SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue, SWIGPythonUpdateSynthProviderInstance python_swig_update_provider, - SWIGPythonCallCommand python_swig_call_command) + SWIGPythonCallCommand python_swig_call_command, + SWIGPythonCallModuleInit python_swig_call_mod_init) { g_swig_init_callback = python_swig_init_callback; g_swig_breakpoint_callback = python_swig_breakpoint_callback; @@ -1917,6 +2015,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_ini g_swig_cast_to_sbvalue = python_swig_cast_to_sbvalue; g_swig_update_provider = python_swig_update_provider; g_swig_call_command = python_swig_call_command; + g_swig_call_module_init = python_swig_call_mod_init; } void diff --git a/lldb/test/functionalities/command_script/import/Makefile b/lldb/test/functionalities/command_script/import/Makefile new file mode 100644 index 00000000000..9374aef487f --- /dev/null +++ b/lldb/test/functionalities/command_script/import/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +EXE := hello_world + +include $(LEVEL)/Makefile.rules diff --git a/lldb/test/functionalities/command_script/import/TestImport.py b/lldb/test/functionalities/command_script/import/TestImport.py new file mode 100644 index 00000000000..a983e285c39 --- /dev/null +++ b/lldb/test/functionalities/command_script/import/TestImport.py @@ -0,0 +1,71 @@ +"""Test custom import command to import files by path.""" + +import os, sys, time +import unittest2 +import lldb +from lldbtest import * + +class ImportTestCase(TestBase): + + mydir = os.path.join("functionalities", "command_script", "import") + + @python_api_test + def test_import_command(self): + """Import some Python scripts by path and test them""" + self.run_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def run_test(self): + """Import some Python scripts by path and test them.""" + + # This is the function to remove the custom commands in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('command script delete foo2cmd', check=False) + self.runCmd('command script delete foocmd', check=False) + self.runCmd('command script delete foobarcmd', check=False) + self.runCmd('command script delete barcmd', check=False) + self.runCmd('command script delete barothercmd', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("command script import ./foo/foo.py") + self.runCmd("command script import ./foo/foo2.py") + self.runCmd("command script import ./foo/bar/foobar.py") + self.runCmd("command script import ./bar/bar.py") + + self.expect("command script import ./nosuchfile.py", + error=True, startstr='error: module importing failed') + self.expect("command script import ./nosuchfolder/", + error=True, startstr='error: module importing failed') + self.expect("command script import ./foo/foo.py", + error=True, startstr='error: module importing failed') + + self.runCmd("script import dummymodule") + self.expect("command script import ./dummymodule.py", + error=True, startstr='error: module importing failed') + + self.runCmd("command script add -f foo.foo_function foocmd") + self.runCmd("command script add -f foobar.foo_function foobarcmd") + self.runCmd("command script add -f bar.bar_function barcmd") + self.expect("foocmd hello", + substrs = ['foo says', 'hello']) + self.expect("foo2cmd hello", + substrs = ['foo2 says', 'hello']) + self.expect("barcmd hello", + substrs = ['barutil says', 'bar told me', 'hello']) + self.expect("barothercmd hello", + substrs = ['barutil says', 'bar told me', 'hello']) + self.expect("foobarcmd hello", + substrs = ['foobar says', 'hello']) + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/functionalities/command_script/import/bar/bar.py b/lldb/test/functionalities/command_script/import/bar/bar.py new file mode 100644 index 00000000000..269fc935204 --- /dev/null +++ b/lldb/test/functionalities/command_script/import/bar/bar.py @@ -0,0 +1,10 @@ +def bar_function(debugger, args, result, dict): + global UtilityModule + result.Printf(UtilityModule.barutil_function("bar told me " + args)) + return None + +def __lldb_init_module(debugger, session_dict): + global UtilityModule + UtilityModule = __import__("barutil") + debugger.HandleCommand("command script add -f bar.bar_function barothercmd") + return None
\ No newline at end of file diff --git a/lldb/test/functionalities/command_script/import/bar/barutil.py b/lldb/test/functionalities/command_script/import/bar/barutil.py new file mode 100644 index 00000000000..0d3d2eb1b2d --- /dev/null +++ b/lldb/test/functionalities/command_script/import/bar/barutil.py @@ -0,0 +1,2 @@ +def barutil_function(x): + return "barutil says: " + x diff --git a/lldb/test/functionalities/command_script/import/dummymodule.py b/lldb/test/functionalities/command_script/import/dummymodule.py new file mode 100644 index 00000000000..dcc724ec9c2 --- /dev/null +++ b/lldb/test/functionalities/command_script/import/dummymodule.py @@ -0,0 +1,2 @@ +def no_useful_code(foo): + return foo diff --git a/lldb/test/functionalities/command_script/import/foo/bar/foobar.py b/lldb/test/functionalities/command_script/import/foo/bar/foobar.py new file mode 100644 index 00000000000..c76afea903c --- /dev/null +++ b/lldb/test/functionalities/command_script/import/foo/bar/foobar.py @@ -0,0 +1,3 @@ +def foo_function(debugger, args, result, dict): + result.Printf("foobar says " + args) + return None diff --git a/lldb/test/functionalities/command_script/import/foo/foo.py b/lldb/test/functionalities/command_script/import/foo/foo.py new file mode 100644 index 00000000000..852bd83c2ee --- /dev/null +++ b/lldb/test/functionalities/command_script/import/foo/foo.py @@ -0,0 +1,3 @@ +def foo_function(debugger, args, result, dict): + result.Printf("foo says " + args) + return None diff --git a/lldb/test/functionalities/command_script/import/foo/foo2.py b/lldb/test/functionalities/command_script/import/foo/foo2.py new file mode 100644 index 00000000000..120f5b2dd41 --- /dev/null +++ b/lldb/test/functionalities/command_script/import/foo/foo2.py @@ -0,0 +1,7 @@ +def foo2_function(debugger, args, result, dict): + result.Printf("foo2 says " + args) + return None + +def __lldb_init_module(debugger, session_dict): + debugger.HandleCommand("command script add -f foo2.foo2_function foo2cmd") + return None
\ No newline at end of file diff --git a/lldb/test/functionalities/command_script/import/main.c b/lldb/test/functionalities/command_script/import/main.c new file mode 100644 index 00000000000..dffc8c77b04 --- /dev/null +++ b/lldb/test/functionalities/command_script/import/main.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int main(int argc, char const *argv[]) { + printf("Hello world.\n"); // Set break point at this line. + if (argc == 1) + return 0; + + // Waiting to be attached by the debugger, otherwise. + char line[100]; + while (fgets(line, sizeof(line), stdin)) { // Waiting to be attached... + printf("input line=>%s\n", line); + } + + printf("Exiting now\n"); +} |