[Lldb-commits] [lldb] r142283 - in /lldb/trunk: include/lldb/Host/ include/lldb/Interpreter/ scripts/Python/ source/API/ source/Commands/ source/Host/common/ source/Interpreter/ test/functionalities/command_script/import/ test/functionalities/command_script/import/bar/ test/functionalities/command_script/import/foo/ test/functionalities/command_script/import/foo/bar/

Enrico Granata granata.enrico at gmail.com
Mon Oct 17 14:45:27 PDT 2011


Author: enrico
Date: Mon Oct 17 16:45:27 2011
New Revision: 142283

URL: http://llvm.org/viewvc/llvm-project?rev=142283&view=rev
Log:
this patch introduces a new command script import command which takes as input a filename for a Python script and imports the module contained in that file. the containing directory is added to the Python path such that dependencies are honored. also, the module may contain an __lldb_init_module(debugger,dict) function, which gets called after importing, and which can somehow initialize the module's interaction with lldb

Added:
    lldb/trunk/test/functionalities/command_script/import/
    lldb/trunk/test/functionalities/command_script/import/Makefile
    lldb/trunk/test/functionalities/command_script/import/TestImport.py
    lldb/trunk/test/functionalities/command_script/import/bar/
    lldb/trunk/test/functionalities/command_script/import/bar/bar.py
    lldb/trunk/test/functionalities/command_script/import/bar/barutil.py
    lldb/trunk/test/functionalities/command_script/import/dummymodule.py
    lldb/trunk/test/functionalities/command_script/import/foo/
    lldb/trunk/test/functionalities/command_script/import/foo/bar/
    lldb/trunk/test/functionalities/command_script/import/foo/bar/foobar.py
    lldb/trunk/test/functionalities/command_script/import/foo/foo.py
    lldb/trunk/test/functionalities/command_script/import/foo/foo2.py
    lldb/trunk/test/functionalities/command_script/import/main.c
Modified:
    lldb/trunk/include/lldb/Host/FileSpec.h
    lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
    lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h
    lldb/trunk/scripts/Python/python-wrapper.swig
    lldb/trunk/source/API/SBCommandInterpreter.cpp
    lldb/trunk/source/Commands/CommandObjectCommands.cpp
    lldb/trunk/source/Host/common/FileSpec.cpp
    lldb/trunk/source/Interpreter/ScriptInterpreter.cpp
    lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp

Modified: lldb/trunk/include/lldb/Host/FileSpec.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/FileSpec.h?rev=142283&r1=142282&r2=142283&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/FileSpec.h (original)
+++ lldb/trunk/include/lldb/Host/FileSpec.h Mon Oct 17 16:45:27 2011
@@ -357,6 +357,34 @@
     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;
 

Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h?rev=142283&r1=142282&r2=142283&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h Mon Oct 17 16:45:27 2011
@@ -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 @@
                                                                      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 @@
     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 @@
     }
         
     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 @@
                            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 ();

Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h?rev=142283&r1=142282&r2=142283&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h (original)
+++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h Mon Oct 17 16:45:27 2011
@@ -40,7 +40,7 @@
 
     bool
     ExecuteOneLineWithReturn (const char *in_string, 
-                              ScriptInterpreter::ReturnType return_type,
+                              ScriptInterpreter::ScriptReturnType return_type,
                               void *ret_value);
 
     bool
@@ -108,7 +108,11 @@
                               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 @@
                            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:
 

Modified: lldb/trunk/scripts/Python/python-wrapper.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/python-wrapper.swig?rev=142283&r1=142282&r2=142283&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/python-wrapper.swig (original)
+++ lldb/trunk/scripts/Python/python-wrapper.swig Mon Oct 17 16:45:27 2011
@@ -676,7 +676,89 @@
         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;
 }
 
 %}

Modified: lldb/trunk/source/API/SBCommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBCommandInterpreter.cpp?rev=142283&r1=142282&r2=142283&view=diff
==============================================================================
--- lldb/trunk/source/API/SBCommandInterpreter.cpp (original)
+++ lldb/trunk/source/API/SBCommandInterpreter.cpp Mon Oct 17 16:45:27 2011
@@ -358,6 +358,13 @@
     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 @@
                                                   LLDBSwigPython_GetIndexOfChildWithName,
                                                   LLDBSWIGPython_CastPyObjectToSBValue,
                                                   LLDBSwigPython_UpdateSynthProviderInstance,
-                                                  LLDBSwigPythonCallCommand);
+                                                  LLDBSwigPythonCallCommand,
+                                                  LLDBSwigPythonCallModuleInit);
     }
 }

