[Lldb-commits] [lldb] r135865 - in /lldb/trunk: include/lldb/ include/lldb/API/ include/lldb/Core/ include/lldb/Interpreter/ include/lldb/Utility/ lldb.xcodeproj/ scripts/ source/API/ source/Commands/ source/Core/ source/Interpreter/ test/functionalities/data-formatter/data-formatter-python-synth/

Enrico Granata granata.enrico at gmail.com
Sat Jul 23 17:14:56 PDT 2011


Author: enrico
Date: Sat Jul 23 19:14:56 2011
New Revision: 135865

URL: http://llvm.org/viewvc/llvm-project?rev=135865&view=rev
Log:
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

Added:
    lldb/trunk/include/lldb/Utility/PythonPointer.h
    lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/
    lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/Makefile
    lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py
    lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py
    lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp
Modified:
    lldb/trunk/include/lldb/API/SBValue.h
    lldb/trunk/include/lldb/Core/Debugger.h
    lldb/trunk/include/lldb/Core/FormatClasses.h
    lldb/trunk/include/lldb/Core/FormatManager.h
    lldb/trunk/include/lldb/Core/ValueObject.h
    lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h
    lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
    lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h
    lldb/trunk/include/lldb/lldb-forward-rtti.h
    lldb/trunk/include/lldb/lldb-forward.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/scripts/lldb.swig
    lldb/trunk/source/API/SBCommandInterpreter.cpp
    lldb/trunk/source/Commands/CommandObjectType.cpp
    lldb/trunk/source/Core/Debugger.cpp
    lldb/trunk/source/Core/FormatClasses.cpp
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp
    lldb/trunk/source/Interpreter/CommandObjectScript.cpp
    lldb/trunk/source/Interpreter/ScriptInterpreter.cpp
    lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp

Modified: lldb/trunk/include/lldb/API/SBValue.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBValue.h?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBValue.h (original)
+++ lldb/trunk/include/lldb/API/SBValue.h Sat Jul 23 19:14:56 2011
@@ -14,6 +14,10 @@
 
 #include <stdio.h>
 
