[Lldb-commits] [lldb] r134108 - in /lldb/trunk: include/lldb/ include/lldb/Core/ include/lldb/Symbol/ lldb.xcodeproj/ lldb.xcodeproj/xcshareddata/xcschemes/ source/Commands/ source/Core/ source/Symbol/ test/functionalities/data-formatter/

Enrico Granata granata.enrico at gmail.com
Wed Jun 29 15:27:15 PDT 2011


Author: enrico
Date: Wed Jun 29 17:27:15 2011
New Revision: 134108

URL: http://llvm.org/viewvc/llvm-project?rev=134108&view=rev
Log:
This commit adds a new top subcommand "summary" to command type named "type". Currently this command
implements three commands:

type summary add <format> <typename1> [<typename2> ...]
type summary delete <typename1> [<typename2> ...]
type summary list [<typename1> [<typename2>] ...]
type summary clear

This allows you to specify the default format that will be used to display
summaries for variables, shown when you use "frame variable" or "expression", or the SBValue classes.

Examples:
type summary add "x = ${var.x}" Point

type summary list

type summary add --one-liner SimpleType

Modified:
    lldb/trunk/include/lldb/Core/Debugger.h
    lldb/trunk/include/lldb/Core/FormatManager.h
    lldb/trunk/include/lldb/Core/ValueObject.h
    lldb/trunk/include/lldb/Symbol/ClangASTType.h
    lldb/trunk/include/lldb/lldb-forward-rtti.h
    lldb/trunk/include/lldb/lldb-forward.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
    lldb/trunk/source/Commands/CommandObjectType.cpp
    lldb/trunk/source/Core/Debugger.cpp
    lldb/trunk/source/Core/FormatManager.cpp
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Symbol/ClangASTType.cpp
    lldb/trunk/test/functionalities/data-formatter/TestDataFormatter.py
    lldb/trunk/test/functionalities/data-formatter/main.cpp

Modified: lldb/trunk/include/lldb/Core/Debugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Debugger.h (original)
+++ lldb/trunk/include/lldb/Core/Debugger.h Wed Jun 29 17:27:15 2011
@@ -415,7 +415,8 @@
                   const ExecutionContext *exe_ctx,
                   const Address *addr,
                   Stream &s,
-                  const char **end);
+                  const char **end,
+                  ValueObject* vobj = NULL);
 
 
     void
@@ -473,18 +474,50 @@
     
 public:
     
-    static bool
-    GetFormatForType (const ConstString &type, lldb::Format& format, bool& cascade);
-    
-    static void
-    AddFormatForType (const ConstString &type, lldb::Format format, bool cascade);
+    class ValueFormats
+    {
+        public:
+            static bool
+            Get(ValueObject& vobj, ValueFormat::SharedPointer &entry);
+            
+            static void
+            Add(const ConstString &type, const ValueFormat::SharedPointer &entry);
+            
+            static bool
+            Delete(const ConstString &type);
+            
+            static void
+            Clear();
+            
+            static void
+            LoopThrough(FormatManager::ValueCallback callback, void* callback_baton);
+            
+            static uint32_t GetCurrentRevision();
+    };
     
-    static bool
-    DeleteFormatForType (const ConstString &type);
+    class SummaryFormats
+    {
+        public:
+        
+            static bool
+            Get(ValueObject& vobj, SummaryFormat::SharedPointer &entry);
+            
+            static void
+            Add(const ConstString &type, const SummaryFormat::SharedPointer &entry);
+            
+            static bool
+            Delete(const ConstString &type);
+            
+            static void
+            Clear();
+            
+            static void
+            LoopThrough(FormatManager::SummaryCallback callback, void* callback_baton);
+            
+            static uint32_t
+            GetCurrentRevision();
+    };
     
-    static void
-    LoopThroughFormatList (FormatManager::Callback callback, 
-                           void* callback_baton);
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/include/lldb/Core/FormatManager.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatManager.h (original)
+++ lldb/trunk/include/lldb/Core/FormatManager.h Wed Jun 29 17:27:15 2011
@@ -40,42 +40,288 @@
 #include "lldb/Core/Communication.h"
 #include "lldb/Core/InputReaderStack.h"
 #include "lldb/Core/Listener.h"
-#include "lldb/Core/Stream.h"
 #include "lldb/Core/StreamFile.h"
 #include "lldb/Core/SourceManager.h"
 #include "lldb/Core/UserID.h"
 #include "lldb/Core/UserSettingsController.h"
+#include "lldb/Core/ValueObject.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Platform.h"
 #include "lldb/Target/TargetList.h"
 
