Fixed a bug where deleting a regex summary would not immediately reflect in the variables display
The "systemwide summaries" feature has been removed and replaced with a more general and
powerful mechanism.
Categories:
 - summaries can now be grouped into buckets, called "categories" (it is expected that categories
   correspond to libraries and/or runtime environments)
 - to add a summary to a category, you can use the -w option to type summary add and give
   a category name (e.g. type summary add -f "foo" foo_t -w foo_category)
 - categories are by default disabled, which means LLDB will not look into them for summaries,
   to enable a category use "type category enable". once a category is enabled, LLDB will
   look into that category for summaries. the rules are quite trivial: every enabled category
   is searched for an exact match. if an exact match is nowhere to be found, any match is
   searched for in every enabled category (whether it involves cascading, going to base classes,
   ...). categories are searched into the order in which they were enabled (the most recently
   enabled category first, then the second most and so on..)
 - by default, most commands that deal with summaries, use a category named "default" if no
   explicit -w parameter is given (the observable behavior of LLDB should not change when
   categories are not explicitly used)
 - the systemwide summaries are now part of a "system" category

git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@135463 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp
index e99c1e0..12670a1 100644
--- a/source/Commands/CommandObjectFrame.cpp
+++ b/source/Commands/CommandObjectFrame.cpp
@@ -442,7 +442,7 @@
             
             SummaryFormatSP summary_format_sp;
             if (!m_option_variable.summary.empty())
-                Debugger::NamedSummaryFormats::Get(ConstString(m_option_variable.summary.c_str()), summary_format_sp);
+                Debugger::Formatting::NamedSummaryFormats::Get(ConstString(m_option_variable.summary.c_str()), summary_format_sp);
 
             if (variable_list)
             {
diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp
index d408a60..8db88e7 100644
--- a/source/Commands/CommandObjectType.cpp
+++ b/source/Commands/CommandObjectType.cpp
@@ -196,7 +196,7 @@
             const char* typeA = command.GetArgumentAtIndex(i);
             ConstString typeCS(typeA);
             if (typeCS)
-                Debugger::ValueFormats::Add(typeCS, entry);
+                Debugger::Formatting::ValueFormats::Add(typeCS, entry);
             else
             {
                 result.AppendError("empty typenames not allowed");
@@ -273,7 +273,7 @@
         }
         
         
-        if (Debugger::ValueFormats::Delete(typeCS))
+        if (Debugger::Formatting::ValueFormats::Delete(typeCS))
         {
             result.SetStatus(eReturnStatusSuccessFinishNoResult);
             return result.Succeeded();
@@ -311,7 +311,7 @@
     bool
     Execute (Args& command, CommandReturnObject &result)
     {
-        Debugger::ValueFormats::Clear();
+        Debugger::Formatting::ValueFormats::Clear();
         result.SetStatus(eReturnStatusSuccessFinishResult);
         return result.Succeeded();
     }
@@ -372,7 +372,7 @@
         }
         else
             param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result);
-        Debugger::ValueFormats::LoopThrough(CommandObjectTypeFormatList_LoopCallback, param);
+        Debugger::Formatting::ValueFormats::LoopThrough(CommandObjectTypeFormatList_LoopCallback, param);
         delete param;
         result.SetStatus(eReturnStatusSuccessFinishResult);
         return result.Succeeded();
@@ -549,7 +549,7 @@
             CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
                                                     script_format,
                                                     (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary),