+#ifndef SWIG
+class lldb_private::SyntheticScriptProvider;
+#endif
+
 namespace lldb {
 
 class SBValue
@@ -205,7 +209,9 @@
     friend class SBFrame;
 
 #ifndef SWIG
-
+    // need this to decapsulate the SP from here
+    friend class lldb_private::SyntheticScriptProvider;
+    
     // Mimic shared pointer...
     lldb_private::ValueObject *
     get() const;

Modified: lldb/trunk/include/lldb/Core/Debugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Debugger.h (original)
+++ lldb/trunk/include/lldb/Core/Debugger.h Sat Jul 23 19:14:56 2011
@@ -477,6 +477,11 @@
     class Formatting
     {
     public:
+        
+        // use this call to force the FM to consider itself updated even when there is no apparent reason for that
+        static void
+        ForceUpdate();
+        
         class ValueFormats
         {
         public:
@@ -507,7 +512,7 @@
                          lldb::SummaryFormatSP& entry);
         static bool
         GetSyntheticFilter(ValueObject& vobj,
-                           lldb::SyntheticFilterSP& entry);
+                           lldb::SyntheticChildrenSP& entry);
         
         class NamedSummaryFormats
         {

Modified: lldb/trunk/include/lldb/Core/FormatClasses.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatClasses.h?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatClasses.h (original)
+++ lldb/trunk/include/lldb/Core/FormatClasses.h Sat Jul 23 19:14:56 2011
@@ -12,6 +12,12 @@
 
 // C Includes
 
+#if defined (__APPLE__)
+#include <Python/Python.h>
+#else
+#include <Python.h>
+#endif
+
 #include <stdint.h>
 #include <unistd.h>
 
@@ -25,6 +31,7 @@
 #include "lldb/lldb-public.h"
 #include "lldb/lldb-enumerations.h"
 
+#include "lldb/API/SBValue.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Interpreter/ScriptInterpreterPython.h"
 #include "lldb/Symbol/SymbolContext.h"
@@ -82,19 +89,90 @@
     
 };
     
-struct SyntheticFilter
+class SyntheticChildrenFrontEnd
 {
+protected:
+    lldb::ValueObjectSP m_backend;
+public:
+    
+    SyntheticChildrenFrontEnd(lldb::ValueObjectSP be) :
+    m_backend(be)
+    {}
+    
+    virtual
+    ~SyntheticChildrenFrontEnd()
+    {
+    }
+    
+    virtual uint32_t
+    CalculateNumChildren() = 0;
+    
+    virtual lldb::ValueObjectSP
+    GetChildAtIndex (uint32_t idx, bool can_create) = 0;
+    
+    virtual uint32_t
+    GetIndexOfChildWithName (const ConstString &name) = 0;
+    
+    typedef lldb::SharedPtr<SyntheticChildrenFrontEnd>::Type SharedPointer;
+
+};
+    
+class SyntheticChildren
+{
+public:
     bool m_cascades;
     bool m_skip_pointers;
     bool m_skip_references;
-    std::vector<std::string> m_expression_paths;
+public:
+    SyntheticChildren(bool casc = false,
+                      bool skipptr = false,
+                      bool skipref = false) :
+    m_cascades(casc),
+    m_skip_pointers(skipptr),
+    m_skip_references(skipref)
+    {
+    }
     
+    virtual
+    ~SyntheticChildren()
+    {
+    }
+    
+    bool
+    Cascades() const
+    {
+        return m_cascades;
+    }
+    bool
+    SkipsPointers() const
+    {
+        return m_skip_pointers;
+    }
+    bool
+    SkipsReferences() const
+    {
+        return m_skip_references;
+    }
+    
+    virtual std::string
+    GetDescription() = 0;
+    
+    virtual SyntheticChildrenFrontEnd::SharedPointer
+    GetFrontEnd(lldb::ValueObjectSP backend) = 0;
+    
+    typedef lldb::SharedPtr<SyntheticChildren>::Type SharedPointer;
+    typedef bool(*SyntheticChildrenCallback)(void*, const char*, const SyntheticChildren::SharedPointer&);
+    
+};
+
+class SyntheticFilter : public SyntheticChildren
+{
+    std::vector<std::string> m_expression_paths;
+public:
     SyntheticFilter(bool casc = false,
                     bool skipptr = false,
                     bool skipref = false) :
-    m_cascades(casc),
-    m_skip_pointers(skipptr),
-    m_skip_references(skipref),
+    SyntheticChildren(casc, skipptr, skipref),
     m_expression_paths()
     {
     }
@@ -129,10 +207,149 @@
     std::string
     GetDescription();
     
-    typedef lldb::SharedPtr<SyntheticFilter>::Type SharedPointer;
-    typedef bool(*SyntheticFilterCallback)(void*, const char*, const SyntheticFilter::SharedPointer&);
+    class FrontEnd : public SyntheticChildrenFrontEnd
+    {
+    private:
+        SyntheticFilter* filter;
+    public:
+        
+        FrontEnd(SyntheticFilter* flt,
+                 lldb::ValueObjectSP be) :
+        SyntheticChildrenFrontEnd(be),
+        filter(flt)
+        {}
+        
+        virtual
+        ~FrontEnd()
+        {
+        }
+        
+        virtual uint32_t
+        CalculateNumChildren()
+        {
+            return filter->GetCount();
+        }
+        
+        virtual lldb::ValueObjectSP
+        GetChildAtIndex (uint32_t idx, bool can_create)
+        {
+            if (idx >= filter->GetCount())
+                return lldb::ValueObjectSP();
+            return m_backend->GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx).c_str(), can_create);
+        }
+        
+        virtual uint32_t
+        GetIndexOfChildWithName (const ConstString &name)
+        {
+            const char* name_cstr = name.GetCString();
+            for (int i = 0; i < filter->GetCount(); i++)
+            {
+                const char* expr_cstr = filter->GetExpressionPathAtIndex(i).c_str();
+                if (::strcmp(name_cstr, expr_cstr))
+                    return i;
+            }
+            return UINT32_MAX;
+        }
+        
+        typedef lldb::SharedPtr<SyntheticChildrenFrontEnd>::Type SharedPointer;
+        
+    };
+    
+    virtual SyntheticChildrenFrontEnd::SharedPointer
+    GetFrontEnd(lldb::ValueObjectSP backend)
+    {
+        return SyntheticChildrenFrontEnd::SharedPointer(new FrontEnd(this, backend));
+    }
+    
 };
 