-namespace lldb_private {
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
 
+namespace lldb_private {
     
-class FormatManager
+class IFormatChangeListener
 {
 public:
+    virtual void
+    Changed() = 0;
+    
+    virtual
+    ~IFormatChangeListener() {}
+    
+};
 
-    typedef bool(*Callback)(void*, const char*, lldb::Format, bool);
+struct SummaryFormat
+{
+    std::string m_format;
+    bool m_dont_show_children;
+    bool m_dont_show_value;
+    bool m_show_members_oneliner;
+    bool m_cascades;
+    SummaryFormat(std::string f = "", bool c = false, bool nochildren = true, bool novalue = true, bool oneliner = false) :
+    m_format(f),
+    m_dont_show_children(nochildren),
+    m_dont_show_value(novalue),
+    m_show_members_oneliner(oneliner),
+    m_cascades(c)
+    {
+    }
+    
+    bool
+    DoesPrintChildren() const
+    {
+        return !m_dont_show_children;
+    }
+    
+    bool
+    DoesPrintValue() const
+    {
+        return !m_dont_show_value;
+    }
+    
+    bool
+    IsOneliner() const
+    {
+        return m_show_members_oneliner;
+    }
+    
+    typedef lldb::SharedPtr<SummaryFormat>::Type SharedPointer;
+    
+};
 
-    FormatManager() : 
-        m_format_map(FormatMap()), 
-        m_format_map_mutex(Mutex::eMutexTypeRecursive) 
+struct ValueFormat
+{
+    lldb::Format m_format;
+    bool m_cascades;
+    ValueFormat (lldb::Format f = lldb::eFormatInvalid, bool c = false) : 
+    m_format (f), 
+    m_cascades (c)
+    {
+    }
+    
+    typedef lldb::SharedPtr<ValueFormat>::Type SharedPointer;
+    
+    ~ValueFormat()
     {
     }
+    
+};
+    
+template<typename MapType, typename CallbackType>
+class FormatNavigator
+{
+public:
 
+    typedef typename MapType::iterator MapIterator;
+    typedef typename MapType::key_type MapKeyType;
+    typedef typename MapType::mapped_type MapValueType;
+    
+    FormatNavigator(IFormatChangeListener* lst = NULL) :
+    m_map_mutex(Mutex::eMutexTypeRecursive),
+    m_map(MapType()),
+    listener(lst)
+    {
+    }
+        
     bool
-    GetFormatForType (const ConstString &type, lldb::Format& format, bool& cascade);
-
+    Get(ValueObject& vobj, MapValueType& entry)
+    {
+        Mutex::Locker(m_map_mutex);
+        clang::QualType type = clang::QualType::getFromOpaquePtr(vobj.GetClangType());
+        bool ret = Get(vobj, type, entry);
+        if(ret)
+            entry = MapValueType(entry);
+        else
+            entry = MapValueType();
+        return ret;
+    }
+    
     void
-    AddFormatForType (const ConstString &type, lldb::Format format, bool cascade);
-
+    Add(const MapKeyType &type, const MapValueType& entry)
+    {
+        Mutex::Locker(m_map_mutex);
+        m_map[type] = MapValueType(entry);
+        if(listener)
+            listener->Changed();
+    }
+    
     bool
-    DeleteFormatForType (const ConstString &type);
-
+    Delete(const MapKeyType& type)
+    {
+        Mutex::Locker(m_map_mutex);
+        MapIterator iter = m_map.find(type);
+        if (iter == m_map.end())
+            return false;
+        m_map.erase(type);
+        if(listener)
+            listener->Changed();
+        return true;
+    }
+    
+    void
+    Clear()
+    {
+        Mutex::Locker(m_map_mutex);
+        m_map.clear();
+        if(listener)
+            listener->Changed();
+    }
+    
     void
-    LoopThroughFormatList (Callback cback, void* param);
+    LoopThrough(CallbackType callback, void* param)
+    {
+        if (callback)
+        {
+            Mutex::Locker(m_map_mutex);
+            MapIterator pos, end = m_map.end();
+            for (pos = m_map.begin(); pos != end; pos++)
+            {
+                MapKeyType type = pos->first;
+                if(!callback(param, type, MapValueType(pos->second)))
+                    break;
+            }
+        }
+    }
+    
+    ~FormatNavigator()
+    {
+    }
+    
+private:
+    
+    Mutex m_map_mutex;
+    MapType m_map;
+    IFormatChangeListener* listener;
+    
+    DISALLOW_COPY_AND_ASSIGN(FormatNavigator);
+    
+    bool
+    Get(const MapKeyType &type, MapValueType& entry)
+    {
+        Mutex::Locker(m_map_mutex);
+        MapIterator iter = m_map.find(type);
+        if (iter == m_map.end())
+            return false;
+        entry = iter->second;
+        return true;
+    }
+    
+    bool Get(ValueObject& vobj,
+             const clang::QualType& q_type,
+             MapValueType& entry)
+    {
+        if (q_type.isNull())
+            return false;
+        clang::QualType type = q_type.getUnqualifiedType();
+        type.removeLocalConst(); type.removeLocalVolatile(); type.removeLocalRestrict();
+        ConstString name(type.getAsString().c_str());
+        //printf("trying to get format for VO name %s of type %s\n",vobj.GetName().AsCString(),name.AsCString());
+        if (Get(name.GetCString(), entry))
+            return true;
+        // look for a "base type", whatever that means
+        const clang::Type* typePtr = type.getTypePtrOrNull();
+        if (!typePtr)
+            return false;
+        if (typePtr->isReferenceType())
+            return Get(vobj,type.getNonReferenceType(),entry);
+        // for C++ classes, navigate up the hierarchy
+        if (typePtr->isRecordType())
+        {
+            clang::CXXRecordDecl* record = typePtr->getAsCXXRecordDecl();
+            if (record)
+            {
+                if (!record->hasDefinition())
+                    // dummy call to do the complete
+                    ClangASTContext::GetNumChildren(vobj.GetClangAST(), vobj.GetClangType(), false);
+                clang::IdentifierInfo *info = record->getIdentifier();
+                if (info) {
+                    // this is the class name, plain and simple
+                    ConstString id_info(info->getName().str().c_str());
+                    if (Get(id_info.GetCString(), entry))
+                        return true;
+                }
+                if (record->hasDefinition())
+                {
+                    clang::CXXRecordDecl::base_class_iterator pos,end;
+                    if( record->getNumBases() > 0)
+                    {
+                        end = record->bases_end();
+                        for (pos = record->bases_begin(); pos != end; pos++)
+                        {
+                            if((Get(vobj, pos->getType(), entry)) && entry->m_cascades)
+                                return true; // if it does not cascade, just move on to other base classes which might
+                        }
+                    }
+                    if (record->getNumVBases() > 0)
+                    {
+                        end = record->vbases_end();
+                        for (pos = record->vbases_begin(); pos != end; pos++)
+                        {
+                            if((Get(vobj, pos->getType(), entry)) && entry->m_cascades)
+                                return true;
+                        }
+                    }
+                }
+            }
+        }
+        // try to strip typedef chains
+        const clang::TypedefType* type_tdef = type->getAs<clang::TypedefType>();
+        if (type_tdef)
+            if ((Get(vobj, type_tdef->getDecl()->getUnderlyingType(), entry)) && entry->m_cascades)
+                return true;
+        return false;
+    }
+    
+};
+
+class FormatManager : public IFormatChangeListener
+{
+    
+public:
+    
+    typedef bool(*ValueCallback)(void*, const char*, const ValueFormat::SharedPointer&);
+    typedef bool(*SummaryCallback)(void*, const char*, const SummaryFormat::SharedPointer&);
+    
+private:
+    
+    typedef std::map<const char*, ValueFormat::SharedPointer> ValueMap;
+    typedef std::map<const char*, SummaryFormat::SharedPointer> SummaryMap;
+    
+    typedef FormatNavigator<ValueMap, ValueCallback> ValueNavigator;
+    typedef FormatNavigator<SummaryMap, SummaryCallback> SummaryNavigator;
+    
+    ValueNavigator m_value_nav;
+    SummaryNavigator m_summary_nav;
+        
+    uint32_t m_last_revision;
+    
+public:
+        
+    FormatManager() : 
+    m_value_nav(this),
+    m_summary_nav(this),
+    m_last_revision(0)
+    {
+    }
+
 
+    ValueNavigator& Value() { return m_value_nav; }
+    SummaryNavigator& Summary() { return m_summary_nav; }
+    
     static bool
     GetFormatFromCString (const char *format_cstr,
                           bool partial_match_ok,
@@ -86,24 +332,23 @@
 
     static const char *
     GetFormatAsCString (lldb::Format format);
-
-private:
-    struct Entry 
+    
+    void
+    Changed()
     {
-        lldb::Format format;
-        bool cascades;
-        Entry (lldb::Format f = lldb::eFormatInvalid, bool c = false) : 
-            format (f), 
-            cascades (c) 
-        {
-        }
-    };
+        __sync_add_and_fetch(&m_last_revision, +1);
+    }
+    
+    uint32_t
+    GetCurrentRevision() const
+    {
+        return m_last_revision;
+    }
     
-    typedef std::map<const char*, Entry> FormatMap;
-    typedef FormatMap::iterator FormatIterator;
+    ~FormatManager()
+    {
+    }
 
-    FormatMap m_format_map;
-    Mutex m_format_map_mutex;
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Wed Jun 29 17:27:15 2011
@@ -64,6 +64,12 @@
 class ValueObject : public UserID
 {
 public:
+    
+    enum GetExpressionPathFormat
+    {
+        eDereferencePointers = 1,
+        eHonorPointers,
+    };
 
     class EvaluationPoint 
     {
@@ -262,8 +268,8 @@
     GetBaseClassPath (Stream &s);
 
     virtual void
-    GetExpressionPath (Stream &s, bool qualify_cxx_base_classes);
-
+    GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat = eDereferencePointers);
+    
     virtual bool
     IsInScope ()
     {
@@ -347,6 +353,9 @@
 
     bool
     UpdateValueIfNeeded ();
+    
+    void
+    UpdateFormatsIfNeeded();
 
     DataExtractor &
     GetDataExtractor ();
@@ -508,7 +517,9 @@
     ValueObject *m_deref_valobj;
 
     lldb::Format        m_format;
-    lldb::Format        m_last_format;
+    uint32_t            m_last_format_mgr_revision;
+    lldb::SummaryFormatSP m_last_summary_format;
+    lldb::ValueFormatSP m_last_value_format;
     bool                m_value_is_valid:1,
                         m_value_did_change:1,
                         m_children_count_valid:1,

Modified: lldb/trunk/include/lldb/Symbol/ClangASTType.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTType.h?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTType.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTType.h Wed Jun 29 17:27:15 2011
@@ -182,6 +182,13 @@
                  
     static lldb::Format
     GetFormat (lldb::clang_type_t opaque_clang_qual_type);
+    
+    uint32_t
+    GetTypeByteSize();
+    
+    static uint32_t
+    GetTypeByteSize(clang::ASTContext *ast_context,
+                    lldb::clang_type_t opaque_clang_qual_type);
 
     bool
     GetValueAsScalar (const DataExtractor &data,

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=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward-rtti.h (original)
+++ lldb/trunk/include/lldb/lldb-forward-rtti.h Wed Jun 29 17:27:15 2011
@@ -60,6 +60,7 @@
     typedef SharedPtr<lldb_private::StopInfo>::Type StopInfoSP;
     typedef SharedPtr<lldb_private::StoppointLocation>::Type StoppointLocationSP;
     typedef SharedPtr<lldb_private::Stream>::Type StreamSP;
+    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::Target>::Type TargetSP;
@@ -72,6 +73,7 @@
     typedef SharedPtr<lldb_private::UnwindPlan>::Type UnwindPlanSP;
     typedef SharedPtr<lldb_private::ValueObject>::Type ValueObjectSP;
     typedef SharedPtr<lldb_private::Value>::Type ValueSP;
+    typedef SharedPtr<lldb_private::ValueFormat>::Type ValueFormatSP;
     typedef SharedPtr<lldb_private::ValueList>::Type ValueListSP;
     typedef SharedPtr<lldb_private::Variable>::Type VariableSP;
     typedef SharedPtr<lldb_private::VariableList>::Type VariableListSP;

Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Wed Jun 29 17:27:15 2011
@@ -76,6 +76,7 @@
 class   FileSpec;
 class   FileSpecList;
 class   Flags;
+class   FormatManager;
 class   FuncUnwinders;
 class   Function;
 class   FunctionInfo;
@@ -130,6 +131,7 @@
 class   StreamFile;
 class   StreamString;
 class   StringList;
+class   SummaryFormat;
 class   Symbol;
 class   SymbolContext;
 class   SymbolContextList;
@@ -164,6 +166,7 @@
 class   UserSettingsController;
 class   VMRange;
 class   Value;
+class   ValueFormat;
 class   ValueList;
 class   ValueObject;
 class   ValueObjectList;

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Jun 29 17:27:15 2011
@@ -924,7 +924,7 @@
 		26BC7E9610F1B85900F91463 /* Timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Timer.cpp; path = source/Core/Timer.cpp; sourceTree = "<group>"; };
 		26BC7E9810F1B85900F91463 /* UserID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UserID.cpp; path = source/Core/UserID.cpp; sourceTree = "<group>"; };
 		26BC7E9910F1B85900F91463 /* Value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Value.cpp; path = source/Core/Value.cpp; sourceTree = "<group>"; };
-		26BC7E9A10F1B85900F91463 /* ValueObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObject.cpp; path = source/Core/ValueObject.cpp; sourceTree = "<group>"; };
+		26BC7E9A10F1B85900F91463 /* ValueObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; name = ValueObject.cpp; path = source/Core/ValueObject.cpp; sourceTree = "<group>"; };
 		26BC7E9B10F1B85900F91463 /* ValueObjectChild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectChild.cpp; path = source/Core/ValueObjectChild.cpp; sourceTree = "<group>"; };
 		26BC7E9C10F1B85900F91463 /* ValueObjectList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectList.cpp; path = source/Core/ValueObjectList.cpp; sourceTree = "<group>"; };
 		26BC7E9D10F1B85900F91463 /* ValueObjectVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectVariable.cpp; path = source/Core/ValueObjectVariable.cpp; sourceTree = "<group>"; };

Modified: lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme (original)
+++ lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme Wed Jun 29 17:27:15 2011
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   version = "1.3">
+   version = "1.8">
    <BuildAction
       parallelizeBuildables = "NO"
       buildImplicitDependencies = "YES">
@@ -77,7 +77,7 @@
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       customWorkingDirectory = "/Volumes/work/gclayton/Documents/devb/attach"
-      buildConfiguration = "Release"
+      buildConfiguration = "Debug"
       ignoresPersistentStateOnLaunch = "YES"
       enablesOpenGLESFrameCapture = "YES">
       <BuildableProductRunnable>

Modified: lldb/trunk/source/Commands/CommandObjectType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectType.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectType.cpp Wed Jun 29 17:27:15 2011
@@ -25,10 +25,10 @@
 using namespace lldb_private;
 
 //-------------------------------------------------------------------------
-// CommandObjectTypeAdd
+// CommandObjectTypeFormatAdd
 //-------------------------------------------------------------------------
 
-class CommandObjectTypeAdd : public CommandObject
+class CommandObjectTypeFormatAdd : public CommandObject
 {
     
 private:
@@ -97,7 +97,7 @@
     }
     
 public:
-    CommandObjectTypeAdd (CommandInterpreter &interpreter) :
+    CommandObjectTypeFormatAdd (CommandInterpreter &interpreter) :
     CommandObject (interpreter,
                    "type format add",
                    "Add a new formatting style for a type.",
@@ -121,7 +121,7 @@
         m_arguments.push_back (type_arg);
     }
     
-    ~CommandObjectTypeAdd ()
+    ~CommandObjectTypeFormatAdd ()
     {
     }
     
@@ -138,9 +138,22 @@
         }
         
         const char* format_cstr = command.GetArgumentAtIndex(0);
+        
+        if (!format_cstr || !format_cstr[0])
+        {
+            result.AppendError("empty format strings not allowed");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
         lldb::Format format;
-        Error error = Args::StringToFormat(format_cstr, format, NULL);
+        Error error;
         
+        error = Args::StringToFormat(format_cstr, format, NULL);
+        ValueFormat::SharedPointer entry;
+        
+        entry.reset(new ValueFormat(format,m_options.m_cascade));
+
         if (error.Fail()) 
         {
             result.AppendError(error.AsCString());
@@ -153,7 +166,14 @@
         for(int i = 1; i < argc; i++) {
             const char* typeA = command.GetArgumentAtIndex(i);
             ConstString typeCS(typeA);
-            Debugger::AddFormatForType(typeCS, format, m_options.m_cascade);
+            if (typeCS)
+                Debugger::ValueFormats::Add(typeCS, entry);
+            else
+            {
+                result.AppendError("empty typenames not allowed");
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
         }
         
         result.SetStatus(eReturnStatusSuccessFinishNoResult);
@@ -163,7 +183,7 @@
 };
 
 OptionDefinition
-CommandObjectTypeAdd::CommandOptions::g_option_table[] =
+CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] =
 {
     { LLDB_OPT_SET_ALL, false, "cascade", 'c', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade to derived typedefs."},
     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
@@ -171,13 +191,13 @@
 
 
 //-------------------------------------------------------------------------
-// CommandObjectTypeDelete
+// CommandObjectTypeFormatDelete
 //-------------------------------------------------------------------------
 
-class CommandObjectTypeDelete : public CommandObject
+class CommandObjectTypeFormatDelete : public CommandObject
 {
 public:
-    CommandObjectTypeDelete (CommandInterpreter &interpreter) :
+    CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) :
     CommandObject (interpreter,
                    "type format delete",
                    "Delete an existing formatting style for a type.",
@@ -185,17 +205,17 @@
     {
         CommandArgumentEntry type_arg;
         CommandArgumentData type_style_arg;
-                
+        
         type_style_arg.arg_type = eArgTypeName;
         type_style_arg.arg_repetition = eArgRepeatPlain;
         
         type_arg.push_back (type_style_arg);
         
         m_arguments.push_back (type_arg);
-
+        
     }
     
-    ~CommandObjectTypeDelete ()
+    ~CommandObjectTypeFormatDelete ()
     {
     }
     
@@ -214,7 +234,15 @@
         const char* typeA = command.GetArgumentAtIndex(0);
         ConstString typeCS(typeA);
         
-        if (Debugger::DeleteFormatForType(typeCS))
+        if(!typeCS)
+        {
+            result.AppendError("empty typenames not allowed");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        
+        if (Debugger::ValueFormats::Delete(typeCS))
         {
             result.SetStatus(eReturnStatusSuccessFinishNoResult);
             return result.Succeeded();
@@ -225,31 +253,60 @@
             result.SetStatus(eReturnStatusFailed);
             return false;
         }
+        
+    }
+    
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeFormatClear
+//-------------------------------------------------------------------------
 
+class CommandObjectTypeFormatClear : public CommandObject
+{
+public:
+    CommandObjectTypeFormatClear (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type format clear",
+                   "Delete all existing format styles.",
+                   NULL)
+    {
+    }
+    
+    ~CommandObjectTypeFormatClear ()
+    {
+    }
+    
+    bool
+    Execute (Args& command, CommandReturnObject &result)
+    {
+        Debugger::ValueFormats::Clear();
+        result.SetStatus(eReturnStatusSuccessFinishResult);
+        return result.Succeeded();
     }
     
 };
 
 //-------------------------------------------------------------------------
-// CommandObjectTypeList
+// CommandObjectTypeFormatList
 //-------------------------------------------------------------------------
 
-bool CommandObjectTypeList_LoopCallback(void* pt2self, const char* type, lldb::Format format, bool cascade);
+bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, const char* type, const ValueFormat::SharedPointer& entry);
 
-class CommandObjectTypeList;
+class CommandObjectTypeFormatList;
 
-struct CommandObjectTypeList_LoopCallbackParam {
-    CommandObjectTypeList* self;
+struct CommandObjectTypeFormatList_LoopCallbackParam {
+    CommandObjectTypeFormatList* self;
     CommandReturnObject* result;
     RegularExpression* regex;
-    CommandObjectTypeList_LoopCallbackParam(CommandObjectTypeList* S, CommandReturnObject* R,
+    CommandObjectTypeFormatList_LoopCallbackParam(CommandObjectTypeFormatList* S, CommandReturnObject* R,
                                             RegularExpression* X = NULL) : self(S), result(R), regex(X) {}
 };
 
-class CommandObjectTypeList : public CommandObject
+class CommandObjectTypeFormatList : public CommandObject
 {
 public:
-    CommandObjectTypeList (CommandInterpreter &interpreter) :
+    CommandObjectTypeFormatList (CommandInterpreter &interpreter) :
     CommandObject (interpreter,
                    "type format list",
                    "Show a list of current formatting styles.",
@@ -266,7 +323,7 @@
         m_arguments.push_back (type_arg);
     }
     
-    ~CommandObjectTypeList ()
+    ~CommandObjectTypeFormatList ()
     {
     }
     
@@ -275,16 +332,16 @@
     {
         const size_t argc = command.GetArgumentCount();
         
-        CommandObjectTypeList_LoopCallbackParam *param;
+        CommandObjectTypeFormatList_LoopCallbackParam *param;
         
         if (argc == 1) {
             RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
             regex->Compile(command.GetArgumentAtIndex(0));
-            param = new CommandObjectTypeList_LoopCallbackParam(this,&result,regex);
+            param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,regex);
         }
         else
-            param = new CommandObjectTypeList_LoopCallbackParam(this,&result);
-        Debugger::LoopThroughFormatList(CommandObjectTypeList_LoopCallback, param);
+            param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result);
+        Debugger::ValueFormats::LoopThrough(CommandObjectTypeFormatList_LoopCallback, param);
         delete param;
         result.SetStatus(eReturnStatusSuccessFinishResult);
         return result.Succeeded();
@@ -294,45 +351,438 @@
     
     bool
     LoopCallback (const char* type,
-                  lldb::Format format,
-                  bool cascade,
+                  const ValueFormat::SharedPointer& entry,
                   RegularExpression* regex,
                   CommandReturnObject *result)
     {
         if (regex == NULL || regex->Execute(type)) 
         {
-            result->GetOutputStream().Printf ("%s: %s\n", type, FormatManager::GetFormatAsCString (format));
+            result->GetOutputStream().Printf ("%s: %s%s\n", type, 
+                                              FormatManager::GetFormatAsCString (entry->m_format),
+                                              entry->m_cascades ? "" : " (not cascading)");
         }
         return true;
     }
     
-    friend bool CommandObjectTypeList_LoopCallback(void* pt2self, const char* type, lldb::Format format, bool cascade);
+    friend bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, const char* type, const ValueFormat::SharedPointer& entry);
     
 };
 
 bool
-CommandObjectTypeList_LoopCallback (
+CommandObjectTypeFormatList_LoopCallback (
                                     void* pt2self,
                                     const char* type,
-                                    lldb::Format format,
-                                    bool cascade)
+                                    const ValueFormat::SharedPointer& entry)
 {
-    CommandObjectTypeList_LoopCallbackParam* param = (CommandObjectTypeList_LoopCallbackParam*)pt2self;
-    return param->self->LoopCallback(type, format, cascade, param->regex, param->result);
+    CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self;
+    return param->self->LoopCallback(type, entry, param->regex, param->result);
 }
 
+
+
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeSummaryAdd
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeSummaryAdd : public CommandObject
+{
+    
+private:
+    
+    class CommandOptions : public Options
+    {
+    public:
+        
+        CommandOptions (CommandInterpreter &interpreter) :
+        Options (interpreter)
+        {
+        }
+        
+        virtual
+        ~CommandOptions (){}
+        
+        virtual Error
+        SetOptionValue (uint32_t option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+            bool success;
+            
+            switch (short_option)
+            {
+                case 'c':
+                    m_cascade = Args::StringToBoolean(option_arg, true, &success);
+                    if (!success)
+                        error.SetErrorStringWithFormat("Invalid value for cascade: %s.\n", option_arg);
+                    break;
+                case 'h':
+                    m_no_children = !Args::StringToBoolean(option_arg, true, &success);
+                    if (!success)
+                        error.SetErrorStringWithFormat("Invalid value for nochildren: %s.\n", option_arg);
+                    break;
+                case 'v':
+                    m_no_value = !Args::StringToBoolean(option_arg, true, &success);
+                    if (!success)
+                        error.SetErrorStringWithFormat("Invalid value for novalue: %s.\n", option_arg);
+                    break;
+                case 'o':
+                    m_one_liner = Args::StringToBoolean(option_arg, true, &success);
+                    if (!success)
+                        error.SetErrorStringWithFormat("Invalid value for oneliner: %s.\n", option_arg);
+                    break;
+                default:
+                    error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+                    break;
+            }
+            
+            return error;
+        }
+        
+        void
+        OptionParsingStarting ()
+        {
+            m_cascade = true;
+            m_no_children = true;
+            m_no_value = false;
+            m_one_liner = false;
+        }
+        
+        const OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+        
+        // Options table: Required for subclasses of Options.
+        
+        static OptionDefinition g_option_table[];
+        
+        // Instance variables to hold the values for command options.
+        
+        bool m_cascade;
+        bool m_no_children;
+        bool m_no_value;
+        bool m_one_liner;
+    };
+    
+    CommandOptions m_options;
+    
+    virtual Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+    
+public:
+    CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type summary add",
+                   "Add a new summary style for a type.",
+                   NULL), m_options (interpreter)
+    {
+        CommandArgumentEntry format_arg;
+        CommandArgumentData format_style_arg;
+        CommandArgumentEntry type_arg;
+        CommandArgumentData type_style_arg;
+        
+        format_style_arg.arg_type = eArgTypeFormat;
+        format_style_arg.arg_repetition = eArgRepeatPlain;
+        
+        type_style_arg.arg_type = eArgTypeName;
+        type_style_arg.arg_repetition = eArgRepeatPlus;
+        
+        format_arg.push_back (format_style_arg);
+        type_arg.push_back (type_style_arg);
+        
+        m_arguments.push_back (format_arg);
+        m_arguments.push_back (type_arg);
+    }
+    
+    ~CommandObjectTypeSummaryAdd ()
+    {
+    }
+    
+    bool
+    Execute (Args& command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        
+        // we support just one custom syntax: type summary add -o yes typeName
+        // anything else, must take the usual route
+        // e.g. type summary add -o yes "" type1 type2 ... typeN
+        
+        bool isValidShortcut = m_options.m_one_liner && (argc == 1);
+        bool isValid = (argc >= 2);
+        
+        if (!isValidShortcut && !isValid)
+        {
+            result.AppendErrorWithFormat ("%s takes two or more args.\n", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        const char* format_cstr = (isValidShortcut ? "" : command.GetArgumentAtIndex(0));
+        
+        if ( (!format_cstr || !format_cstr[0]) && !m_options.m_one_liner )
+        {
+            result.AppendError("empty summary strings not allowed");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        Error error;
+        
+        SummaryFormat::SharedPointer entry(new SummaryFormat(format_cstr,m_options.m_cascade,
+                                             m_options.m_no_children,m_options.m_no_value,
+                                             m_options.m_one_liner));
+        
+        if (error.Fail()) 
+        {
+            result.AppendError(error.AsCString());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        // now I have a valid format, let's add it to every type
+        
+        for(int i = (isValidShortcut ? 0 : 1); i < argc; i++) {
+            const char* typeA = command.GetArgumentAtIndex(i);
+            ConstString typeCS(typeA);
+            if (typeCS)
+                Debugger::SummaryFormats::Add(typeCS, entry);
+            else
+            {
+                result.AppendError("empty typenames not allowed");
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
+        }
+        result.SetStatus(eReturnStatusSuccessFinishNoResult);
+        return result.Succeeded();
+    }
+    
+};
+
+OptionDefinition
+CommandObjectTypeSummaryAdd::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, "show-children", 'h', required_argument, NULL, 0, eArgTypeBoolean,    "If true, print children."},
+    { LLDB_OPT_SET_ALL, false, "show-value", 'v', required_argument, NULL, 0, eArgTypeBoolean,    "If true, print value."},
+    { LLDB_OPT_SET_ALL, false, "one-liner", 'o', required_argument, NULL, 0, eArgTypeBoolean,    "If true, just print a one-line preformatted summary."},
+    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeSummaryDelete
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeSummaryDelete : public CommandObject
+{
+public:
+    CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type summary delete",
+                   "Delete an existing summary style for a type.",
+                   NULL)
+    {
+        CommandArgumentEntry type_arg;
+        CommandArgumentData type_style_arg;
+        
+        type_style_arg.arg_type = eArgTypeName;
+        type_style_arg.arg_repetition = eArgRepeatPlain;
+        
+        type_arg.push_back (type_style_arg);
+        
+        m_arguments.push_back (type_arg);
+        
+    }
+    
+    ~CommandObjectTypeSummaryDelete ()
+    {
+    }
+    
+    bool
+    Execute (Args& command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        
+        if (argc != 1)
+        {
+            result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        const char* typeA = command.GetArgumentAtIndex(0);
+        ConstString typeCS(typeA);
+        
+        if(!typeCS)
+        {
+            result.AppendError("empty typenames not allowed");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        
+        if (Debugger::SummaryFormats::Delete(typeCS))
+        {
+            result.SetStatus(eReturnStatusSuccessFinishNoResult);
+            return result.Succeeded();
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("no custom summary for %s.\n", typeA);
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+    }
+    
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeSummaryClear
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeSummaryClear : public CommandObject
+{
+public:
+    CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type summary clear",
+                   "Delete all existing summary styles.",
+                   NULL)
+    {
+    }
+    
+    ~CommandObjectTypeSummaryClear ()
+    {
+    }
+    
+    bool
+    Execute (Args& command, CommandReturnObject &result)
+    {
+        Debugger::SummaryFormats::Clear();
+        result.SetStatus(eReturnStatusSuccessFinishResult);
+        return result.Succeeded();
+    }
+    
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeSummaryList
+//-------------------------------------------------------------------------
+
+bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const SummaryFormat::SharedPointer& entry);
+
+class CommandObjectTypeSummaryList;
+
+struct CommandObjectTypeSummaryList_LoopCallbackParam {
+    CommandObjectTypeSummaryList* self;
+    CommandReturnObject* result;
+    RegularExpression* regex;
+    CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R,
+                                                  RegularExpression* X = NULL) : self(S), result(R), regex(X) {}
+};
+
+class CommandObjectTypeSummaryList : public CommandObject
+{
+public:
+    CommandObjectTypeSummaryList (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type summary list",
+                   "Show a list of current summary styles.",
+                   NULL)
+    {
+        CommandArgumentEntry type_arg;
+        CommandArgumentData type_style_arg;
+        
+        type_style_arg.arg_type = eArgTypeName;
+        type_style_arg.arg_repetition = eArgRepeatOptional;
+        
+        type_arg.push_back (type_style_arg);
+        
+        m_arguments.push_back (type_arg);
+    }
+    
+    ~CommandObjectTypeSummaryList ()
+    {
+    }
+    
+    bool
+    Execute (Args& command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        
+        CommandObjectTypeSummaryList_LoopCallbackParam *param;
+        
+        if (argc == 1) {
+            RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
+            regex->Compile(command.GetArgumentAtIndex(0));
+            param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex);
+        }
+        else
+            param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result);
+        Debugger::SummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
+        delete param;
+        result.SetStatus(eReturnStatusSuccessFinishResult);
+        return result.Succeeded();
+    }
+    
+private:
+    
+    bool
+    LoopCallback (const char* type,
+                  const SummaryFormat::SharedPointer& entry,
+                  RegularExpression* regex,
+                  CommandReturnObject *result)
+    {
+        if (regex == NULL || regex->Execute(type)) 
+        {
+                result->GetOutputStream().Printf ("%s: `%s`%s%s%s%s\n", type, 
+                                                  entry->m_format.c_str(),
+                                                  entry->m_cascades ? "" : " (not cascading)",
+                                                  entry->m_dont_show_children ? "" : " (show children)",
+                                                  entry->m_dont_show_value ? "" : " (show value)",
+                                                  entry->m_show_members_oneliner ? " (one-line printout)" : "");
+        }
+        return true;
+    }
+    
+    friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const SummaryFormat::SharedPointer& entry);
+    
+};
+
+bool
+CommandObjectTypeSummaryList_LoopCallback (
+                                          void* pt2self,
+                                          const char* type,
+                                          const SummaryFormat::SharedPointer& entry)
+{
+    CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
+    return param->self->LoopCallback(type, entry, param->regex, param->result);
+}
+
+
+
+
+
 class CommandObjectTypeFormat : public CommandObjectMultiword
 {
 public:
     CommandObjectTypeFormat (CommandInterpreter &interpreter) :
         CommandObjectMultiword (interpreter,
                                 "type format",
-                                "A set of commands for editing variable display options",
+                                "A set of commands for editing variable value display options",
                                 "type format [<sub-command-options>] ")
     {
-        LoadSubCommand ("add",    CommandObjectSP (new CommandObjectTypeAdd (interpreter)));
-        LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeDelete (interpreter)));
-        LoadSubCommand ("list",   CommandObjectSP (new CommandObjectTypeList (interpreter)));
+        LoadSubCommand ("add",    CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter)));
+        LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectTypeFormatClear (interpreter)));
+        LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter)));
+        LoadSubCommand ("list",   CommandObjectSP (new CommandObjectTypeFormatList (interpreter)));
     }
 
 
@@ -341,6 +791,27 @@
     }
 };
 
+class CommandObjectTypeSummary : public CommandObjectMultiword
+{
+public:
+    CommandObjectTypeSummary (CommandInterpreter &interpreter) :
+    CommandObjectMultiword (interpreter,
+                            "type format",
+                            "A set of commands for editing variable summary display options",
+                            "type summary [<sub-command-options>] ")
+    {
+        LoadSubCommand ("add",    CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter)));
+        LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));
+        LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));
+        LoadSubCommand ("list",   CommandObjectSP (new CommandObjectTypeSummaryList (interpreter)));
+    }
+    
+    
+    ~CommandObjectTypeSummary ()
+    {
+    }
+};
+
 //-------------------------------------------------------------------------
 // CommandObjectType
 //-------------------------------------------------------------------------
@@ -352,6 +823,7 @@
                             "type [<sub-command-options>]")
 {
     LoadSubCommand ("format",    CommandObjectSP (new CommandObjectTypeFormat (interpreter)));
+    LoadSubCommand ("summary",   CommandObjectSP (new CommandObjectTypeSummary (interpreter)));
 }
 
 

Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Wed Jun 29 17:27:15 2011
@@ -11,6 +11,9 @@
 
 #include <map>
 
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+
 #include "lldb/lldb-private.h"
 #include "lldb/Core/ConnectionFileDescriptor.h"
 #include "lldb/Core/FormatManager.h"
@@ -20,6 +23,7 @@
 #include "lldb/Core/StreamAsynchronousIO.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/Timer.h"
+#include "lldb/Core/ValueObject.h"
 #include "lldb/Host/Terminal.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Target/TargetList.h"
@@ -698,13 +702,20 @@
     const ExecutionContext *exe_ctx,
     const Address *addr,
     Stream &s,
-    const char **end
+    const char **end,
+    ValueObject* vobj
 )
 {
+    ValueObject* realvobj = NULL; // makes it super-easy to parse pointers
     bool success = true;
     const char *p;
     for (p = format; *p != '\0'; ++p)
     {
+        if(realvobj)
+        {
+            vobj = realvobj;
+            realvobj = NULL;
+        }
         size_t non_special_chars = ::strcspn (p, "${}\\");
         if (non_special_chars > 0)
         {
@@ -732,7 +743,7 @@
 
             ++p;  // Skip the '{'
             
-            if (FormatPrompt (p, sc, exe_ctx, addr, sub_strm, &p))
+            if (FormatPrompt (p, sc, exe_ctx, addr, sub_strm, &p, vobj))
             {
                 // The stream had all it needed
                 s.Write(sub_strm.GetData(), sub_strm.GetSize());
@@ -777,6 +788,284 @@
                         bool var_success = false;
                         switch (var_name_begin[0])
                         {
+                        case '*':
+                            {
+                                if (!vobj) break;
+                                var_name_begin++;
+                                lldb::clang_type_t pointer_clang_type = vobj->GetClangType();
+                                clang_type_t elem_or_pointee_clang_type;
+                                const Flags type_flags (ClangASTContext::GetTypeInfo (pointer_clang_type, 
+                                                                                      vobj->GetClangAST(), 
+                                                                                      &elem_or_pointee_clang_type));
+                                if (type_flags.Test (ClangASTContext::eTypeIsPointer))
+                                {
+                                    if (ClangASTContext::IsCharType (elem_or_pointee_clang_type))
+                                    {
+                                        StreamString sstr;
+                                        ExecutionContextScope *exe_scope = vobj->GetExecutionContextScope();
+                                        Process *process = exe_scope->CalculateProcess();
+                                        if(!process) break;
+                                        lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS;
+                                        AddressType cstr_address_type = eAddressTypeInvalid;
+                                        DataExtractor data;
+                                        size_t bytes_read = 0;
+                                        std::vector<char> data_buffer;
+                                        Error error;
+                                        cstr_address = vobj->GetPointerValue (cstr_address_type, true);
+                                        {
+                                            const size_t k_max_buf_size = 256;
+                                            data_buffer.resize (k_max_buf_size + 1);
+                                            // NULL terminate in case we don't get the entire C string
+                                            data_buffer.back() = '\0';
+                                            
+                                            sstr << '"';
+                                            
+                                            data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder());
+                                            while ((bytes_read = process->ReadMemory (cstr_address, &data_buffer.front(), k_max_buf_size, error)) > 0)
+                                            {
+                                                size_t len = strlen(&data_buffer.front());
+                                                if (len == 0)
+                                                    break;
+                                                if (len > bytes_read)
+                                                    len = bytes_read;
+                                                
+                                                data.Dump (&sstr,
+                                                           0,                 // Start offset in "data"
+                                                           eFormatCharArray,  // Print as characters
+                                                           1,                 // Size of item (1 byte for a char!)
+                                                           len,               // How many bytes to print?
+                                                           UINT32_MAX,        // num per line
+                                                           LLDB_INVALID_ADDRESS,// base address
+                                                           0,                 // bitfield bit size
+                                                           0);                // bitfield bit offset
+                                                
+                                                if (len < k_max_buf_size)
+                                                    break;
+                                                cstr_address += k_max_buf_size;
+                                            }
+                                            sstr << '"';
+                                            s.PutCString(sstr.GetData());
+                                            var_success = true;
+                                            break;
+                                        }
+                                    }
+                                    else /*if (ClangASTContext::IsAggregateType (elem_or_pointee_clang_type)) or this is some other pointer type*/
+                                    {
+                                        Error error;
+                                        realvobj = vobj;
+                                        vobj = vobj->Dereference(error).get();
+                                        if(!vobj || error.Fail())
+                                            break;
+                                    }
+                                }
+                                else
+                                    break;
+                            }
+                        case 'v':
+                            {
+                            const char* targetvalue;
+                            bool use_summary = false;
+                            ValueObject* target;
+                            lldb::Format custom_format = eFormatInvalid;
+                            int bitfield_lower = -1;
+                            int bitfield_higher = -1;
+                            if (!vobj) break;
+                            // simplest case ${var}, just print vobj's value
+                            if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0)
+                                target = vobj;
+                            else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0)
+                            {
+                                // this is a variable with some custom format applied to it
+                                const char* var_name_final;
+                                target = vobj;
+                                {
+                                    const char* percent_position = ::strchr(var_name_begin,'%'); // TODO: make this a constant
+                                    //if(!percent_position || percent_position > var_name_end)
+                                    //    var_name_final = var_name_end;
+                                    //else
+                                    //{
+                                    var_name_final = percent_position;
+                                    char* format_name = new char[var_name_end-var_name_final]; format_name[var_name_end-var_name_final-1] = '\0';
+                                    memcpy(format_name, var_name_final+1, var_name_end-var_name_final-1);
+                                    FormatManager::GetFormatFromCString(format_name,
+                                                                        true,
+                                                                        custom_format); // if this fails, custom_format is reset to invalid
+                                    delete format_name;
+                                    //}
+                                }
+                            }
+                            else if (::strncmp(var_name_begin,"var[",strlen("var[")) == 0)
+                            {
+                                // this is a bitfield variable
+                                const char *var_name_final;
+                                target = vobj;
+                                
+                                {
+                                    const char* percent_position = ::strchr(var_name_begin,'%');
+                                    if(!percent_position || percent_position > var_name_end)
+                                        var_name_final = var_name_end;
+                                    else
+                                    {
+                                        var_name_final = percent_position;
+                                        char* format_name = new char[var_name_end-var_name_final]; format_name[var_name_end-var_name_final-1] = '\0';
+                                        memcpy(format_name, var_name_final+1, var_name_end-var_name_final-1);
+                                        FormatManager::GetFormatFromCString(format_name,
+                                                                            true,
+                                                                            custom_format); // if this fails, custom_format is reset to invalid
+                                        delete format_name;
+                                    }
+                                }
+                                
+                                {
+                                    // code here might be simpler than in the case below
+                                    const char* open_bracket_position = ::strchr(var_name_begin,'[');
+                                    if(open_bracket_position && open_bracket_position < var_name_final)
+                                    {
+                                        char* separator_position = ::strchr(open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield
+                                        char* close_bracket_position = ::strchr(open_bracket_position,']');
+                                        // as usual, we assume that [] will come before %
+                                        //printf("trying to expand a []\n");
+                                        var_name_final = open_bracket_position;
+                                        if (separator_position == NULL || separator_position > var_name_end)
+                                        {
+                                            char *end = NULL;
+                                            bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0);
+                                            bitfield_higher = bitfield_lower;
+                                            //printf("got to read low=%d high same\n",bitfield_lower);
+                                        }
+                                        else if(close_bracket_position && close_bracket_position < var_name_end)
+                                        {
+                                            char *end = NULL;
+                                            bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0);
+                                            bitfield_higher = ::strtoul (separator_position+1, &end, 0);
+                                            //printf("got to read low=%d high=%d\n",bitfield_lower,bitfield_higher);
+                                        }
+                                        else
+                                            break;
+                                        if(bitfield_lower > bitfield_higher)
+                                            break;
+                                    }
+                                }
+                            }
+                                // this is ${var.something} or multiple .something nested
+                            else if (::strncmp (var_name_begin, "var", strlen("var")) == 0)
+                            {
+                                // check for custom format string
+                                
+                                // we need this because we might have ${var.something%format}. in this case var_name_end
+                                // still points to the closing }, but we must extract the variable name only up to
+                                // before the %. var_name_final will point to that % sign position
+                                const char* var_name_final;
+                                
+                                {
+                                    const char* percent_position = ::strchr(var_name_begin,'%');
+                                    if(!percent_position || percent_position > var_name_end)
+                                        var_name_final = var_name_end;
+                                    else
+                                    {
+                                        var_name_final = percent_position;
+                                        char* format_name = new char[var_name_end-var_name_final]; format_name[var_name_end-var_name_final-1] = '\0';
+                                        memcpy(format_name, var_name_final+1, var_name_end-var_name_final-1);
+                                        FormatManager::GetFormatFromCString(format_name,
+                                                                            true,
+                                                                            custom_format); // if this fails, custom_format is reset to invalid
+                                        delete format_name;
+                                    }
+                                }
+                                
+                                {
+                                    const char* open_bracket_position = ::strchr(var_name_begin,'[');
+                                    if(open_bracket_position && open_bracket_position < var_name_final)
+                                    {
+                                        char* separator_position = ::strchr(open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield
+                                        char* close_bracket_position = ::strchr(open_bracket_position,']');
+                                        // as usual, we assume that [] will come before %
+                                        //printf("trying to expand a []\n");
+                                        var_name_final = open_bracket_position;
+                                        if (separator_position == NULL || separator_position > var_name_end)
+                                        {
+                                            char *end = NULL;
+                                            bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0);
+                                            bitfield_higher = bitfield_lower;
+                                            //printf("got to read low=%d high same\n",bitfield_lower);
+                                        }
+                                        else if(close_bracket_position && close_bracket_position < var_name_end)
+                                        {
+                                            char *end = NULL;
+                                            bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0);
+                                            bitfield_higher = ::strtoul (separator_position+1, &end, 0);
+                                            //printf("got to read low=%d high=%d\n",bitfield_lower,bitfield_higher);
+                                        }
+                                        else
+                                            break;
+                                        if(bitfield_lower > bitfield_higher)
+                                            break;
+                                        //*((char*)open_bracket_position) = '\0';
+                                        //printf("variable name is %s\n",var_name_begin);
+                                        //*((char*)open_bracket_position) = '[';
+                                    }
+                                }
+
+                                Error error;
+                                lldb::VariableSP var_sp;
+                                StreamString sstring;
+                                vobj->GetExpressionPath(sstring, true, ValueObject::eHonorPointers);
+                                //printf("name to expand in phase 0: %s\n",sstring.GetData());
+                                sstring.PutRawBytes(var_name_begin+3, var_name_final-var_name_begin-3);
+                                //printf("name to expand in phase 1: %s\n",sstring.GetData());
+                                std::string name = std::string(sstring.GetData());
+                                target = exe_ctx->frame->GetValueForVariableExpressionPath (name.c_str(),
+                                                                                            eNoDynamicValues, 
+                                                                                            0,
+                                                                                            var_sp,
+                                                                                            error).get();
+                                if (error.Fail())
+                                {
+                                    //printf("ERROR: %s\n",error.AsCString("unknown"));
+                                    break;
+                                }
+                            }
+                            else
+                                break;
+                            if(*(var_name_end+1)=='s')
+                            {
+                                use_summary = true;
+                                var_name_end++;
+                            }
+                            if (bitfield_lower >= 0)
+                            {
+                                //printf("trying to print a []\n");
+                                // format this as a bitfield
+                                DataExtractor extractor = target->GetDataExtractor();
+                                uint32_t item_byte_size = ClangASTType::GetTypeByteSize(target->GetClangAST(), target->GetClangType());
+                                if(custom_format == eFormatInvalid)
+                                    custom_format = eFormatHex;
+                                var_success = 
+                                    extractor.Dump(&s, 0, custom_format, item_byte_size, 1, 1, LLDB_INVALID_ADDRESS, bitfield_higher-bitfield_lower+1, bitfield_lower) > 0;
+                                //printf("var_success = %s\n",var_success ? "true" : "false");
+                            }
+                            else
+                            {
+                                //printf("here I come 1\n");
+                                // format this as usual
+                                if(custom_format != eFormatInvalid)
+                                    target->SetFormat(custom_format);
+                                //printf("here I come 2\n");
+                                if(!use_summary)
+                                    targetvalue = target->GetValueAsCString();
+                                else
+                                    targetvalue = target->GetSummaryAsCString();
+                                //printf("here I come 3\n");
+                                if(targetvalue)
+                                    s.PutCString(targetvalue);
+                                var_success = targetvalue;
+                                //printf("here I come 4 : %s\n",var_success ? "good" : "bad");
+                                if(custom_format != eFormatInvalid)
+                                    target->SetFormat(eFormatDefault);
+                                //printf("here I come 5\n");
+                            }
+                                break;
+                            }
                         case 'a':
                             if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0)
                             {
@@ -1321,27 +1610,76 @@
 }
 
 bool