-                                                    options->m_is_system,
+                                                    options->m_category,
                                                     &error);
             if (error.Fail())
             {
@@ -566,7 +566,7 @@
                 CommandObjectTypeSummaryAdd::AddSummary(*(options->m_name),
                                                                   script_format,
                                                                   CommandObjectTypeSummaryAdd::eNamedSummary,
-                                                                  options->m_is_system,
+                                                                  options->m_category,
                                                                   &error);
                 if (error.Fail())
                 {
@@ -635,7 +635,7 @@
             m_is_add_script = true;
             break;
         case 'w':
-            m_is_system = true;
+            m_category = ConstString(option_arg).GetCString();
             break;
         default:
             error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
@@ -660,6 +660,7 @@
     m_python_function = "";
     m_is_add_script = false;
     m_is_system = false;
+    m_category = NULL;
 }
 
 void
@@ -786,7 +787,8 @@
                                                          m_options.m_one_liner,
                                                          m_options.m_regex,
                                                          m_options.m_is_system,
-                                                         m_options.m_name);
+                                                         m_options.m_name,
+                                                         m_options.m_category);
         
         for(int i = 0; i < argc; i++) {
             const char* typeA = command.GetArgumentAtIndex(i);
@@ -815,7 +817,7 @@
         CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
                                                 script_format,
                                                 (m_options.m_regex ? eRegexSummary : eRegularSummary),
-                                                m_options.m_is_system,
+                                                m_options.m_category,
                                                 &error);
         if (error.Fail())
         {
@@ -829,7 +831,7 @@
     {
         if ( (bool)(*(m_options.m_name)) )
         {
-            AddSummary(*(m_options.m_name), script_format, eNamedSummary, m_options.m_is_system, &error);
+            AddSummary(*(m_options.m_name), script_format, eNamedSummary, m_options.m_category, &error);
             if (error.Fail())
             {
                 result.AppendError(error.AsCString());
@@ -903,7 +905,7 @@
         AddSummary(typeCS,
                    entry,
                    (m_options.m_regex ? eRegexSummary : eRegularSummary),
-                   m_options.m_is_system,
+                   m_options.m_category,
                    &error);
         
         if (error.Fail())
@@ -918,7 +920,7 @@
     {
         if ( (bool)(*(m_options.m_name)) )
         {
-            AddSummary(*(m_options.m_name), entry, eNamedSummary, m_options.m_is_system, &error);
+            AddSummary(*(m_options.m_name), entry, eNamedSummary, m_options.m_category, &error);
             if (error.Fail())
             {
                 result.AppendError(error.AsCString());
@@ -1037,7 +1039,7 @@
 CommandObjectTypeSummaryAdd::AddSummary(const ConstString& type_name,
                                         SummaryFormatSP entry,
                                         SummaryFormatType type,
-                                        bool is_system,
+                                        const char* category,
                                         Error* error)
 {
     if (type == eRegexSummary)
@@ -1050,30 +1052,20 @@
             return false;
         }
         
-        if (!is_system)
-        {
-            Debugger::RegexSummaryFormats::Delete(type_name);
-            Debugger::RegexSummaryFormats::Add(typeRX, entry);
-        }
-        else
-        {
-            Debugger::SystemRegexSummaryFormats::Delete(type_name);
-            Debugger::SystemRegexSummaryFormats::Add(typeRX, entry);
-        }
+        Debugger::Formatting::SummaryFormats(category)->RegexSummary()->Delete(type_name.GetCString());
+        Debugger::Formatting::SummaryFormats(category)->RegexSummary()->Add(typeRX, entry);
+        
         return true;
     }
     else if (type == eNamedSummary)
     {
         // system named summaries do not exist (yet?)
-        Debugger::NamedSummaryFormats::Add(type_name,entry);
+        Debugger::Formatting::NamedSummaryFormats::Add(type_name,entry);
         return true;
     }
     else
     {
-        if (!is_system)
-            Debugger::SummaryFormats::Add(type_name,entry);
-        else
-            Debugger::SystemSummaryFormats::Add(type_name,entry);
+        Debugger::Formatting::SummaryFormats(category)->Summary()->Add(type_name.GetCString(), entry);
         return true;
     }
 }    
@@ -1081,7 +1073,7 @@
 OptionDefinition
 CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
 {
-    { LLDB_OPT_SET_ALL, false, "system", 'w', no_argument, NULL, 0, eArgTypeBoolean,    "This is a system summary (makes it harder to delete it by accident)."},
+    { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,    "Add this to the given category instead of the default one."},
     { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade to derived typedefs."},
     { LLDB_OPT_SET_ALL, false, "no-value", 'v', no_argument, NULL, 0, eArgTypeBoolean,         "Don't show the value, just show the summary, for this type."},
     { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean,         "Don't use this format for pointers-to-type objects."},
@@ -1126,7 +1118,10 @@
             switch (short_option)
             {
                 case 'a':
-                    m_delete_system = true;
+                    m_delete_all = true;
+                    break;
+                case 'w':
+                    m_category = ConstString(option_arg).GetCString();
                     break;
                 default:
                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
@@ -1139,7 +1134,8 @@
         void
         OptionParsingStarting ()
         {
-            m_delete_system = false;
+            m_delete_all = false;
+            m_category = NULL;
         }
         
         const OptionDefinition*
@@ -1154,7 +1150,9 @@
         
         // Instance variables to hold the values for command options.
         
-        bool m_delete_system;
+        bool m_delete_all;
+        const char* m_category;
+        
     };
     
     CommandOptions m_options;
@@ -1164,6 +1162,17 @@
     {
         return &m_options;
     }
+    
+    static bool
+    PerCategoryCallback(void* param,
+                        const char* cate_name,
+                        const FormatCategory::SharedPointer& cate)
+    {
+        const char* name = (const char*)param;
+        cate->Summary()->Delete(name);
+        cate->RegexSummary()->Delete(name);
+        return true;
+    }
 
 public:
     CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) :
@@ -1210,13 +1219,17 @@
             return false;
         }
         
-        bool delete_summary = Debugger::SummaryFormats::Delete(typeCS);
-        bool delete_regex = Debugger::RegexSummaryFormats::Delete(typeCS);
-        bool delete_named = Debugger::NamedSummaryFormats::Delete(typeCS);
-        bool delete_sys = m_options.m_delete_system ? Debugger::SystemSummaryFormats::Delete(typeCS) : false;
-        bool delete_sys_regex = m_options.m_delete_system ? Debugger::SystemRegexSummaryFormats::Delete(typeCS) : false;
+        if (m_options.m_delete_all)
+        {
+            Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, (void*)typeCS.GetCString());
+            result.SetStatus(eReturnStatusSuccessFinishNoResult);
+            return result.Succeeded();
+        }
         
-        if (delete_summary || delete_regex || delete_named || delete_sys || delete_sys_regex)
+        bool delete_category = Debugger::Formatting::SummaryFormats(m_options.m_category)->Delete(typeCS.GetCString());
+        bool delete_named = Debugger::Formatting::NamedSummaryFormats::Delete(typeCS);
+        
+        if (delete_category || delete_named)
         {
             result.SetStatus(eReturnStatusSuccessFinishNoResult);
             return result.Succeeded();
@@ -1234,14 +1247,11 @@
 OptionDefinition
 CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] =
 {
-    { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean,  "Also delete system summaries (not recommended)."},
+    { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean,  "Delete from every category."},
+    { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,  "Delete from given category."},
     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
 };
 
-//-------------------------------------------------------------------------
-// CommandObjectTypeSummaryClear
-//-------------------------------------------------------------------------
-
 class CommandObjectTypeSummaryClear : public CommandObject
 {
 private:
@@ -1267,7 +1277,7 @@
             switch (short_option)
             {
                 case 'a':
-                    m_delete_system = true;
+                    m_delete_all = true;
                     break;
                 default:
                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
@@ -1280,7 +1290,7 @@
         void
         OptionParsingStarting ()
         {
-            m_delete_system = false;
+            m_delete_all = false;
         }
         
         const OptionDefinition*
@@ -1295,7 +1305,8 @@
         
         // Instance variables to hold the values for command options.
         
-        bool m_delete_system;
+        bool m_delete_all;
+        bool m_delete_named;
     };
     
     CommandOptions m_options;
@@ -1305,7 +1316,18 @@
     {
         return &m_options;
     }
-
+    
+    static bool
+    PerCategoryCallback(void* param,
+                        const char* cate_name,
+                        const FormatCategory::SharedPointer& cate)
+    {
+        cate->Summary()->Clear();
+        cate->RegexSummary()->Clear();
+        return true;
+        
+    }
+    
 public:
     CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) :
     CommandObject (interpreter,
@@ -1322,15 +1344,19 @@
     bool
     Execute (Args& command, CommandReturnObject &result)
     {
-        Debugger::SummaryFormats::Clear();
-        Debugger::RegexSummaryFormats::Clear();
-        Debugger::NamedSummaryFormats::Clear();
         
-        if (m_options.m_delete_system)
+        if (m_options.m_delete_all)
+            Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, NULL);
+        else if (command.GetArgumentCount() > 0)
         {
-            Debugger::SystemSummaryFormats::Clear();
-            Debugger::SystemRegexSummaryFormats::Clear();
+            const char* cat_name = command.GetArgumentAtIndex(0);
+            ConstString cat_nameCS(cat_name);
+            Debugger::Formatting::SummaryFormats(cat_nameCS.GetCString())->Clear();
         }
+        else
+            Debugger::Formatting::SummaryFormats()->Clear();
+        
+        Debugger::Formatting::NamedSummaryFormats::Clear();
         
         result.SetStatus(eReturnStatusSuccessFinishResult);
         return result.Succeeded();
@@ -1341,7 +1367,7 @@
 OptionDefinition
 CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] =
 {
-    { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean,  "Also clear system summaries (not recommended)."},
+    { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean,  "Clear every category."},
     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
 };
 
@@ -1362,14 +1388,6 @@
                                                   RegularExpression* X = NULL) : self(S), result(R), regex(X) {}
 };
 
-struct CommandObjectTypeRXSummaryList_LoopCallbackParam {
-    CommandObjectTypeSummaryList* self;
-    CommandReturnObject* result;
-    RegularExpression* regex;
-    CommandObjectTypeRXSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R,
-                                                   RegularExpression* X = NULL) : self(S), result(R), regex(X) {}
-};
-
 class CommandObjectTypeSummaryList : public CommandObject
 {
 public:
@@ -1400,7 +1418,6 @@
         const size_t argc = command.GetArgumentCount();
         
         CommandObjectTypeSummaryList_LoopCallbackParam *param;
-        CommandObjectTypeRXSummaryList_LoopCallbackParam *rxparam;
         
         if (argc == 1) {
             RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
@@ -1409,26 +1426,10 @@
         }
         else
             param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result);
-        Debugger::SummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
-        Debugger::SystemSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
-        delete param;
         
-        if (Debugger::RegexSummaryFormats::GetCount() > 0 || Debugger::SystemRegexSummaryFormats::GetCount() > 0 )
-        {
-            result.GetOutputStream().Printf("Regex-based summaries (slower):\n");
-            if (argc == 1) {
-                RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
-                regex->Compile(command.GetArgumentAtIndex(0));
-                rxparam = new CommandObjectTypeRXSummaryList_LoopCallbackParam(this,&result,regex);
-            }
-            else
-                rxparam = new CommandObjectTypeRXSummaryList_LoopCallbackParam(this,&result);
-            Debugger::RegexSummaryFormats::LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, rxparam);
-            Debugger::SystemRegexSummaryFormats::LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, rxparam);
-            delete rxparam;
-        }
-        
-        if (Debugger::NamedSummaryFormats::GetCount() > 0)
+        Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback,param);
+                
+        if (Debugger::Formatting::NamedSummaryFormats::GetCount() > 0)
         {
             result.GetOutputStream().Printf("Named summaries:\n");
             if (argc == 1) {
@@ -1438,7 +1439,7 @@
             }
             else
                 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result);