+class SyntheticScriptProvider : public SyntheticChildren
+{
+    std::string m_python_class;
+public:
+    SyntheticScriptProvider(bool casc = false,
+                            bool skipptr = false,
+                            bool skipref = false,
+                            std::string pclass = "") :
+    SyntheticChildren(casc, skipptr, skipref),
+    m_python_class(pclass)
+    {
+    }
+    
+    
+    std::string
+    GetPythonClassName() { return m_python_class; }
+    
+    std::string
+    GetDescription();
+    
+    class FrontEnd : public SyntheticChildrenFrontEnd
+    {
+    private:
+        std::string m_python_class;
+        PyObject* m_wrapper;
+        ScriptInterpreter *m_interpreter;
+    public:
+        
+        FrontEnd(std::string pclass,
+                 lldb::ValueObjectSP be);
+        
+        virtual
+        ~FrontEnd()
+        {
+            Py_XDECREF(m_wrapper);
+        }
+        
+        virtual uint32_t
+        CalculateNumChildren()
+        {
+            if (m_wrapper == NULL)
+                return 0;
+            return m_interpreter->CalculateNumChildren(m_wrapper);
+        }
+        
+        virtual lldb::ValueObjectSP
+        GetChildAtIndex (uint32_t idx, bool can_create)
+        {
+            if (m_wrapper == NULL)
+                return lldb::ValueObjectSP();
+            
+            PyObject* py_return = (PyObject*)m_interpreter->GetChildAtIndex(m_wrapper, idx);
+            if (py_return == NULL || py_return == Py_None)
+            {
+                Py_XDECREF(py_return);
+                return lldb::ValueObjectSP();
+            }
+            
+            lldb::SBValue *sb_ptr = m_interpreter->CastPyObjectToSBValue(py_return);
+            
+            if (py_return == NULL)
+                return lldb::ValueObjectSP();
+            
+            return sb_ptr->m_opaque_sp;
+        }
+                
+        virtual uint32_t
+        GetIndexOfChildWithName (const ConstString &name)
+        {
+            if (m_wrapper == NULL)
+                return UINT32_MAX;
+            return m_interpreter->GetIndexOfChildWithName(m_wrapper, name.GetCString());
+        }
+        
+        typedef lldb::SharedPtr<SyntheticChildrenFrontEnd>::Type SharedPointer;
+        
+    };
+    
+    virtual SyntheticChildrenFrontEnd::SharedPointer
+    GetFrontEnd(lldb::ValueObjectSP backend)
+    {
+        return SyntheticChildrenFrontEnd::SharedPointer(new FrontEnd(m_python_class, backend));
+    }
+    
+};
+
+
 struct SummaryFormat
 {
     bool m_cascades;

Modified: lldb/trunk/include/lldb/Core/FormatManager.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatManager.h (original)
+++ lldb/trunk/include/lldb/Core/FormatManager.h Sat Jul 23 19:14:56 2011
@@ -545,7 +545,7 @@
     
     bool
     Get(ValueObject& vobj,
-        lldb::SyntheticFilterSP& entry,
+        lldb::SyntheticChildrenSP& entry,
         uint32_t* reason = NULL)
     {
         if (!IsEnabled())
@@ -791,7 +791,7 @@
     
     bool
     Get(ValueObject& vobj,
-        lldb::SyntheticFilterSP& entry)
+        lldb::SyntheticChildrenSP& entry)
     {
         Mutex::Locker(m_map_mutex);
         
@@ -803,7 +803,7 @@
         for (begin = m_active_categories.begin(); begin != end; begin++)
         {
             FormatCategory::SharedPointer category = *begin;
-            lldb::SyntheticFilterSP current_format;
+            lldb::SyntheticChildrenSP current_format;
             if (!category->Get(vobj, current_format, &reason_why))
                 continue;
             if (reason_why == lldb::eFormatterDirectChoice)
@@ -947,7 +947,7 @@
     }
     bool
     Get(ValueObject& vobj,
-        lldb::SyntheticFilterSP& entry)
+        lldb::SyntheticChildrenSP& entry)
     {
         return m_categories_map.Get(vobj, entry);
     }

Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Sat Jul 23 19:14:56 2011
@@ -739,13 +739,14 @@
                                              // as an independent ValueObjectConstResult, which isn't managed by us.
     ValueObject *m_deref_valobj;
 
-    lldb::Format            m_format;
-    uint32_t                m_last_format_mgr_revision;
-    lldb::SummaryFormatSP   m_last_summary_format;
-    lldb::SummaryFormatSP   m_forced_summary_format;
-    lldb::ValueFormatSP     m_last_value_format;
-    lldb::SyntheticFilterSP m_last_synthetic_filter;
-    lldb::user_id_t         m_user_id_of_forced_summary;
+    lldb::Format                m_format;
+    uint32_t                    m_last_format_mgr_revision;
+    lldb::SummaryFormatSP       m_last_summary_format;
+    lldb::SummaryFormatSP       m_forced_summary_format;
+    lldb::ValueFormatSP         m_last_value_format;
+    lldb::SyntheticChildrenSP   m_last_synthetic_filter;
+    lldb::user_id_t             m_user_id_of_forced_summary;
+    
     bool                m_value_is_valid:1,
                         m_value_did_change:1,
                         m_children_count_valid:1,

Modified: lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h Sat Jul 23 19:14:56 2011
@@ -12,6 +12,7 @@
 
 // C Includes
 // C++ Includes
+#include <map>
 #include <ostream>
 #include <vector>
 // Other libraries and framework includes
@@ -21,14 +22,17 @@
 namespace lldb_private {
 
 //----------------------------------------------------------------------
-// A ValueObject that represents memory at a given address, viewed as some 
-// set lldb type.
+// A ValueObject that obtains its children from some source other than
+// real information
+// This is currently used to implement children filtering, where only
+// a subset of the real children are shown, but it can be used for any
+// source of made-up children information
 //----------------------------------------------------------------------
-class ValueObjectSyntheticFilter : public ValueObject
+class ValueObjectSynthetic : public ValueObject
 {
 public:
     virtual
-    ~ValueObjectSyntheticFilter();
+    ~ValueObjectSynthetic();
 
     virtual size_t
     GetByteSize();
@@ -105,16 +109,25 @@
     lldb::TypeSP m_type_sp;
     lldb::ValueObjectSP m_owning_valobj_sp;
     lldb::SyntheticValueType m_use_synthetic;
-    lldb::SyntheticFilterSP m_synth_filter;
+    lldb::SyntheticChildrenFrontEndSP m_synth_filter;
+    
+    typedef std::map<uint32_t, lldb::ValueObjectSP> ByIndexMap;
+    typedef std::map<const char*, uint32_t> NameToIndexMap;
+    
+    typedef ByIndexMap::iterator ByIndexIterator;
+    typedef NameToIndexMap::iterator NameToIndexIterator;
+    
+    ByIndexMap m_children_byindex;
+    NameToIndexMap m_name_toindex;
 
 private:
     friend class ValueObject;
-    ValueObjectSyntheticFilter (ValueObject &parent, lldb::SyntheticFilterSP filter);
+    ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter);
     
     //------------------------------------------------------------------
     // For ValueObject only
     //------------------------------------------------------------------
-    DISALLOW_COPY_AND_ASSIGN (ValueObjectSyntheticFilter);
+    DISALLOW_COPY_AND_ASSIGN (ValueObjectSynthetic);
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h Sat Jul 23 19:14:56 2011
@@ -10,10 +10,13 @@
 #ifndef liblldb_ScriptInterpreter_h_
 #define liblldb_ScriptInterpreter_h_
 
+#include "lldb/API/SBValue.h"
+
 #include "lldb/lldb-private.h"
 #include "lldb/Core/Broadcaster.h"
 #include "lldb/Utility/PseudoTerminal.h"
 
+
 namespace lldb_private {
 
 class ScriptInterpreter
@@ -30,6 +33,15 @@
     typedef std::string (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name,
                                                                  const char *session_dictionary_name,
                                                                  const lldb::ValueObjectSP& valobj_sp);
+    
+    typedef void* (*SWIGPythonCreateSyntheticProvider) (const std::string python_class_name,
+                                                        const char *session_dictionary_name,
+                                                        const lldb::ValueObjectSP& valobj_sp);
+    
+    typedef uint32_t       (*SWIGPythonCalculateNumChildren)    (void *implementor);
+    typedef void*          (*SWIGPythonGetChildAtIndex)         (void *implementor, uint32_t idx);
+    typedef int            (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name);
+    typedef lldb::SBValue* (*SWIGPythonCastPyObjectToSBValue)   (void* data);
 
     typedef enum
     {
@@ -89,6 +101,13 @@
         return false;
     }
     
+    virtual void*
+    CreateSyntheticScriptedProvider (std::string class_name,
+                                     lldb::ValueObjectSP valobj)
+    {
+        return NULL;
+    }
+    
     // use this if the function code is just a one-liner script
     virtual bool
     GenerateTypeScriptFunction (const char* oneliner, StringList &output)
@@ -113,6 +132,30 @@
     {
         return;
     }
+    
+    virtual uint32_t
+    CalculateNumChildren (void *implementor)
+    {
+        return 0;
+    }
+    
+    virtual void*
+    GetChildAtIndex (void *implementor, uint32_t idx)
+    {
+        return NULL;
+    }
+    
+    virtual int
+    GetIndexOfChildWithName (void *implementor, const char* child_name)
+    {
+        return UINT32_MAX;
+    }
+    
+    virtual lldb::SBValue*
+    CastPyObjectToSBValue (void* data)
+    {
+        return NULL;
+    }
 
     const char *
     GetScriptInterpreterPtyName ();
@@ -129,7 +172,12 @@
     static void
     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);
 
     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=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h (original)
+++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h Sat Jul 23 19:14:56 2011
@@ -56,6 +56,22 @@
     bool
     GenerateTypeScriptFunction (const char* oneliner, StringList &output);
     
+    void*
+    CreateSyntheticScriptedProvider (std::string class_name,
+                                     lldb::ValueObjectSP valobj);
+    
+    virtual uint32_t
+    CalculateNumChildren (void *implementor);
+    
+    virtual void*
+    GetChildAtIndex (void *implementor, uint32_t idx);
+    
+    virtual int
+    GetIndexOfChildWithName (void *implementor, const char* child_name);
+    
+    virtual lldb::SBValue*
+    CastPyObjectToSBValue (void* data);
+    
     bool
     GenerateFunction(std::string& signature, StringList &input, StringList &output);
     
@@ -103,7 +119,12 @@
     static void
     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_sbvalu);
 
 protected:
 

Added: lldb/trunk/include/lldb/Utility/PythonPointer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/PythonPointer.h?rev=135865&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Utility/PythonPointer.h (added)
+++ lldb/trunk/include/lldb/Utility/PythonPointer.h Sat Jul 23 19:14:56 2011
@@ -0,0 +1,78 @@
+//===---------------------PythonPointer.h ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_PythonPointer_h_
+#define utility_PythonPointer_h_
+
+#include <algorithm>
+#include <memory>
+
+#if defined (__APPLE__)
+#include <Python/Python.h>
+#else
+#include <Python.h>
+#endif
+
+namespace lldb_private {
+
+template<class T>
+class PythonPointer
+{
+public: 
+    typedef PyObject* element_type; 
+private:
+    element_type*      ptr_;
+    bool my_ref;
+public:
+    
+    PythonPointer(element_type p, bool steal_ref = false) :
+    ptr_(p),
+    my_ref(!steal_ref)
+    {
+        if (my_ref)
+            Py_INCREF(ptr_);
+    }
+    
+    PythonPointer(const PythonPointer& r, bool steal_ref = false) :
+    ptr_(r.ptr_),
+    my_ref(!steal_ref)
+    {
+        if (my_ref)
+            Py_INCREF(ptr_);
+    }
+
+    ~PythonPointer()
+    {
+        if (my_ref)
+            Py_XDECREF(ptr_);
+    }
+    
+    PythonPointer
+    StealReference()
+    {
+        return PythonPointer(ptr_,true);
+    }
+    
+    PythonPointer
+    DuplicateReference()
+    {
+        return PythonPointer(ptr_, false);
+    }
+
+    element_type get() const {return ptr_;}
+    
+    bool IsNull() { return ptr_ == NULL; }
+    bool IsNone() { return ptr_ == Py_None; }
+    
+    operator PyObject* () { return ptr_; }
+};
+
+} // namespace lldb
+
+#endif  // utility_PythonPointer_h_

Modified: lldb/trunk/include/lldb/lldb-forward-rtti.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward-rtti.h?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward-rtti.h (original)
+++ lldb/trunk/include/lldb/lldb-forward-rtti.h Sat Jul 23 19:14:56 2011
@@ -67,7 +67,8 @@
     typedef SharedPtr<lldb_private::SummaryFormat>::Type SummaryFormatSP;
     typedef SharedPtr<lldb_private::SymbolFile>::Type SymbolFileSP;
     typedef SharedPtr<lldb_private::SymbolContextSpecifier>::Type SymbolContextSpecifierSP;
-    typedef SharedPtr<lldb_private::SyntheticFilter>::Type SyntheticFilterSP;
+    typedef SharedPtr<lldb_private::SyntheticChildren>::Type SyntheticChildrenSP;
+    typedef SharedPtr<lldb_private::SyntheticChildrenFrontEnd>::Type SyntheticChildrenFrontEndSP;
     typedef SharedPtr<lldb_private::Target>::Type TargetSP;
     typedef SharedPtr<lldb_private::Thread>::Type ThreadSP;
     typedef SharedPtr<lldb_private::ThreadPlan>::Type ThreadPlanSP;

Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Sat Jul 23 19:14:56 2011
@@ -144,7 +144,9 @@
 class   SymbolFile;
 class   SymbolVendor;
 class   Symtab;
-class   SyntheticFilter;
+class   SyntheticChildren;
+class   SyntheticChildrenFrontEnd;
+class   SyntheticScriptProvider;
 class   Target;
 class   TargetList;
 class   Thread;

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Sat Jul 23 19:14:56 2011
@@ -1221,6 +1221,7 @@
 		94A9112D13D5DF210046D8A6 /* FormatClasses.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatClasses.cpp; path = source/Core/FormatClasses.cpp; sourceTree = "<group>"; };
 		94B6E76013D8833C005F417F /* ValueObjectSyntheticFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectSyntheticFilter.h; path = include/lldb/Core/ValueObjectSyntheticFilter.h; sourceTree = "<group>"; };
 		94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectSyntheticFilter.cpp; path = source/Core/ValueObjectSyntheticFilter.cpp; sourceTree = "<group>"; };
+		94EBAC8313D9EE26009BA64E /* PythonPointer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PythonPointer.h; path = include/lldb/Utility/PythonPointer.h; sourceTree = "<group>"; };
 		961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FuncUnwinders.cpp; path = source/Symbol/FuncUnwinders.cpp; sourceTree = "<group>"; };
 		961FABB91235DE1600F93A47 /* UnwindPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindPlan.cpp; path = source/Symbol/UnwindPlan.cpp; sourceTree = "<group>"; };
 		961FABBA1235DE1600F93A47 /* UnwindTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindTable.cpp; path = source/Symbol/UnwindTable.cpp; sourceTree = "<group>"; };
@@ -1864,6 +1865,7 @@
 				2682F16B115EDA0D00CCFF99 /* PseudoTerminal.h */,
 				2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */,
 				94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */,
+				94EBAC8313D9EE26009BA64E /* PythonPointer.h */,
 			);
 			name = Utility;
 			sourceTree = "<group>";

