diff options
author | Enrico Granata <granata.enrico@gmail.com> | 2011-07-19 18:03:25 +0000 |
---|---|---|
committer | Enrico Granata <granata.enrico@gmail.com> | 2011-07-19 18:03:25 +0000 |
commit | 20edcdbe8a267924e19646374cbead05ec9ea027 (patch) | |
tree | 9fa2db828ee6766299dde760d07431b4602c2423 /lldb | |
parent | 33824e572253bcb491a7e0d2a09a7f857f259f34 (diff) | |
download | bcm5719-llvm-20edcdbe8a267924e19646374cbead05ec9ea027.tar.gz bcm5719-llvm-20edcdbe8a267924e19646374cbead05ec9ea027.zip |
The implementation of categories is now synchronization safe
Code cleanup:
- The Format Manager implementation is now split between two files: FormatClasses.{h|cpp} where the
actual formatter classes (ValueFormat, SummaryFormat, ...) are implemented and
FormatManager.{h|cpp} where the infrastructure classes (FormatNavigator, FormatManager, ...)
are contained. The wrapper code always remains in Debugger.{h|cpp}
- Several leftover fields, methods and comments from previous design choices have been removed
type category subcommands (enable, disable, delete) now can take a list of category names as input
- for type category enable, saying "enable A B C" is the same as saying
enable C
enable B
enable A
(the ordering is relevant in enabling categories, and it is expected that a user typing
enable A B C wants to look into category A, then into B, then into C and not the other
way round)
- for the other two commands, the order is not really relevant (however, the same inverted ordering
is used for consistency)
llvm-svn: 135494
Diffstat (limited to 'lldb')
21 files changed, 805 insertions, 678 deletions
diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index af8524144be..b06db9a090f 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -501,10 +501,7 @@ public: static uint32_t GetCount(); }; - - static lldb::FormatCategorySP - SummaryFormats(const char* category_name = NULL); - + static bool GetSummaryFormat(ValueObject& vobj, lldb::SummaryFormatSP& entry); diff --git a/lldb/include/lldb/Core/FormatClasses.h b/lldb/include/lldb/Core/FormatClasses.h new file mode 100644 index 00000000000..a6002abb54e --- /dev/null +++ b/lldb/include/lldb/Core/FormatClasses.h @@ -0,0 +1,244 @@ +//===-- FormatClasses.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_FormatClasses_h_ +#define lldb_FormatClasses_h_ + +// C Includes + +#include <stdint.h> +#include <unistd.h> + +// C++ Includes +#include <string> + +// Other libraries and framework includes + +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" +#include "lldb/Symbol/SymbolContext.h" + +namespace lldb_private { + +struct ValueFormat +{ + bool m_cascades; + bool m_skip_pointers; + bool m_skip_references; + lldb::Format m_format; + ValueFormat (lldb::Format f = lldb::eFormatInvalid, + bool casc = false, + bool skipptr = false, + bool skipref = false) : + m_cascades(casc), + m_skip_pointers(skipptr), + m_skip_references(skipref), + m_format (f) + { + } + + typedef lldb::SharedPtr<ValueFormat>::Type SharedPointer; + typedef bool(*ValueCallback)(void*, const char*, const ValueFormat::SharedPointer&); + + ~ValueFormat() + { + } + + bool + Cascades() + { + return m_cascades; + } + bool + SkipsPointers() + { + return m_skip_pointers; + } + bool + SkipsReferences() + { + return m_skip_references; + } + + lldb::Format + GetFormat() + { + return m_format; + } + + std::string + FormatObject(lldb::ValueObjectSP object); + +}; + +struct SummaryFormat +{ + bool m_cascades; + bool m_skip_pointers; + bool m_skip_references; + bool m_dont_show_children; + bool m_dont_show_value; + bool m_show_members_oneliner; + + SummaryFormat(bool casc = false, + bool skipptr = false, + bool skipref = false, + bool nochildren = true, + bool novalue = true, + bool oneliner = false) : + m_cascades(casc), + m_skip_pointers(skipptr), + m_skip_references(skipref), + m_dont_show_children(nochildren), + m_dont_show_value(novalue), + m_show_members_oneliner(oneliner) + { + } + + bool + Cascades() + { + return m_cascades; + } + bool + SkipsPointers() + { + return m_skip_pointers; + } + bool + SkipsReferences() + { + return m_skip_references; + } + + bool + DoesPrintChildren() const + { + return !m_dont_show_children; + } + + bool + DoesPrintValue() const + { + return !m_dont_show_value; + } + + bool + IsOneliner() const + { + return m_show_members_oneliner; + } + + virtual + ~SummaryFormat() + { + } + + virtual std::string + FormatObject(lldb::ValueObjectSP object) = 0; + + virtual std::string + GetDescription() = 0; + + typedef lldb::SharedPtr<SummaryFormat>::Type SharedPointer; + typedef bool(*SummaryCallback)(void*, const char*, const SummaryFormat::SharedPointer&); + typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const SummaryFormat::SharedPointer&); + +}; + +// simple string-based summaries, using ${var to show data +struct StringSummaryFormat : public SummaryFormat +{ + std::string m_format; + + StringSummaryFormat(bool casc = false, + bool skipptr = false, + bool skipref = false, + bool nochildren = true, + bool novalue = true, + bool oneliner = false, + std::string f = "") : + SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner), + m_format(f) + { + } + + std::string + GetFormat() + { + return m_format; + } + + virtual + ~StringSummaryFormat() + { + } + + virtual std::string + FormatObject(lldb::ValueObjectSP object); + + virtual std::string + GetDescription(); + +}; + +// Python-based summaries, running script code to show data +struct ScriptSummaryFormat : public SummaryFormat +{ + std::string m_function_name; + std::string m_python_script; + + ScriptSummaryFormat(bool casc = false, + bool skipptr = false, + bool skipref = false, + bool nochildren = true, + bool novalue = true, + bool oneliner = false, + std::string fname = "", + std::string pscri = "") : + SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner), + m_function_name(fname), + m_python_script(pscri) + { + } + + std::string + GetFunctionName() + { + return m_function_name; + } + + std::string + GetPythonScript() + { + return m_python_script; + } + + virtual + ~ScriptSummaryFormat() + { + } + + virtual std::string + FormatObject(lldb::ValueObjectSP object); + + virtual std::string + GetDescription(); + + typedef lldb::SharedPtr<ScriptSummaryFormat>::Type SharedPointer; + +}; + +} // namespace lldb_private + +#endif // lldb_FormatClasses_h_ diff --git a/lldb/include/lldb/Core/FormatManager.h b/lldb/include/lldb/Core/FormatManager.h index 69bc63a3fb3..739e6aed371 100644 --- a/lldb/include/lldb/Core/FormatManager.h +++ b/lldb/include/lldb/Core/FormatManager.h @@ -43,6 +43,7 @@ namespace std #include "lldb/lldb-enumerations.h" #include "lldb/Core/Communication.h" +#include "lldb/Core/FormatClasses.h" #include "lldb/Core/InputReaderStack.h" #include "lldb/Core/Listener.h" #include "lldb/Core/RegularExpression.h" @@ -69,380 +70,10 @@ public: ~IFormatChangeListener() {} }; - -struct ValueFormat -{ - bool m_cascades; - bool m_skip_pointers; - bool m_skip_references; - lldb::Format m_format; - ValueFormat (lldb::Format f = lldb::eFormatInvalid, - bool casc = false, - bool skipptr = false, - bool skipref = false) : - m_cascades(casc), - m_skip_pointers(skipptr), - m_skip_references(skipref), - m_format (f) - { - } - typedef lldb::SharedPtr<ValueFormat>::Type SharedPointer; - typedef bool(*ValueCallback)(void*, const char*, const ValueFormat::SharedPointer&); - - ~ValueFormat() - { - } - - bool - Cascades() - { - return m_cascades; - } - bool - SkipsPointers() - { - return m_skip_pointers; - } - bool - SkipsReferences() - { - return m_skip_references; - } - - lldb::Format - GetFormat() - { - return m_format; - } - - std::string - FormatObject(lldb::ValueObjectSP object) - { - if (!object.get()) - return "NULL"; - - StreamString sstr; - - if (ClangASTType::DumpTypeValue (object->GetClangAST(), // The clang AST - object->GetClangType(), // The clang type to display - &sstr, - m_format, // Format to display this type with - object->GetDataExtractor(), // Data to extract from - 0, // Byte offset into "data" - object->GetByteSize(), // Byte size of item in "data" - object->GetBitfieldBitSize(), // Bitfield bit size - object->GetBitfieldBitOffset())) // Bitfield bit offset - return (sstr.GetString()); - else - { - return ("unsufficient data for value"); - } - - } - -}; - -struct SummaryFormat -{ - bool m_cascades; - bool m_skip_pointers; - bool m_skip_references; - bool m_dont_show_children; - bool m_dont_show_value; - bool m_show_members_oneliner; - bool m_is_system; - - uint32_t m_priority; - - SummaryFormat(bool casc = false, - bool skipptr = false, - bool skipref = false, - bool nochildren = true, - bool novalue = true, - bool oneliner = false, - bool system = false, - uint32_t priority = 2) : - m_cascades(casc), - m_skip_pointers(skipptr), - m_skip_references(skipref), - m_dont_show_children(nochildren), - m_dont_show_value(novalue), - m_show_members_oneliner(oneliner), - m_is_system(system), - m_priority(priority) - { - } - - bool - Cascades() - { - return m_cascades; - } - bool - SkipsPointers() - { - return m_skip_pointers; - } - bool - SkipsReferences() - { - return m_skip_references; - } - - bool - DoesPrintChildren() const - { - return !m_dont_show_children; - } - - bool - DoesPrintValue() const - { - return !m_dont_show_value; - } - - bool - IsOneliner() const - { - return m_show_members_oneliner; - } - - bool - IsSystem() const - { - return m_is_system; - } - - uint32_t - GetPriority() const - { - return m_priority; - } - - void - SetPriority(uint32_t newprio) - { - m_priority = newprio; - } - - virtual - ~SummaryFormat() - { - } - - virtual std::string - FormatObject(lldb::ValueObjectSP object) = 0; - - virtual std::string - GetDescription() = 0; - - typedef lldb::SharedPtr<SummaryFormat>::Type SharedPointer; - typedef bool(*SummaryCallback)(void*, const char*, const SummaryFormat::SharedPointer&); - typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const SummaryFormat::SharedPointer&); - -}; - -// simple string-based summaries, using ${var to show data -struct StringSummaryFormat : public SummaryFormat -{ - std::string m_format; - - StringSummaryFormat(bool casc = false, - bool skipptr = false, - bool skipref = false, - bool nochildren = true, - bool novalue = true, - bool oneliner = false, - bool system = false, - std::string f = "", - uint32_t priority = 2) : - SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner,system, priority), - m_format(f) - { - } - - std::string - GetFormat() - { - return m_format; - } - - virtual - ~StringSummaryFormat() - { - } - - virtual std::string - FormatObject(lldb::ValueObjectSP object); - - virtual std::string - GetDescription() - { - StreamString sstr; - sstr.Printf ("`%s`%s%s%s%s%s%s%s", m_format.c_str(), - m_cascades ? "" : " (not cascading)", - m_dont_show_children ? "" : " (show children)", - m_dont_show_value ? " (hide value)" : "", - m_show_members_oneliner ? " (one-line printout)" : "", - m_skip_pointers ? " (skip pointers)" : "", - m_skip_references ? " (skip references)" : "", - m_is_system ? " (system)" : ""); - return sstr.GetString(); - } - -}; - -// Python-based summaries, running script code to show data -struct ScriptSummaryFormat : public SummaryFormat -{ - std::string m_function_name; - std::string m_python_script; - - ScriptSummaryFormat(bool casc = false, - bool skipptr = false, - bool skipref = false, - bool nochildren = true, - bool novalue = true, - bool oneliner = false, - bool system = false, - std::string fname = "", - std::string pscri = "", - uint32_t priority = 2) : - SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner,system,priority), - m_function_name(fname), - m_python_script(pscri) - { - } - - std::string - GetFunctionName() - { - return m_function_name; - } - - std::string - GetPythonScript() - { - return m_python_script; - } - - virtual - ~ScriptSummaryFormat() - { - } - - virtual std::string - FormatObject(lldb::ValueObjectSP object) - { - return std::string(ScriptInterpreterPython::CallPythonScriptFunction(m_function_name.c_str(), - object).c_str()); - } - - virtual std::string - GetDescription() - { - StreamString sstr; - sstr.Printf ("%s%s%s%s%s%s%s\n%s", m_cascades ? "" : " (not cascading)", - m_dont_show_children ? "" : " (show children)", - m_dont_show_value ? " (hide value)" : "", - m_show_members_oneliner ? " (one-line printout)" : "", - m_skip_pointers ? " (skip pointers)" : "", - m_skip_references ? " (skip references)" : "", - m_is_system ? " (system)" : "", - m_python_script.c_str()); - return sstr.GetString(); - - } - - typedef lldb::SharedPtr<ScriptSummaryFormat>::Type SharedPointer; - -}; - -/*struct SummaryFormat -{ - std::string m_format; - bool m_dont_show_children; - bool m_dont_show_value; - bool m_show_members_oneliner; - bool m_cascades; - bool m_skip_references; - bool m_skip_pointers; - SummaryFormat(std::string f = "", - bool c = false, - bool nochildren = true, - bool novalue = true, - bool oneliner = false, - bool skipptr = false, - bool skipref = false) : - m_format(f), - m_dont_show_children(nochildren), - m_dont_show_value(novalue), - m_show_members_oneliner(oneliner), - m_cascades(c), - m_skip_references(skipref), - m_skip_pointers(skipptr) - { - } - - 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; - typedef bool(*SummaryCallback)(void*, const char*, const SummaryFormat::SharedPointer&); - typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const SummaryFormat::SharedPointer&); - -}; - -struct ScriptFormat -{ - std::string m_function_name; - std::string m_python_script; - bool m_cascades; - bool m_skip_references; - bool m_skip_pointers; - ScriptFormat (std::string n, - std::string s = "", - bool c = false, - bool skipptr = false, - bool skipref = false) : - m_function_name (n), - m_python_script(s), - m_cascades (c), - m_skip_references(skipref), - m_skip_pointers(skipptr) - { - } - - typedef lldb::SharedPtr<ScriptFormat>::Type SharedPointer; - typedef bool(*ScriptCallback)(void*, const char*, const ScriptFormat::SharedPointer&); - - ~ScriptFormat() - { - } - -};*/ - template<typename KeyType, typename ValueType> class FormatNavigator; - -class FormatManager; - + template<typename KeyType, typename ValueType> class FormatMap { @@ -500,7 +131,7 @@ public: if (iter == m_map.end()) return false; m_map.erase(name); - if(listener) + if (listener) listener->Changed(); return true; } @@ -510,7 +141,7 @@ public: { Mutex::Locker(m_map_mutex); m_map.clear(); - if(listener) + if (listener) listener->Changed(); } @@ -536,7 +167,7 @@ public: for (pos = m_map.begin(); pos != end; pos++) { KeyType type = pos->first; - if(!callback(param, type, pos->second)) + if (!callback(param, type, pos->second)) break; } } @@ -549,8 +180,6 @@ public: } }; - -class FormatCategory; template<typename KeyType, typename ValueType> class FormatNavigator @@ -650,7 +279,7 @@ private: if (!typePtr) return false; ConstString name(ClangASTType::GetTypeNameForQualType(type).c_str()); - if(vobj.GetBitfieldBitSize() > 0) + if (vobj.GetBitfieldBitSize() > 0) { // for bitfields, append size to the typename so one can custom format them StreamString sstring; @@ -687,7 +316,7 @@ private: */ Error error; ValueObject* target = vobj.Dereference(error).get(); - if(error.Fail() || !target) + if (error.Fail() || !target) return false; if (Get(*target, typePtr->getPointeeType(), entry, reason) && !entry->m_skip_pointers) { @@ -703,12 +332,12 @@ private: if (ClangASTContext::GetCompleteType(ast, vobj.GetClangType()) && !objc_class_type->isObjCId()) { clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if(class_interface_decl) + if (class_interface_decl) { //printf("down here\n"); clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); //printf("one further step and we're there...\n"); - if(superclass_interface_decl) + if (superclass_interface_decl) { //printf("the end is here\n"); clang::QualType ivar_qual_type(ast->getObjCInterfaceType(superclass_interface_decl)); @@ -732,12 +361,12 @@ private: if (record->hasDefinition()) { clang::CXXRecordDecl::base_class_iterator pos,end; - if( record->getNumBases() > 0) + if (record->getNumBases() > 0) { end = record->bases_end(); for (pos = record->bases_begin(); pos != end; pos++) { - if((Get(vobj, pos->getType(), entry, reason)) && entry->m_cascades) + if ((Get(vobj, pos->getType(), entry, reason)) && entry->m_cascades) { reason |= lldb::eFormatterNavigatedBaseClasses; return true; @@ -749,7 +378,7 @@ private: end = record->vbases_end(); for (pos = record->vbases_begin(); pos != end; pos++) { - if((Get(vobj, pos->getType(), entry, reason)) && entry->m_cascades) + if ((Get(vobj, pos->getType(), entry, reason)) && entry->m_cascades) { reason |= lldb::eFormatterNavigatedBaseClasses; return true; @@ -781,6 +410,8 @@ template<> bool FormatNavigator<lldb::RegularExpressionSP, SummaryFormat>::Delete(const char* type); +class CategoryMap; + class FormatCategory { private: @@ -799,6 +430,23 @@ private: Mutex m_mutex; + void + Enable(bool value = true) + { + Mutex::Locker(m_mutex); + m_enabled = value; + if (m_change_listener) + m_change_listener->Changed(); + } + + void + Disable() + { + Enable(false); + } + + friend class CategoryMap; + public: typedef SummaryNavigator::SharedPointer SummaryNavigatorSP; @@ -829,22 +477,7 @@ public: { return m_enabled; } - - void - Enable(bool value = true) - { - Mutex::Locker(m_mutex); - m_enabled = value; - if(m_change_listener) - m_change_listener->Changed(); - } - - void - Disable() - { - Enable(false); - } - + bool Get(ValueObject& vobj, lldb::SummaryFormatSP& entry, @@ -856,7 +489,7 @@ public: return true; bool regex = RegexSummary()->Get(vobj, entry, reason); if (regex && reason) - *reason |= lldb::eFormatterRegularExpressionSummary; // penalize regex summaries over normal ones + *reason |= lldb::eFormatterRegularExpressionSummary; return regex; } @@ -876,79 +509,215 @@ public: return (del_sum || del_rex); } - void - ChooseAsPreferential(const char* name); - typedef lldb::SharedPtr<FormatCategory>::Type SharedPointer; }; -class FormatManager : public IFormatChangeListener +class CategoryMap { private: + typedef const char* KeyType; + typedef FormatCategory ValueType; + typedef ValueType::SharedPointer ValueSP; + typedef std::list<FormatCategory::SharedPointer> ActiveCategoriesList; + typedef ActiveCategoriesList::iterator ActiveCategoriesIterator; - typedef FormatNavigator<const char*, ValueFormat> ValueNavigator; - - typedef FormatMap<const char*, FormatCategory> CategoryMap; - - typedef ValueNavigator::MapType ValueMap; - typedef FormatMap<const char*, SummaryFormat> NamedSummariesMap; + Mutex m_map_mutex; + IFormatChangeListener* listener; - typedef std::list<FormatCategory::SharedPointer> ActiveCategoriesList; - typedef ActiveCategoriesList::iterator ActiveCategoriesIterator; + friend class FormatNavigator<KeyType, ValueType>; + friend class FormatManager; - ValueNavigator m_value_nav; - NamedSummariesMap m_named_summaries_map; - uint32_t m_last_revision; - CategoryMap m_categories_map; +public: + typedef std::map<KeyType, ValueSP> MapType; + +private: + MapType m_map; ActiveCategoriesList m_active_categories; - - const char* m_default_category_name; - const char* m_system_category_name; - - typedef CategoryMap::MapType::iterator CategoryMapIterator; + + MapType& map() + { + return m_map; + } + + ActiveCategoriesList& active_list() + { + return m_active_categories; + } + + Mutex& mutex() + { + return m_map_mutex; + } + +public: + + typedef MapType::iterator MapIterator; + typedef bool(*CallbackType)(void*, KeyType, const ValueSP&); + + CategoryMap(IFormatChangeListener* lst = NULL) : + m_map_mutex(Mutex::eMutexTypeRecursive), + listener(lst), + m_map(), + m_active_categories() + { + } + + void + Add(KeyType name, + const ValueSP& entry) + { + Mutex::Locker(m_map_mutex); + m_map[name] = entry; + if (listener) + listener->Changed(); + } bool - Get_ExactMatch(ValueObject& vobj, - lldb::SummaryFormatSP& entry) + Delete(KeyType name) { - ActiveCategoriesIterator begin, end = m_active_categories.end(); - - SummaryFormat::SharedPointer current_category_pick; - uint32_t reason_to_pick_current; + Mutex::Locker(m_map_mutex); + MapIterator iter = m_map.find(name); + if (iter == m_map.end()) + return false; + m_map.erase(name); + DisableCategory(name); + if (listener) + listener->Changed(); + return true; + } + + void + EnableCategory(KeyType category_name) + { + Mutex::Locker(m_map_mutex); + ValueSP category; + if (!Get(category_name,category)) + return; + category->Enable(); + m_active_categories.push_front(category); + } + + class delete_matching_categories + { + FormatCategory::SharedPointer ptr; + public: + delete_matching_categories(FormatCategory::SharedPointer p) : ptr(p) + {} - for (begin = m_active_categories.begin(); begin != end; begin++) + bool operator()(const FormatCategory::SharedPointer& other) { - FormatCategory::SharedPointer category = *begin; - if ( category->Get(vobj, current_category_pick, &reason_to_pick_current) && reason_to_pick_current == lldb::eFormatterDirectChoice ) + return ptr.get() == other.get(); + } + }; + + void + DisableCategory(KeyType category_name) + { + Mutex::Locker(m_map_mutex); + ValueSP category; + if (!Get(category_name,category)) + return; + category->Disable(); + m_active_categories.remove_if(delete_matching_categories(category)); + } + + void + Clear() + { + Mutex::Locker(m_map_mutex); + m_map.clear(); + m_active_categories.clear(); + if (listener) + listener->Changed(); + } + + bool + Get(KeyType name, + ValueSP& entry) + { + Mutex::Locker(m_map_mutex); + MapIterator iter = m_map.find(name); + if (iter == m_map.end()) + return false; + entry = iter->second; + return true; + } + + void + 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++) { - entry = SummaryFormat::SharedPointer(current_category_pick); - return true; + KeyType type = pos->first; + if (!callback(param, type, pos->second)) + break; } } - return false; } - + + uint32_t + GetCount() + { + return m_map.size(); + } + bool - Get_AnyMatch(ValueObject& vobj, - lldb::SummaryFormatSP& entry) + Get(ValueObject& vobj, + lldb::SummaryFormatSP& entry) { - ActiveCategoriesIterator begin, end = m_active_categories.end(); + Mutex::Locker(m_map_mutex); + + uint32_t reason_why; + bool first = true; - SummaryFormat::SharedPointer current_category_pick; + ActiveCategoriesIterator begin, end = m_active_categories.end(); for (begin = m_active_categories.begin(); begin != end; begin++) { FormatCategory::SharedPointer category = *begin; - if ( category->Get(vobj, current_category_pick, NULL) ) + lldb::SummaryFormatSP current_format; + if (!category->Get(vobj, current_format, &reason_why)) + continue; + if (reason_why == lldb::eFormatterDirectChoice) { - entry = SummaryFormat::SharedPointer(current_category_pick); + entry = current_format; return true; } + else if (first) + { + entry = current_format; + first = false; + } } - return false; + return !first; } +}; + + +class FormatManager : public IFormatChangeListener +{ +private: + + typedef FormatNavigator<const char*, ValueFormat> ValueNavigator; + + typedef ValueNavigator::MapType ValueMap; + typedef FormatMap<const char*, SummaryFormat> NamedSummariesMap; + + ValueNavigator m_value_nav; + NamedSummariesMap m_named_summaries_map; + uint32_t m_last_revision; + CategoryMap m_categories_map; + const char* m_default_category_name; + const char* m_system_category_name; + + typedef CategoryMap::MapType::iterator CategoryMapIterator; + public: typedef bool (*CategoryCallback)(void*, const char*, const FormatCategory::SharedPointer&); @@ -957,18 +726,14 @@ public: m_value_nav(this), m_named_summaries_map(this), m_last_revision(0), - m_categories_map(this), - m_active_categories() + m_categories_map(this) { // build default categories m_default_category_name = ConstString("default").GetCString(); m_system_category_name = ConstString("system").GetCString(); - - Category(m_default_category_name)->Enable(); - Category(m_system_category_name)->Enable(); - + // add some default stuff // most formats, summaries, ... actually belong to the users' lldbinit file rather than here SummaryFormat::SharedPointer string_format(new StringSummaryFormat(false, @@ -977,9 +742,7 @@ public: true, false, false, - true, - "${var%s}", - 1)); + "${var%s}")); SummaryFormat::SharedPointer string_array_format(new StringSummaryFormat(false, @@ -988,19 +751,20 @@ public: false, false, false, - true, - "${var%s}", - 1)); + "${var%s}")); lldb::RegularExpressionSP any_size_char_arr(new RegularExpression("char \\[[0-9]+\\]")); - Summary(m_system_category_name)->Add(ConstString("char *").GetCString(), string_format); - Summary(m_system_category_name)->Add(ConstString("const char *").GetCString(), string_format); - RegexSummary(m_system_category_name)->Add(any_size_char_arr, string_array_format); + Category(m_system_category_name)->Summary()->Add(ConstString("char *").GetCString(), string_format); + Category(m_system_category_name)->Summary()->Add(ConstString("const char *").GetCString(), string_format); + Category(m_system_category_name)->RegexSummary()->Add(any_size_char_arr, string_array_format); - m_active_categories.push_front(Category(m_system_category_name)); - m_active_categories.push_front(Category(m_default_category_name)); + Category(m_default_category_name); // this call is there to force LLDB into creating an empty "default" category + + // the order of these two calls IS important, if you invert it "system" summaries will prevail over the user's + EnableCategory(m_system_category_name); + EnableCategory(m_default_category_name); } @@ -1012,62 +776,31 @@ public: void EnableCategory(const char* category_name) { - Category(category_name)->Enable(); - m_active_categories.push_front(Category(category_name)); + m_categories_map.EnableCategory(category_name); } - class delete_matching_categories - { - FormatCategory::SharedPointer ptr; - public: - delete_matching_categories(FormatCategory::SharedPointer p) : ptr(p) - {} - - bool operator()(const FormatCategory::SharedPointer& other) - { - return ptr.get() == other.get(); - } - }; - void DisableCategory(const char* category_name) { - Category(category_name)->Disable(); - m_active_categories.remove_if(delete_matching_categories(Category(category_name))); + m_categories_map.DisableCategory(category_name); } void LoopThroughCategories(CategoryCallback callback, void* param) { - CategoryMapIterator begin, end = m_categories_map.m_map.end(); - - for (begin = m_categories_map.m_map.begin(); begin != end; begin++) - { - if (!callback(param, begin->first, begin->second)) - return; - } + m_categories_map.LoopThrough(callback, param); } FormatCategory::SummaryNavigatorSP Summary(const char* category_name = NULL) { - if (!category_name) - return Summary(m_default_category_name); - lldb::FormatCategorySP category; - if (m_categories_map.Get(category_name, category)) - return category->Summary(); - return FormatCategory::SummaryNavigatorSP(); + return Category(category_name)->Summary(); } FormatCategory::RegexSummaryNavigatorSP RegexSummary(const char* category_name = NULL) { - if (!category_name) - return RegexSummary(m_default_category_name); - lldb::FormatCategorySP category; - if (m_categories_map.Get(category_name, category)) - return category->RegexSummary(); - return FormatCategory::RegexSummaryNavigatorSP(); + return Category(category_name)->RegexSummary(); } lldb::FormatCategorySP @@ -1086,9 +819,7 @@ public: Get(ValueObject& vobj, lldb::SummaryFormatSP& entry) { - if ( Get_ExactMatch(vobj,entry) ) - return true; - return Get_AnyMatch(vobj,entry); + return m_categories_map.Get(vobj, entry); } static bool diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index a631a215fd8..c934073aa21 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -492,16 +492,14 @@ namespace lldb { // this enum determines how a FormatNavigator picked a specific format for a datatype // these values can be used together (e.g. eFormatterStrippedPointerReference | eFormatterNavigatedBaseClasses - // if you went from DerivedType& to BaseType to find a valid format). the priority rules are embedded in the - // ordering of these values (i.e. if you want to make a choice look really bad, give it a high value in this - // enum). eFormatterDirectChoice should always be left at 0 because it's our favorite choice all the time + // if you went from DerivedType& to BaseType to find a valid format) typedef enum FormatterChoiceCriterion { eFormatterDirectChoice = 0x00000000, eFormatterStrippedPointerReference = 0x00000001, eFormatterNavigatedTypedefs = 0x00000002, eFormatterNavigatedBaseClasses = 0x00000004, - eFormatterRegularExpressionSummary = 0x00000004 + eFormatterRegularExpressionSummary = 0x00000008 } FormatterChoiceCriterion; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index f8cf9c47b76..37845a61651 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -419,6 +419,7 @@ 94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94611EB113CCA4A4003A22AF /* RefCounter.cpp */; }; 9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */; }; 9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */; }; + 94A9112E13D5DF210046D8A6 /* FormatClasses.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94A9112D13D5DF210046D8A6 /* FormatClasses.cpp */; }; 9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */; }; 9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */; }; @@ -1215,6 +1216,8 @@ 9463D4CE13B179A500C230D4 /* CommandObjectType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectType.h; path = source/Commands/CommandObjectType.h; sourceTree = "<group>"; }; 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeHierarchyNavigator.cpp; path = source/Symbol/TypeHierarchyNavigator.cpp; sourceTree = "<group>"; }; 9467E65413C3D98900B3B6F3 /* TypeHierarchyNavigator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeHierarchyNavigator.h; path = include/lldb/Symbol/TypeHierarchyNavigator.h; sourceTree = "<group>"; }; + 94A9112B13D5DEF80046D8A6 /* FormatClasses.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatClasses.h; path = include/lldb/Core/FormatClasses.h; sourceTree = "<group>"; }; + 94A9112D13D5DF210046D8A6 /* FormatClasses.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatClasses.cpp; path = source/Core/FormatClasses.cpp; 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>"; }; @@ -1990,6 +1993,8 @@ 26BC7D6310F1B77400F91463 /* FileSpecList.h */, 26BC7E7B10F1B85900F91463 /* FileSpecList.cpp */, 26BC7D6410F1B77400F91463 /* Flags.h */, + 94A9112B13D5DEF80046D8A6 /* FormatClasses.h */, + 94A9112D13D5DF210046D8A6 /* FormatClasses.cpp */, 9415F61613B2C0DC00A52B36 /* FormatManager.h */, 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */, 26F7305F139D8FC900FD51C7 /* History.h */, diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp index 8db88e759ed..ab3574133df 100644 --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -192,7 +192,7 @@ public: // now I have a valid format, let's add it to every type - for(int i = 0; i < argc; i++) { + for (int i = 0; i < argc; i++) { const char* typeA = command.GetArgumentAtIndex(i); ConstString typeCS(typeA); if (typeCS) @@ -537,7 +537,6 @@ public: options->m_no_children, options->m_no_value, options->m_one_liner, - options->m_is_system, std::string(funct_name), options->m_user_source.CopyList(" "))); @@ -659,7 +658,6 @@ CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting () m_python_script = ""; m_python_function = ""; m_is_add_script = false; - m_is_system = false; m_category = NULL; } @@ -730,7 +728,6 @@ CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturn m_options.m_no_children, m_options.m_no_value, m_options.m_one_liner, - m_options.m_is_system, std::string(funct_name), " " + m_options.m_python_function + "(valobj,dict)")); } @@ -773,7 +770,6 @@ CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturn m_options.m_no_children, m_options.m_no_value, m_options.m_one_liner, - m_options.m_is_system, std::string(funct_name), " " + m_options.m_python_script)); } @@ -786,11 +782,10 @@ CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturn m_options.m_no_value, m_options.m_one_liner, m_options.m_regex, - m_options.m_is_system, m_options.m_name, m_options.m_category); - for(int i = 0; i < argc; i++) { + for (int i = 0; i < argc; i++) { const char* typeA = command.GetArgumentAtIndex(i); if (typeA && *typeA) options->m_target_types << typeA; @@ -880,7 +875,6 @@ CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturn m_options.m_no_children, m_options.m_no_value, m_options.m_one_liner, - m_options.m_is_system, format_cstr)); if (error.Fail()) @@ -892,7 +886,7 @@ CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturn // now I have a valid format, let's add it to every type - for(int i = 0; i < argc; i++) { + for (int i = 0; i < argc; i++) { const char* typeA = command.GetArgumentAtIndex(i); if (!typeA || typeA[0] == '\0') { @@ -1039,9 +1033,12 @@ bool CommandObjectTypeSummaryAdd::AddSummary(const ConstString& type_name, SummaryFormatSP entry, SummaryFormatType type, - const char* category, + const char* category_name, Error* error) { + lldb::FormatCategorySP category; + Debugger::Formatting::Categories::Get(ConstString(category_name), category); + if (type == eRegexSummary) { RegularExpressionSP typeRX(new RegularExpression()); @@ -1052,8 +1049,8 @@ CommandObjectTypeSummaryAdd::AddSummary(const ConstString& type_name, return false; } - Debugger::Formatting::SummaryFormats(category)->RegexSummary()->Delete(type_name.GetCString()); - Debugger::Formatting::SummaryFormats(category)->RegexSummary()->Add(typeRX, entry); + category->RegexSummary()->Delete(type_name.GetCString()); + category->RegexSummary()->Add(typeRX, entry); return true; } @@ -1065,7 +1062,7 @@ CommandObjectTypeSummaryAdd::AddSummary(const ConstString& type_name, } else { - Debugger::Formatting::SummaryFormats(category)->Summary()->Add(type_name.GetCString(), entry); + category->Summary()->Add(type_name.GetCString(), entry); return true; } } @@ -1226,7 +1223,10 @@ public: return result.Succeeded(); } - bool delete_category = Debugger::Formatting::SummaryFormats(m_options.m_category)->Delete(typeCS.GetCString()); + lldb::FormatCategorySP category; + Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category); + + bool delete_category = category->Delete(typeCS.GetCString()); bool delete_named = Debugger::Formatting::NamedSummaryFormats::Delete(typeCS); if (delete_category || delete_named) @@ -1347,14 +1347,20 @@ public: if (m_options.m_delete_all) Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, NULL); - else if (command.GetArgumentCount() > 0) - { - const char* cat_name = command.GetArgumentAtIndex(0); - ConstString cat_nameCS(cat_name); - Debugger::Formatting::SummaryFormats(cat_nameCS.GetCString())->Clear(); - } + else - Debugger::Formatting::SummaryFormats()->Clear(); + { + lldb::FormatCategorySP category; + if (command.GetArgumentCount() > 0) + { + const char* cat_name = command.GetArgumentAtIndex(0); + ConstString cat_nameCS(cat_name); + Debugger::Formatting::Categories::Get(cat_nameCS, category); + } + else + Debugger::Formatting::Categories::Get(ConstString(NULL), category); + category->Clear(); + } Debugger::Formatting::NamedSummaryFormats::Clear(); @@ -1523,7 +1529,7 @@ public: CommandArgumentData type_style_arg; type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlain; + type_style_arg.arg_repetition = eArgRepeatPlus; type_arg.push_back (type_style_arg); @@ -1540,24 +1546,27 @@ public: { const size_t argc = command.GetArgumentCount(); - if (argc != 1) + if (argc < 1) { - result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); + result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } - const char* typeA = command.GetArgumentAtIndex(0); - ConstString typeCS(typeA); - - if (!typeCS) + for (int i = argc - 1; i >= 0; i--) { - result.AppendError("empty category name not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; + const char* typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + + if (!typeCS) + { + result.AppendError("empty category name not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + Debugger::Formatting::Categories::Enable(typeCS); } - Debugger::Formatting::Categories::Enable(typeCS); result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } @@ -1581,7 +1590,7 @@ public: CommandArgumentData type_style_arg; type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlain; + type_style_arg.arg_repetition = eArgRepeatPlus; type_arg.push_back (type_style_arg); @@ -1598,36 +1607,42 @@ public: { const size_t argc = command.GetArgumentCount(); - if (argc != 1) + if (argc < 1) { - result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); + result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } - const char* typeA = command.GetArgumentAtIndex(0); - ConstString typeCS(typeA); + bool success = true; - if (!typeCS) + // the order is not relevant here + for (int i = argc - 1; i >= 0; i--) { - result.AppendError("empty category name not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; + const char* typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + + if (!typeCS) + { + result.AppendError("empty category name not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + if (!Debugger::Formatting::Categories::Delete(typeCS)) + success = false; // keep deleting even if we hit an error } - - if (Debugger::Formatting::Categories::Delete(typeCS)) + if (success) { result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } else { - result.AppendErrorWithFormat ("cannot delete category %s.\n", typeA); + result.AppendError("cannot delete one or more categories\n"); result.SetStatus(eReturnStatusFailed); return false; - } + } } - }; //------------------------------------------------------------------------- @@ -1647,7 +1662,7 @@ public: CommandArgumentData type_style_arg; type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlain; + type_style_arg.arg_repetition = eArgRepeatPlus; type_arg.push_back (type_style_arg); @@ -1664,24 +1679,28 @@ public: { const size_t argc = command.GetArgumentCount(); - if (argc != 1) + if (argc < 1) { - result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); + result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } - const char* typeA = command.GetArgumentAtIndex(0); - ConstString typeCS(typeA); - - if (!typeCS) + // the order is not relevant here + for (int i = argc - 1; i >= 0; i--) { - result.AppendError("empty category name not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; + const char* typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + + if (!typeCS) + { + result.AppendError("empty category name not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + Debugger::Formatting::Categories::Disable(typeCS); } - - Debugger::Formatting::Categories::Disable(typeCS); + result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } diff --git a/lldb/source/Commands/CommandObjectType.h b/lldb/source/Commands/CommandObjectType.h index d9242879bea..c37bc70a8b3 100644 --- a/lldb/source/Commands/CommandObjectType.h +++ b/lldb/source/Commands/CommandObjectType.h @@ -39,8 +39,6 @@ public: bool m_one_liner; bool m_regex; - bool m_is_system; - ConstString* m_name; const char* m_category; @@ -52,7 +50,6 @@ public: bool novl, bool onel, bool regx, - bool syst, ConstString* name, const char* catg) : m_skip_pointers(sptr), @@ -64,7 +61,6 @@ public: m_no_value(novl), m_one_liner(onel), m_regex(regx), - m_is_system(syst), m_name(name), m_category(catg) { @@ -130,7 +126,6 @@ private: std::string m_python_script; std::string m_python_function; bool m_is_add_script; - bool m_is_system; const char* m_category; }; diff --git a/lldb/source/Core/DataExtractor.cpp b/lldb/source/Core/DataExtractor.cpp index e364dfd6097..f8be9a421e0 100644 --- a/lldb/source/Core/DataExtractor.cpp +++ b/lldb/source/Core/DataExtractor.cpp @@ -754,7 +754,7 @@ DataExtractor::GetMaxU64Bitfield (uint32_t *offset_ptr, uint32_t size, uint32_t if (bitfield_bit_offset > 0) uval64 >>= bitfield_bit_offset; uint64_t bitfield_mask = ((1ul << bitfield_bit_size) - 1); - if(!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64) + if (!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64) return uval64; uval64 &= bitfield_mask; } diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 1c62a8cb46f..cce768f8684 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1755,12 +1755,6 @@ Debugger::Formatting::ValueFormats::GetCount() return GetFormatManager().Value().GetCount(); } -lldb::FormatCategorySP -Debugger::Formatting::SummaryFormats(const char* category_name) -{ - return GetFormatManager().Category(category_name); -} - bool Debugger::Formatting::GetSummaryFormat(ValueObject& vobj, lldb::SummaryFormatSP& entry) @@ -1804,15 +1798,10 @@ void Debugger::Formatting::Categories::Enable(ConstString& category) { if (GetFormatManager().Category(category.GetCString())->IsEnabled() == false) - { - //GetFormatManager().Category(category.GetCString())->Enable(); GetFormatManager().EnableCategory(category.GetCString()); - } else { - //GetFormatManager().Category(category.GetCString())->Disable(); GetFormatManager().DisableCategory(category.GetCString()); - //GetFormatManager().Category(category.GetCString())->Enable(); GetFormatManager().EnableCategory(category.GetCString()); } } @@ -1821,10 +1810,7 @@ void Debugger::Formatting::Categories::Disable(ConstString& category) { if (GetFormatManager().Category(category.GetCString())->IsEnabled() == true) - { - //GetFormatManager().Category(category.GetCString())->Disable(); GetFormatManager().DisableCategory(category.GetCString()); - } } void diff --git a/lldb/source/Core/FormatClasses.cpp b/lldb/source/Core/FormatClasses.cpp new file mode 100644 index 00000000000..8ff237a603a --- /dev/null +++ b/lldb/source/Core/FormatClasses.cpp @@ -0,0 +1,140 @@ +//===-- FormatClasses.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes + +// C++ Includes +#include <ostream> + +// Other libraries and framework includes + +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" + +#include "lldb/Core/Debugger.h" +#include "lldb/Core/FormatClasses.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Target/StackFrame.h" + +using namespace lldb; +using namespace lldb_private; + +std::string +ValueFormat::FormatObject(lldb::ValueObjectSP object) +{ + if (!object.get()) + return "NULL"; + + StreamString sstr; + + if (ClangASTType::DumpTypeValue (object->GetClangAST(), // The clang AST + object->GetClangType(), // The clang type to display + &sstr, + m_format, // Format to display this type with + object->GetDataExtractor(), // Data to extract from + 0, // Byte offset into "data" + object->GetByteSize(), // Byte size of item in "data" + object->GetBitfieldBitSize(), // Bitfield bit size + object->GetBitfieldBitOffset())) // Bitfield bit offset + return (sstr.GetString()); + else + { + return ("unsufficient data for value"); + } +} + +std::string +StringSummaryFormat::FormatObject(lldb::ValueObjectSP object) +{ + if (!object.get()) + return "NULL"; + + StreamString s; + ExecutionContext exe_ctx; + object->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); + SymbolContext sc; + if (exe_ctx.frame) + sc = exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything); + + if (m_show_members_oneliner) + { + const uint32_t num_children = object->GetNumChildren(); + if (num_children) + { + s.PutChar('('); + + for (uint32_t idx=0; idx<num_children; ++idx) + { + lldb::ValueObjectSP child_sp(object->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()->GetPrintableRepresentation()); + } + } + + s.PutChar(')'); + + return s.GetString(); + } + else + return ""; + + } + else + { + if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, object.get())) + return s.GetString(); + else + return ""; + } +} + +std::string +StringSummaryFormat::GetDescription() +{ + StreamString sstr; + sstr.Printf ("`%s`%s%s%s%s%s%s", m_format.c_str(), + m_cascades ? "" : " (not cascading)", + m_dont_show_children ? "" : " (show children)", + m_dont_show_value ? " (hide value)" : "", + m_show_members_oneliner ? " (one-line printout)" : "", + m_skip_pointers ? " (skip pointers)" : "", + m_skip_references ? " (skip references)" : ""); + return sstr.GetString(); +} + +std::string +ScriptSummaryFormat::FormatObject(lldb::ValueObjectSP object) +{ + return std::string(ScriptInterpreterPython::CallPythonScriptFunction(m_function_name.c_str(), + object).c_str()); +} + +std::string +ScriptSummaryFormat::GetDescription() +{ + StreamString sstr; + sstr.Printf ("%s%s%s%s%s%s\n%s", m_cascades ? "" : " (not cascading)", + m_dont_show_children ? "" : " (show children)", + m_dont_show_value ? " (hide value)" : "", + m_show_members_oneliner ? " (one-line printout)" : "", + m_skip_pointers ? " (skip pointers)" : "", + m_skip_references ? " (skip references)" : "", + m_python_script.c_str()); + return sstr.GetString(); + +} + + diff --git a/lldb/source/Core/FormatManager.cpp b/lldb/source/Core/FormatManager.cpp index 2ce91aed8fd..e064534028f 100644 --- a/lldb/source/Core/FormatManager.cpp +++ b/lldb/source/Core/FormatManager.cpp @@ -184,7 +184,7 @@ FormatNavigator<lldb::RegularExpressionSP, SummaryFormat>::Delete(const char* ty if ( ::strcmp(type,regex->GetText()) == 0) { m_format_map.map().erase(pos); - if(m_format_map.listener) + if (m_format_map.listener) m_format_map.listener->Changed(); return true; } @@ -220,75 +220,4 @@ FormatManager::GetSingleItemFormat(lldb::Format vector_format) default: return lldb::eFormatInvalid; } -} - -std::string -StringSummaryFormat::FormatObject(lldb::ValueObjectSP object) -{ - if (!object.get()) - return "NULL"; - - StreamString s; - ExecutionContext exe_ctx; - object->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); - SymbolContext sc; - if (exe_ctx.frame) - sc = exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything); - - if (m_show_members_oneliner) - { - const uint32_t num_children = object->GetNumChildren(); - if (num_children) - { - s.PutChar('('); - - for (uint32_t idx=0; idx<num_children; ++idx) - { - lldb::ValueObjectSP child_sp(object->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()->GetPrintableRepresentation()); - } - } - - s.PutChar(')'); - - return s.GetString(); - } - else - return ""; - - } - else - { - if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, object.get())) - return s.GetString(); - else - return ""; - } -} - -void -FormatCategory::ChooseAsPreferential(const char* name) -{ - Mutex::Locker(m_mutex); - lldb::SummaryFormatSP format; - - uint32_t revision = Debugger::Formatting::ValueFormats::GetCurrentRevision(); - - if ( Summary()->Get(name, format) ) - format->SetPriority(revision); - - format.reset(); - - if ( RegexSummary()->Get(name, format) ) - format->SetPriority(revision); - - if(m_change_listener) - m_change_listener->Changed(); - -} +}
\ No newline at end of file diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp index 2c411e4a623..c7050f328f4 100644 --- a/lldb/source/Expression/ClangExpressionParser.cpp +++ b/lldb/source/Expression/ClangExpressionParser.cpp @@ -506,7 +506,7 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr, } else { - if(log) + if (log) log->Printf("Found function %s for %s", function_name.c_str(), m_expr.FunctionName()); } @@ -733,7 +733,7 @@ ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &ex return ret; } - if(log) + if (log) log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr); std::pair <lldb::addr_t, lldb::addr_t> func_range; @@ -747,7 +747,7 @@ ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &ex return ret; } - if(log) + if (log) log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second); if (!exe_ctx.target) diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp index 0df6a5b63b7..359b011c546 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Expression/ClangUserExpression.cpp @@ -179,7 +179,7 @@ ClangUserExpression::Parse (Stream &error_stream, m_needs_object_ptr = true; } - else if(m_objectivec) + else if (m_objectivec) { const char *function_name = FunctionName(); diff --git a/lldb/source/Expression/IRDynamicChecks.cpp b/lldb/source/Expression/IRDynamicChecks.cpp index 09f520c731c..dd09b12e716 100644 --- a/lldb/source/Expression/IRDynamicChecks.cpp +++ b/lldb/source/Expression/IRDynamicChecks.cpp @@ -307,7 +307,7 @@ private: { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - if(log) + if (log) log->Printf("Instrumenting load/store instruction: %s\n", PrintValue(inst).c_str()); diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp index 03716ff1eb6..e20af16f61d 100644 --- a/lldb/source/Expression/IRForTarget.cpp +++ b/lldb/source/Expression/IRForTarget.cpp @@ -253,7 +253,7 @@ IRForTarget::MaybeSetCastResult (lldb_private::TypeFromParser type) { next_value = cast_inst->getOperand(0); } - else if(load_inst) + else if (load_inst) { if (isa<LoadInst>(load_inst->getPointerOperand())) { @@ -1064,7 +1064,7 @@ IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block) if (m_error_stream) m_error_stream->Printf("Internal error [IRForTarget]: Couldn't change a static reference to an Objective-C selector to a dynamic reference\n"); - if(log) + if (log) log->PutCString("Couldn't rewrite a reference to an Objective-C selector"); return false; @@ -1198,7 +1198,7 @@ IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) if (m_error_stream) m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable\n"); - if(log) + if (log) log->PutCString("Couldn't rewrite the creation of a persistent variable"); return false; diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp index caed8c51063..972d9a3ad16 100644 --- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp +++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp @@ -325,7 +325,7 @@ InstructionLLVM::Dump if (show_token) { - if(EDGetTokenString(&tokenStr, token)) + if (EDGetTokenString(&tokenStr, token)) { printTokenized = false; break; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index cc42306b20c..e62c3bb7749 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -167,7 +167,7 @@ AppleObjCRuntime::GetPrintForDebuggerAddr() SymbolContextList contexts; SymbolContext context; - if((!modules.FindSymbolsWithNameAndType(ConstString ("_NSPrintForDebugger"), eSymbolTypeCode, contexts)) && + if ((!modules.FindSymbolsWithNameAndType(ConstString ("_NSPrintForDebugger"), eSymbolTypeCode, contexts)) && (!modules.FindSymbolsWithNameAndType(ConstString ("_CFPrintForDebugger"), eSymbolTypeCode, contexts))) return NULL; diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index ac67767b6e5..48055d075e7 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -752,15 +752,15 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, // able to find the child member break; } - else if(end && *end == '-') + else if (end && *end == '-') { // this is most probably a BitField, let's take a look char *real_end = NULL; long final_index = ::strtol (end+1, &real_end, 0); - if(real_end && *real_end == ']') + if (real_end && *real_end == ']') { // if the format given is [high-low], swap range - if(child_index > final_index) + if (child_index > final_index) { long temp = child_index; child_index = final_index; diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp index 163322a661a..07608726908 100644 --- a/lldb/source/Target/ThreadPlanCallFunction.cpp +++ b/lldb/source/Target/ThreadPlanCallFunction.cpp @@ -339,7 +339,7 @@ ThreadPlanCallFunction::PlanExplainsStop () // If our subplan knows why we stopped, even if it's done (which would forward the question to us) // we answer yes. - if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop()) + if (m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop()) return true; // Check if the breakpoint is one of ours. diff --git a/lldb/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py b/lldb/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py index 266a12fdb5e..b48462e69c5 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py @@ -45,13 +45,18 @@ class DataFormatterTestCase(TestBase): 'stop reason = breakpoint']) # This is the function to remove the custom formats in order to have a - # clean slate for the next test case. + # clean slate for the next test case (most of these categories do not + # exist anymore, but we just make sure we delete all of them) def cleanup(): self.runCmd('type format clear', check=False) self.runCmd('type summary clear', check=False) self.runCmd('type category delete Category1', check=False) self.runCmd('type category delete Category2', check=False) self.runCmd('type category delete NewCategory', check=False) + self.runCmd("type category delete CircleCategory", check=False) + self.runCmd("type category delete RectangleStarCategory", check=False) + self.runCmd("type category delete BaseCategory", check=False) + # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) @@ -99,8 +104,8 @@ class DataFormatterTestCase(TestBase): self.runCmd("type summary add -f \"Width = ${var.w}, Height = ${var.h}\" Rectangle -w Category1") self.runCmd("type summary add -s \"return 'Area = ' + str( int(valobj.GetChildMemberWithName('w').GetValue()) * int(valobj.GetChildMemberWithName('h').GetValue()) );\" Rectangle -w Category2") - self.runCmd("type category enable Category2") - self.runCmd("type category enable Category1") + # check that enable A B is the same as enable B enable A + self.runCmd("type category enable Category1 Category2") self.expect("frame variable r1 r2 r3", substrs = ['r1 = Width = ', @@ -149,8 +154,7 @@ class DataFormatterTestCase(TestBase): 'r3 = Width = ']) # Now add another summary to another category and switch back and forth - self.runCmd("type category delete Category1") - self.runCmd("type category delete Category2") + self.runCmd("type category delete Category1 Category2") self.runCmd("type summary add Rectangle -f \"Category1\" -w Category1") self.runCmd("type summary add Rectangle -f \"Category2\" -w Category2") @@ -170,7 +174,7 @@ class DataFormatterTestCase(TestBase): 'r2 = Category2', 'r3 = Category2']) - self.runCmd("type category disable Category1") + # Check that re-enabling an enabled category works self.runCmd("type category enable Category1") self.expect("frame variable r1 r2 r3", @@ -245,6 +249,79 @@ class DataFormatterTestCase(TestBase): 'c2 = summary2', 'c3 = summary2']) + # Check that our order of priority works. Start by clearing categories + self.runCmd("type category delete Category1") + + self.runCmd("type summary add Shape -w BaseCategory -f \"AShape\"") + self.runCmd("type category enable BaseCategory") + + self.expect("frame variable c1 r1 c_ptr r_ptr", + substrs = ['AShape', + 'AShape', + 'AShape', + 'AShape']) + + self.runCmd("type summary add Circle -w CircleCategory -f \"ACircle\"") + self.runCmd("type summary add Rectangle -w RectangleCategory -f \"ARectangle\"") + self.runCmd("type category enable CircleCategory") + + self.expect("frame variable c1 r1 c_ptr r_ptr", + substrs = ['ACircle', + 'AShape', + 'ACircle', + 'AShape']) + + self.runCmd("type summary add \"Rectangle *\" -w RectangleStarCategory -f \"ARectangleStar\"") + self.runCmd("type category enable RectangleStarCategory") + + self.expect("frame variable c1 r1 c_ptr r_ptr", + substrs = ['ACircle', + 'AShape', + 'ACircle', + 'ARectangleStar']) + + self.runCmd("type category enable RectangleCategory") + + self.expect("frame variable c1 r1 c_ptr r_ptr", + substrs = ['ACircle', + 'ARectangle', + 'ACircle', + 'ARectangleStar']) + + # Check that abruptly deleting an enabled category does not crash us + self.runCmd("type category delete RectangleCategory") + + self.expect("frame variable c1 r1 c_ptr r_ptr", + substrs = ['ACircle', + 'AShape', + 'ACircle', + 'ARectangleStar']) + + # check that list commands work + self.expect("type category list", + substrs = ['RectangleStarCategory', + 'is enabled']) + + self.expect("type summary list", + substrs = ['ARectangleStar']) + + # Disable a category and check that it fallsback + self.runCmd("type category disable CircleCategory") + + # check that list commands work + self.expect("type category list", + substrs = ['CircleCategory', + 'not enabled']) + + self.expect("frame variable c1 r1 c_ptr r_ptr", + substrs = ['AShape', + 'AShape', + 'AShape', + 'ARectangleStar']) + + # Now delete all categories + self.runCmd("type category delete CircleCategory RectangleStarCategory BaseCategory") + if __name__ == '__main__': import atexit lldb.SBDebugger.Initialize() diff --git a/lldb/test/functionalities/data-formatter/data-formatter-categories/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-categories/main.cpp index 389adc9a25a..59f2c24b506 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-categories/main.cpp +++ b/lldb/test/functionalities/data-formatter/data-formatter-categories/main.cpp @@ -11,13 +11,16 @@ #include <stdlib.h> #include <stdint.h> -struct Rectangle { +struct Shape +{}; + +struct Rectangle : public Shape { int w; int h; Rectangle(int W = 3, int H = 5) : w(W), h(H) {} }; -struct Circle { +struct Circle : public Shape { int r; Circle(int R = 6) : r(R) {} }; @@ -32,6 +35,9 @@ int main (int argc, const char * argv[]) Circle c2(6); Circle c3(7); + Circle *c_ptr = new Circle(8); + Rectangle *r_ptr = new Rectangle(9,7); + return 0; // Set break point at this line. } |