-            Debugger::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
+            Debugger::Formatting::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
             delete param;
         }
         
@@ -1448,6 +1449,28 @@
     
 private:
     
+    static bool
+    PerCategoryCallback(void* param,
+                        const char* cate_name,
+                        const FormatCategory::SharedPointer& cate)
+    {
+        
+        CommandReturnObject* result = ((CommandObjectTypeSummaryList_LoopCallbackParam*)param)->result;
+
+        result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
+                                         cate_name,
+                                         (cate->IsEnabled() ? "enabled" : "disabled"));
+        
+        cate->Summary()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
+        
+        if (cate->RegexSummary()->GetCount() > 0)
+        {
+            result->GetOutputStream().Printf("Regex-based summaries (slower):\n");
+            cate->RegexSummary()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param);
+        }
+        return true;
+    }
+    
     bool
     LoopCallback (const char* type,
                   const SummaryFormat::SharedPointer& entry,
@@ -1479,10 +1502,233 @@
                                            lldb::RegularExpressionSP regex,
                                            const SummaryFormat::SharedPointer& entry)
 {
-    CommandObjectTypeRXSummaryList_LoopCallbackParam* param = (CommandObjectTypeRXSummaryList_LoopCallbackParam*)pt2self;
+    CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
     return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
 }
 