Modified: lldb/trunk/scripts/lldb.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/lldb.swig?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/scripts/lldb.swig (original)
+++ lldb/trunk/scripts/lldb.swig Sat Jul 23 19:14:56 2011
@@ -281,7 +281,6 @@
             // Find the current session's dictionary in the main module's dictionary.
 
             if (PyDict_Check (main_dict))
-             
             {
                 session_dict = NULL;   
                 while (PyDict_Next (main_dict, &pos, &key, &value))
@@ -401,7 +400,6 @@
             // Find the current session's dictionary in the main module's dictionary.
 
             if (PyDict_Check (main_dict))
-             
             {
                 session_dict = NULL;   
                 while (PyDict_Next (main_dict, &pos, &key, &value))
@@ -493,5 +491,278 @@
     return retval;
 }
 
+SWIGEXPORT void*
+LLDBSwigPythonCreateSyntheticProvider 
+(
+    const std::string python_class_name,
+    const char *session_dictionary_name,
+    const lldb::ValueObjectSP& valobj_sp
+)
+{
+    PyObject* retval = NULL;
+
+    if (python_class_name.empty() || !session_dictionary_name)
+        Py_RETURN_NONE;
+
+    lldb::ValueObjectSP* valobj_sp_ptr = new lldb::ValueObjectSP(valobj_sp);
+
+    PyObject *ValObj_PyObj = SWIG_NewPointerObj((void *) valobj_sp_ptr, SWIGTYPE_p_lldb__SBValue, SWIG_POINTER_OWN);
+
+    if (ValObj_PyObj == NULL)
+        Py_RETURN_NONE;
+
+    const char* python_function_name = python_class_name.c_str();
+
+    PyObject *pmodule, *main_dict, *session_dict, *pfunc;
+    PyObject *pvalue;
+
+    pmodule = PyImport_AddModule ("__main__");
+    if (pmodule != NULL)
+    {
+        main_dict = PyModule_GetDict (pmodule);
+        if (main_dict != NULL)
+        {
+            PyObject *key, *value;
+            Py_ssize_t pos = 0;
+
+            // Find the current session's dictionary in the main module's dictionary.
+
+            if (PyDict_Check (main_dict))
+            {
+                session_dict = NULL;   
+                while (PyDict_Next (main_dict, &pos, &key, &value))
+                {
+                    // We have stolen references to the key and value objects in the dictionary; we need to increment 
+                    // them now so that Python's garbage collector doesn't collect them out from under us.
+                    Py_INCREF (key);
+                    Py_INCREF (value);
+                    if (strcmp (PyString_AsString (key), session_dictionary_name) == 0)
+                    {
+                        session_dict = value;
+                        break;
+                    }
+                }
+            }
+
+            if (!session_dict || !PyDict_Check (session_dict))
+                return retval;
+
+            // Find the function we need to call in the current session's dictionary.
+
+            pos = 0;
+            pfunc = NULL;
+            while (PyDict_Next (session_dict, &pos, &key, &value))
+            {
+                if (PyString_Check (key))
+                {
+                    // We have stolen references to the key and value objects in the dictionary; we need to increment 
+                    // them now so that Python's garbage collector doesn't collect them out from under us.
+                    Py_INCREF (key);
+                    Py_INCREF (value);
+                    if (strcmp (PyString_AsString (key), python_function_name) == 0)
+                    {
+                        pfunc = value;
+                        break;
+                    }
+                }
+            }
+
+            // Set up the arguments and call the function.
+
+            if (pfunc && PyCallable_Check (pfunc))
+            {
+                PyObject *argList = Py_BuildValue("SS", ValObj_PyObj, session_dict);
+
+                if (PyErr_Occurred ())
+                {
+                    PyErr_Print();
+                    PyErr_Clear();
+                    return retval;
+                }
+
+                if (argList == NULL)
+                {
+                    return retval;
+                }
+
+                Py_INCREF(ValObj_PyObj);
+
+                pvalue = PyObject_CallObject(pfunc, argList);
+
+                Py_DECREF(argList);
+
+                if (pvalue != NULL)
+                {
+                    if (pvalue != Py_None)
+                        retval = pvalue;
+                    else
+                    {
+                        retval = Py_None;
+                        Py_INCREF(retval);
+                    }
+                }
+                else if (PyErr_Occurred ())
+                {
+                    PyErr_Print();
+                    PyErr_Clear();
+                }
+                Py_INCREF (session_dict);
+            }
+            else if (PyErr_Occurred())
+            {
+                PyErr_Print();
+                PyErr_Clear();
+            }
+        }
+        else if (PyErr_Occurred())
+        {
+            PyErr_Print();
+            PyErr_Clear();
+        }
+    }
+    else if (PyErr_Occurred ())
+    {
+        PyErr_Print();
+        PyErr_Clear ();
+    }
+    if (retval)
+        return retval;
+    else
+        Py_RETURN_NONE;
+}
+
+/*
+these four calls below are meant to support
+Python-based synthetic children providers
+they essentially mimic the four pure virtual
+method calls provided by the frontend class
+*/
+
+SWIGEXPORT uint32_t
+LLDBSwigPython_CalculateNumChildren
+(
+    PyObject *implementor
+)
+{
+
+    static char callee_name[] = "num_children";
+
+    if (implementor == NULL || implementor == Py_None)
+        return 0;
+    PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL);
+    if (PyErr_Occurred())
+    {
+        PyErr_Print();
+        PyErr_Clear();
+    }
+
+    if (py_return == NULL || py_return == Py_None)
+    {
+        Py_XDECREF(py_return);
+        return UINT32_MAX;
+    }
+    long retval = PyInt_AsLong(py_return);
+    Py_DECREF(py_return);
+    if (retval >= 0)
+        return (uint32_t)retval;
+    if (PyErr_Occurred())
+    {
+        PyErr_Print();
+        PyErr_Clear();
+    }
+    return 0;
+}
+
+SWIGEXPORT PyObject*
+LLDBSwigPython_GetChildAtIndex
+(
+    PyObject *implementor,
+    uint32_t idx
+)
+{
+
+    static char callee_name[] = "get_child_at_index";
+    static char param_format[] = "i";
+
+    if (implementor == NULL || implementor == Py_None)
+        return NULL;
+    PyObject* py_return = PyObject_CallMethod(implementor, callee_name, param_format, idx);
+    if (PyErr_Occurred())
+    {
+        PyErr_Print();
+        PyErr_Clear();
+    }
+    
+    if (py_return == NULL || py_return == Py_None)
+    {
+        Py_XDECREF(py_return);
+        return NULL;
+    }
+    
+    lldb::SBValue* sbvalue_ptr = NULL;
+
+    if (SWIG_ConvertPtr(py_return, (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1)
+    {
+        Py_DECREF(py_return);
+        return NULL;
+    }
+    
+    if (sbvalue_ptr == NULL)
+        return NULL;
+
+    return py_return;
+}
+
+SWIGEXPORT int
+LLDBSwigPython_GetIndexOfChildWithName
+(
+    PyObject *implementor,
+    const char* child_name
+)
+{
+    static char callee_name[] = "get_child_index";
+    static char param_format[] = "s";
+
+    if (implementor == NULL || implementor == Py_None)
+        return 0;
+    PyObject* py_return = PyObject_CallMethod(implementor, callee_name, param_format, child_name);
+    if (PyErr_Occurred())
+    {
+        PyErr_Print();
+        PyErr_Clear();
+    }
+    
+    if (py_return == NULL || py_return == Py_None)
+    {
+        Py_XDECREF(py_return);
+        return UINT32_MAX;
+    }
+    long retval = PyInt_AsLong(py_return);
+    Py_DECREF(py_return);
+    if (retval >= 0)
+        return (uint32_t)retval;
+    if (PyErr_Occurred())
+    {
+        PyErr_Print();
+        PyErr_Clear();
+    }
+    return 0;
+}
+
+SWIGEXPORT lldb::SBValue*
+LLDBSWIGPython_CastPyObjectToSBValue
+(
+    PyObject* data
+)
+{
+    lldb::SBValue* sb_ptr = NULL;
+    
+    int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBValue, 0);
+
+    if (valid_cast == -1)
+        return NULL;
+
+    return sb_ptr;
+}
 
 %}

