Python synthetic children:
- you can now define a Python class as a synthetic children producer for a type
the class must adhere to this "interface":
def __init__(self, valobj, dict):
def get_child_at_index(self, index):
def get_child_index(self, name):
then using type synth add -l className typeName
(e.g. type synth add -l fooSynthProvider foo)
(This is still WIP with lots to be added)
A small test case is available also as reference
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@135865 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp
index 97b9314..1124d56 100644
--- a/source/API/SBCommandInterpreter.cpp
+++ b/source/API/SBCommandInterpreter.cpp
@@ -322,6 +322,19 @@
const lldb::ValueObjectSP& valobj_sp
);
+extern "C" void*
+LLDBSwigPythonCreateSyntheticProvider
+(
+ const std::string python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ValueObjectSP& valobj_sp
+);
+
+
+extern "C" uint32_t LLDBSwigPython_CalculateNumChildren (void *implementor);
+extern "C" void* LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx);
+extern "C" int LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name);
+extern "C" lldb::SBValue* LLDBSWIGPython_CastPyObjectToSBValue (void* data);
extern "C" void init_lldb(void);
@@ -334,6 +347,11 @@
g_initialized = true;
ScriptInterpreter::InitializeInterpreter (init_lldb,
LLDBSwigPythonBreakpointCallbackFunction,
- LLDBSwigPythonCallTypeScript);
+ LLDBSwigPythonCallTypeScript,
+ LLDBSwigPythonCreateSyntheticProvider,
+ LLDBSwigPython_CalculateNumChildren,
+ LLDBSwigPython_GetChildAtIndex,
+ LLDBSwigPython_GetIndexOfChildWithName,
+ LLDBSWIGPython_CastPyObjectToSBValue);
}
}
diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp
index 3a8b16c..0e15dbc 100644
--- a/source/Commands/CommandObjectType.cpp
+++ b/source/Commands/CommandObjectType.cpp
@@ -10,6 +10,9 @@
#include "CommandObjectType.h"
// C Includes
+
+#include <ctype.h>
+
// C++ Includes
#include "lldb/Core/ConstString.h"
@@ -418,8 +421,8 @@
// CommandObjectTypeSummaryAdd
//-------------------------------------------------------------------------
-static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
- "def function (valobj,dict):";
+static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
+ "def function (valobj,dict):";
class TypeScriptAddInputReader : public InputReaderEZ
{
@@ -441,7 +444,7 @@
bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
if (!batch_mode)
{
- out_stream->Printf ("%s\n", g_reader_instructions);
+ out_stream->Printf ("%s\n", g_summary_addreader_instructions);
if (data.reader.GetPrompt())
out_stream->Printf ("%s", data.reader.GetPrompt());
out_stream->Flush();
@@ -1016,7 +1019,7 @@
" value = valobj.GetChildMemberWithName('value');\n"
" return 'My value is ' + value.GetValue();\n"
"DONE\n"
- "(lldb)"
+ "(lldb) <-- type further LLDB commands here\n"
);
}
@@ -2404,6 +2407,10 @@
case 'c':
m_expr_paths.push_back(option_arg);
break;
+ case 'l':
+ m_class_name = std::string(option_arg);
+ is_class_based = true;
+ break;
case 'p':
m_skip_pointers = true;
break;
@@ -2425,10 +2432,12 @@
OptionParsingStarting ()
{
m_cascade = true;
- m_expr_paths.clear();
+ m_class_name = "";
m_skip_pointers = false;
m_skip_references = false;
m_category = NULL;
+ m_expr_paths.clear();
+ is_class_based = false;
}
const OptionDefinition*
@@ -2446,9 +2455,13 @@
bool m_cascade;
bool m_skip_references;
bool m_skip_pointers;
+ std::string m_class_name;
+ bool m_input_python;
option_vector m_expr_paths;
const char* m_category;
+ bool is_class_based;
+
typedef option_vector::iterator ExpressionPathsIterator;
};
@@ -2460,7 +2473,114 @@
return &m_options;
}
+ bool
+ Execute_ChildrenList (Args& command, CommandReturnObject &result)
+ {
+ const size_t argc = command.GetArgumentCount();
+
+ if (argc < 1)
+ {
+ result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ if (m_options.m_expr_paths.size() == 0)
+ {
+ result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ SyntheticChildrenSP entry;
+
+ SyntheticFilter* impl = new SyntheticFilter(m_options.m_cascade,
+ m_options.m_skip_pointers,
+ m_options.m_skip_references);
+
+ entry.reset(impl);
+
+ // go through the expression paths
+ CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
+
+ for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
+ impl->AddExpressionPath(*begin);
+
+
+ // now I have a valid provider, let's add it to every type
+
+ lldb::FormatCategorySP category;
+ Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
+
+ for (size_t i = 0; i < argc; i++) {
+ const char* typeA = command.GetArgumentAtIndex(i);
+ ConstString typeCS(typeA);
+ if (typeCS)
+ category->Filter()->Add(typeCS.GetCString(), entry);
+ else
+ {
+ result.AppendError("empty typenames not allowed");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return result.Succeeded();
+ }
+
+ bool
+ Execute_PythonClass (Args& command, CommandReturnObject &result)
+ {
+ const size_t argc = command.GetArgumentCount();
+
+ if (argc < 1)
+ {
+ result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ if (m_options.m_class_name.empty() && !m_options.m_input_python)
+ {
+ result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ SyntheticChildrenSP entry;
+
+ SyntheticScriptProvider* impl = new SyntheticScriptProvider(m_options.m_cascade,
+ m_options.m_skip_pointers,
+ m_options.m_skip_references,
+ m_options.m_class_name);
+
+ entry.reset(impl);
+
+ // now I have a valid provider, let's add it to every type
+
+ lldb::FormatCategorySP category;
+ Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
+
+ for (size_t i = 0; i < argc; i++) {
+ const char* typeA = command.GetArgumentAtIndex(i);
+ ConstString typeCS(typeA);
+ if (typeCS)
+ category->Filter()->Add(typeCS.GetCString(), entry);
+ else
+ {
+ result.AppendError("empty typenames not allowed");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return result.Succeeded();
+ }
+
public:
+
CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) :
CommandObject (interpreter,
"type synth add",
@@ -2486,55 +2606,10 @@
bool
Execute (Args& command, CommandReturnObject &result)
{
- const size_t argc = command.GetArgumentCount();
-
- if (argc < 1)
- {
- result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- if (m_options.m_expr_paths.size() == 0)
- {
- result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- SyntheticFilterSP entry;
-
- entry.reset(new SyntheticFilter(m_options.m_cascade,
- m_options.m_skip_pointers,
- m_options.m_skip_references));
-
- // go through the expression paths
- CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
-
- for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
- entry->AddExpressionPath(*begin);
-
-
- // now I have a valid provider, let's add it to every type
-
- lldb::FormatCategorySP category;
- Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
-
- for (size_t i = 0; i < argc; i++) {
- const char* typeA = command.GetArgumentAtIndex(i);
- ConstString typeCS(typeA);
- if (typeCS)
- category->Filter()->Add(typeCS.GetCString(), entry);
- else
- {
- result.AppendError("empty typenames not allowed");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- }
-
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
+ if (m_options.is_class_based)
+ return Execute_PythonClass(command, result);
+ else
+ return Execute_ChildrenList(command, result);
}
};
@@ -2542,10 +2617,11 @@
CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."},
- { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeName, "Include this expression path in the synthetic view."},
{ LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for pointers-to-type objects."},
{ LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for references-to-type objects."},
{ LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
+ { LLDB_OPT_SET_1, false, "child", 'c', required_argument, NULL, 0, eArgTypeName, "Include this expression path in the synthetic view."},
+ { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypeName, "Use this Python class to produce synthetic children."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index d7538f6..dff2eb0 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -1746,6 +1746,12 @@
return g_format_manager;
}
+void
+Debugger::Formatting::ForceUpdate()
+{
+ GetFormatManager().Changed();
+}
+
bool
Debugger::Formatting::ValueFormats::Get(ValueObject& vobj, ValueFormat::SharedPointer &entry)
{
@@ -1796,7 +1802,7 @@
}
bool
Debugger::Formatting::GetSyntheticFilter(ValueObject& vobj,
- lldb::SyntheticFilterSP& entry)
+ lldb::SyntheticChildrenSP& entry)
{
return GetFormatManager().Get(vobj, entry);
}
diff --git a/source/Core/FormatClasses.cpp b/source/Core/FormatClasses.cpp
index f301a7b..9a232ae 100644
--- a/source/Core/FormatClasses.cpp
+++ b/source/Core/FormatClasses.cpp
@@ -21,8 +21,10 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FormatClasses.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
@@ -156,3 +158,25 @@
sstr.Printf("}");
return sstr.GetString();
}
+
+SyntheticScriptProvider::FrontEnd::FrontEnd(std::string pclass,
+ lldb::ValueObjectSP be) :
+SyntheticChildrenFrontEnd(be),
+m_python_class(pclass)
+{
+ m_interpreter = be->GetUpdatePoint().GetTarget()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ m_wrapper = (PyObject*)m_interpreter->CreateSyntheticScriptedProvider(m_python_class, m_backend);
+}
+
+std::string
+SyntheticScriptProvider::GetDescription()
+{
+ StreamString sstr;
+ sstr.Printf("%s%s%s Python class: %s",
+ m_cascades ? "" : " (not cascading)",
+ m_skip_pointers ? " (skip pointers)" : "",
+ m_skip_references ? " (skip references)" : "",
+ m_python_class.c_str());
+
+ return sstr.GetString();
+}
\ No newline at end of file
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
index 76deaf9..a98d0be 100644
--- a/source/Core/ValueObject.cpp
+++ b/source/Core/ValueObject.cpp
@@ -219,6 +219,8 @@
m_last_value_format.reset(/*(ValueFormat*)NULL*/);
if (m_last_synthetic_filter.get())
m_last_synthetic_filter.reset(/*(SyntheticFilter*)NULL*/);
+
+ m_synthetic_value = NULL;
Debugger::Formatting::ValueFormats::Get(*this, m_last_value_format);
Debugger::Formatting::GetSummaryFormat(*this, m_last_summary_format);
@@ -1493,7 +1495,8 @@
if (m_last_synthetic_filter.get() == NULL)
return;
- m_synthetic_value = new ValueObjectSyntheticFilter(*this, m_last_synthetic_filter);
+ if (m_synthetic_value == NULL)
+ m_synthetic_value = new ValueObjectSynthetic(*this, m_last_synthetic_filter);
}
diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp
index 4756b1c..d7d00b6 100644
--- a/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/source/Core/ValueObjectSyntheticFilter.cpp
@@ -35,23 +35,25 @@
using namespace lldb_private;
-ValueObjectSyntheticFilter::ValueObjectSyntheticFilter (ValueObject &parent, lldb::SyntheticFilterSP filter) :
+ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) :
ValueObject(parent),
m_address (),
m_type_sp(),
-m_use_synthetic (lldb::eUseSyntheticFilter),
- m_synth_filter(filter)
+ m_use_synthetic (lldb::eUseSyntheticFilter),
+ m_synth_filter(filter->GetFrontEnd(parent.GetSP())),
+ m_children_byindex(),
+ m_name_toindex()
{
SetName (parent.GetName().AsCString());
}
-ValueObjectSyntheticFilter::~ValueObjectSyntheticFilter()
+ValueObjectSynthetic::~ValueObjectSynthetic()
{
m_owning_valobj_sp.reset();
}
lldb::clang_type_t
-ValueObjectSyntheticFilter::GetClangType ()
+ValueObjectSynthetic::GetClangType ()
{
if (m_type_sp)
return m_value.GetClangType();
@@ -60,7 +62,7 @@
}
ConstString
-ValueObjectSyntheticFilter::GetTypeName()
+ValueObjectSynthetic::GetTypeName()
{
const bool success = UpdateValueIfNeeded();
if (success && m_type_sp)
@@ -70,22 +72,13 @@
}
uint32_t
-ValueObjectSyntheticFilter::CalculateNumChildren()
+ValueObjectSynthetic::CalculateNumChildren()
{
- const bool success = UpdateValueIfNeeded();
- if (!success)
- return 0;
- if (m_synth_filter.get())
- return m_synth_filter->GetCount();
- return 0;
- if (success && m_type_sp)
- return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true);
- else
- return m_parent->GetNumChildren();
+ return m_synth_filter->CalculateNumChildren();
}
clang::ASTContext *
-ValueObjectSyntheticFilter::GetClangAST ()
+ValueObjectSynthetic::GetClangAST ()
{
const bool success = UpdateValueIfNeeded(false);
if (success && m_type_sp)
@@ -95,7 +88,7 @@
}
size_t
-ValueObjectSyntheticFilter::GetByteSize()
+ValueObjectSynthetic::GetByteSize()
{
const bool success = UpdateValueIfNeeded();
if (success && m_type_sp)
@@ -105,13 +98,13 @@
}
lldb::ValueType
-ValueObjectSyntheticFilter::GetValueType() const
+ValueObjectSynthetic::GetValueType() const
{
return m_parent->GetValueType();
}
bool
-ValueObjectSyntheticFilter::UpdateValue ()
+ValueObjectSynthetic::UpdateValue ()
{
SetValueIsValid (false);
m_error.Clear();
@@ -124,46 +117,61 @@
return false;
}
+ m_children_byindex.clear();
+ m_name_toindex.clear();
+
SetValueIsValid(true);
return true;
}
lldb::ValueObjectSP
-ValueObjectSyntheticFilter::GetChildAtIndex (uint32_t idx, bool can_create)
+ValueObjectSynthetic::GetChildAtIndex (uint32_t idx, bool can_create)
{
- if (!m_synth_filter.get())
- return lldb::ValueObjectSP();
- if (idx >= m_synth_filter->GetCount())
- return lldb::ValueObjectSP();
- return m_parent->GetSyntheticExpressionPathChild(m_synth_filter->GetExpressionPathAtIndex(idx).c_str(), can_create);
+ ByIndexIterator iter = m_children_byindex.find(idx);
+
+ if (iter == m_children_byindex.end())
+ {
+ if (can_create)
+ {
+ lldb::ValueObjectSP synth_guy = m_synth_filter->GetChildAtIndex (idx, can_create);
+ m_children_byindex[idx]= synth_guy;
+ return synth_guy;
+ }
+ else
+ return lldb::ValueObjectSP();
+ }
+ else
+ return iter->second;
}
lldb::ValueObjectSP
-ValueObjectSyntheticFilter::GetChildMemberWithName (const ConstString &name, bool can_create)
+ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_create)
{
- if (!m_synth_filter.get())
+
+ uint32_t index = GetIndexOfChildWithName(name);
+
+ if (index == UINT32_MAX)
return lldb::ValueObjectSP();
- uint32_t idx = GetIndexOfChildWithName(name);
- if (idx >= m_synth_filter->GetCount())
- return lldb::ValueObjectSP();
- return m_parent->GetSyntheticExpressionPathChild(name.GetCString(), can_create);
+
+ return GetChildAtIndex(index, can_create);
}
uint32_t
-ValueObjectSyntheticFilter::GetIndexOfChildWithName (const ConstString &name)
+ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name)
{
- const char* name_cstr = name.GetCString();
- for (int i = 0; i < m_synth_filter->GetCount(); i++)
+ NameToIndexIterator iter = m_name_toindex.find(name.GetCString());
+
+ if (iter == m_name_toindex.end())
{
- const char* expr_cstr = m_synth_filter->GetExpressionPathAtIndex(i).c_str();
- if (::strcmp(name_cstr, expr_cstr))
- return i;
+ uint32_t index = m_synth_filter->GetIndexOfChildWithName (name);
+ m_name_toindex[name.GetCString()] = index;
+ return index;
}
- return UINT32_MAX;
+ return iter->second;
}
bool
-ValueObjectSyntheticFilter::IsInScope ()
+ValueObjectSynthetic::IsInScope ()
{
return m_parent->IsInScope();
}
diff --git a/source/Interpreter/CommandObjectScript.cpp b/source/Interpreter/CommandObjectScript.cpp
index 70a4ead..e586497 100644
--- a/source/Interpreter/CommandObjectScript.cpp
+++ b/source/Interpreter/CommandObjectScript.cpp
@@ -13,6 +13,9 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+
+#include "lldb/Core/Debugger.h"
+
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -54,6 +57,8 @@
result.SetStatus (eReturnStatusFailed);
}
+ Debugger::Formatting::ForceUpdate(); // script might change Python code we use for formatting.. make sure we keep up to date with it
+
if (command == NULL || command[0] == '\0') {
script_interpreter->ExecuteInterpreterLoop ();
result.SetStatus (eReturnStatusSuccessFinishNoResult);
diff --git a/source/Interpreter/ScriptInterpreter.cpp b/source/Interpreter/ScriptInterpreter.cpp
index 294aeec..27c7bad 100644
--- a/source/Interpreter/ScriptInterpreter.cpp
+++ b/source/Interpreter/ScriptInterpreter.cpp
@@ -93,11 +93,21 @@
void
ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
SWIGBreakpointCallbackFunction python_swig_breakpoint_callback,
- SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback)
+ SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback,
+ SWIGPythonCreateSyntheticProvider python_swig_synthetic_script,
+ SWIGPythonCalculateNumChildren python_swig_calc_children,
+ SWIGPythonGetChildAtIndex python_swig_get_child_index,
+ SWIGPythonGetIndexOfChildWithName python_swig_get_index_child,
+ SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue)
{
ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback,
python_swig_breakpoint_callback,
- python_swig_typescript_callback);
+ python_swig_typescript_callback,
+ python_swig_synthetic_script,
+ python_swig_calc_children,
+ python_swig_get_child_index,
+ python_swig_get_index_child,
+ python_swig_cast_to_sbvalue);
}
void
diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
index 57a5929..03eadc6 100644
--- a/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/source/Interpreter/ScriptInterpreterPython.cpp
@@ -35,7 +35,11 @@
static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL;
static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL;
static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL;
-
+static ScriptInterpreter::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = NULL;
+static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children = NULL;
+static ScriptInterpreter::SWIGPythonGetChildAtIndex g_swig_get_child_index = NULL;
+static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = NULL;
+static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = NULL;
static int
_check_and_flush (FILE *stream)
@@ -1245,6 +1249,55 @@
return true;
}
+void*
+ScriptInterpreterPython::CreateSyntheticScriptedProvider (std::string class_name,
+ lldb::ValueObjectSP valobj)
+{
+ if (class_name.empty())
+ return NULL;
+
+ if (!valobj.get())
+ return NULL;
+
+ Target *target = valobj->GetUpdatePoint().GetTarget();
+
+ if (!target)
+ return NULL;
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
+
+ if (!script_interpreter)
+ return NULL;
+
+ void* ret_val;
+
+ FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
+ if (CurrentThreadHasPythonLock())
+ {
+ python_interpreter->EnterSession ();
+ ret_val = g_swig_synthetic_script (class_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ valobj);
+ python_interpreter->LeaveSession ();
+ }
+ else
+ {
+ while (!GetPythonLock (1))
+ fprintf (tmp_fh,
+ "Python interpreter locked on another thread; waiting to acquire lock...\n");
+ python_interpreter->EnterSession ();
+ ret_val = g_swig_synthetic_script (class_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ valobj);
+ python_interpreter->LeaveSession ();
+ ReleasePythonLock ();
+ }
+
+ return ret_val;
+}
+
bool
ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, StringList &output)
{
@@ -1565,15 +1618,161 @@
return NULL;
}
+uint32_t
+ScriptInterpreterPython::CalculateNumChildren (void *implementor)
+{
+ if (!implementor)
+ return 0;
+
+ if (!g_swig_calc_children)
+ return 0;
+
+ ScriptInterpreterPython *python_interpreter = this;
+
+ uint32_t ret_val = 0;
+
+ FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
+ if (CurrentThreadHasPythonLock())
+ {
+ python_interpreter->EnterSession ();
+ ret_val = g_swig_calc_children (implementor);
+ python_interpreter->LeaveSession ();
+ }
+ else
+ {
+ while (!GetPythonLock (1))
+ fprintf (tmp_fh,
+ "Python interpreter locked on another thread; waiting to acquire lock...\n");
+ python_interpreter->EnterSession ();
+ ret_val = g_swig_calc_children (implementor);
+ python_interpreter->LeaveSession ();
+ ReleasePythonLock ();
+ }
+
+ return ret_val;
+}
+
+void*
+ScriptInterpreterPython::GetChildAtIndex (void *implementor, uint32_t idx)
+{
+ if (!implementor)
+ return 0;
+
+ if (!g_swig_get_child_index)
+ return 0;
+
+ ScriptInterpreterPython *python_interpreter = this;
+
+ void* ret_val = NULL;
+
+ FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
+ if (CurrentThreadHasPythonLock())
+ {
+ python_interpreter->EnterSession ();
+ ret_val = g_swig_get_child_index (implementor,idx);
+ python_interpreter->LeaveSession ();
+ }
+ else
+ {
+ while (!GetPythonLock (1))
+ fprintf (tmp_fh,
+ "Python interpreter locked on another thread; waiting to acquire lock...\n");
+ python_interpreter->EnterSession ();
+ ret_val = g_swig_get_child_index (implementor,idx);
+ python_interpreter->LeaveSession ();
+ ReleasePythonLock ();
+ }
+
+ return ret_val;
+}
+
+int
+ScriptInterpreterPython::GetIndexOfChildWithName (void *implementor, const char* child_name)
+{
+ if (!implementor)
+ return UINT32_MAX;
+
+ if (!g_swig_get_index_child)
+ return UINT32_MAX;
+
+ ScriptInterpreterPython *python_interpreter = this;
+
+ int ret_val = UINT32_MAX;
+
+ FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
+ if (CurrentThreadHasPythonLock())
+ {
+ python_interpreter->EnterSession ();
+ ret_val = g_swig_get_index_child (implementor, child_name);
+ python_interpreter->LeaveSession ();
+ }
+ else
+ {
+ while (!GetPythonLock (1))
+ fprintf (tmp_fh,
+ "Python interpreter locked on another thread; waiting to acquire lock...\n");
+ python_interpreter->EnterSession ();
+ ret_val = g_swig_get_index_child (implementor, child_name);
+ python_interpreter->LeaveSession ();
+ ReleasePythonLock ();
+ }
+
+ return ret_val;
+}
+
+lldb::SBValue*
+ScriptInterpreterPython::CastPyObjectToSBValue (void* data)
+{
+ if (!data)
+ return NULL;
+
+ if (!g_swig_cast_to_sbvalue)
+ return NULL;
+
+ ScriptInterpreterPython *python_interpreter = this;
+
+ lldb::SBValue* ret_val = NULL;
+
+ FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
+ if (CurrentThreadHasPythonLock())
+ {
+ python_interpreter->EnterSession ();
+ ret_val = g_swig_cast_to_sbvalue (data);
+ python_interpreter->LeaveSession ();
+ }
+ else
+ {
+ while (!GetPythonLock (1))
+ fprintf (tmp_fh,
+ "Python interpreter locked on another thread; waiting to acquire lock...\n");
+ python_interpreter->EnterSession ();
+ ret_val = g_swig_cast_to_sbvalue (data);
+ python_interpreter->LeaveSession ();
+ ReleasePythonLock ();
+ }
+
+ return ret_val;
+}
+
void
ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
SWIGBreakpointCallbackFunction python_swig_breakpoint_callback,
- SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback)
+ SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback,
+ SWIGPythonCreateSyntheticProvider python_swig_synthetic_script,
+ SWIGPythonCalculateNumChildren python_swig_calc_children,
+ SWIGPythonGetChildAtIndex python_swig_get_child_index,
+ SWIGPythonGetIndexOfChildWithName python_swig_get_index_child,
+ SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue)
{
g_swig_init_callback = python_swig_init_callback;
g_swig_breakpoint_callback = python_swig_breakpoint_callback;
g_swig_typescript_callback = python_swig_typescript_callback;
+ g_swig_synthetic_script = python_swig_synthetic_script;
+ g_swig_calc_children = python_swig_calc_children;
+ g_swig_get_child_index = python_swig_get_child_index;
+ g_swig_get_index_child = python_swig_get_index_child;
+ g_swig_cast_to_sbvalue = python_swig_cast_to_sbvalue;
}
void