+//-------------------------------------------------------------------------
+// CommandObjectTypeCategoryEnable
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeCategoryEnable : public CommandObject
+{
+public:
+    CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type category enable",
+                   "Enable a category as a source of summaries.",
+                   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);
+        
+    }
+    
+    ~CommandObjectTypeCategoryEnable ()
+    {
+    }
+    
+    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 category name not allowed");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        Debugger::Formatting::Categories::Enable(typeCS);
+        result.SetStatus(eReturnStatusSuccessFinishResult);
+        return result.Succeeded();
+    }
+    
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeCategoryDelete
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeCategoryDelete : public CommandObject
+{
+public:
+    CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type category delete",
+                   "Delete a category and all associated summaries.",
+                   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);
+        
+    }
+    
+    ~CommandObjectTypeCategoryDelete ()
+    {
+    }
+    
+    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 category name not allowed");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        if (Debugger::Formatting::Categories::Delete(typeCS))
+        {
+            result.SetStatus(eReturnStatusSuccessFinishResult);
+            return result.Succeeded();
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("cannot delete category %s.\n", typeA);
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }        
+    }
+    
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeCategoryDisable
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeCategoryDisable : public CommandObject
+{
+public:
+    CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type category disable",
+                   "Disable a category as a source of summaries.",
+                   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);
+        
+    }
+    
+    ~CommandObjectTypeCategoryDisable ()
+    {
+    }
+    
+    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 category name not allowed");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        Debugger::Formatting::Categories::Disable(typeCS);
+        result.SetStatus(eReturnStatusSuccessFinishResult);
+        return result.Succeeded();
+    }
+    
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeCategoryList
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeCategoryList : public CommandObject
+{
+private:
+    static bool
+    PerCategoryCallback(void* param,
+                        const char* cate_name,
+                        const FormatCategory::SharedPointer& cate)
+    {
+        CommandReturnObject* result = (CommandReturnObject*)param;
+        result->GetOutputStream().Printf("Category %s is%s enabled\n",
+                                       cate_name,
+                                       (cate->IsEnabled() ? "" : " not"));
+        return true;
+    }
+public:
+    CommandObjectTypeCategoryList (CommandInterpreter &interpreter) :
+    CommandObject (interpreter,
+                   "type category list",
+                   "Provide a list of all existing categories.",
+                   NULL)
+    {
+    }
+    
+    ~CommandObjectTypeCategoryList ()
+    {
+    }
+    
+    bool
+    Execute (Args& command, CommandReturnObject &result)
+    {
+        Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, (void*)&result);
+        result.SetStatus(eReturnStatusSuccessFinishResult);
+        return result.Succeeded();
+    }
+    
+};
+
 class CommandObjectTypeFormat : public CommandObjectMultiword
 {
 public:
@@ -1504,6 +1750,27 @@
     }
 };
 