-Debugger::GetFormatForType (const ConstString &type, lldb::Format& format, bool& cascade)
+Debugger::ValueFormats::Get(ValueObject& vobj, ValueFormat::SharedPointer &entry)
+{
+    return GetFormatManager().Value().Get(vobj,entry);
+}
+
+void
+Debugger::ValueFormats::Add(const ConstString &type, const ValueFormat::SharedPointer &entry)
+{
+    GetFormatManager().Value().Add(type.AsCString(),entry);
+}
+
+bool
+Debugger::ValueFormats::Delete(const ConstString &type)
 {
-    return GetFormatManager().GetFormatForType(type, format, cascade);
+    return GetFormatManager().Value().Delete(type.AsCString());
 }
 
 void
-Debugger::AddFormatForType (const ConstString &type, lldb::Format format, bool cascade)
+Debugger::ValueFormats::Clear()
 {
-    GetFormatManager().AddFormatForType(type,format, cascade);
+    GetFormatManager().Value().Clear();
 }
 
+void
+Debugger::ValueFormats::LoopThrough(FormatManager::ValueCallback callback, void* callback_baton)
+{
+    GetFormatManager().Value().LoopThrough(callback, callback_baton);
+}
+
+uint32_t
+Debugger::ValueFormats::GetCurrentRevision()
+{
+    return GetFormatManager().GetCurrentRevision();
+}
+
+
 bool