Modified: lldb/trunk/source/Commands/CommandObjectCommands.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectCommands.cpp?rev=142283&r1=142282&r2=142283&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectCommands.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectCommands.cpp Mon Oct 17 16:45:27 2011
@@ -1220,6 +1220,78 @@
     
 };
 
+//-------------------------------------------------------------------------
+// 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 @@
         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 ()

Modified: lldb/trunk/source/Host/common/FileSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/FileSpec.cpp?rev=142283&r1=142282&r2=142283&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/FileSpec.cpp (original)
+++ lldb/trunk/source/Host/common/FileSpec.cpp Mon Oct 17 16:45:27 2011
@@ -699,10 +699,39 @@
             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

Modified: lldb/trunk/source/Interpreter/ScriptInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreter.cpp?rev=142283&r1=142282&r2=142283&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreter.cpp Mon Oct 17 16:45:27 2011
@@ -100,7 +100,8 @@
                                           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 @@
                                                     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

Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=142283&r1=142282&r2=142283&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Mon Oct 17 16:45:27 2011
@@ -42,6 +42,7 @@
 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 @@
     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 @@
 
 bool
 ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
-                                                   ScriptInterpreter::ReturnType return_type,
+                                                   ScriptInterpreter::ScriptReturnType return_type,
                                                    void *ret_value)
 {
 
@@ -783,85 +788,85 @@
         {
             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 @@
 }
 
 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 @@
     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 @@
                                                 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 @@
     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

Added: lldb/trunk/test/functionalities/command_script/import/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/command_script/import/Makefile?rev=142283&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/command_script/import/Makefile (added)
+++ lldb/trunk/test/functionalities/command_script/import/Makefile Mon Oct 17 16:45:27 2011
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+EXE := hello_world
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/functionalities/command_script/import/TestImport.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/command_script/import/TestImport.py?rev=142283&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/command_script/import/TestImport.py (added)
+++ lldb/trunk/test/functionalities/command_script/import/TestImport.py Mon Oct 17 16:45:27 2011
@@ -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()

Added: lldb/trunk/test/functionalities/command_script/import/bar/bar.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/command_script/import/bar/bar.py?rev=142283&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/command_script/import/bar/bar.py (added)
+++ lldb/trunk/test/functionalities/command_script/import/bar/bar.py Mon Oct 17 16:45:27 2011
@@ -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

Added: lldb/trunk/test/functionalities/command_script/import/bar/barutil.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/command_script/import/bar/barutil.py?rev=142283&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/command_script/import/bar/barutil.py (added)
+++ lldb/trunk/test/functionalities/command_script/import/bar/barutil.py Mon Oct 17 16:45:27 2011
@@ -0,0 +1,2 @@
+def barutil_function(x):
+	return "barutil says: " + x

Added: lldb/trunk/test/functionalities/command_script/import/dummymodule.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/command_script/import/dummymodule.py?rev=142283&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/command_script/import/dummymodule.py (added)
+++ lldb/trunk/test/functionalities/command_script/import/dummymodule.py Mon Oct 17 16:45:27 2011
@@ -0,0 +1,2 @@
+def no_useful_code(foo):
+	return foo

Added: lldb/trunk/test/functionalities/command_script/import/foo/bar/foobar.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/command_script/import/foo/bar/foobar.py?rev=142283&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/command_script/import/foo/bar/foobar.py (added)
+++ lldb/trunk/test/functionalities/command_script/import/foo/bar/foobar.py Mon Oct 17 16:45:27 2011
@@ -0,0 +1,3 @@
+def foo_function(debugger, args, result, dict):
+	result.Printf("foobar says " + args)
+	return None

Added: lldb/trunk/test/functionalities/command_script/import/foo/foo.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/command_script/import/foo/foo.py?rev=142283&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/command_script/import/foo/foo.py (added)
+++ lldb/trunk/test/functionalities/command_script/import/foo/foo.py Mon Oct 17 16:45:27 2011
@@ -0,0 +1,3 @@
+def foo_function(debugger, args, result, dict):
+	result.Printf("foo says " + args)
+	return None

Added: lldb/trunk/test/functionalities/command_script/import/foo/foo2.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/command_script/import/foo/foo2.py?rev=142283&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/command_script/import/foo/foo2.py (added)
+++ lldb/trunk/test/functionalities/command_script/import/foo/foo2.py Mon Oct 17 16:45:27 2011
@@ -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

Added: lldb/trunk/test/functionalities/command_script/import/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/command_script/import/main.c?rev=142283&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/command_script/import/main.c (added)
+++ lldb/trunk/test/functionalities/command_script/import/main.c Mon Oct 17 16:45:27 2011
@@ -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");
+}





More information about the lldb-commits mailing list