Modified: lldb/trunk/source/API/SBCommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBCommandInterpreter.cpp?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/source/API/SBCommandInterpreter.cpp (original)
+++ lldb/trunk/source/API/SBCommandInterpreter.cpp Sat Jul 23 19:14:56 2011
@@ -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);
     }
 }

Modified: lldb/trunk/source/Commands/CommandObjectType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectType.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectType.cpp Sat Jul 23 19:14:56 2011
@@ -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,31 +2473,8 @@
         return &m_options;
     }
     
-public:
-    CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) :
-    CommandObject (interpreter,
-                   "type synth add",
-                   "Add a new synthetic provider for a type.",
-                   NULL), m_options (interpreter)
-    {
-        CommandArgumentEntry type_arg;
-        CommandArgumentData type_style_arg;
-        
-        type_style_arg.arg_type = eArgTypeName;
-        type_style_arg.arg_repetition = eArgRepeatPlus;
-        
-        type_arg.push_back (type_style_arg);
-        
-        m_arguments.push_back (type_arg);
-        
-    }
-    
-    ~CommandObjectTypeSynthAdd ()
-    {
-    }
-    
     bool
-    Execute (Args& command, CommandReturnObject &result)
+    Execute_ChildrenList (Args& command, CommandReturnObject &result)
     {
         const size_t argc = command.GetArgumentCount();
         
@@ -2502,17 +2492,19 @@
             return false;
         }
         
