| //===-- SBTypeCategory.cpp ----------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "lldb/API/SBTypeCategory.h" |
| |
| #include "lldb/API/SBTypeFilter.h" |
| #include "lldb/API/SBTypeFormat.h" |
| #include "lldb/API/SBTypeSummary.h" |
| #include "lldb/API/SBTypeSynthetic.h" |
| #include "lldb/API/SBTypeNameSpecifier.h" |
| #include "lldb/API/SBStream.h" |
| |
| #include "lldb/Core/DataVisualization.h" |
| #include "lldb/Core/Debugger.h" |
| #include "lldb/Interpreter/CommandInterpreter.h" |
| #include "lldb/Interpreter/ScriptInterpreter.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| typedef std::pair<lldb::TypeCategoryImplSP,user_id_t> ImplType; |
| |
| SBTypeCategory::SBTypeCategory() : |
| m_opaque_sp() |
| { |
| } |
| |
| SBTypeCategory::SBTypeCategory (const char* name) : |
| m_opaque_sp() |
| { |
| DataVisualization::Categories::GetCategory(ConstString(name), m_opaque_sp); |
| } |
| |
| SBTypeCategory::SBTypeCategory (const lldb::SBTypeCategory &rhs) : |
| m_opaque_sp(rhs.m_opaque_sp) |
| { |
| } |
| |
| SBTypeCategory::~SBTypeCategory () |
| { |
| } |
| |
| bool |
| SBTypeCategory::IsValid() const |
| { |
| return (m_opaque_sp.get() != NULL); |
| } |
| |
| bool |
| SBTypeCategory::GetEnabled () |
| { |
| if (!IsValid()) |
| return false; |
| return m_opaque_sp->IsEnabled(); |
| } |
| |
| void |
| SBTypeCategory::SetEnabled (bool enabled) |
| { |
| if (!IsValid()) |
| return; |
| if (enabled) |
| DataVisualization::Categories::Enable(m_opaque_sp); |
| else |
| DataVisualization::Categories::Disable(m_opaque_sp); |
| } |
| |
| const char* |
| SBTypeCategory::GetName() |
| { |
| if (!IsValid()) |
| return NULL; |
| return m_opaque_sp->GetName(); |
| } |
| |
| uint32_t |
| SBTypeCategory::GetNumFormats () |
| { |
| if (!IsDefaultCategory()) |
| return 0; |
| |
| return DataVisualization::ValueFormats::GetCount(); |
| } |
| |
| uint32_t |
| SBTypeCategory::GetNumSummaries () |
| { |
| if (!IsValid()) |
| return 0; |
| return m_opaque_sp->GetSummaryNavigator()->GetCount() + m_opaque_sp->GetRegexSummaryNavigator()->GetCount(); |
| } |
| |
| uint32_t |
| SBTypeCategory::GetNumFilters () |
| { |
| if (!IsValid()) |
| return 0; |
| return m_opaque_sp->GetFilterNavigator()->GetCount() + m_opaque_sp->GetRegexFilterNavigator()->GetCount(); |
| } |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| uint32_t |
| SBTypeCategory::GetNumSynthetics () |
| { |
| if (!IsValid()) |
| return 0; |
| return m_opaque_sp->GetSyntheticNavigator()->GetCount() + m_opaque_sp->GetRegexSyntheticNavigator()->GetCount(); |
| } |
| #endif |
| |
| lldb::SBTypeNameSpecifier |
| SBTypeCategory::GetTypeNameSpecifierForFilterAtIndex (uint32_t index) |
| { |
| if (!IsValid()) |
| return SBTypeNameSpecifier(); |
| return SBTypeNameSpecifier(m_opaque_sp->GetTypeNameSpecifierForFilterAtIndex(index)); |
| } |
| |
| lldb::SBTypeNameSpecifier |
| SBTypeCategory::GetTypeNameSpecifierForFormatAtIndex (uint32_t index) |
| { |
| if (!IsDefaultCategory()) |
| return SBTypeNameSpecifier(); |
| return SBTypeNameSpecifier(DataVisualization::ValueFormats::GetTypeNameSpecifierForFormatAtIndex(index)); |
| } |
| |
| lldb::SBTypeNameSpecifier |
| SBTypeCategory::GetTypeNameSpecifierForSummaryAtIndex (uint32_t index) |
| { |
| if (!IsValid()) |
| return SBTypeNameSpecifier(); |
| return SBTypeNameSpecifier(m_opaque_sp->GetTypeNameSpecifierForSummaryAtIndex(index)); |
| } |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| lldb::SBTypeNameSpecifier |
| SBTypeCategory::GetTypeNameSpecifierForSyntheticAtIndex (uint32_t index) |
| { |
| if (!IsValid()) |
| return SBTypeNameSpecifier(); |
| return SBTypeNameSpecifier(m_opaque_sp->GetTypeNameSpecifierForSyntheticAtIndex(index)); |
| } |
| #endif |
| |
| SBTypeFilter |
| SBTypeCategory::GetFilterForType (SBTypeNameSpecifier spec) |
| { |
| if (!IsValid()) |
| return SBTypeFilter(); |
| |
| if (!spec.IsValid()) |
| return SBTypeFilter(); |
| |
| lldb::SyntheticChildrenSP children_sp; |
| |
| if (spec.IsRegex()) |
| m_opaque_sp->GetRegexFilterNavigator()->GetExact(ConstString(spec.GetName()), children_sp); |
| else |
| m_opaque_sp->GetFilterNavigator()->GetExact(ConstString(spec.GetName()), children_sp); |
| |
| if (!children_sp) |
| return lldb::SBTypeFilter(); |
| |
| TypeFilterImplSP filter_sp = STD_STATIC_POINTER_CAST(TypeFilterImpl,children_sp); |
| |
| return lldb::SBTypeFilter(filter_sp); |
| |
| } |
| SBTypeFormat |
| SBTypeCategory::GetFormatForType (SBTypeNameSpecifier spec) |
| { |
| if (!IsDefaultCategory()) |
| return SBTypeFormat(); |
| |
| if (!spec.IsValid()) |
| return SBTypeFormat(); |
| |
| if (spec.IsRegex()) |
| return SBTypeFormat(); |
| |
| return SBTypeFormat(DataVisualization::ValueFormats::GetFormat(ConstString(spec.GetName()))); |
| } |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| SBTypeSummary |
| SBTypeCategory::GetSummaryForType (SBTypeNameSpecifier spec) |
| { |
| if (!IsValid()) |
| return SBTypeSummary(); |
| |
| if (!spec.IsValid()) |
| return SBTypeSummary(); |
| |
| lldb::TypeSummaryImplSP summary_sp; |
| |
| if (spec.IsRegex()) |
| m_opaque_sp->GetRegexSummaryNavigator()->GetExact(ConstString(spec.GetName()), summary_sp); |
| else |
| m_opaque_sp->GetSummaryNavigator()->GetExact(ConstString(spec.GetName()), summary_sp); |
| |
| if (!summary_sp) |
| return lldb::SBTypeSummary(); |
| |
| return lldb::SBTypeSummary(summary_sp); |
| } |
| #endif // LLDB_DISABLE_PYTHON |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| SBTypeSynthetic |
| SBTypeCategory::GetSyntheticForType (SBTypeNameSpecifier spec) |
| { |
| if (!IsValid()) |
| return SBTypeSynthetic(); |
| |
| if (!spec.IsValid()) |
| return SBTypeSynthetic(); |
| |
| lldb::SyntheticChildrenSP children_sp; |
| |
| if (spec.IsRegex()) |
| m_opaque_sp->GetRegexSyntheticNavigator()->GetExact(ConstString(spec.GetName()), children_sp); |
| else |
| m_opaque_sp->GetSyntheticNavigator()->GetExact(ConstString(spec.GetName()), children_sp); |
| |
| if (!children_sp) |
| return lldb::SBTypeSynthetic(); |
| |
| TypeSyntheticImplSP synth_sp = STD_STATIC_POINTER_CAST(TypeSyntheticImpl,children_sp); |
| |
| return lldb::SBTypeSynthetic(synth_sp); |
| } |
| #endif |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| SBTypeFilter |
| SBTypeCategory::GetFilterAtIndex (uint32_t index) |
| { |
| if (!IsValid()) |
| return SBTypeFilter(); |
| lldb::SyntheticChildrenSP children_sp = m_opaque_sp->GetSyntheticAtIndex((index)); |
| |
| if (!children_sp.get()) |
| return lldb::SBTypeFilter(); |
| |
| TypeFilterImplSP filter_sp = STD_STATIC_POINTER_CAST(TypeFilterImpl,children_sp); |
| |
| return lldb::SBTypeFilter(filter_sp); |
| } |
| #endif |
| |
| SBTypeFormat |
| SBTypeCategory::GetFormatAtIndex (uint32_t index) |
| { |
| if (!IsDefaultCategory()) |
| return SBTypeFormat(); |
| return SBTypeFormat(DataVisualization::ValueFormats::GetFormatAtIndex((index))); |
| } |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| SBTypeSummary |
| SBTypeCategory::GetSummaryAtIndex (uint32_t index) |
| { |
| if (!IsValid()) |
| return SBTypeSummary(); |
| return SBTypeSummary(m_opaque_sp->GetSummaryAtIndex((index))); |
| } |
| #endif |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| SBTypeSynthetic |
| SBTypeCategory::GetSyntheticAtIndex (uint32_t index) |
| { |
| if (!IsValid()) |
| return SBTypeSynthetic(); |
| lldb::SyntheticChildrenSP children_sp = m_opaque_sp->GetSyntheticAtIndex((index)); |
| |
| if (!children_sp.get()) |
| return lldb::SBTypeSynthetic(); |
| |
| TypeSyntheticImplSP synth_sp = STD_STATIC_POINTER_CAST(TypeSyntheticImpl,children_sp); |
| |
| return lldb::SBTypeSynthetic(synth_sp); |
| } |
| #endif |
| |
| bool |
| SBTypeCategory::AddTypeFormat (SBTypeNameSpecifier type_name, |
| SBTypeFormat format) |
| { |
| if (!IsDefaultCategory()) |
| return false; |
| |
| if (!type_name.IsValid()) |
| return false; |
| |
| if (!format.IsValid()) |
| return false; |
| |
| if (type_name.IsRegex()) |
| return false; |
| |
| DataVisualization::ValueFormats::Add(ConstString(type_name.GetName()), format.GetSP()); |
| |
| return true; |
| } |
| |
| bool |
| SBTypeCategory::DeleteTypeFormat (SBTypeNameSpecifier type_name) |
| { |
| if (!IsDefaultCategory()) |
| return false; |
| |
| if (!type_name.IsValid()) |
| return false; |
| |
| if (type_name.IsRegex()) |
| return false; |
| |
| return DataVisualization::ValueFormats::Delete(ConstString(type_name.GetName())); |
| } |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| bool |
| SBTypeCategory::AddTypeSummary (SBTypeNameSpecifier type_name, |
| SBTypeSummary summary) |
| { |
| if (!IsValid()) |
| return false; |
| |
| if (!type_name.IsValid()) |
| return false; |
| |
| if (!summary.IsValid()) |
| return false; |
| |
| // FIXME: we need to iterate over all the Debugger objects and have each of them contain a copy of the function |
| // since we currently have formatters live in a global space, while Python code lives in a specific Debugger-related environment |
| // this should eventually be fixed by deciding a final location in the LLDB object space for formatters |
| if (summary.IsFunctionCode()) |
| { |
| void *name_token = (void*)ConstString(type_name.GetName()).GetCString(); |
| const char* script = summary.GetData(); |
| StringList input; input.SplitIntoLines(script, strlen(script)); |
| uint32_t num_debuggers = lldb_private::Debugger::GetNumDebuggers(); |
| bool need_set = true; |
| for (uint32_t j = 0; |
| j < num_debuggers; |
| j++) |
| { |
| DebuggerSP debugger_sp = lldb_private::Debugger::GetDebuggerAtIndex(j); |
| if (debugger_sp) |
| { |
| ScriptInterpreter* interpreter_ptr = debugger_sp->GetCommandInterpreter().GetScriptInterpreter(); |
| if (interpreter_ptr) |
| { |
| std::string output; |
| if (interpreter_ptr->GenerateTypeScriptFunction(input, output, name_token) && !output.empty()) |
| { |
| if (need_set) |
| { |
| need_set = false; |
| summary.SetFunctionName(output.c_str()); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| if (type_name.IsRegex()) |
| m_opaque_sp->GetRegexSummaryNavigator()->Add(lldb::RegularExpressionSP(new RegularExpression(type_name.GetName())), summary.GetSP()); |
| else |
| m_opaque_sp->GetSummaryNavigator()->Add(ConstString(type_name.GetName()), summary.GetSP()); |
| |
| return true; |
| } |
| #endif |
| |
| bool |
| SBTypeCategory::DeleteTypeSummary (SBTypeNameSpecifier type_name) |
| { |
| if (!IsValid()) |
| return false; |
| |
| if (!type_name.IsValid()) |
| return false; |
| |
| if (type_name.IsRegex()) |
| return m_opaque_sp->GetRegexSummaryNavigator()->Delete(ConstString(type_name.GetName())); |
| else |
| return m_opaque_sp->GetSummaryNavigator()->Delete(ConstString(type_name.GetName())); |
| } |
| |
| bool |
| SBTypeCategory::AddTypeFilter (SBTypeNameSpecifier type_name, |
| SBTypeFilter filter) |
| { |
| if (!IsValid()) |
| return false; |
| |
| if (!type_name.IsValid()) |
| return false; |
| |
| if (!filter.IsValid()) |
| return false; |
| |
| if (type_name.IsRegex()) |
| m_opaque_sp->GetRegexFilterNavigator()->Add(lldb::RegularExpressionSP(new RegularExpression(type_name.GetName())), filter.GetSP()); |
| else |
| m_opaque_sp->GetFilterNavigator()->Add(ConstString(type_name.GetName()), filter.GetSP()); |
| |
| return true; |
| } |
| |
| bool |
| SBTypeCategory::DeleteTypeFilter (SBTypeNameSpecifier type_name) |
| { |
| if (!IsValid()) |
| return false; |
| |
| if (!type_name.IsValid()) |
| return false; |
| |
| if (type_name.IsRegex()) |
| return m_opaque_sp->GetRegexFilterNavigator()->Delete(ConstString(type_name.GetName())); |
| else |
| return m_opaque_sp->GetFilterNavigator()->Delete(ConstString(type_name.GetName())); |
| } |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| bool |
| SBTypeCategory::AddTypeSynthetic (SBTypeNameSpecifier type_name, |
| SBTypeSynthetic synth) |
| { |
| if (!IsValid()) |
| return false; |
| |
| if (!type_name.IsValid()) |
| return false; |
| |
| if (!synth.IsValid()) |
| return false; |
| |
| // FIXME: we need to iterate over all the Debugger objects and have each of them contain a copy of the function |
| // since we currently have formatters live in a global space, while Python code lives in a specific Debugger-related environment |
| // this should eventually be fixed by deciding a final location in the LLDB object space for formatters |
| if (synth.IsClassCode()) |
| { |
| void *name_token = (void*)ConstString(type_name.GetName()).GetCString(); |
| const char* script = synth.GetData(); |
| StringList input; input.SplitIntoLines(script, strlen(script)); |
| uint32_t num_debuggers = lldb_private::Debugger::GetNumDebuggers(); |
| bool need_set = true; |
| for (uint32_t j = 0; |
| j < num_debuggers; |
| j++) |
| { |
| DebuggerSP debugger_sp = lldb_private::Debugger::GetDebuggerAtIndex(j); |
| if (debugger_sp) |
| { |
| ScriptInterpreter* interpreter_ptr = debugger_sp->GetCommandInterpreter().GetScriptInterpreter(); |
| if (interpreter_ptr) |
| { |
| std::string output; |
| if (interpreter_ptr->GenerateTypeSynthClass(input, output, name_token) && !output.empty()) |
| { |
| if (need_set) |
| { |
| need_set = false; |
| synth.SetClassName(output.c_str()); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| if (type_name.IsRegex()) |
| m_opaque_sp->GetRegexSyntheticNavigator()->Add(lldb::RegularExpressionSP(new RegularExpression(type_name.GetName())), synth.GetSP()); |
| else |
| m_opaque_sp->GetSyntheticNavigator()->Add(ConstString(type_name.GetName()), synth.GetSP()); |
| |
| return true; |
| } |
| |
| bool |
| SBTypeCategory::DeleteTypeSynthetic (SBTypeNameSpecifier type_name) |
| { |
| if (!IsValid()) |
| return false; |
| |
| if (!type_name.IsValid()) |
| return false; |
| |
| if (type_name.IsRegex()) |
| return m_opaque_sp->GetRegexSyntheticNavigator()->Delete(ConstString(type_name.GetName())); |
| else |
| return m_opaque_sp->GetSyntheticNavigator()->Delete(ConstString(type_name.GetName())); |
| } |
| #endif // LLDB_DISABLE_PYTHON |
| |
| bool |
| SBTypeCategory::GetDescription (lldb::SBStream &description, |
| lldb::DescriptionLevel description_level) |
| { |
| if (!IsValid()) |
| return false; |
| description.Printf("Category name: %s\n",GetName()); |
| return true; |
| } |
| |
| lldb::SBTypeCategory & |
| SBTypeCategory::operator = (const lldb::SBTypeCategory &rhs) |
| { |
| if (this != &rhs) |
| { |
| m_opaque_sp = rhs.m_opaque_sp; |
| } |
| return *this; |
| } |
| |
| bool |
| SBTypeCategory::operator == (lldb::SBTypeCategory &rhs) |
| { |
| if (IsValid() == false) |
| return !rhs.IsValid(); |
| |
| return m_opaque_sp.get() == rhs.m_opaque_sp.get(); |
| |
| } |
| |
| bool |
| SBTypeCategory::operator != (lldb::SBTypeCategory &rhs) |
| { |
| if (IsValid() == false) |
| return rhs.IsValid(); |
| |
| return m_opaque_sp.get() != rhs.m_opaque_sp.get(); |
| } |
| |
| lldb::TypeCategoryImplSP |
| SBTypeCategory::GetSP () |
| { |
| if (!IsValid()) |
| return lldb::TypeCategoryImplSP(); |
| return m_opaque_sp; |
| } |
| |
| void |
| SBTypeCategory::SetSP (const lldb::TypeCategoryImplSP &typecategory_impl_sp) |
| { |
| m_opaque_sp = typecategory_impl_sp; |
| } |
| |
| SBTypeCategory::SBTypeCategory (const lldb::TypeCategoryImplSP &typecategory_impl_sp) : |
| m_opaque_sp(typecategory_impl_sp) |
| { |
| } |
| |
| bool |
| SBTypeCategory::IsDefaultCategory() |
| { |
| if (!IsValid()) |
| return false; |
| |
| return (strcmp(m_opaque_sp->GetName(),"default") == 0); |
| } |
| |