-Debugger::DeleteFormatForType (const ConstString &type)
+Debugger::SummaryFormats::Get(ValueObject& vobj, SummaryFormat::SharedPointer &entry)
 {
-    return GetFormatManager().DeleteFormatForType(type);
+    return GetFormatManager().Summary().Get(vobj,entry);
 }
 
 void
-Debugger::LoopThroughFormatList (FormatManager::Callback callback, void* callback_baton)
+Debugger::SummaryFormats::Add(const ConstString &type, const SummaryFormat::SharedPointer &entry)
+{
+    GetFormatManager().Summary().Add(type.AsCString(),entry);
+}
+
+bool
+Debugger::SummaryFormats::Delete(const ConstString &type)
+{
+    return GetFormatManager().Summary().Delete(type.AsCString());
+}
+
+void
+Debugger::SummaryFormats::Clear()
+{
+    GetFormatManager().Summary().Clear();
+}
+
+void
+Debugger::SummaryFormats::LoopThrough(FormatManager::SummaryCallback callback, void* callback_baton)
+{
+    GetFormatManager().Summary().LoopThrough(callback, callback_baton);
+}
+
+uint32_t
+Debugger::SummaryFormats::GetCurrentRevision()
 {
-    return GetFormatManager().LoopThroughFormatList(callback, callback_baton);
+    return GetFormatManager().GetCurrentRevision();
 }
 
 #pragma mark Debugger::SettingsController