-        SyntheticFilterSP entry;
+        SyntheticChildrenSP entry;
         
-        entry.reset(new SyntheticFilter(m_options.m_cascade,
-                                        m_options.m_skip_pointers,
-                                        m_options.m_skip_references));
+        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++)
-            entry->AddExpressionPath(*begin);
+            impl->AddExpressionPath(*begin);
         
         
         // now I have a valid provider, let's add it to every type
@@ -2536,16 +2528,100 @@
         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",
+                   "Add a new synthetic provider for a type.",
+                   NULL), m_options (interpreter)
+    {
+        CommandArgumentEntry type_arg;
+        CommandArgumentData type_style_arg;
+        
+        type_style_arg.arg_type = eArgTypeName;
+        type_style_arg.arg_repetition = eArgRepeatPlus;
+        
+        type_arg.push_back (type_style_arg);
+        
+        m_arguments.push_back (type_arg);
+        
+    }
+    
+    ~CommandObjectTypeSynthAdd ()
+    {
+    }
+    
+    bool
+    Execute (Args& command, CommandReturnObject &result)
+    {
+        if (m_options.is_class_based)
+            return Execute_PythonClass(command, result);
+        else
+            return Execute_ChildrenList(command, result);
+    }
 };
 
 OptionDefinition
 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 }
 };
 

Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Sat Jul 23 19:14:56 2011
@@ -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);
 }