+class CommandObjectTypeCategory : public CommandObjectMultiword
+{
+public:
+    CommandObjectTypeCategory (CommandInterpreter &interpreter) :
+    CommandObjectMultiword (interpreter,
+                            "type category",
+                            "A set of commands for operating on categories",
+                            "type category [<sub-command-options>] ")
+    {
+        LoadSubCommand ("enable",        CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter)));
+        LoadSubCommand ("disable",       CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter)));
+        LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter)));
+        LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeCategoryList (interpreter)));
+    }
+    
+    
+    ~CommandObjectTypeCategory ()
+    {
+    }
+};
+
 class CommandObjectTypeSummary : public CommandObjectMultiword
 {
 public:
@@ -1535,6 +1802,7 @@
                             "A set of commands for operating on the type system",
                             "type [<sub-command-options>]")
 {
+    LoadSubCommand ("category",  CommandObjectSP (new CommandObjectTypeCategory (interpreter)));
     LoadSubCommand ("format",    CommandObjectSP (new CommandObjectTypeFormat (interpreter)));
     LoadSubCommand ("summary",   CommandObjectSP (new CommandObjectTypeSummary (interpreter)));
 }
diff --git a/source/Commands/CommandObjectType.h b/source/Commands/CommandObjectType.h
index 0c45378..d924287 100644
--- a/source/Commands/CommandObjectType.h
+++ b/source/Commands/CommandObjectType.h
@@ -43,6 +43,8 @@
     
     ConstString* m_name;
     
+    const char* m_category;
+    
     ScriptAddOptions(bool sptr,
                      bool sref,
                      bool casc,
@@ -51,7 +53,8 @@
                      bool onel,
                      bool regx,
                      bool syst,
-                     ConstString* name) :
+                     ConstString* name,
+                     const char* catg) :
     m_skip_pointers(sptr),
     m_skip_references(sref),
     m_cascade(casc),
@@ -62,7 +65,8 @@
     m_one_liner(onel),
     m_regex(regx),
     m_is_system(syst),
-    m_name(name)
+    m_name(name),
+    m_category(catg)
     {
     }
     
@@ -127,6 +131,7 @@
         std::string m_python_function;
         bool m_is_add_script;
         bool m_is_system;
+        const char* m_category;
     };
     
     CommandOptions m_options;
@@ -169,7 +174,7 @@
     AddSummary(const ConstString& type_name,
                lldb::SummaryFormatSP entry,
                SummaryFormatType type,
-               bool is_system,
+               const char* category,
                Error* error = NULL);
 };