Modified: lldb/trunk/source/Core/FormatManager.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatManager.cpp?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/source/Core/FormatManager.cpp (original)
+++ lldb/trunk/source/Core/FormatManager.cpp Wed Jun 29 17:27:15 2011
@@ -151,61 +151,3 @@
         return g_format_infos[format].format_name;
     return NULL;
 }
-
-bool 
-FormatManager::GetFormatForType (const ConstString &type_name, lldb::Format& format, bool& cascade)
-{
-    Mutex::Locker locker (m_format_map_mutex);
-    FormatMap& fmtmap = m_format_map;
-    FormatMap::iterator iter = fmtmap.find(type_name.GetCString());
-    if(iter == fmtmap.end())
-        return false;
-    else {
-        format = iter->second.format;
-        cascade = iter->second.cascades;
-        return true;
-    }
-}
-
-void
-FormatManager::AddFormatForType (const ConstString &type_name, lldb::Format format, bool cascade)
-{
-    Entry entry(format, cascade);
-    Mutex::Locker locker (m_format_map_mutex);
-    FormatMap& fmtmap = m_format_map;
-    fmtmap[type_name.GetCString()] = entry;
-}
-
-bool
-FormatManager::DeleteFormatForType (const ConstString &type_name)
-{
-    Mutex::Locker locker (m_format_map_mutex);
-    FormatMap& fmtmap = m_format_map;
-    const char* typeCS = type_name.GetCString();
-    FormatMap::iterator iter = fmtmap.find(typeCS);
-    if (iter != fmtmap.end())
-    {
-        fmtmap.erase(typeCS);
-        return true;
-    }
-    return false;
-}
-
-void
-FormatManager::LoopThroughFormatList (Callback callback, void* param)
-{
-    if (callback)
-    {
-        Mutex::Locker locker (m_format_map_mutex);
-        FormatIterator pos, end = m_format_map.end();
-        for (pos = m_format_map.begin(); pos != end; ++pos)
-        {
-            const char* type = pos->first;
-            lldb::Format format = pos->second.format;
-            bool cascade = pos->second.cascades;
-            if (!callback(param, type, format, cascade)) 
-                break;
-        }
-    }
-}
-

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Wed Jun 29 17:27:15 2011
@@ -19,6 +19,7 @@
 
 // Project includes
 #include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/ValueObjectChild.h"
 #include "lldb/Core/ValueObjectConstResult.h"