Modified: lldb/trunk/source/Core/FormatClasses.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatClasses.cpp?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/source/Core/FormatClasses.cpp (original)
+++ lldb/trunk/source/Core/FormatClasses.cpp Sat Jul 23 19:14:56 2011
@@ -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

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Sat Jul 23 19:14:56 2011
@@ -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);
     
 }
 

Modified: lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp (original)
+++ lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp Sat Jul 23 19:14:56 2011
@@ -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())
-        return lldb::ValueObjectSP();
-    uint32_t idx = GetIndexOfChildWithName(name);
-    if (idx >= m_synth_filter->GetCount())
+    
+    uint32_t index = GetIndexOfChildWithName(name);
+    
+    if (index == UINT32_MAX)
         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();
 }

Modified: lldb/trunk/source/Interpreter/CommandObjectScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObjectScript.cpp?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObjectScript.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObjectScript.cpp Sat Jul 23 19:14:56 2011
@@ -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);

Modified: lldb/trunk/source/Interpreter/ScriptInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreter.cpp?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreter.cpp Sat Jul 23 19:14:56 2011
@@ -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

Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=135865&r1=135864&r2=135865&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Sat Jul 23 19:14:56 2011
@@ -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

Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/Makefile?rev=135865&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/Makefile (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/Makefile Sat Jul 23 19:14:56 2011
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py?rev=135865&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py Sat Jul 23 19:14:56 2011
@@ -0,0 +1,95 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class DataFormatterTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "data-formatter", "data-formatter-python-synth")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    def test_with_dsym_and_run_command(self):
+        """Test data formatter commands."""
+        self.buildDsym()
+        self.data_formatter_commands()
+
+    def test_with_dwarf_and_run_command(self):
+        """Test data formatter commands."""
+        self.buildDwarf()
+        self.data_formatter_commands()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line number to break at.
+        self.line = line_number('main.cpp', '// Set break point at this line.')
+
+    def data_formatter_commands(self):
+        """Test that that file and class static variables display correctly."""
+        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+        self.expect("breakpoint set -f main.cpp -l %d" % self.line,
+                    BREAKPOINT_CREATED,
+            startstr = "Breakpoint created: 1: file ='main.cpp', line = %d, locations = 1" %
+                        self.line)
+
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # This is the function to remove the custom formats in order to have a
+        # clean slate for the next test case.
+        def cleanup():
+            self.runCmd('type format clear', check=False)
+            self.runCmd('type summary clear', check=False)
+            self.runCmd('type synth clear', check=False)
+
+        # Execute the cleanup function during test case tear down.
+        self.addTearDownHook(cleanup)
+
+        # print the f00_1 variable without a synth
+        self.expect("frame variable f00_1",
+            substrs = ['a = 0',
+                       'b = 1',
+                       'r = 33']);
+
+        # now set up the synth
+        self.runCmd("script from fooSynthProvider import *")
+        self.runCmd("type synth add -l fooSynthProvider foo")
+
+        # check that we get only the two variables
+        self.expect("frame variable f00_1",
+                    substrs = ['r = 33',
+                               'a = 0']);
+
+        # check that we do not get the extra vars and that we cache results
+        self.expect("frame variable f00_1", matching=False,
+                    substrs = ['looking for',
+                               'b = 1']);
+
+        # check that the caching does not span beyond the stopoint
+        self.runCmd("n")
+
+        self.expect("frame variable f00_1",
+                    substrs = ['r = 33',
+                               'a = 1']);
+
+        # delete the synth and check that we get good output
+        self.runCmd("type synth delete foo")
+        self.expect("frame variable f00_1",
+                    substrs = ['a = 1',
+                               'b = 1',
+                               'r = 33']);
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py?rev=135865&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py Sat Jul 23 19:14:56 2011
@@ -0,0 +1,16 @@
+class fooSynthProvider:
+     def __init__(self, valobj, dict):
+         self.valobj = valobj;
+     def num_children(self):
+         return 2;
+     def get_child_at_index(self, index):
+         if index == 1:
+             child = self.valobj.GetChildMemberWithName('a');
+         else:
+             child = self.valobj.GetChildMemberWithName('r');
+         return child;
+     def get_child_index(self, name):
+         if name == 'a':
+             return 1;
+         else:
+             return 0;
\ No newline at end of file

Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp?rev=135865&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp (added)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp Sat Jul 23 19:14:56 2011
@@ -0,0 +1,53 @@
+struct foo
+{
+    int a;
+    int b;
+    int c;
+    int d;
+    int e;
+    int f;
+    int g;
+    int h;
+    int i;
+    int j;
+    int k;
+    int l;
+    int m;
+    int n;
+    int o;
+    int p;
+    int q;
+    int r;
+    
+    foo(int X) :
+    a(X),
+    b(X+1),
+    c(X+3),
+    d(X+5),
+    e(X+7),
+    f(X+9),
+    g(X+11),
+    h(X+13),
+    i(X+15),
+    j(X+17),
+    k(X+19),
+    l(X+21),
+    m(X+23),
+    n(X+25),
+    o(X+27),
+    p(X+29),
+    q(X+31),
+    r(X+33) {}
+};
+
+int main()
+{
+    foo f00_1(0);
+    foo f00_2(6);
+    foo *f00_3 = new foo(12);
+    foo& f00_4 = *(new foo(18));
+    
+    f00_1.a++; // Set break point at this line.
+    
+    return 0;
+}
\ No newline at end of file





More information about the lldb-commits mailing list