@@ -71,7 +72,10 @@
     m_children_count_valid (false),
     m_old_value_valid (false),
     m_pointers_point_to_load_addrs (false),
-    m_is_deref_of_parent (false)
+    m_is_deref_of_parent (false),
+    m_last_format_mgr_revision(0),
+    m_last_summary_format(),
+    m_last_value_format()
 {
     m_manager->ManageObject(this);
 }
@@ -103,7 +107,10 @@
     m_children_count_valid (false),
     m_old_value_valid (false),
     m_pointers_point_to_load_addrs (false),
-    m_is_deref_of_parent (false)
+    m_is_deref_of_parent (false),
+    m_last_format_mgr_revision(0),
+    m_last_summary_format(),
+    m_last_value_format()
 {
     m_manager = new ValueObjectManager();
     m_manager->ManageObject (this);
@@ -119,6 +126,9 @@
 bool
 ValueObject::UpdateValueIfNeeded ()
 {
+    
+    UpdateFormatsIfNeeded();
+    
     // If this is a constant value, then our success is predicated on whether
     // we have an error or not
     if (GetIsConstant())
@@ -168,6 +178,26 @@
     return m_error.Success();
 }
 
+void
+ValueObject::UpdateFormatsIfNeeded()
+{
+    /*printf("CHECKING FOR UPDATES. I am at revision %d, while the format manager is at revision %d\n",
+           m_last_format_mgr_revision,
+           Debugger::ValueFormats::GetCurrentRevision());*/
+    if (m_last_format_mgr_revision != Debugger::ValueFormats::GetCurrentRevision())
+    {
+        if (m_last_summary_format.get())
+            m_last_summary_format.reset((SummaryFormat*)NULL);
+        if (m_last_value_format.get())
+            m_last_value_format.reset((ValueFormat*)NULL);
+        Debugger::ValueFormats::Get(*this, m_last_value_format);
+        Debugger::SummaryFormats::Get(*this, m_last_summary_format);
+        m_last_format_mgr_revision = Debugger::ValueFormats::GetCurrentRevision();
+        m_value_str.clear();
+        m_summary_str.clear();
+    }
+}
+
 DataExtractor &
 ValueObject::GetDataExtractor ()
 {
@@ -454,9 +484,23 @@
 ValueObject::GetSummaryAsCString ()
 {
     if (UpdateValueIfNeeded ())
-    {
+    {        
         if (m_summary_str.empty())
         {
+            if (m_last_summary_format.get())
+            {
+                StreamString s;
+                ExecutionContext exe_ctx;
+                this->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx);
+                SymbolContext sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything);
+                if (Debugger::FormatPrompt(m_last_summary_format->m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, this))
+                {
+                    m_summary_str.swap(s.GetString());
+                    return m_summary_str.c_str();
+                }
+                return NULL;
+            }
+            
             clang_type_t clang_type = GetClangType();
 
             // See if this is a pointer to a C string?
@@ -664,28 +708,6 @@
     {
         if (UpdateValueIfNeeded())
         {
-            /*
-             this is a quick fix for the case in which we display a variable, then change its format with
-             type format add and the old display string keeps showing until one steps through the code
-             */
-            {
-                const Value::ContextType context_type = m_value.GetContextType();
-                switch (context_type)
-                {
-                    case Value::eContextTypeClangType:
-                    case Value::eContextTypeLLDBType:
-                    case Value::eContextTypeVariable:
-                        {
-                            Format format = GetFormat();
-                            if (format != m_last_format)
-                                m_value_str.clear();
-                        }
-                        break;
-
-                    default:
-                        break;
-                }
-            }
             if (m_value_str.empty())
             {
                 const Value::ContextType context_type = m_value.GetContextType();
@@ -701,13 +723,18 @@
                         {
                             StreamString sstr;
                             Format format = GetFormat();
-                            if (format == eFormatDefault)
-                                format = ClangASTType::GetFormat(clang_type);
+                            if (format == eFormatDefault)                                
+                            {
+                                if (m_last_value_format)
+                                    format = m_last_value_format->m_format;
+                                else
+                                    format = ClangASTType::GetFormat(clang_type);
+                            }
 
                             if (ClangASTType::DumpTypeValue (GetClangAST(),            // The clang AST
                                                              clang_type,               // The clang type to display
                                                              &sstr,
-                                                             m_last_format = format,   // Format to display this type with
+                                                             format,                   // Format to display this type with
                                                              m_data,                   // Data to extract from
                                                              0,                        // Byte offset into "m_data"
                                                              GetByteSize(),            // Byte size of item in "m_data"
@@ -1123,16 +1150,22 @@
 }
 
 void
-ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes)
+ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat)
 {
     const bool is_deref_of_parent = IsDereferenceOfParent ();
-    
-    if (is_deref_of_parent)
-        s.PutCString("*(");
 
-    if (GetParent())
-        GetParent()->GetExpressionPath (s, qualify_cxx_base_classes);
+    if(is_deref_of_parent && epformat == eDereferencePointers) {
+        // this is the original format of GetExpressionPath() producing code like *(a_ptr).memberName, which is entirely
+        // fine, until you put this into StackFrame::GetValueForVariableExpressionPath() which prefers to see a_ptr->memberName.
+        // the eHonorPointers mode is meant to produce strings in this latter format
+        s.PutCString("*(");
+    }
     
+    ValueObject* parent = GetParent();
+    
+    if (parent)
+        parent->GetExpressionPath (s, qualify_cxx_base_classes, epformat);
+            
     if (!IsBaseClass())
     {
         if (!is_deref_of_parent)
@@ -1145,14 +1178,21 @@
                 {
                     const uint32_t non_base_class_parent_type_info = ClangASTContext::GetTypeInfo (non_base_class_parent_clang_type, NULL, NULL);
                     
-                    if (non_base_class_parent_type_info & ClangASTContext::eTypeIsPointer)
+                    if(parent && parent->IsDereferenceOfParent() && epformat == eHonorPointers)
                     {
                         s.PutCString("->");
                     }
-                    else if ((non_base_class_parent_type_info & ClangASTContext::eTypeHasChildren) &&
-                        !(non_base_class_parent_type_info & ClangASTContext::eTypeIsArray))
-                    {
-                        s.PutChar('.');
+                    else
+                    {                    
+                        if (non_base_class_parent_type_info & ClangASTContext::eTypeIsPointer)
+                        {
+                            s.PutCString("->");
+                        }
+                        else if ((non_base_class_parent_type_info & ClangASTContext::eTypeHasChildren) &&
+                                 !(non_base_class_parent_type_info & ClangASTContext::eTypeIsArray))
+                        {
+                            s.PutChar('.');
+                        }
                     }
                 }
             }
@@ -1170,8 +1210,9 @@
         }
     }
     
-    if (is_deref_of_parent)
+    if (is_deref_of_parent && epformat == eDereferencePointers) {
         s.PutChar(')');
+    }
 }
 
 void
@@ -1245,6 +1286,8 @@
         }
         
         const char *val_cstr = NULL;
+        const char *sum_cstr = NULL;
+        SummaryFormat* entry = valobj->m_last_summary_format.get();
         
         if (err_cstr == NULL)
         {
@@ -1261,10 +1304,13 @@
             const bool is_ref = type_flags.Test (ClangASTContext::eTypeIsReference);
             if (print_valobj)
             {
-                const char *sum_cstr = valobj->GetSummaryAsCString();
+                
+                sum_cstr = valobj->GetSummaryAsCString();
 
-                if (val_cstr)
-                    s.Printf(" %s", val_cstr);
+                // We must calculate this value in realtime because entry might alter this variable's value
+                // (e.g. by saying ${var%fmt}) and render precached values useless
+                if (val_cstr && (!entry || entry->DoesPrintValue() || !sum_cstr))
+                    s.Printf(" %s", valobj->GetValueAsCString());
 
                 if (sum_cstr)
                     s.Printf(" %s", sum_cstr);
@@ -1314,7 +1360,32 @@
                         print_children = false;
                 }
                 
-                if (print_children)
+                if (entry && entry->IsOneliner())
+                {
+                    const uint32_t num_children = valobj->GetNumChildren();
+                    if (num_children)
+                    {
+                        
+                        s.PutChar('(');
+                        
+                        for (uint32_t idx=0; idx<num_children; ++idx)
+                        {
+                            ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true));
+                            if (child_sp.get())
+                            {
+                                if (idx)
+                                    s.PutCString(", ");
+                                s.PutCString(child_sp.get()->GetName().AsCString());
+                                s.PutChar('=');
+                                s.PutCString(child_sp.get()->GetValueAsCString());
+                            }
+                        }
+                        
+                        s.PutChar(')');
+                        s.EOL();
+                    }
+                }
+                else if (print_children && (!entry || entry->DoesPrintChildren() || !sum_cstr))
                 {
                     const uint32_t num_children = valobj->GetNumChildren();
                     if (num_children)

Modified: lldb/trunk/source/Symbol/ClangASTType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTType.cpp?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTType.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTType.cpp Wed Jun 29 17:27:15 2011
@@ -247,25 +247,8 @@
 lldb::Format
 ClangASTType::GetFormat (clang_type_t clang_type)
 {
-    // first of all, check for a valid format for this type itself
     clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
-    lldb::Format format;
-    bool cascade;
-    if(Debugger::GetFormatForType(GetClangTypeName(qual_type), format, cascade))
-        return format; // return it if found
-    
-    // here, I know this type does not have a direct format. two things can happen:
-    // 1) this is a typedef - I expand this to its parent type and look there
-    // 2) this is not a typedef - I use the default formatting options
-    const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
-    while (typedef_type) {
-        qual_type = typedef_type->getDecl()->getUnderlyingType();
-        std::string name = qual_type.getAsString();
-        if(Debugger::GetFormatForType(GetClangTypeName(qual_type), format, cascade) && cascade) // if I have a cascading format...
-            return format; // ...use it
-        typedef_type = qual_type->getAs<clang::TypedefType>(); // try to expand another level
-    }
-    
+
     switch (qual_type->getTypeClass())
     {
     case clang::Type::FunctionNoProto:
@@ -1347,6 +1330,23 @@
                            data);
 }
 
+uint32_t
+ClangASTType::GetTypeByteSize()
+{
+    return GetTypeByteSize(m_ast,
+                           m_type);
+}
+
+uint32_t
+ClangASTType::GetTypeByteSize(
+                clang::ASTContext *ast_context,
+                lldb::clang_type_t opaque_clang_qual_type)
+{
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_clang_qual_type));
+    
+    return (ast_context->getTypeSize (qual_type) + 7) / 8;
+}
+
 
 bool
 ClangASTType::ReadFromMemory

Modified: lldb/trunk/test/functionalities/data-formatter/TestDataFormatter.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/TestDataFormatter.py?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/TestDataFormatter.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/TestDataFormatter.py Wed Jun 29 17:27:15 2011
@@ -51,11 +51,8 @@
         # 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 delete Speed', check=False)
-            self.runCmd('type format delete Bitfield', check=False)
-            self.runCmd('type format delete RealNumber', check=False)
-            self.runCmd('type format delete Type2', check=False)
-            self.runCmd('type format delete Type1', check=False)
+            self.runCmd('type format clear', check=False)
+            self.runCmd('type summary clear', check=False)
 
         # Execute the cleanup function during test case tear down.
         self.addTearDownHook(cleanup)
@@ -87,6 +84,33 @@
         # Delete type format for 'Speed', we should expect an error message.
         self.expect("type format delete Speed", error=True,
             substrs = ['no custom format for Speed'])
+        
+        # For some reason the type system is calling this "struct"
+        self.runCmd("type summary add -o yes \"\" Point")
+            
+        self.expect("frame variable iAmSomewhere",
+            substrs = ['x=4',
+                       'y=6'])
+        
+        self.expect("type summary list",
+            substrs = ['Point',
+                       'one-line'])
+
+        self.runCmd("type summary add \"y=${var.y%x}\" Point")
+
+        self.expect("frame variable iAmSomewhere",
+            substrs = ['y=0x'])
+
+        self.runCmd("type summary add \"hello\" Point -h yes")
+
+        self.expect("type summary list",
+            substrs = ['Point',
+                       'show children'])
+        
+        self.expect("frame variable iAmSomewhere",
+            substrs = ['hello',
+                       'x = 4',
+                       '}'])
 
 
 if __name__ == '__main__':

Modified: lldb/trunk/test/functionalities/data-formatter/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/main.cpp?rev=134108&r1=134107&r2=134108&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/main.cpp (original)
+++ lldb/trunk/test/functionalities/data-formatter/main.cpp Wed Jun 29 17:27:15 2011
@@ -31,6 +31,12 @@
 typedef int ChildType; // should show as int
 typedef int AnotherChildType; // should show as int
 
+struct Point {
+    int x;
+    int y;
+    Point(int X = 3, int Y = 2) : x(X), y(Y) {}
+};
+
 int main (int argc, const char * argv[])
 {
     
@@ -57,6 +63,8 @@
     
     Speed* SPPtrILookHex = new Speed(16);
     
+    Point iAmSomewhere(4,6);
+        
     return 0; // Set break point at this line.
 }
 





More information about the lldb-commits mailing list