CommandObjectType.cpp revision 598df88bd6fc33c6fb330bc859bdc277795501f3
1//===-- CommandObjectType.cpp ----------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "CommandObjectType.h"
11
12// C Includes
13
14#include <ctype.h>
15
16// C++ Includes
17
18#include "lldb/Core/DataVisualization.h"
19#include "lldb/Core/ConstString.h"
20#include "lldb/Core/Debugger.h"
21#include "lldb/Core/InputReaderEZ.h"
22#include "lldb/Core/RegularExpression.h"
23#include "lldb/Core/State.h"
24#include "lldb/Core/StringList.h"
25#include "lldb/Interpreter/CommandInterpreter.h"
26#include "lldb/Interpreter/CommandObject.h"
27#include "lldb/Interpreter/CommandReturnObject.h"
28#include "lldb/Interpreter/Options.h"
29#include "lldb/Interpreter/OptionGroupFormat.h"
30
31using namespace lldb;
32using namespace lldb_private;
33
34
35class ScriptAddOptions
36{
37
38public:
39
40    TypeSummaryImpl::Flags m_flags;
41
42    StringList m_target_types;
43    StringList m_user_source;
44
45    bool m_regex;
46
47    ConstString m_name;
48
49    std::string m_category;
50
51    ScriptAddOptions(const TypeSummaryImpl::Flags& flags,
52                     bool regx,
53                     const ConstString& name,
54                     std::string catg) :
55        m_flags(flags),
56        m_regex(regx),
57        m_name(name),
58        m_category(catg)
59    {
60    }
61
62    typedef STD_SHARED_PTR(ScriptAddOptions) SharedPointer;
63
64};
65
66class SynthAddOptions
67{
68
69public:
70
71    bool m_skip_pointers;
72    bool m_skip_references;
73    bool m_cascade;
74    bool m_regex;
75    StringList m_user_source;
76    StringList m_target_types;
77
78    std::string m_category;
79
80    SynthAddOptions(bool sptr,
81                    bool sref,
82                    bool casc,
83                    bool regx,
84                    std::string catg) :
85    m_skip_pointers(sptr),
86    m_skip_references(sref),
87    m_cascade(casc),
88    m_regex(regx),
89    m_user_source(),
90    m_target_types(),
91    m_category(catg)
92    {
93    }
94
95    typedef STD_SHARED_PTR(SynthAddOptions) SharedPointer;
96
97};
98
99
100
101class CommandObjectTypeSummaryAdd : public CommandObject
102{
103
104private:
105
106    class CommandOptions : public Options
107    {
108    public:
109
110        CommandOptions (CommandInterpreter &interpreter) :
111        Options (interpreter)
112        {
113        }
114
115        virtual
116        ~CommandOptions (){}
117
118        virtual Error
119        SetOptionValue (uint32_t option_idx, const char *option_arg);
120
121        void
122        OptionParsingStarting ();
123
124        const OptionDefinition*
125        GetDefinitions ()
126        {
127            return g_option_table;
128        }
129
130        // Options table: Required for subclasses of Options.
131
132        static OptionDefinition g_option_table[];
133
134        // Instance variables to hold the values for command options.
135
136        TypeSummaryImpl::Flags m_flags;
137        bool m_regex;
138        std::string m_format_string;
139        ConstString m_name;
140        std::string m_python_script;
141        std::string m_python_function;
142        bool m_is_add_script;
143        std::string m_category;
144    };
145
146    CommandOptions m_options;
147
148    virtual Options *
149    GetOptions ()
150    {
151        return &m_options;
152    }
153
154    void
155    CollectPythonScript(ScriptAddOptions *options,
156                        CommandReturnObject &result);
157
158    bool
159    Execute_ScriptSummary (Args& command, CommandReturnObject &result);
160
161    bool
162    Execute_StringSummary (Args& command, CommandReturnObject &result);
163
164public:
165
166    enum SummaryFormatType
167    {
168        eRegularSummary,
169        eRegexSummary,
170        eNamedSummary
171    };
172
173    CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter);
174
175    ~CommandObjectTypeSummaryAdd ()
176    {
177    }
178
179    bool
180    Execute (Args& command, CommandReturnObject &result);
181
182    static bool
183    AddSummary(const ConstString& type_name,
184               lldb::TypeSummaryImplSP entry,
185               SummaryFormatType type,
186               std::string category,
187               Error* error = NULL);
188};
189
190class CommandObjectTypeSynthAdd : public CommandObject
191{
192
193private:
194
195    class CommandOptions : public Options
196    {
197    public:
198
199        CommandOptions (CommandInterpreter &interpreter) :
200        Options (interpreter)
201        {
202        }
203
204        virtual
205        ~CommandOptions (){}
206
207        virtual Error
208        SetOptionValue (uint32_t option_idx, const char *option_arg)
209        {
210            Error error;
211            char short_option = (char) m_getopt_table[option_idx].val;
212            bool success;
213
214            switch (short_option)
215            {
216                case 'C':
217                    m_cascade = Args::StringToBoolean(option_arg, true, &success);
218                    if (!success)
219                        error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg);
220                    break;
221                case 'P':
222                    handwrite_python = true;
223                    break;
224                case 'l':
225                    m_class_name = std::string(option_arg);
226                    is_class_based = true;
227                    break;
228                case 'p':
229                    m_skip_pointers = true;
230                    break;
231                case 'r':
232                    m_skip_references = true;
233                    break;
234                case 'w':
235                    m_category = std::string(option_arg);
236                    break;
237                case 'x':
238                    m_regex = true;
239                    break;
240                default:
241                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
242                    break;
243            }
244
245            return error;
246        }
247
248        void
249        OptionParsingStarting ()
250        {
251            m_cascade = true;
252            m_class_name = "";
253            m_skip_pointers = false;
254            m_skip_references = false;
255            m_category = "default";
256            is_class_based = false;
257            handwrite_python = false;
258            m_regex = false;
259        }
260
261        const OptionDefinition*
262        GetDefinitions ()
263        {
264            return g_option_table;
265        }
266
267        // Options table: Required for subclasses of Options.
268
269        static OptionDefinition g_option_table[];
270
271        // Instance variables to hold the values for command options.
272
273        bool m_cascade;
274        bool m_skip_references;
275        bool m_skip_pointers;
276        std::string m_class_name;
277        bool m_input_python;
278        std::string m_category;
279
280        bool is_class_based;
281
282        bool handwrite_python;
283
284        bool m_regex;
285
286    };
287
288    CommandOptions m_options;
289
290    virtual Options *
291    GetOptions ()
292    {
293        return &m_options;
294    }
295
296    void
297    CollectPythonScript (SynthAddOptions *options,
298                         CommandReturnObject &result);
299    bool
300    Execute_HandwritePython (Args& command, CommandReturnObject &result);
301
302    bool
303    Execute_PythonClass (Args& command, CommandReturnObject &result);
304
305    bool
306    Execute (Args& command, CommandReturnObject &result);
307
308public:
309
310    enum SynthFormatType
311    {
312        eRegularSynth,
313        eRegexSynth
314    };
315
316    CommandObjectTypeSynthAdd (CommandInterpreter &interpreter);
317
318    ~CommandObjectTypeSynthAdd ()
319    {
320    }
321
322    static bool
323    AddSynth(const ConstString& type_name,
324             lldb::SyntheticChildrenSP entry,
325             SynthFormatType type,
326             std::string category_name,
327             Error* error);
328};
329
330//-------------------------------------------------------------------------
331// CommandObjectTypeFormatAdd
332//-------------------------------------------------------------------------
333
334class CommandObjectTypeFormatAdd : public CommandObject
335{
336
337private:
338
339    class CommandOptions : public OptionGroup
340    {
341    public:
342
343        CommandOptions () :
344            OptionGroup()
345        {
346        }
347
348        virtual
349        ~CommandOptions ()
350        {
351        }
352
353        virtual uint32_t
354        GetNumDefinitions ();
355
356        virtual const OptionDefinition*
357        GetDefinitions ()
358        {
359            return g_option_table;
360        }
361
362        virtual void
363        OptionParsingStarting (CommandInterpreter &interpreter)
364        {
365            m_cascade = true;
366            m_skip_pointers = false;
367            m_skip_references = false;
368        }
369        virtual Error
370        SetOptionValue (CommandInterpreter &interpreter,
371                        uint32_t option_idx,
372                        const char *option_value)
373        {
374            Error error;
375            const char short_option = (char) g_option_table[option_idx].short_option;
376            bool success;
377
378            switch (short_option)
379            {
380                case 'C':
381                    m_cascade = Args::StringToBoolean(option_value, true, &success);
382                    if (!success)
383                        error.SetErrorStringWithFormat("invalid value for cascade: %s", option_value);
384                    break;
385                case 'p':
386                    m_skip_pointers = true;
387                    break;
388                case 'r':
389                    m_skip_references = true;
390                    break;
391                default:
392                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
393                    break;
394            }
395
396            return error;
397        }
398
399        // Options table: Required for subclasses of Options.
400
401        static OptionDefinition g_option_table[];
402
403        // Instance variables to hold the values for command options.
404
405        bool m_cascade;
406        bool m_skip_references;
407        bool m_skip_pointers;
408    };
409
410    OptionGroupOptions m_option_group;
411    OptionGroupFormat m_format_options;
412    CommandOptions m_command_options;
413
414    virtual Options *
415    GetOptions ()
416    {
417        return &m_option_group;
418    }
419
420public:
421    CommandObjectTypeFormatAdd (CommandInterpreter &interpreter) :
422    CommandObject (interpreter,
423                   "type format add",
424                   "Add a new formatting style for a type.",
425                   NULL),
426        m_option_group (interpreter),
427        m_format_options (eFormatInvalid),
428        m_command_options ()
429    {
430        CommandArgumentEntry type_arg;
431        CommandArgumentData type_style_arg;
432
433        type_style_arg.arg_type = eArgTypeName;
434        type_style_arg.arg_repetition = eArgRepeatPlus;
435
436        type_arg.push_back (type_style_arg);
437
438        m_arguments.push_back (type_arg);
439
440        SetHelpLong(
441                    "Some examples of using this command.\n"
442                    "We use as reference the following snippet of code:\n"
443                    "\n"
444                    "typedef int Aint;\n"
445                    "typedef float Afloat;\n"
446                    "typedef Aint Bint;\n"
447                    "typedef Afloat Bfloat;\n"
448                    "\n"
449                    "Aint ix = 5;\n"
450                    "Bint iy = 5;\n"
451                    "\n"
452                    "Afloat fx = 3.14;\n"
453                    "BFloat fy = 3.14;\n"
454                    "\n"
455                    "Typing:\n"
456                    "type format add -f hex AInt\n"
457                    "frame variable iy\n"
458                    "will produce an hex display of iy, because no formatter is available for Bint and the one for Aint is used instead\n"
459                    "To prevent this type\n"
460                    "type format add -f hex -C no AInt\n"
461                    "\n"
462                    "A similar reasoning applies to\n"
463                    "type format add -f hex -C no float -p\n"
464                    "which now prints all floats and float&s as hexadecimal, but does not format float*s\n"
465                    "and does not change the default display for Afloat and Bfloat objects.\n"
466                    );
467
468        // Add the "--format" to all options groups
469        m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_ALL);
470        m_option_group.Append (&m_command_options);
471        m_option_group.Finalize();
472
473    }
474
475    ~CommandObjectTypeFormatAdd ()
476    {
477    }
478
479    bool
480    Execute (Args& command, CommandReturnObject &result)
481    {
482        const size_t argc = command.GetArgumentCount();
483
484        if (argc < 1)
485        {
486            result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
487            result.SetStatus(eReturnStatusFailed);
488            return false;
489        }
490
491        const Format format = m_format_options.GetFormat();
492        if (format == eFormatInvalid)
493        {
494            result.AppendErrorWithFormat ("%s needs a valid format.\n", m_cmd_name.c_str());
495            result.SetStatus(eReturnStatusFailed);
496            return false;
497        }
498
499        TypeFormatImplSP entry;
500
501        entry.reset(new TypeFormatImpl(format,
502                                    TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade).
503                                    SetSkipPointers(m_command_options.m_skip_pointers).
504                                    SetSkipReferences(m_command_options.m_skip_references)));
505
506        // now I have a valid format, let's add it to every type
507
508        for (size_t i = 0; i < argc; i++)
509        {
510            const char* typeA = command.GetArgumentAtIndex(i);
511            ConstString typeCS(typeA);
512            if (typeCS)
513                DataVisualization::ValueFormats::Add(typeCS, entry);
514            else
515            {
516                result.AppendError("empty typenames not allowed");
517                result.SetStatus(eReturnStatusFailed);
518                return false;
519            }
520        }
521
522        result.SetStatus(eReturnStatusSuccessFinishNoResult);
523        return result.Succeeded();
524    }
525};
526
527OptionDefinition
528CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] =
529{
530    { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade to derived typedefs."},
531    { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
532    { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
533};
534
535
536uint32_t
537CommandObjectTypeFormatAdd::CommandOptions::GetNumDefinitions ()
538{
539    return sizeof(g_option_table) / sizeof (OptionDefinition);
540}
541
542
543//-------------------------------------------------------------------------
544// CommandObjectTypeFormatDelete
545//-------------------------------------------------------------------------
546
547class CommandObjectTypeFormatDelete : public CommandObject
548{
549public:
550    CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) :
551    CommandObject (interpreter,
552                   "type format delete",
553                   "Delete an existing formatting style for a type.",
554                   NULL)
555    {
556        CommandArgumentEntry type_arg;
557        CommandArgumentData type_style_arg;
558
559        type_style_arg.arg_type = eArgTypeName;
560        type_style_arg.arg_repetition = eArgRepeatPlain;
561
562        type_arg.push_back (type_style_arg);
563
564        m_arguments.push_back (type_arg);
565
566    }
567
568    ~CommandObjectTypeFormatDelete ()
569    {
570    }
571
572    bool
573    Execute (Args& command, CommandReturnObject &result)
574    {
575        const size_t argc = command.GetArgumentCount();
576
577        if (argc != 1)
578        {
579            result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
580            result.SetStatus(eReturnStatusFailed);
581            return false;
582        }
583
584        const char* typeA = command.GetArgumentAtIndex(0);
585        ConstString typeCS(typeA);
586
587        if (!typeCS)
588        {
589            result.AppendError("empty typenames not allowed");
590            result.SetStatus(eReturnStatusFailed);
591            return false;
592        }
593
594
595        if (DataVisualization::ValueFormats::Delete(typeCS))
596        {
597            result.SetStatus(eReturnStatusSuccessFinishNoResult);
598            return result.Succeeded();
599        }
600        else
601        {
602            result.AppendErrorWithFormat ("no custom format for %s.\n", typeA);
603            result.SetStatus(eReturnStatusFailed);
604            return false;
605        }
606
607    }
608
609};
610
611//-------------------------------------------------------------------------
612// CommandObjectTypeFormatClear
613//-------------------------------------------------------------------------
614
615class CommandObjectTypeFormatClear : public CommandObject
616{
617public:
618    CommandObjectTypeFormatClear (CommandInterpreter &interpreter) :
619    CommandObject (interpreter,
620                   "type format clear",
621                   "Delete all existing format styles.",
622                   NULL)
623    {
624    }
625
626    ~CommandObjectTypeFormatClear ()
627    {
628    }
629
630    bool
631    Execute (Args& command, CommandReturnObject &result)
632    {
633        DataVisualization::ValueFormats::Clear();
634        result.SetStatus(eReturnStatusSuccessFinishResult);
635        return result.Succeeded();
636    }
637
638};
639
640//-------------------------------------------------------------------------
641// CommandObjectTypeFormatList
642//-------------------------------------------------------------------------
643
644bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry);
645
646class CommandObjectTypeFormatList;
647
648struct CommandObjectTypeFormatList_LoopCallbackParam {
649    CommandObjectTypeFormatList* self;
650    CommandReturnObject* result;
651    RegularExpression* regex;
652    CommandObjectTypeFormatList_LoopCallbackParam(CommandObjectTypeFormatList* S, CommandReturnObject* R,
653                                            RegularExpression* X = NULL) : self(S), result(R), regex(X) {}
654};
655
656class CommandObjectTypeFormatList : public CommandObject
657{
658public:
659    CommandObjectTypeFormatList (CommandInterpreter &interpreter) :
660    CommandObject (interpreter,
661                   "type format list",
662                   "Show a list of current formatting styles.",
663                   NULL)
664    {
665        CommandArgumentEntry type_arg;
666        CommandArgumentData type_style_arg;
667
668        type_style_arg.arg_type = eArgTypeName;
669        type_style_arg.arg_repetition = eArgRepeatOptional;
670
671        type_arg.push_back (type_style_arg);
672
673        m_arguments.push_back (type_arg);
674    }
675
676    ~CommandObjectTypeFormatList ()
677    {
678    }
679
680    bool
681    Execute (Args& command, CommandReturnObject &result)
682    {
683        const size_t argc = command.GetArgumentCount();
684
685        CommandObjectTypeFormatList_LoopCallbackParam *param;
686
687        if (argc == 1)
688        {
689            RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
690            regex->Compile(command.GetArgumentAtIndex(0));
691            param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,regex);
692        }
693        else
694            param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result);
695        DataVisualization::ValueFormats::LoopThrough(CommandObjectTypeFormatList_LoopCallback, param);
696        delete param;
697        result.SetStatus(eReturnStatusSuccessFinishResult);
698        return result.Succeeded();
699    }
700
701private:
702
703    bool
704    LoopCallback (ConstString type,
705                  const lldb::TypeFormatImplSP& entry,
706                  RegularExpression* regex,
707                  CommandReturnObject *result)
708    {
709        if (regex == NULL || regex->Execute(type.AsCString()))
710        {
711            result->GetOutputStream().Printf ("%s: %s\n", type.AsCString(),
712                                              entry->GetDescription().c_str());
713        }
714        return true;
715    }
716
717    friend bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry);
718
719};
720
721bool
722CommandObjectTypeFormatList_LoopCallback (
723                                    void* pt2self,
724                                    ConstString type,
725                                    const lldb::TypeFormatImplSP& entry)
726{
727    CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self;
728    return param->self->LoopCallback(type, entry, param->regex, param->result);
729}
730
731
732#ifndef LLDB_DISABLE_PYTHON
733
734//-------------------------------------------------------------------------
735// CommandObjectTypeSummaryAdd
736//-------------------------------------------------------------------------
737
738static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
739                                                       "def function (valobj,dict):";
740
741class TypeScriptAddInputReader : public InputReaderEZ
742{
743private:
744    DISALLOW_COPY_AND_ASSIGN (TypeScriptAddInputReader);
745public:
746    TypeScriptAddInputReader(Debugger& debugger) :
747    InputReaderEZ(debugger)
748    {}
749
750    virtual
751    ~TypeScriptAddInputReader()
752    {
753    }
754
755    virtual void ActivateHandler(HandlerData& data)
756    {
757        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
758        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
759        if (!batch_mode)
760        {
761            out_stream->Printf ("%s\n", g_summary_addreader_instructions);
762            if (data.reader.GetPrompt())
763                out_stream->Printf ("%s", data.reader.GetPrompt());
764            out_stream->Flush();
765        }
766    }
767
768    virtual void ReactivateHandler(HandlerData& data)
769    {
770        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
771        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
772        if (data.reader.GetPrompt() && !batch_mode)
773        {
774            out_stream->Printf ("%s", data.reader.GetPrompt());
775            out_stream->Flush();
776        }
777    }
778    virtual void GotTokenHandler(HandlerData& data)
779    {
780        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
781        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
782        if (data.bytes && data.bytes_len && data.baton)
783        {
784            ((ScriptAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len);
785        }
786        if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
787        {
788            out_stream->Printf ("%s", data.reader.GetPrompt());
789            out_stream->Flush();
790        }
791    }
792    virtual void InterruptHandler(HandlerData& data)
793    {
794        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
795        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
796        data.reader.SetIsDone (true);
797        if (!batch_mode)
798        {
799            out_stream->Printf ("Warning: No command attached to breakpoint.\n");
800            out_stream->Flush();
801        }
802    }
803    virtual void EOFHandler(HandlerData& data)
804    {
805        data.reader.SetIsDone (true);
806    }
807    virtual void DoneHandler(HandlerData& data)
808    {
809        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
810        ScriptAddOptions *options_ptr = ((ScriptAddOptions*)data.baton);
811        if (!options_ptr)
812        {
813            out_stream->Printf ("Internal error #1: no script attached.\n");
814            out_stream->Flush();
815            return;
816        }
817
818        ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
819
820        ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
821        if (!interpreter)
822        {
823            out_stream->Printf ("Internal error #2: no script attached.\n");
824            out_stream->Flush();
825            return;
826        }
827        std::string funct_name_str;
828        if (!interpreter->GenerateTypeScriptFunction (options->m_user_source,
829                                                      funct_name_str))
830        {
831            out_stream->Printf ("Internal error #3: no script attached.\n");
832            out_stream->Flush();
833            return;
834        }
835        if (funct_name_str.empty())
836        {
837            out_stream->Printf ("Internal error #4: no script attached.\n");
838            out_stream->Flush();
839            return;
840        }
841        // now I have a valid function name, let's add this as script for every type in the list
842
843        TypeSummaryImplSP script_format;
844        script_format.reset(new ScriptSummaryFormat(options->m_flags,
845                                                    funct_name_str.c_str(),
846                                                    options->m_user_source.CopyList("     ").c_str()));
847
848        Error error;
849
850        for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
851        {
852            const char *type_name = options->m_target_types.GetStringAtIndex(i);
853            CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
854                                                    script_format,
855                                                    (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary),
856                                                    options->m_category,
857                                                    &error);
858            if (error.Fail())
859            {
860                out_stream->Printf ("%s", error.AsCString());
861                out_stream->Flush();
862                return;
863            }
864        }
865
866        if (options->m_name)
867        {
868            CommandObjectTypeSummaryAdd::AddSummary (options->m_name,
869                                                     script_format,
870                                                     CommandObjectTypeSummaryAdd::eNamedSummary,
871                                                     options->m_category,
872                                                     &error);
873            if (error.Fail())
874            {
875                CommandObjectTypeSummaryAdd::AddSummary (options->m_name,
876                                                         script_format,
877                                                         CommandObjectTypeSummaryAdd::eNamedSummary,
878                                                         options->m_category,
879                                                         &error);
880                if (error.Fail())
881                {
882                    out_stream->Printf ("%s", error.AsCString());
883                    out_stream->Flush();
884                    return;
885                }
886            }
887            else
888            {
889                out_stream->Printf ("%s", error.AsCString());
890                out_stream->Flush();
891                return;
892            }
893        }
894        else
895        {
896            if (error.AsCString())
897            {
898                out_stream->PutCString (error.AsCString());
899                out_stream->Flush();
900            }
901            return;
902        }
903    }
904};
905
906#endif // #ifndef LLDB_DISABLE_PYTHON
907
908Error
909CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
910{
911    Error error;
912    char short_option = (char) m_getopt_table[option_idx].val;
913    bool success;
914
915    switch (short_option)
916    {
917        case 'C':
918            m_flags.SetCascades(Args::StringToBoolean(option_arg, true, &success));
919            if (!success)
920                error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg);
921            break;
922        case 'e':
923            m_flags.SetDontShowChildren(false);
924            break;
925        case 'v':
926            m_flags.SetDontShowValue(true);
927            break;
928        case 'c':
929            m_flags.SetShowMembersOneLiner(true);
930            break;
931        case 's':
932            m_format_string = std::string(option_arg);
933            break;
934        case 'p':
935            m_flags.SetSkipPointers(true);
936            break;
937        case 'r':
938            m_flags.SetSkipReferences(true);
939            break;
940        case 'x':
941            m_regex = true;
942            break;
943        case 'n':
944            m_name.SetCString(option_arg);
945            break;
946        case 'o':
947            m_python_script = std::string(option_arg);
948            m_is_add_script = true;
949            break;
950        case 'F':
951            m_python_function = std::string(option_arg);
952            m_is_add_script = true;
953            break;
954        case 'P':
955            m_is_add_script = true;
956            break;
957        case 'w':
958            m_category = std::string(option_arg);
959            break;
960        case 'O':
961            m_flags.SetHideItemNames(true);
962            break;
963        default:
964            error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
965            break;
966    }
967
968    return error;
969}
970
971void
972CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting ()
973{
974    m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
975    m_flags.SetShowMembersOneLiner(false).SetSkipPointers(false).SetSkipReferences(false).SetHideItemNames(false);
976
977    m_regex = false;
978    m_name.Clear();
979    m_python_script = "";
980    m_python_function = "";
981    m_format_string = "";
982    m_is_add_script = false;
983    m_category = "default";
984}
985
986#ifndef LLDB_DISABLE_PYTHON
987void
988CommandObjectTypeSummaryAdd::CollectPythonScript (ScriptAddOptions *options,
989                                                  CommandReturnObject &result)
990{
991    InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger()));
992    if (reader_sp && options)
993    {
994
995        InputReaderEZ::InitializationParameters ipr;
996
997        Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt("     ")));
998        if (err.Success())
999        {
1000            m_interpreter.GetDebugger().PushInputReader (reader_sp);
1001            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1002        }
1003        else
1004        {
1005            result.AppendError (err.AsCString());
1006            result.SetStatus (eReturnStatusFailed);
1007        }
1008    }
1009    else
1010    {
1011        result.AppendError("out of memory");
1012        result.SetStatus (eReturnStatusFailed);
1013    }
1014}
1015
1016bool
1017CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result)
1018{
1019    const size_t argc = command.GetArgumentCount();
1020
1021    if (argc < 1 && !m_options.m_name)
1022    {
1023        result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
1024        result.SetStatus(eReturnStatusFailed);
1025        return false;
1026    }
1027
1028    TypeSummaryImplSP script_format;
1029
1030    if (!m_options.m_python_function.empty()) // we have a Python function ready to use
1031    {
1032        ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1033        if (!interpreter)
1034        {
1035            result.AppendError ("Internal error #1N: no script attached.\n");
1036            result.SetStatus (eReturnStatusFailed);
1037            return false;
1038        }
1039        const char *funct_name = m_options.m_python_function.c_str();
1040        if (!funct_name || !funct_name[0])
1041        {
1042            result.AppendError ("Internal error #2N: no script attached.\n");
1043            result.SetStatus (eReturnStatusFailed);
1044            return false;
1045        }
1046
1047        std::string code = ("     " + m_options.m_python_function + "(valobj,dict)");
1048
1049        script_format.reset(new ScriptSummaryFormat(m_options.m_flags,
1050                                                    funct_name,
1051                                                    code.c_str()));
1052    }
1053    else if (!m_options.m_python_script.empty()) // we have a quick 1-line script, just use it
1054    {
1055        ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1056        if (!interpreter)
1057        {
1058            result.AppendError ("Internal error #1Q: no script attached.\n");
1059            result.SetStatus (eReturnStatusFailed);
1060            return false;
1061        }
1062        StringList funct_sl;
1063        funct_sl << m_options.m_python_script.c_str();
1064        std::string funct_name_str;
1065        if (!interpreter->GenerateTypeScriptFunction (funct_sl,
1066                                                      funct_name_str))
1067        {
1068            result.AppendError ("Internal error #2Q: no script attached.\n");
1069            result.SetStatus (eReturnStatusFailed);
1070            return false;
1071        }
1072        if (funct_name_str.empty())
1073        {
1074            result.AppendError ("Internal error #3Q: no script attached.\n");
1075            result.SetStatus (eReturnStatusFailed);
1076            return false;
1077        }
1078
1079        std::string code = "     " + m_options.m_python_script;
1080
1081        script_format.reset(new ScriptSummaryFormat(m_options.m_flags,
1082                                                    funct_name_str.c_str(),
1083                                                    code.c_str()));
1084    }
1085    else // use an InputReader to grab Python code from the user
1086    {
1087        ScriptAddOptions *options = new ScriptAddOptions(m_options.m_flags,
1088                                                         m_options.m_regex,
1089                                                         m_options.m_name,
1090                                                         m_options.m_category);
1091
1092        for (size_t i = 0; i < argc; i++)
1093        {
1094            const char* typeA = command.GetArgumentAtIndex(i);
1095            if (typeA && *typeA)
1096                options->m_target_types << typeA;
1097            else
1098            {
1099                result.AppendError("empty typenames not allowed");
1100                result.SetStatus(eReturnStatusFailed);
1101                return false;
1102            }
1103        }
1104
1105        CollectPythonScript(options,result);
1106        return result.Succeeded();
1107    }
1108
1109    // if I am here, script_format must point to something good, so I can add that
1110    // as a script summary to all interested parties
1111
1112    Error error;
1113
1114    for (size_t i = 0; i < command.GetArgumentCount(); i++)
1115    {
1116        const char *type_name = command.GetArgumentAtIndex(i);
1117        CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
1118                                                script_format,
1119                                                (m_options.m_regex ? eRegexSummary : eRegularSummary),
1120                                                m_options.m_category,
1121                                                &error);
1122        if (error.Fail())
1123        {
1124            result.AppendError(error.AsCString());
1125            result.SetStatus(eReturnStatusFailed);
1126            return false;
1127        }
1128    }
1129
1130    if (m_options.m_name)
1131    {
1132        AddSummary(m_options.m_name, script_format, eNamedSummary, m_options.m_category, &error);
1133        if (error.Fail())
1134        {
1135            result.AppendError(error.AsCString());
1136            result.AppendError("added to types, but not given a name");
1137            result.SetStatus(eReturnStatusFailed);
1138            return false;
1139        }
1140    }
1141
1142    return result.Succeeded();
1143}
1144
1145#endif
1146
1147
1148bool
1149CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result)
1150{
1151    const size_t argc = command.GetArgumentCount();
1152
1153    if (argc < 1 && !m_options.m_name)
1154    {
1155        result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
1156        result.SetStatus(eReturnStatusFailed);
1157        return false;
1158    }
1159
1160    if (!m_options.m_flags.GetShowMembersOneLiner() && m_options.m_format_string.empty())
1161    {
1162        result.AppendError("empty summary strings not allowed");
1163        result.SetStatus(eReturnStatusFailed);
1164        return false;
1165    }
1166
1167    const char* format_cstr = (m_options.m_flags.GetShowMembersOneLiner() ? "" : m_options.m_format_string.c_str());
1168
1169    // ${var%S} is an endless recursion, prevent it
1170    if (strcmp(format_cstr, "${var%S}") == 0)
1171    {
1172        result.AppendError("recursive summary not allowed");
1173        result.SetStatus(eReturnStatusFailed);
1174        return false;
1175    }
1176
1177    Error error;
1178
1179    lldb::TypeSummaryImplSP entry(new StringSummaryFormat(m_options.m_flags,
1180                                                        format_cstr));
1181
1182    if (error.Fail())
1183    {
1184        result.AppendError(error.AsCString());
1185        result.SetStatus(eReturnStatusFailed);
1186        return false;
1187    }
1188
1189    // now I have a valid format, let's add it to every type
1190
1191    for (size_t i = 0; i < argc; i++)
1192    {
1193        const char* typeA = command.GetArgumentAtIndex(i);
1194        if (!typeA || typeA[0] == '\0')
1195        {
1196            result.AppendError("empty typenames not allowed");
1197            result.SetStatus(eReturnStatusFailed);
1198            return false;
1199        }
1200        ConstString typeCS(typeA);
1201
1202        AddSummary(typeCS,
1203                   entry,
1204                   (m_options.m_regex ? eRegexSummary : eRegularSummary),
1205                   m_options.m_category,
1206                   &error);
1207
1208        if (error.Fail())
1209        {
1210            result.AppendError(error.AsCString());
1211            result.SetStatus(eReturnStatusFailed);
1212            return false;
1213        }
1214    }
1215
1216    if (m_options.m_name)
1217    {
1218        AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, &error);
1219        if (error.Fail())
1220        {
1221            result.AppendError(error.AsCString());
1222            result.AppendError("added to types, but not given a name");
1223            result.SetStatus(eReturnStatusFailed);
1224            return false;
1225        }
1226    }
1227
1228    result.SetStatus(eReturnStatusSuccessFinishNoResult);
1229    return result.Succeeded();
1230}
1231
1232CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) :
1233CommandObject (interpreter,
1234               "type summary add",
1235               "Add a new summary style for a type.",
1236               NULL), m_options (interpreter)
1237{
1238    CommandArgumentEntry type_arg;
1239    CommandArgumentData type_style_arg;
1240
1241    type_style_arg.arg_type = eArgTypeName;
1242    type_style_arg.arg_repetition = eArgRepeatPlus;
1243
1244    type_arg.push_back (type_style_arg);
1245
1246    m_arguments.push_back (type_arg);
1247
1248    SetHelpLong(
1249                "Some examples of using this command.\n"
1250                "We use as reference the following snippet of code:\n"
1251                "struct JustADemo\n"
1252                "{\n"
1253                "int* ptr;\n"
1254                "float value;\n"
1255                "JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n"
1256                "};\n"
1257                "JustADemo object(42,3.14);\n"
1258                "struct AnotherDemo : public JustADemo\n"
1259                "{\n"
1260                "uint8_t byte;\n"
1261                "AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n"
1262                "};\n"
1263                "AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n"
1264                "\n"
1265                "type summary add --summary-string \"the answer is ${*var.ptr}\" JustADemo\n"
1266                "when typing frame variable object you will get \"the answer is 42\"\n"
1267                "type summary add --summary-string \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n"
1268                "when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n"
1269                "\n"
1270                "Alternatively, you could also say\n"
1271                "type summary add --summary-string \"${var%V} -> ${*var}\" \"int *\"\n"
1272                "and replace the above summary string with\n"
1273                "type summary add --summary-string \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n"
1274                "to obtain a similar result\n"
1275                "\n"
1276                "To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n"
1277                "type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n"
1278                "\n"
1279                "This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n"
1280                "If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n"
1281                "type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n"
1282                "A similar option -r exists for references.\n"
1283                "\n"
1284                "If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n"
1285                "you can use the -c option, without giving any summary string:\n"
1286                "type summary add -c JustADemo\n"
1287                "frame variable object\n"
1288                "the output being similar to (ptr=0xsomeaddress, value=3.14)\n"
1289                "\n"
1290                "If you want to display some summary text, but also expand the structure of your object, you can add the -e option, as in:\n"
1291                "type summary add -e --summary-string \"*ptr = ${*var.ptr}\" JustADemo\n"
1292                "Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n"
1293                "to get an output like:\n"
1294                "\n"
1295                "*ptr = 42 {\n"
1296                " ptr = 0xsomeaddress\n"
1297                " value = 3.14\n"
1298                "}\n"
1299                "\n"
1300                "You can also add Python summaries, in which case you will use lldb public API to gather information from your variables"
1301                "and elaborate them to a meaningful summary inside a script written in Python. The variable object will be passed to your"
1302                "script as an SBValue object. The following example might help you when starting to use the Python summaries feature:\n"
1303                "type summary add JustADemo -o \"value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();\"\n"
1304                "If you prefer to type your scripts on multiple lines, you will use the -P option and then type your script, ending it with "
1305                "the word DONE on a line by itself to mark you're finished editing your code:\n"
1306                "(lldb)type summary add JustADemo -P\n"
1307                "     value = valobj.GetChildMemberWithName('value');\n"
1308                "     return 'My value is ' + value.GetValue();\n"
1309                "DONE\n"
1310                "(lldb) <-- type further LLDB commands here\n"
1311                );
1312}
1313
1314bool
1315CommandObjectTypeSummaryAdd::Execute (Args& command, CommandReturnObject &result)
1316{
1317    if (m_options.m_is_add_script)
1318    {
1319#ifndef LLDB_DISABLE_PYTHON
1320        return Execute_ScriptSummary(command, result);
1321#else
1322        result.AppendError ("python is disabled");
1323        result.SetStatus(eReturnStatusFailed);
1324        return false;
1325#endif
1326    }
1327
1328    return Execute_StringSummary(command, result);
1329}
1330
1331bool
1332CommandObjectTypeSummaryAdd::AddSummary(const ConstString& type_name,
1333                                        TypeSummaryImplSP entry,
1334                                        SummaryFormatType type,
1335                                        std::string category_name,
1336                                        Error* error)
1337{
1338    lldb::TypeCategoryImplSP category;
1339    DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
1340
1341    if (type == eRegexSummary)
1342    {
1343        RegularExpressionSP typeRX(new RegularExpression());
1344        if (!typeRX->Compile(type_name.GetCString()))
1345        {
1346            if (error)
1347                error->SetErrorString("regex format error (maybe this is not really a regex?)");
1348            return false;
1349        }
1350
1351        category->GetRegexSummaryNavigator()->Delete(type_name);
1352        category->GetRegexSummaryNavigator()->Add(typeRX, entry);
1353
1354        return true;
1355    }
1356    else if (type == eNamedSummary)
1357    {
1358        // system named summaries do not exist (yet?)
1359        DataVisualization::NamedSummaryFormats::Add(type_name,entry);
1360        return true;
1361    }
1362    else
1363    {
1364        category->GetSummaryNavigator()->Add(type_name, entry);
1365        return true;
1366    }
1367}
1368
1369OptionDefinition
1370CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
1371{
1372    { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,    "Add this to the given category instead of the default one."},
1373    { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade to derived typedefs."},
1374    { LLDB_OPT_SET_ALL, false, "no-value", 'v', no_argument, NULL, 0, eArgTypeNone,         "Don't show the value, just show the summary, for this type."},
1375    { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
1376    { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
1377    { LLDB_OPT_SET_ALL, false,  "regex", 'x', no_argument, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
1378    { LLDB_OPT_SET_1  , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeNone,    "If true, inline all child values into summary string."},
1379    { LLDB_OPT_SET_1  , false, "omit-names", 'O', no_argument, NULL, 0, eArgTypeNone,    "If true, omit value names in the summary display."},
1380    { LLDB_OPT_SET_2  , true, "summary-string", 's', required_argument, NULL, 0, eArgTypeSummaryString,    "Summary string used to display text and object contents."},
1381    { LLDB_OPT_SET_3, false, "python-script", 'o', required_argument, NULL, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command."},
1382    { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type."},
1383    { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."},
1384    { LLDB_OPT_SET_2 | LLDB_OPT_SET_3,   false, "expand", 'e', no_argument, NULL, 0, eArgTypeNone,    "Expand aggregate data types to show children on separate lines."},
1385    { LLDB_OPT_SET_2 | LLDB_OPT_SET_3,   false, "name", 'n', required_argument, NULL, 0, eArgTypeName,    "A name for this summary string."},
1386    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1387};
1388
1389
1390//-------------------------------------------------------------------------
1391// CommandObjectTypeSummaryDelete
1392//-------------------------------------------------------------------------
1393
1394class CommandObjectTypeSummaryDelete : public CommandObject
1395{
1396private:
1397    class CommandOptions : public Options
1398    {
1399    public:
1400
1401        CommandOptions (CommandInterpreter &interpreter) :
1402        Options (interpreter)
1403        {
1404        }
1405
1406        virtual
1407        ~CommandOptions (){}
1408
1409        virtual Error
1410        SetOptionValue (uint32_t option_idx, const char *option_arg)
1411        {
1412            Error error;
1413            char short_option = (char) m_getopt_table[option_idx].val;
1414
1415            switch (short_option)
1416            {
1417                case 'a':
1418                    m_delete_all = true;
1419                    break;
1420                case 'w':
1421                    m_category = std::string(option_arg);
1422                    break;
1423                default:
1424                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1425                    break;
1426            }
1427
1428            return error;
1429        }
1430
1431        void
1432        OptionParsingStarting ()
1433        {
1434            m_delete_all = false;
1435            m_category = "default";
1436        }
1437
1438        const OptionDefinition*
1439        GetDefinitions ()
1440        {
1441            return g_option_table;
1442        }
1443
1444        // Options table: Required for subclasses of Options.
1445
1446        static OptionDefinition g_option_table[];
1447
1448        // Instance variables to hold the values for command options.
1449
1450        bool m_delete_all;
1451        std::string m_category;
1452
1453    };
1454
1455    CommandOptions m_options;
1456
1457    virtual Options *
1458    GetOptions ()
1459    {
1460        return &m_options;
1461    }
1462
1463    static bool
1464    PerCategoryCallback(void* param,
1465                        const lldb::TypeCategoryImplSP& category_sp)
1466    {
1467		ConstString *name = (ConstString*)param;
1468		category_sp->Delete(*name, eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary);
1469		return true;
1470    }
1471
1472public:
1473    CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) :
1474    CommandObject (interpreter,
1475                   "type summary delete",
1476                   "Delete an existing summary style for a type.",
1477                   NULL), m_options(interpreter)
1478    {
1479        CommandArgumentEntry type_arg;
1480        CommandArgumentData type_style_arg;
1481
1482        type_style_arg.arg_type = eArgTypeName;
1483        type_style_arg.arg_repetition = eArgRepeatPlain;
1484
1485        type_arg.push_back (type_style_arg);
1486
1487        m_arguments.push_back (type_arg);
1488
1489    }
1490
1491    ~CommandObjectTypeSummaryDelete ()
1492    {
1493    }
1494
1495    bool
1496    Execute (Args& command, CommandReturnObject &result)
1497    {
1498        const size_t argc = command.GetArgumentCount();
1499
1500        if (argc != 1)
1501        {
1502            result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
1503            result.SetStatus(eReturnStatusFailed);
1504            return false;
1505        }
1506
1507        const char* typeA = command.GetArgumentAtIndex(0);
1508        ConstString typeCS(typeA);
1509
1510        if (!typeCS)
1511        {
1512            result.AppendError("empty typenames not allowed");
1513            result.SetStatus(eReturnStatusFailed);
1514            return false;
1515        }
1516
1517        if (m_options.m_delete_all)
1518        {
1519            DataVisualization::Categories::LoopThrough(PerCategoryCallback, &typeCS);
1520            result.SetStatus(eReturnStatusSuccessFinishNoResult);
1521            return result.Succeeded();
1522        }
1523
1524        lldb::TypeCategoryImplSP category;
1525        DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
1526
1527        bool delete_category = category->Delete(typeCS,
1528                                                eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary);
1529        bool delete_named = DataVisualization::NamedSummaryFormats::Delete(typeCS);
1530
1531        if (delete_category || delete_named)
1532        {
1533            result.SetStatus(eReturnStatusSuccessFinishNoResult);
1534            return result.Succeeded();
1535        }
1536        else
1537        {
1538            result.AppendErrorWithFormat ("no custom summary for %s.\n", typeA);
1539            result.SetStatus(eReturnStatusFailed);
1540            return false;
1541        }
1542
1543    }
1544};
1545
1546OptionDefinition
1547CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] =
1548{
1549    { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Delete from every category."},
1550    { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,  "Delete from given category."},
1551    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1552};
1553
1554class CommandObjectTypeSummaryClear : public CommandObject
1555{
1556private:
1557
1558    class CommandOptions : public Options
1559    {
1560    public:
1561
1562        CommandOptions (CommandInterpreter &interpreter) :
1563        Options (interpreter)
1564        {
1565        }
1566
1567        virtual
1568        ~CommandOptions (){}
1569
1570        virtual Error
1571        SetOptionValue (uint32_t option_idx, const char *option_arg)
1572        {
1573            Error error;
1574            char short_option = (char) m_getopt_table[option_idx].val;
1575
1576            switch (short_option)
1577            {
1578                case 'a':
1579                    m_delete_all = true;
1580                    break;
1581                default:
1582                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1583                    break;
1584            }
1585
1586            return error;
1587        }
1588
1589        void
1590        OptionParsingStarting ()
1591        {
1592            m_delete_all = false;
1593        }
1594
1595        const OptionDefinition*
1596        GetDefinitions ()
1597        {
1598            return g_option_table;
1599        }
1600
1601        // Options table: Required for subclasses of Options.
1602
1603        static OptionDefinition g_option_table[];
1604
1605        // Instance variables to hold the values for command options.
1606
1607        bool m_delete_all;
1608        bool m_delete_named;
1609    };
1610
1611    CommandOptions m_options;
1612
1613    virtual Options *
1614    GetOptions ()
1615    {
1616        return &m_options;
1617    }
1618
1619    static bool
1620    PerCategoryCallback(void* param,
1621                        const lldb::TypeCategoryImplSP& cate)
1622    {
1623        cate->GetSummaryNavigator()->Clear();
1624        cate->GetRegexSummaryNavigator()->Clear();
1625        return true;
1626
1627    }
1628
1629public:
1630    CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) :
1631    CommandObject (interpreter,
1632                   "type summary clear",
1633                   "Delete all existing summary styles.",
1634                   NULL), m_options(interpreter)
1635    {
1636    }
1637
1638    ~CommandObjectTypeSummaryClear ()
1639    {
1640    }
1641
1642    bool
1643    Execute (Args& command, CommandReturnObject &result)
1644    {
1645
1646        if (m_options.m_delete_all)
1647            DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL);
1648
1649        else
1650        {
1651            lldb::TypeCategoryImplSP category;
1652            if (command.GetArgumentCount() > 0)
1653            {
1654                const char* cat_name = command.GetArgumentAtIndex(0);
1655                ConstString cat_nameCS(cat_name);
1656                DataVisualization::Categories::GetCategory(cat_nameCS, category);
1657            }
1658            else
1659                DataVisualization::Categories::GetCategory(ConstString(NULL), category);
1660            category->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary);
1661        }
1662
1663        DataVisualization::NamedSummaryFormats::Clear();
1664
1665        result.SetStatus(eReturnStatusSuccessFinishResult);
1666        return result.Succeeded();
1667    }
1668
1669};
1670
1671OptionDefinition
1672CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] =
1673{
1674    { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Clear every category."},
1675    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1676};
1677
1678//-------------------------------------------------------------------------
1679// CommandObjectTypeSummaryList
1680//-------------------------------------------------------------------------
1681
1682bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const StringSummaryFormat::SharedPointer& entry);
1683bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry);
1684
1685class CommandObjectTypeSummaryList;
1686
1687struct CommandObjectTypeSummaryList_LoopCallbackParam {
1688    CommandObjectTypeSummaryList* self;
1689    CommandReturnObject* result;
1690    RegularExpression* regex;
1691    RegularExpression* cate_regex;
1692    CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R,
1693                                                  RegularExpression* X = NULL,
1694                                                  RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
1695};
1696
1697class CommandObjectTypeSummaryList : public CommandObject
1698{
1699
1700    class CommandOptions : public Options
1701    {
1702    public:
1703
1704        CommandOptions (CommandInterpreter &interpreter) :
1705        Options (interpreter)
1706        {
1707        }
1708
1709        virtual
1710        ~CommandOptions (){}
1711
1712        virtual Error
1713        SetOptionValue (uint32_t option_idx, const char *option_arg)
1714        {
1715            Error error;
1716            char short_option = (char) m_getopt_table[option_idx].val;
1717
1718            switch (short_option)
1719            {
1720                case 'w':
1721                    m_category_regex = std::string(option_arg);
1722                    break;
1723                default:
1724                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1725                    break;
1726            }
1727
1728            return error;
1729        }
1730
1731        void
1732        OptionParsingStarting ()
1733        {
1734            m_category_regex = "";
1735        }
1736
1737        const OptionDefinition*
1738        GetDefinitions ()
1739        {
1740            return g_option_table;
1741        }
1742
1743        // Options table: Required for subclasses of Options.
1744
1745        static OptionDefinition g_option_table[];
1746
1747        // Instance variables to hold the values for command options.
1748
1749        std::string m_category_regex;
1750
1751    };
1752
1753    CommandOptions m_options;
1754
1755    virtual Options *
1756    GetOptions ()
1757    {
1758        return &m_options;
1759    }
1760
1761public:
1762    CommandObjectTypeSummaryList (CommandInterpreter &interpreter) :
1763    CommandObject (interpreter,
1764                   "type summary list",
1765                   "Show a list of current summary styles.",
1766                   NULL), m_options(interpreter)
1767    {
1768        CommandArgumentEntry type_arg;
1769        CommandArgumentData type_style_arg;
1770
1771        type_style_arg.arg_type = eArgTypeName;
1772        type_style_arg.arg_repetition = eArgRepeatOptional;
1773
1774        type_arg.push_back (type_style_arg);
1775
1776        m_arguments.push_back (type_arg);
1777    }
1778
1779    ~CommandObjectTypeSummaryList ()
1780    {
1781    }
1782
1783    bool
1784    Execute (Args& command, CommandReturnObject &result)
1785    {
1786        const size_t argc = command.GetArgumentCount();
1787
1788        CommandObjectTypeSummaryList_LoopCallbackParam *param;
1789        RegularExpression* cate_regex =
1790        m_options.m_category_regex.empty() ? NULL :
1791        new RegularExpression(m_options.m_category_regex.c_str());
1792
1793        if (argc == 1)
1794        {
1795            RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
1796            regex->Compile(command.GetArgumentAtIndex(0));
1797            param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex,cate_regex);
1798        }
1799        else
1800            param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,NULL,cate_regex);
1801
1802        DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
1803
1804        if (DataVisualization::NamedSummaryFormats::GetCount() > 0)
1805        {
1806            result.GetOutputStream().Printf("Named summaries:\n");
1807            if (argc == 1)
1808            {
1809                RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
1810                regex->Compile(command.GetArgumentAtIndex(0));
1811                param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex);
1812            }
1813            else
1814                param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result);
1815            DataVisualization::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
1816            delete param;
1817        }
1818
1819        if (cate_regex)
1820            delete cate_regex;
1821
1822        result.SetStatus(eReturnStatusSuccessFinishResult);
1823        return result.Succeeded();
1824    }
1825
1826private:
1827
1828    static bool
1829    PerCategoryCallback(void* param_vp,
1830                        const lldb::TypeCategoryImplSP& cate)
1831    {
1832
1833        CommandObjectTypeSummaryList_LoopCallbackParam* param =
1834            (CommandObjectTypeSummaryList_LoopCallbackParam*)param_vp;
1835        CommandReturnObject* result = param->result;
1836
1837        const char* cate_name = cate->GetName();
1838
1839        // if the category is disabled or empty and there is no regex, just skip it
1840        if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary) == 0) && param->cate_regex == NULL)
1841            return true;
1842
1843        // if we have a regex and this category does not match it, just skip it
1844        if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false)
1845            return true;
1846
1847        result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
1848                                         cate_name,
1849                                         (cate->IsEnabled() ? "enabled" : "disabled"));
1850
1851        cate->GetSummaryNavigator()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param_vp);
1852
1853        if (cate->GetRegexSummaryNavigator()->GetCount() > 0)
1854        {
1855            result->GetOutputStream().Printf("Regex-based summaries (slower):\n");
1856            cate->GetRegexSummaryNavigator()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param_vp);
1857        }
1858        return true;
1859    }
1860
1861
1862    bool
1863    LoopCallback (const char* type,
1864                  const lldb::TypeSummaryImplSP& entry,
1865                  RegularExpression* regex,
1866                  CommandReturnObject *result)
1867    {
1868        if (regex == NULL || regex->Execute(type))
1869                result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
1870        return true;
1871    }
1872
1873    friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeSummaryImplSP& entry);
1874    friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeSummaryImplSP& entry);
1875};
1876
1877bool
1878CommandObjectTypeSummaryList_LoopCallback (
1879                                          void* pt2self,
1880                                          ConstString type,
1881                                          const lldb::TypeSummaryImplSP& entry)
1882{
1883    CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
1884    return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
1885}
1886
1887bool
1888CommandObjectTypeRXSummaryList_LoopCallback (
1889                                           void* pt2self,
1890                                           lldb::RegularExpressionSP regex,
1891                                           const lldb::TypeSummaryImplSP& entry)
1892{
1893    CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
1894    return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
1895}
1896
1897OptionDefinition
1898CommandObjectTypeSummaryList::CommandOptions::g_option_table[] =
1899{
1900    { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
1901    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1902};
1903
1904//-------------------------------------------------------------------------
1905// CommandObjectTypeCategoryEnable
1906//-------------------------------------------------------------------------
1907
1908class CommandObjectTypeCategoryEnable : public CommandObject
1909{
1910public:
1911    CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) :
1912    CommandObject (interpreter,
1913                   "type category enable",
1914                   "Enable a category as a source of formatters.",
1915                   NULL)
1916    {
1917        CommandArgumentEntry type_arg;
1918        CommandArgumentData type_style_arg;
1919
1920        type_style_arg.arg_type = eArgTypeName;
1921        type_style_arg.arg_repetition = eArgRepeatPlus;
1922
1923        type_arg.push_back (type_style_arg);
1924
1925        m_arguments.push_back (type_arg);
1926
1927    }
1928
1929    ~CommandObjectTypeCategoryEnable ()
1930    {
1931    }
1932
1933    bool
1934    Execute (Args& command, CommandReturnObject &result)
1935    {
1936        const size_t argc = command.GetArgumentCount();
1937
1938        if (argc < 1)
1939        {
1940            result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
1941            result.SetStatus(eReturnStatusFailed);
1942            return false;
1943        }
1944
1945        for (int i = argc - 1; i >= 0; i--)
1946        {
1947            const char* typeA = command.GetArgumentAtIndex(i);
1948            ConstString typeCS(typeA);
1949
1950            if (!typeCS)
1951            {
1952                result.AppendError("empty category name not allowed");
1953                result.SetStatus(eReturnStatusFailed);
1954                return false;
1955            }
1956            DataVisualization::Categories::Enable(typeCS);
1957            lldb::TypeCategoryImplSP cate;
1958            if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate.get())
1959            {
1960                if (cate->GetCount() == 0)
1961                {
1962                    result.AppendWarning("empty category enabled (typo?)");
1963                }
1964            }
1965        }
1966
1967        result.SetStatus(eReturnStatusSuccessFinishResult);
1968        return result.Succeeded();
1969    }
1970
1971};
1972
1973//-------------------------------------------------------------------------
1974// CommandObjectTypeCategoryDelete
1975//-------------------------------------------------------------------------
1976
1977class CommandObjectTypeCategoryDelete : public CommandObject
1978{
1979public:
1980    CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) :
1981    CommandObject (interpreter,
1982                   "type category delete",
1983                   "Delete a category and all associated formatters.",
1984                   NULL)
1985    {
1986        CommandArgumentEntry type_arg;
1987        CommandArgumentData type_style_arg;
1988
1989        type_style_arg.arg_type = eArgTypeName;
1990        type_style_arg.arg_repetition = eArgRepeatPlus;
1991
1992        type_arg.push_back (type_style_arg);
1993
1994        m_arguments.push_back (type_arg);
1995
1996    }
1997
1998    ~CommandObjectTypeCategoryDelete ()
1999    {
2000    }
2001
2002    bool
2003    Execute (Args& command, CommandReturnObject &result)
2004    {
2005        const size_t argc = command.GetArgumentCount();
2006
2007        if (argc < 1)
2008        {
2009            result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str());
2010            result.SetStatus(eReturnStatusFailed);
2011            return false;
2012        }
2013
2014        bool success = true;
2015
2016        // the order is not relevant here
2017        for (int i = argc - 1; i >= 0; i--)
2018        {
2019            const char* typeA = command.GetArgumentAtIndex(i);
2020            ConstString typeCS(typeA);
2021
2022            if (!typeCS)
2023            {
2024                result.AppendError("empty category name not allowed");
2025                result.SetStatus(eReturnStatusFailed);
2026                return false;
2027            }
2028            if (!DataVisualization::Categories::Delete(typeCS))
2029                success = false; // keep deleting even if we hit an error
2030        }
2031        if (success)
2032        {
2033            result.SetStatus(eReturnStatusSuccessFinishResult);
2034            return result.Succeeded();
2035        }
2036        else
2037        {
2038            result.AppendError("cannot delete one or more categories\n");
2039            result.SetStatus(eReturnStatusFailed);
2040            return false;
2041        }
2042    }
2043};
2044
2045//-------------------------------------------------------------------------
2046// CommandObjectTypeCategoryDisable
2047//-------------------------------------------------------------------------
2048
2049class CommandObjectTypeCategoryDisable : public CommandObject
2050{
2051public:
2052    CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) :
2053    CommandObject (interpreter,
2054                   "type category disable",
2055                   "Disable a category as a source of formatters.",
2056                   NULL)
2057    {
2058        CommandArgumentEntry type_arg;
2059        CommandArgumentData type_style_arg;
2060
2061        type_style_arg.arg_type = eArgTypeName;
2062        type_style_arg.arg_repetition = eArgRepeatPlus;
2063
2064        type_arg.push_back (type_style_arg);
2065
2066        m_arguments.push_back (type_arg);
2067
2068    }
2069
2070    ~CommandObjectTypeCategoryDisable ()
2071    {
2072    }
2073
2074    bool
2075    Execute (Args& command, CommandReturnObject &result)
2076    {
2077        const size_t argc = command.GetArgumentCount();
2078
2079        if (argc < 1)
2080        {
2081            result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
2082            result.SetStatus(eReturnStatusFailed);
2083            return false;
2084        }
2085
2086        // the order is not relevant here
2087        for (int i = argc - 1; i >= 0; i--)
2088        {
2089            const char* typeA = command.GetArgumentAtIndex(i);
2090            ConstString typeCS(typeA);
2091
2092            if (!typeCS)
2093            {
2094                result.AppendError("empty category name not allowed");
2095                result.SetStatus(eReturnStatusFailed);
2096                return false;
2097            }
2098            DataVisualization::Categories::Disable(typeCS);
2099        }
2100
2101        result.SetStatus(eReturnStatusSuccessFinishResult);
2102        return result.Succeeded();
2103    }
2104
2105};
2106
2107//-------------------------------------------------------------------------
2108// CommandObjectTypeCategoryList
2109//-------------------------------------------------------------------------
2110
2111class CommandObjectTypeCategoryList : public CommandObject
2112{
2113private:
2114
2115    struct CommandObjectTypeCategoryList_CallbackParam
2116    {
2117        CommandReturnObject* result;
2118        RegularExpression* regex;
2119
2120        CommandObjectTypeCategoryList_CallbackParam(CommandReturnObject* res,
2121                                                    RegularExpression* rex = NULL) :
2122        result(res),
2123        regex(rex)
2124        {
2125        }
2126
2127    };
2128
2129    static bool
2130    PerCategoryCallback(void* param_vp,
2131                        const lldb::TypeCategoryImplSP& cate)
2132    {
2133        CommandObjectTypeCategoryList_CallbackParam* param =
2134            (CommandObjectTypeCategoryList_CallbackParam*)param_vp;
2135        CommandReturnObject* result = param->result;
2136        RegularExpression* regex = param->regex;
2137
2138        const char* cate_name = cate->GetName();
2139
2140        if (regex == NULL || regex->Execute(cate_name))
2141            result->GetOutputStream().Printf("Category %s is%s enabled\n",
2142                                       cate_name,
2143                                       (cate->IsEnabled() ? "" : " not"));
2144        return true;
2145    }
2146public:
2147    CommandObjectTypeCategoryList (CommandInterpreter &interpreter) :
2148    CommandObject (interpreter,
2149                   "type category list",
2150                   "Provide a list of all existing categories.",
2151                   NULL)
2152    {
2153        CommandArgumentEntry type_arg;
2154        CommandArgumentData type_style_arg;
2155
2156        type_style_arg.arg_type = eArgTypeName;
2157        type_style_arg.arg_repetition = eArgRepeatOptional;
2158
2159        type_arg.push_back (type_style_arg);
2160
2161        m_arguments.push_back (type_arg);
2162    }
2163
2164    ~CommandObjectTypeCategoryList ()
2165    {
2166    }
2167
2168    bool
2169    Execute (Args& command, CommandReturnObject &result)
2170    {
2171        const size_t argc = command.GetArgumentCount();
2172        RegularExpression* regex = NULL;
2173
2174        if (argc == 0)
2175            ;
2176        else if (argc == 1)
2177            regex = new RegularExpression(command.GetArgumentAtIndex(0));
2178        else
2179        {
2180            result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str());
2181            result.SetStatus(eReturnStatusFailed);
2182            return false;
2183        }
2184
2185        CommandObjectTypeCategoryList_CallbackParam param(&result,
2186                                                          regex);
2187
2188        DataVisualization::Categories::LoopThrough(PerCategoryCallback, &param);
2189
2190        if (regex)
2191            delete regex;
2192
2193        result.SetStatus(eReturnStatusSuccessFinishResult);
2194        return result.Succeeded();
2195    }
2196
2197};
2198
2199//-------------------------------------------------------------------------
2200// CommandObjectTypeFilterList
2201//-------------------------------------------------------------------------
2202
2203bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
2204bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
2205
2206class CommandObjectTypeFilterList;
2207
2208struct CommandObjectTypeFilterList_LoopCallbackParam {
2209    CommandObjectTypeFilterList* self;
2210    CommandReturnObject* result;
2211    RegularExpression* regex;
2212    RegularExpression* cate_regex;
2213    CommandObjectTypeFilterList_LoopCallbackParam(CommandObjectTypeFilterList* S, CommandReturnObject* R,
2214                                                  RegularExpression* X = NULL,
2215                                                  RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
2216};
2217
2218class CommandObjectTypeFilterList : public CommandObject
2219{
2220
2221    class CommandOptions : public Options
2222    {
2223    public:
2224
2225        CommandOptions (CommandInterpreter &interpreter) :
2226        Options (interpreter)
2227        {
2228        }
2229
2230        virtual
2231        ~CommandOptions (){}
2232
2233        virtual Error
2234        SetOptionValue (uint32_t option_idx, const char *option_arg)
2235        {
2236            Error error;
2237            char short_option = (char) m_getopt_table[option_idx].val;
2238
2239            switch (short_option)
2240            {
2241                case 'w':
2242                    m_category_regex = std::string(option_arg);
2243                    break;
2244                default:
2245                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2246                    break;
2247            }
2248
2249            return error;
2250        }
2251
2252        void
2253        OptionParsingStarting ()
2254        {
2255            m_category_regex = "";
2256        }
2257
2258        const OptionDefinition*
2259        GetDefinitions ()
2260        {
2261            return g_option_table;
2262        }
2263
2264        // Options table: Required for subclasses of Options.
2265
2266        static OptionDefinition g_option_table[];
2267
2268        // Instance variables to hold the values for command options.
2269
2270        std::string m_category_regex;
2271
2272    };
2273
2274    CommandOptions m_options;
2275
2276    virtual Options *
2277    GetOptions ()
2278    {
2279        return &m_options;
2280    }
2281
2282public:
2283    CommandObjectTypeFilterList (CommandInterpreter &interpreter) :
2284    CommandObject (interpreter,
2285                   "type filter list",
2286                   "Show a list of current filters.",
2287                   NULL), m_options(interpreter)
2288    {
2289        CommandArgumentEntry type_arg;
2290        CommandArgumentData type_style_arg;
2291
2292        type_style_arg.arg_type = eArgTypeName;
2293        type_style_arg.arg_repetition = eArgRepeatOptional;
2294
2295        type_arg.push_back (type_style_arg);
2296
2297        m_arguments.push_back (type_arg);
2298    }
2299
2300    ~CommandObjectTypeFilterList ()
2301    {
2302    }
2303
2304    bool
2305    Execute (Args& command, CommandReturnObject &result)
2306    {
2307        const size_t argc = command.GetArgumentCount();
2308
2309        CommandObjectTypeFilterList_LoopCallbackParam *param;
2310        RegularExpression* cate_regex =
2311        m_options.m_category_regex.empty() ? NULL :
2312        new RegularExpression(m_options.m_category_regex.c_str());
2313
2314        if (argc == 1)
2315        {
2316            RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
2317            regex->Compile(command.GetArgumentAtIndex(0));
2318            param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,regex,cate_regex);
2319        }
2320        else
2321            param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,NULL,cate_regex);
2322
2323        DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
2324
2325        if (cate_regex)
2326            delete cate_regex;
2327
2328        result.SetStatus(eReturnStatusSuccessFinishResult);
2329        return result.Succeeded();
2330    }
2331
2332private:
2333
2334    static bool
2335    PerCategoryCallback(void* param_vp,
2336                        const lldb::TypeCategoryImplSP& cate)
2337    {
2338
2339        const char* cate_name = cate->GetName();
2340
2341        CommandObjectTypeFilterList_LoopCallbackParam* param =
2342        (CommandObjectTypeFilterList_LoopCallbackParam*)param_vp;
2343        CommandReturnObject* result = param->result;
2344
2345        // if the category is disabled or empty and there is no regex, just skip it
2346        if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter) == 0) && param->cate_regex == NULL)
2347            return true;
2348
2349        // if we have a regex and this category does not match it, just skip it
2350        if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false)
2351            return true;
2352
2353        result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
2354                                         cate_name,
2355                                         (cate->IsEnabled() ? "enabled" : "disabled"));
2356
2357        cate->GetFilterNavigator()->LoopThrough(CommandObjectTypeFilterList_LoopCallback, param_vp);
2358
2359        if (cate->GetRegexFilterNavigator()->GetCount() > 0)
2360        {
2361            result->GetOutputStream().Printf("Regex-based filters (slower):\n");
2362            cate->GetRegexFilterNavigator()->LoopThrough(CommandObjectTypeFilterRXList_LoopCallback, param_vp);
2363        }
2364
2365        return true;
2366    }
2367
2368    bool
2369    LoopCallback (const char* type,
2370                  const SyntheticChildren::SharedPointer& entry,
2371                  RegularExpression* regex,
2372                  CommandReturnObject *result)
2373    {
2374        if (regex == NULL || regex->Execute(type))
2375            result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
2376        return true;
2377    }
2378
2379    friend bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
2380    friend bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
2381};
2382
2383bool
2384CommandObjectTypeFilterList_LoopCallback (void* pt2self,
2385                                         ConstString type,
2386                                         const SyntheticChildren::SharedPointer& entry)
2387{
2388    CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self;
2389    return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
2390}
2391
2392bool
2393CommandObjectTypeFilterRXList_LoopCallback (void* pt2self,
2394                                           lldb::RegularExpressionSP regex,
2395                                           const SyntheticChildren::SharedPointer& entry)
2396{
2397    CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self;
2398    return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
2399}
2400
2401
2402OptionDefinition
2403CommandObjectTypeFilterList::CommandOptions::g_option_table[] =
2404{
2405    { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
2406    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2407};
2408
2409#ifndef LLDB_DISABLE_PYTHON
2410
2411//-------------------------------------------------------------------------
2412// CommandObjectTypeSynthList
2413//-------------------------------------------------------------------------
2414
2415bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
2416bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
2417
2418class CommandObjectTypeSynthList;
2419
2420struct CommandObjectTypeSynthList_LoopCallbackParam {
2421    CommandObjectTypeSynthList* self;
2422    CommandReturnObject* result;
2423    RegularExpression* regex;
2424    RegularExpression* cate_regex;
2425    CommandObjectTypeSynthList_LoopCallbackParam(CommandObjectTypeSynthList* S, CommandReturnObject* R,
2426                                                 RegularExpression* X = NULL,
2427                                                 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
2428};
2429
2430class CommandObjectTypeSynthList : public CommandObject
2431{
2432
2433    class CommandOptions : public Options
2434    {
2435    public:
2436
2437        CommandOptions (CommandInterpreter &interpreter) :
2438        Options (interpreter)
2439        {
2440        }
2441
2442        virtual
2443        ~CommandOptions (){}
2444
2445        virtual Error
2446        SetOptionValue (uint32_t option_idx, const char *option_arg)
2447        {
2448            Error error;
2449            char short_option = (char) m_getopt_table[option_idx].val;
2450
2451            switch (short_option)
2452            {
2453                case 'w':
2454                    m_category_regex = std::string(option_arg);
2455                    break;
2456                default:
2457                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2458                    break;
2459            }
2460
2461            return error;
2462        }
2463
2464        void
2465        OptionParsingStarting ()
2466        {
2467            m_category_regex = "";
2468        }
2469
2470        const OptionDefinition*
2471        GetDefinitions ()
2472        {
2473            return g_option_table;
2474        }
2475
2476        // Options table: Required for subclasses of Options.
2477
2478        static OptionDefinition g_option_table[];
2479
2480        // Instance variables to hold the values for command options.
2481
2482        std::string m_category_regex;
2483
2484    };
2485
2486    CommandOptions m_options;
2487
2488    virtual Options *
2489    GetOptions ()
2490    {
2491        return &m_options;
2492    }
2493
2494public:
2495    CommandObjectTypeSynthList (CommandInterpreter &interpreter) :
2496    CommandObject (interpreter,
2497                   "type synthetic list",
2498                   "Show a list of current synthetic providers.",
2499                   NULL), m_options(interpreter)
2500    {
2501        CommandArgumentEntry type_arg;
2502        CommandArgumentData type_style_arg;
2503
2504        type_style_arg.arg_type = eArgTypeName;
2505        type_style_arg.arg_repetition = eArgRepeatOptional;
2506
2507        type_arg.push_back (type_style_arg);
2508
2509        m_arguments.push_back (type_arg);
2510    }
2511
2512    ~CommandObjectTypeSynthList ()
2513    {
2514    }
2515
2516    bool
2517    Execute (Args& command, CommandReturnObject &result)
2518    {
2519        const size_t argc = command.GetArgumentCount();
2520
2521        CommandObjectTypeSynthList_LoopCallbackParam *param;
2522        RegularExpression* cate_regex =
2523        m_options.m_category_regex.empty() ? NULL :
2524        new RegularExpression(m_options.m_category_regex.c_str());
2525
2526        if (argc == 1)
2527        {
2528            RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
2529            regex->Compile(command.GetArgumentAtIndex(0));
2530            param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,regex,cate_regex);
2531        }
2532        else
2533            param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,NULL,cate_regex);
2534
2535        DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
2536
2537        if (cate_regex)
2538            delete cate_regex;
2539
2540        result.SetStatus(eReturnStatusSuccessFinishResult);
2541        return result.Succeeded();
2542    }
2543
2544private:
2545
2546    static bool
2547    PerCategoryCallback(void* param_vp,
2548                        const lldb::TypeCategoryImplSP& cate)
2549    {
2550
2551        CommandObjectTypeSynthList_LoopCallbackParam* param =
2552        (CommandObjectTypeSynthList_LoopCallbackParam*)param_vp;
2553        CommandReturnObject* result = param->result;
2554
2555        const char* cate_name = cate->GetName();
2556
2557        // if the category is disabled or empty and there is no regex, just skip it
2558        if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth) == 0) && param->cate_regex == NULL)
2559            return true;
2560
2561        // if we have a regex and this category does not match it, just skip it
2562        if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false)
2563            return true;
2564
2565        result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
2566                                         cate_name,
2567                                         (cate->IsEnabled() ? "enabled" : "disabled"));
2568
2569        cate->GetSyntheticNavigator()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp);
2570
2571        if (cate->GetRegexSyntheticNavigator()->GetCount() > 0)
2572        {
2573            result->GetOutputStream().Printf("Regex-based synthetic providers (slower):\n");
2574            cate->GetRegexSyntheticNavigator()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp);
2575        }
2576
2577        return true;
2578    }
2579
2580    bool
2581    LoopCallback (const char* type,
2582                  const SyntheticChildren::SharedPointer& entry,
2583                  RegularExpression* regex,
2584                  CommandReturnObject *result)
2585    {
2586        if (regex == NULL || regex->Execute(type))
2587            result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
2588        return true;
2589    }
2590
2591    friend bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
2592    friend bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
2593};
2594
2595bool
2596CommandObjectTypeSynthList_LoopCallback (void* pt2self,
2597                                         ConstString type,
2598                                         const SyntheticChildren::SharedPointer& entry)
2599{
2600    CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
2601    return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
2602}
2603
2604bool
2605CommandObjectTypeSynthRXList_LoopCallback (void* pt2self,
2606                                         lldb::RegularExpressionSP regex,
2607                                         const SyntheticChildren::SharedPointer& entry)
2608{
2609    CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
2610    return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
2611}
2612
2613
2614OptionDefinition
2615CommandObjectTypeSynthList::CommandOptions::g_option_table[] =
2616{
2617    { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
2618    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2619};
2620
2621#endif // #ifndef LLDB_DISABLE_PYTHON
2622//-------------------------------------------------------------------------
2623// CommandObjectTypeFilterDelete
2624//-------------------------------------------------------------------------
2625
2626class CommandObjectTypeFilterDelete : public CommandObject
2627{
2628private:
2629    class CommandOptions : public Options
2630    {
2631    public:
2632
2633        CommandOptions (CommandInterpreter &interpreter) :
2634        Options (interpreter)
2635        {
2636        }
2637
2638        virtual
2639        ~CommandOptions (){}
2640
2641        virtual Error
2642        SetOptionValue (uint32_t option_idx, const char *option_arg)
2643        {
2644            Error error;
2645            char short_option = (char) m_getopt_table[option_idx].val;
2646
2647            switch (short_option)
2648            {
2649                case 'a':
2650                    m_delete_all = true;
2651                    break;
2652                case 'w':
2653                    m_category = std::string(option_arg);
2654                    break;
2655                default:
2656                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2657                    break;
2658            }
2659
2660            return error;
2661        }
2662
2663        void
2664        OptionParsingStarting ()
2665        {
2666            m_delete_all = false;
2667            m_category = "default";
2668        }
2669
2670        const OptionDefinition*
2671        GetDefinitions ()
2672        {
2673            return g_option_table;
2674        }
2675
2676        // Options table: Required for subclasses of Options.
2677
2678        static OptionDefinition g_option_table[];
2679
2680        // Instance variables to hold the values for command options.
2681
2682        bool m_delete_all;
2683        std::string m_category;
2684
2685    };
2686
2687    CommandOptions m_options;
2688
2689    virtual Options *
2690    GetOptions ()
2691    {
2692        return &m_options;
2693    }
2694
2695    static bool
2696    PerCategoryCallback(void* param,
2697                        const lldb::TypeCategoryImplSP& cate)
2698    {
2699        ConstString *name = (ConstString*)param;
2700        return cate->Delete(*name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter);
2701    }
2702
2703public:
2704    CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) :
2705    CommandObject (interpreter,
2706                   "type filter delete",
2707                   "Delete an existing filter for a type.",
2708                   NULL), m_options(interpreter)
2709    {
2710        CommandArgumentEntry type_arg;
2711        CommandArgumentData type_style_arg;
2712
2713        type_style_arg.arg_type = eArgTypeName;
2714        type_style_arg.arg_repetition = eArgRepeatPlain;
2715
2716        type_arg.push_back (type_style_arg);
2717
2718        m_arguments.push_back (type_arg);
2719
2720    }
2721
2722    ~CommandObjectTypeFilterDelete ()
2723    {
2724    }
2725
2726    bool
2727    Execute (Args& command, CommandReturnObject &result)
2728    {
2729        const size_t argc = command.GetArgumentCount();
2730
2731        if (argc != 1)
2732        {
2733            result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
2734            result.SetStatus(eReturnStatusFailed);
2735            return false;
2736        }
2737
2738        const char* typeA = command.GetArgumentAtIndex(0);
2739        ConstString typeCS(typeA);
2740
2741        if (!typeCS)
2742        {
2743            result.AppendError("empty typenames not allowed");
2744            result.SetStatus(eReturnStatusFailed);
2745            return false;
2746        }
2747
2748        if (m_options.m_delete_all)
2749        {
2750            DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS);
2751            result.SetStatus(eReturnStatusSuccessFinishNoResult);
2752            return result.Succeeded();
2753        }
2754
2755        lldb::TypeCategoryImplSP category;
2756        DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
2757
2758        bool delete_category = category->GetFilterNavigator()->Delete(typeCS);
2759        delete_category = category->GetRegexFilterNavigator()->Delete(typeCS) || delete_category;
2760
2761        if (delete_category)
2762        {
2763            result.SetStatus(eReturnStatusSuccessFinishNoResult);
2764            return result.Succeeded();
2765        }
2766        else
2767        {
2768            result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA);
2769            result.SetStatus(eReturnStatusFailed);
2770            return false;
2771        }
2772
2773    }
2774};
2775
2776OptionDefinition
2777CommandObjectTypeFilterDelete::CommandOptions::g_option_table[] =
2778{
2779    { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Delete from every category."},
2780    { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,  "Delete from given category."},
2781    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2782};
2783
2784#ifndef LLDB_DISABLE_PYTHON
2785
2786//-------------------------------------------------------------------------
2787// CommandObjectTypeSynthDelete
2788//-------------------------------------------------------------------------
2789
2790class CommandObjectTypeSynthDelete : public CommandObject
2791{
2792private:
2793    class CommandOptions : public Options
2794    {
2795    public:
2796
2797        CommandOptions (CommandInterpreter &interpreter) :
2798        Options (interpreter)
2799        {
2800        }
2801
2802        virtual
2803        ~CommandOptions (){}
2804
2805        virtual Error
2806        SetOptionValue (uint32_t option_idx, const char *option_arg)
2807        {
2808            Error error;
2809            char short_option = (char) m_getopt_table[option_idx].val;
2810
2811            switch (short_option)
2812            {
2813                case 'a':
2814                    m_delete_all = true;
2815                    break;
2816                case 'w':
2817                    m_category = std::string(option_arg);
2818                    break;
2819                default:
2820                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2821                    break;
2822            }
2823
2824            return error;
2825        }
2826
2827        void
2828        OptionParsingStarting ()
2829        {
2830            m_delete_all = false;
2831            m_category = "default";
2832        }
2833
2834        const OptionDefinition*
2835        GetDefinitions ()
2836        {
2837            return g_option_table;
2838        }
2839
2840        // Options table: Required for subclasses of Options.
2841
2842        static OptionDefinition g_option_table[];
2843
2844        // Instance variables to hold the values for command options.
2845
2846        bool m_delete_all;
2847        std::string m_category;
2848
2849    };
2850
2851    CommandOptions m_options;
2852
2853    virtual Options *
2854    GetOptions ()
2855    {
2856        return &m_options;
2857    }
2858
2859    static bool
2860    PerCategoryCallback(void* param,
2861                        const lldb::TypeCategoryImplSP& cate)
2862    {
2863        ConstString* name = (ConstString*)param;
2864        return cate->Delete(*name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth);
2865    }
2866
2867public:
2868    CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) :
2869    CommandObject (interpreter,
2870                   "type synthetic delete",
2871                   "Delete an existing synthetic provider for a type.",
2872                   NULL), m_options(interpreter)
2873    {
2874        CommandArgumentEntry type_arg;
2875        CommandArgumentData type_style_arg;
2876
2877        type_style_arg.arg_type = eArgTypeName;
2878        type_style_arg.arg_repetition = eArgRepeatPlain;
2879
2880        type_arg.push_back (type_style_arg);
2881
2882        m_arguments.push_back (type_arg);
2883
2884    }
2885
2886    ~CommandObjectTypeSynthDelete ()
2887    {
2888    }
2889
2890    bool
2891    Execute (Args& command, CommandReturnObject &result)
2892    {
2893        const size_t argc = command.GetArgumentCount();
2894
2895        if (argc != 1)
2896        {
2897            result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
2898            result.SetStatus(eReturnStatusFailed);
2899            return false;
2900        }
2901
2902        const char* typeA = command.GetArgumentAtIndex(0);
2903        ConstString typeCS(typeA);
2904
2905        if (!typeCS)
2906        {
2907            result.AppendError("empty typenames not allowed");
2908            result.SetStatus(eReturnStatusFailed);
2909            return false;
2910        }
2911
2912        if (m_options.m_delete_all)
2913        {
2914            DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS);
2915            result.SetStatus(eReturnStatusSuccessFinishNoResult);
2916            return result.Succeeded();
2917        }
2918
2919        lldb::TypeCategoryImplSP category;
2920        DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
2921
2922        bool delete_category = category->GetSyntheticNavigator()->Delete(typeCS);
2923        delete_category = category->GetRegexSyntheticNavigator()->Delete(typeCS) || delete_category;
2924
2925        if (delete_category)
2926        {
2927            result.SetStatus(eReturnStatusSuccessFinishNoResult);
2928            return result.Succeeded();
2929        }
2930        else
2931        {
2932            result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA);
2933            result.SetStatus(eReturnStatusFailed);
2934            return false;
2935        }
2936
2937    }
2938};
2939
2940OptionDefinition
2941CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] =
2942{
2943    { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Delete from every category."},
2944    { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,  "Delete from given category."},
2945    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2946};
2947
2948#endif // #ifndef LLDB_DISABLE_PYTHON
2949
2950//-------------------------------------------------------------------------
2951// CommandObjectTypeFilterClear
2952//-------------------------------------------------------------------------
2953
2954class CommandObjectTypeFilterClear : public CommandObject
2955{
2956private:
2957
2958    class CommandOptions : public Options
2959    {
2960    public:
2961
2962        CommandOptions (CommandInterpreter &interpreter) :
2963        Options (interpreter)
2964        {
2965        }
2966
2967        virtual
2968        ~CommandOptions (){}
2969
2970        virtual Error
2971        SetOptionValue (uint32_t option_idx, const char *option_arg)
2972        {
2973            Error error;
2974            char short_option = (char) m_getopt_table[option_idx].val;
2975
2976            switch (short_option)
2977            {
2978                case 'a':
2979                    m_delete_all = true;
2980                    break;
2981                default:
2982                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2983                    break;
2984            }
2985
2986            return error;
2987        }
2988
2989        void
2990        OptionParsingStarting ()
2991        {
2992            m_delete_all = false;
2993        }
2994
2995        const OptionDefinition*
2996        GetDefinitions ()
2997        {
2998            return g_option_table;
2999        }
3000
3001        // Options table: Required for subclasses of Options.
3002
3003        static OptionDefinition g_option_table[];
3004
3005        // Instance variables to hold the values for command options.
3006
3007        bool m_delete_all;
3008        bool m_delete_named;
3009    };
3010
3011    CommandOptions m_options;
3012
3013    virtual Options *
3014    GetOptions ()
3015    {
3016        return &m_options;
3017    }
3018
3019    static bool
3020    PerCategoryCallback(void* param,
3021                        const lldb::TypeCategoryImplSP& cate)
3022    {
3023        cate->Clear(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter);
3024        return true;
3025
3026    }
3027
3028public:
3029    CommandObjectTypeFilterClear (CommandInterpreter &interpreter) :
3030    CommandObject (interpreter,
3031                   "type filter clear",
3032                   "Delete all existing filters.",
3033                   NULL), m_options(interpreter)
3034    {
3035    }
3036
3037    ~CommandObjectTypeFilterClear ()
3038    {
3039    }
3040
3041    bool
3042    Execute (Args& command, CommandReturnObject &result)
3043    {
3044
3045        if (m_options.m_delete_all)
3046            DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL);
3047
3048        else
3049        {
3050            lldb::TypeCategoryImplSP category;
3051            if (command.GetArgumentCount() > 0)
3052            {
3053                const char* cat_name = command.GetArgumentAtIndex(0);
3054                ConstString cat_nameCS(cat_name);
3055                DataVisualization::Categories::GetCategory(cat_nameCS, category);
3056            }
3057            else
3058                DataVisualization::Categories::GetCategory(ConstString(NULL), category);
3059            category->GetFilterNavigator()->Clear();
3060            category->GetRegexFilterNavigator()->Clear();
3061        }
3062
3063        result.SetStatus(eReturnStatusSuccessFinishResult);
3064        return result.Succeeded();
3065    }
3066
3067};
3068
3069OptionDefinition
3070CommandObjectTypeFilterClear::CommandOptions::g_option_table[] =
3071{
3072    { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Clear every category."},
3073    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
3074};
3075
3076#ifndef LLDB_DISABLE_PYTHON
3077//-------------------------------------------------------------------------
3078// CommandObjectTypeSynthClear
3079//-------------------------------------------------------------------------
3080
3081class CommandObjectTypeSynthClear : public CommandObject
3082{
3083private:
3084
3085    class CommandOptions : public Options
3086    {
3087    public:
3088
3089        CommandOptions (CommandInterpreter &interpreter) :
3090        Options (interpreter)
3091        {
3092        }
3093
3094        virtual
3095        ~CommandOptions (){}
3096
3097        virtual Error
3098        SetOptionValue (uint32_t option_idx, const char *option_arg)
3099        {
3100            Error error;
3101            char short_option = (char) m_getopt_table[option_idx].val;
3102
3103            switch (short_option)
3104            {
3105                case 'a':
3106                    m_delete_all = true;
3107                    break;
3108                default:
3109                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
3110                    break;
3111            }
3112
3113            return error;
3114        }
3115
3116        void
3117        OptionParsingStarting ()
3118        {
3119            m_delete_all = false;
3120        }
3121
3122        const OptionDefinition*
3123        GetDefinitions ()
3124        {
3125            return g_option_table;
3126        }
3127
3128        // Options table: Required for subclasses of Options.
3129
3130        static OptionDefinition g_option_table[];
3131
3132        // Instance variables to hold the values for command options.
3133
3134        bool m_delete_all;
3135        bool m_delete_named;
3136    };
3137
3138    CommandOptions m_options;
3139
3140    virtual Options *
3141    GetOptions ()
3142    {
3143        return &m_options;
3144    }
3145
3146    static bool
3147    PerCategoryCallback(void* param,
3148                        const lldb::TypeCategoryImplSP& cate)
3149    {
3150        cate->Clear(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth);
3151        return true;
3152
3153    }
3154
3155public:
3156    CommandObjectTypeSynthClear (CommandInterpreter &interpreter) :
3157    CommandObject (interpreter,
3158                   "type synthetic clear",
3159                   "Delete all existing synthetic providers.",
3160                   NULL), m_options(interpreter)
3161    {
3162    }
3163
3164    ~CommandObjectTypeSynthClear ()
3165    {
3166    }
3167
3168    bool
3169    Execute (Args& command, CommandReturnObject &result)
3170    {
3171
3172        if (m_options.m_delete_all)
3173            DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL);
3174
3175        else
3176        {
3177            lldb::TypeCategoryImplSP category;
3178            if (command.GetArgumentCount() > 0)
3179            {
3180                const char* cat_name = command.GetArgumentAtIndex(0);
3181                ConstString cat_nameCS(cat_name);
3182                DataVisualization::Categories::GetCategory(cat_nameCS, category);
3183            }
3184            else
3185                DataVisualization::Categories::GetCategory(ConstString(NULL), category);
3186            category->GetSyntheticNavigator()->Clear();
3187            category->GetRegexSyntheticNavigator()->Clear();
3188        }
3189
3190        result.SetStatus(eReturnStatusSuccessFinishResult);
3191        return result.Succeeded();
3192    }
3193
3194};
3195
3196OptionDefinition
3197CommandObjectTypeSynthClear::CommandOptions::g_option_table[] =
3198{
3199    { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Clear every category."},
3200    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
3201};
3202
3203
3204//-------------------------------------------------------------------------
3205// TypeSynthAddInputReader
3206//-------------------------------------------------------------------------
3207
3208static const char *g_synth_addreader_instructions =   "Enter your Python command(s). Type 'DONE' to end.\n"
3209                                                      "You must define a Python class with these methods:\n"
3210                                                      "     def __init__(self, valobj, dict):\n"
3211                                                      "     def num_children(self):\n"
3212                                                      "     def get_child_at_index(self, index):\n"
3213                                                      "     def get_child_index(self, name):\n"
3214                                                      "Optionally, you can also define a method:\n"
3215                                                      "     def update(self):\n"
3216                                                      "if your synthetic provider is holding on to any per-object state variables (currently, this is not implemented because of the way LLDB handles instances of SBValue and you should not rely on object persistence and per-object state)\n"
3217                                                      "class synthProvider:";
3218
3219class TypeSynthAddInputReader : public InputReaderEZ
3220{
3221public:
3222    TypeSynthAddInputReader(Debugger& debugger) :
3223        InputReaderEZ(debugger)
3224    {}
3225
3226    virtual
3227    ~TypeSynthAddInputReader()
3228    {
3229    }
3230
3231    virtual void ActivateHandler(HandlerData& data)
3232    {
3233        StreamSP out_stream = data.GetOutStream();
3234        bool batch_mode = data.GetBatchMode();
3235        if (!batch_mode)
3236        {
3237            out_stream->Printf ("%s\n", g_synth_addreader_instructions);
3238            if (data.reader.GetPrompt())
3239                out_stream->Printf ("%s", data.reader.GetPrompt());
3240            out_stream->Flush();
3241        }
3242    }
3243
3244    virtual void ReactivateHandler(HandlerData& data)
3245    {
3246        StreamSP out_stream = data.GetOutStream();
3247        bool batch_mode = data.GetBatchMode();
3248        if (data.reader.GetPrompt() && !batch_mode)
3249        {
3250            out_stream->Printf ("%s", data.reader.GetPrompt());
3251            out_stream->Flush();
3252        }
3253    }
3254    virtual void GotTokenHandler(HandlerData& data)
3255    {
3256        StreamSP out_stream = data.GetOutStream();
3257        bool batch_mode = data.GetBatchMode();
3258        if (data.bytes && data.bytes_len && data.baton)
3259        {
3260            ((SynthAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len);
3261        }
3262        if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
3263        {
3264            out_stream->Printf ("%s", data.reader.GetPrompt());
3265            out_stream->Flush();
3266        }
3267    }
3268    virtual void InterruptHandler(HandlerData& data)
3269    {
3270        StreamSP out_stream = data.GetOutStream();
3271        bool batch_mode = data.GetBatchMode();
3272        data.reader.SetIsDone (true);
3273        if (!batch_mode)
3274        {
3275            out_stream->Printf ("Warning: No command attached to breakpoint.\n");
3276            out_stream->Flush();
3277        }
3278    }
3279    virtual void EOFHandler(HandlerData& data)
3280    {
3281        data.reader.SetIsDone (true);
3282    }
3283    virtual void DoneHandler(HandlerData& data)
3284    {
3285        StreamSP out_stream = data.GetOutStream();
3286        SynthAddOptions *options_ptr = ((SynthAddOptions*)data.baton);
3287        if (!options_ptr)
3288        {
3289            out_stream->Printf ("Internal error #1: no script attached.\n");
3290            out_stream->Flush();
3291            return;
3292        }
3293
3294        SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
3295
3296        ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
3297        if (!interpreter)
3298        {
3299            out_stream->Printf ("Internal error #2: no script attached.\n");
3300            out_stream->Flush();
3301            return;
3302        }
3303        std::string class_name_str;
3304        if (!interpreter->GenerateTypeSynthClass (options->m_user_source,
3305                                                  class_name_str))
3306        {
3307            out_stream->Printf ("Internal error #3: no script attached.\n");
3308            out_stream->Flush();
3309            return;
3310        }
3311        if (class_name_str.empty())
3312        {
3313            out_stream->Printf ("Internal error #4: no script attached.\n");
3314            out_stream->Flush();
3315            return;
3316        }
3317
3318        // everything should be fine now, let's add the synth provider class
3319
3320        SyntheticChildrenSP synth_provider;
3321        synth_provider.reset(new TypeSyntheticImpl(SyntheticChildren::Flags().SetCascades(options->m_cascade).
3322                                                         SetSkipPointers(options->m_skip_pointers).
3323                                                         SetSkipReferences(options->m_skip_references),
3324                                                         class_name_str.c_str()));
3325
3326
3327        lldb::TypeCategoryImplSP category;
3328        DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category);
3329
3330        Error error;
3331
3332        for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
3333        {
3334            const char *type_name = options->m_target_types.GetStringAtIndex(i);
3335            ConstString typeCS(type_name);
3336            if (typeCS)
3337            {
3338                if (!CommandObjectTypeSynthAdd::AddSynth(typeCS,
3339                                                        synth_provider,
3340                                                        options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth,
3341                                                        options->m_category,
3342                                                        &error))
3343                {
3344                    out_stream->Printf("%s\n", error.AsCString());
3345                    out_stream->Flush();
3346                    return;
3347                }
3348            }
3349            else
3350            {
3351                out_stream->Printf ("Internal error #6: no script attached.\n");
3352                out_stream->Flush();
3353                return;
3354            }
3355        }
3356    }
3357
3358private:
3359    DISALLOW_COPY_AND_ASSIGN (TypeSynthAddInputReader);
3360};
3361
3362void
3363CommandObjectTypeSynthAdd::CollectPythonScript (SynthAddOptions *options,
3364                                                CommandReturnObject &result)
3365{
3366    InputReaderSP reader_sp (new TypeSynthAddInputReader(m_interpreter.GetDebugger()));
3367    if (reader_sp && options)
3368    {
3369
3370        InputReaderEZ::InitializationParameters ipr;
3371
3372        Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt("     ")));
3373        if (err.Success())
3374        {
3375            m_interpreter.GetDebugger().PushInputReader (reader_sp);
3376            result.SetStatus (eReturnStatusSuccessFinishNoResult);
3377        }
3378        else
3379        {
3380            result.AppendError (err.AsCString());
3381            result.SetStatus (eReturnStatusFailed);
3382        }
3383    }
3384    else
3385    {
3386        result.AppendError("out of memory");
3387        result.SetStatus (eReturnStatusFailed);
3388    }
3389}
3390
3391bool
3392CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result)
3393{
3394    SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers,
3395                                                     m_options.m_skip_references,
3396                                                     m_options.m_cascade,
3397                                                     m_options.m_regex,
3398                                                     m_options.m_category);
3399
3400    const size_t argc = command.GetArgumentCount();
3401
3402    for (size_t i = 0; i < argc; i++)
3403    {
3404        const char* typeA = command.GetArgumentAtIndex(i);
3405        if (typeA && *typeA)
3406            options->m_target_types << typeA;
3407        else
3408        {
3409            result.AppendError("empty typenames not allowed");
3410            result.SetStatus(eReturnStatusFailed);
3411            return false;
3412        }
3413    }
3414
3415    CollectPythonScript(options,result);
3416    return result.Succeeded();
3417}
3418
3419bool
3420CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result)
3421{
3422    const size_t argc = command.GetArgumentCount();
3423
3424    if (argc < 1)
3425    {
3426        result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
3427        result.SetStatus(eReturnStatusFailed);
3428        return false;
3429    }
3430
3431    if (m_options.m_class_name.empty() && !m_options.m_input_python)
3432    {
3433        result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str());
3434        result.SetStatus(eReturnStatusFailed);
3435        return false;
3436    }
3437
3438    SyntheticChildrenSP entry;
3439
3440    TypeSyntheticImpl* impl = new TypeSyntheticImpl(SyntheticChildren::Flags().
3441                                                    SetCascades(m_options.m_cascade).
3442                                                    SetSkipPointers(m_options.m_skip_pointers).
3443                                                    SetSkipReferences(m_options.m_skip_references),
3444                                                    m_options.m_class_name.c_str());
3445
3446    entry.reset(impl);
3447
3448    // now I have a valid provider, let's add it to every type
3449
3450    lldb::TypeCategoryImplSP category;
3451    DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
3452
3453    Error error;
3454
3455    for (size_t i = 0; i < argc; i++)
3456    {
3457        const char* typeA = command.GetArgumentAtIndex(i);
3458        ConstString typeCS(typeA);
3459        if (typeCS)
3460        {
3461            if (!AddSynth(typeCS,
3462                          entry,
3463                          m_options.m_regex ? eRegexSynth : eRegularSynth,
3464                          m_options.m_category,
3465                          &error))
3466            {
3467                result.AppendError(error.AsCString());
3468                result.SetStatus(eReturnStatusFailed);
3469                return false;
3470            }
3471        }
3472        else
3473        {
3474            result.AppendError("empty typenames not allowed");
3475            result.SetStatus(eReturnStatusFailed);
3476            return false;
3477        }
3478    }
3479
3480    result.SetStatus(eReturnStatusSuccessFinishNoResult);
3481    return result.Succeeded();
3482}
3483
3484CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) :
3485CommandObject (interpreter,
3486               "type synthetic add",
3487               "Add a new synthetic provider for a type.",
3488               NULL), m_options (interpreter)
3489{
3490    CommandArgumentEntry type_arg;
3491    CommandArgumentData type_style_arg;
3492
3493    type_style_arg.arg_type = eArgTypeName;
3494    type_style_arg.arg_repetition = eArgRepeatPlus;
3495
3496    type_arg.push_back (type_style_arg);
3497
3498    m_arguments.push_back (type_arg);
3499
3500}
3501
3502bool
3503CommandObjectTypeSynthAdd::AddSynth(const ConstString& type_name,
3504         SyntheticChildrenSP entry,
3505         SynthFormatType type,
3506         std::string category_name,
3507         Error* error)
3508{
3509    lldb::TypeCategoryImplSP category;
3510    DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
3511
3512    if (category->AnyMatches(type_name,
3513                             eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
3514                             false))
3515    {
3516        if (error)
3517            error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString());
3518        return false;
3519    }
3520
3521    if (type == eRegexSynth)
3522    {
3523        RegularExpressionSP typeRX(new RegularExpression());
3524        if (!typeRX->Compile(type_name.GetCString()))
3525        {
3526            if (error)
3527                error->SetErrorString("regex format error (maybe this is not really a regex?)");
3528            return false;
3529        }
3530
3531        category->GetRegexSyntheticNavigator()->Delete(type_name);
3532        category->GetRegexSyntheticNavigator()->Add(typeRX, entry);
3533
3534        return true;
3535    }
3536    else
3537    {
3538        category->GetSyntheticNavigator()->Add(type_name, entry);
3539        return true;
3540    }
3541}
3542
3543bool
3544CommandObjectTypeSynthAdd::Execute (Args& command, CommandReturnObject &result)
3545{
3546    if (m_options.handwrite_python)
3547        return Execute_HandwritePython(command, result);
3548    else if (m_options.is_class_based)
3549        return Execute_PythonClass(command, result);
3550    else
3551    {
3552        result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line");
3553        result.SetStatus(eReturnStatusFailed);
3554        return false;
3555    }
3556}
3557
3558OptionDefinition
3559CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
3560{
3561    { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade to derived typedefs."},
3562    { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
3563    { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
3564    { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,         "Add this to the given category instead of the default one."},
3565    { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypePythonClass,    "Use this Python class to produce synthetic children."},
3566    { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone,    "Type Python code to generate a class that provides synthetic children."},
3567    { LLDB_OPT_SET_ALL, false,  "regex", 'x', no_argument, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
3568    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
3569};
3570
3571#endif // #ifndef LLDB_DISABLE_PYTHON
3572
3573class CommandObjectTypeFilterAdd : public CommandObject
3574{
3575
3576private:
3577
3578    class CommandOptions : public Options
3579    {
3580        typedef std::vector<std::string> option_vector;
3581    public:
3582
3583        CommandOptions (CommandInterpreter &interpreter) :
3584        Options (interpreter)
3585        {
3586        }
3587
3588        virtual
3589        ~CommandOptions (){}
3590
3591        virtual Error
3592        SetOptionValue (uint32_t option_idx, const char *option_arg)
3593        {
3594            Error error;
3595            char short_option = (char) m_getopt_table[option_idx].val;
3596            bool success;
3597
3598            switch (short_option)
3599            {
3600                case 'C':
3601                    m_cascade = Args::StringToBoolean(option_arg, true, &success);
3602                    if (!success)
3603                        error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg);
3604                    break;
3605                case 'c':
3606                    m_expr_paths.push_back(option_arg);
3607                    has_child_list = true;
3608                    break;
3609                case 'p':
3610                    m_skip_pointers = true;
3611                    break;
3612                case 'r':
3613                    m_skip_references = true;
3614                    break;
3615                case 'w':
3616                    m_category = std::string(option_arg);
3617                    break;
3618                case 'x':
3619                    m_regex = true;
3620                    break;
3621                default:
3622                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
3623                    break;
3624            }
3625
3626            return error;
3627        }
3628
3629        void
3630        OptionParsingStarting ()
3631        {
3632            m_cascade = true;
3633            m_skip_pointers = false;
3634            m_skip_references = false;
3635            m_category = "default";
3636            m_expr_paths.clear();
3637            has_child_list = false;
3638            m_regex = false;
3639        }
3640
3641        const OptionDefinition*
3642        GetDefinitions ()
3643        {
3644            return g_option_table;
3645        }
3646
3647        // Options table: Required for subclasses of Options.
3648
3649        static OptionDefinition g_option_table[];
3650
3651        // Instance variables to hold the values for command options.
3652
3653        bool m_cascade;
3654        bool m_skip_references;
3655        bool m_skip_pointers;
3656        bool m_input_python;
3657        option_vector m_expr_paths;
3658        std::string m_category;
3659
3660        bool has_child_list;
3661
3662        bool m_regex;
3663
3664        typedef option_vector::iterator ExpressionPathsIterator;
3665    };
3666
3667    CommandOptions m_options;
3668
3669    virtual Options *
3670    GetOptions ()
3671    {
3672        return &m_options;
3673    }
3674
3675    enum FilterFormatType
3676    {
3677        eRegularFilter,
3678        eRegexFilter
3679    };
3680
3681    bool
3682    AddFilter(const ConstString& type_name,
3683              SyntheticChildrenSP entry,
3684              FilterFormatType type,
3685              std::string category_name,
3686              Error* error)
3687    {
3688        lldb::TypeCategoryImplSP category;
3689        DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
3690
3691        if (category->AnyMatches(type_name,
3692                                 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
3693                                 false))
3694        {
3695            if (error)
3696                error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString());
3697            return false;
3698        }
3699
3700        if (type == eRegexFilter)
3701        {
3702            RegularExpressionSP typeRX(new RegularExpression());
3703            if (!typeRX->Compile(type_name.GetCString()))
3704            {
3705                if (error)
3706                    error->SetErrorString("regex format error (maybe this is not really a regex?)");
3707                return false;
3708            }
3709
3710            category->GetRegexFilterNavigator()->Delete(type_name);
3711            category->GetRegexFilterNavigator()->Add(typeRX, entry);
3712
3713            return true;
3714        }
3715        else
3716        {
3717            category->GetFilterNavigator()->Add(type_name, entry);
3718            return true;
3719        }
3720    }
3721
3722
3723public:
3724
3725    CommandObjectTypeFilterAdd (CommandInterpreter &interpreter) :
3726    CommandObject (interpreter,
3727                   "type filter add",
3728                   "Add a new filter for a type.",
3729                   NULL),
3730    m_options (interpreter)
3731    {
3732        CommandArgumentEntry type_arg;
3733        CommandArgumentData type_style_arg;
3734
3735        type_style_arg.arg_type = eArgTypeName;
3736        type_style_arg.arg_repetition = eArgRepeatPlus;
3737
3738        type_arg.push_back (type_style_arg);
3739
3740        m_arguments.push_back (type_arg);
3741
3742        SetHelpLong(
3743                    "Some examples of using this command.\n"
3744                    "We use as reference the following snippet of code:\n"
3745                    "\n"
3746                    "class Foo {;\n"
3747                    "    int a;\n"
3748                    "    int b;\n"
3749                    "    int c;\n"
3750                    "    int d;\n"
3751                    "    int e;\n"
3752                    "    int f;\n"
3753                    "    int g;\n"
3754                    "    int h;\n"
3755                    "    int i;\n"
3756                    "} \n"
3757                    "Typing:\n"
3758                    "type filter add --child a -- child g Foo\n"
3759                    "frame variable a_foo\n"
3760                    "will produce an output where only a and b are displayed\n"
3761                    "Other children of a_foo (b,c,d,e,f,h and i) are available by asking for them, as in:\n"
3762                    "frame variable a_foo.b a_foo.c ... a_foo.i\n"
3763                    "\n"
3764                    "Use option --raw to frame variable prevails on the filter\n"
3765                    "frame variable a_foo --raw\n"
3766                    "shows all the children of a_foo (a thru i) as if no filter was defined\n"
3767                    );
3768    }
3769
3770    ~CommandObjectTypeFilterAdd ()
3771    {
3772    }
3773
3774    bool
3775    Execute (Args& command, CommandReturnObject &result)
3776    {
3777        const size_t argc = command.GetArgumentCount();
3778
3779        if (argc < 1)
3780        {
3781            result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
3782            result.SetStatus(eReturnStatusFailed);
3783            return false;
3784        }
3785
3786        if (m_options.m_expr_paths.size() == 0)
3787        {
3788            result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
3789            result.SetStatus(eReturnStatusFailed);
3790            return false;
3791        }
3792
3793        SyntheticChildrenSP entry;
3794
3795        TypeFilterImpl* impl = new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade).
3796                                                    SetSkipPointers(m_options.m_skip_pointers).
3797                                                    SetSkipReferences(m_options.m_skip_references));
3798
3799        entry.reset(impl);
3800
3801        // go through the expression paths
3802        CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
3803
3804        for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
3805            impl->AddExpressionPath(*begin);
3806
3807
3808        // now I have a valid provider, let's add it to every type
3809
3810        lldb::TypeCategoryImplSP category;
3811        DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
3812
3813        Error error;
3814
3815        for (size_t i = 0; i < argc; i++)
3816        {
3817            const char* typeA = command.GetArgumentAtIndex(i);
3818            ConstString typeCS(typeA);
3819            if (typeCS)
3820            {
3821                if (!AddFilter(typeCS,
3822                          entry,
3823                          m_options.m_regex ? eRegexFilter : eRegularFilter,
3824                          m_options.m_category,
3825                          &error))
3826                {
3827                    result.AppendError(error.AsCString());
3828                    result.SetStatus(eReturnStatusFailed);
3829                    return false;
3830                }
3831            }
3832            else
3833            {
3834                result.AppendError("empty typenames not allowed");
3835                result.SetStatus(eReturnStatusFailed);
3836                return false;
3837            }
3838        }
3839
3840        result.SetStatus(eReturnStatusSuccessFinishNoResult);
3841        return result.Succeeded();
3842    }
3843
3844};
3845
3846OptionDefinition
3847CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] =
3848{
3849    { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade to derived typedefs."},
3850    { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
3851    { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
3852    { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,         "Add this to the given category instead of the default one."},
3853    { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeExpressionPath,    "Include this expression path in the synthetic view."},
3854    { LLDB_OPT_SET_ALL, false,  "regex", 'x', no_argument, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
3855    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
3856};
3857
3858class CommandObjectTypeFormat : public CommandObjectMultiword
3859{
3860public:
3861    CommandObjectTypeFormat (CommandInterpreter &interpreter) :
3862        CommandObjectMultiword (interpreter,
3863                                "type format",
3864                                "A set of commands for editing variable value display options",
3865                                "type format [<sub-command-options>] ")
3866    {
3867        LoadSubCommand ("add",    CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter)));
3868        LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectTypeFormatClear (interpreter)));
3869        LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter)));
3870        LoadSubCommand ("list",   CommandObjectSP (new CommandObjectTypeFormatList (interpreter)));
3871    }
3872
3873
3874    ~CommandObjectTypeFormat ()
3875    {
3876    }
3877};
3878
3879#ifndef LLDB_DISABLE_PYTHON
3880
3881class CommandObjectTypeSynth : public CommandObjectMultiword
3882{
3883public:
3884    CommandObjectTypeSynth (CommandInterpreter &interpreter) :
3885    CommandObjectMultiword (interpreter,
3886                            "type synthetic",
3887                            "A set of commands for operating on synthetic type representations",
3888                            "type synthetic [<sub-command-options>] ")
3889    {
3890        LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter)));
3891        LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSynthClear (interpreter)));
3892        LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter)));
3893        LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSynthList (interpreter)));
3894    }
3895
3896
3897    ~CommandObjectTypeSynth ()
3898    {
3899    }
3900};
3901
3902#endif // #ifndef LLDB_DISABLE_PYTHON
3903
3904class CommandObjectTypeFilter : public CommandObjectMultiword
3905{
3906public:
3907    CommandObjectTypeFilter (CommandInterpreter &interpreter) :
3908    CommandObjectMultiword (interpreter,
3909                            "type filter",
3910                            "A set of commands for operating on type filters",
3911                            "type synthetic [<sub-command-options>] ")
3912    {
3913        LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeFilterAdd (interpreter)));
3914        LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeFilterClear (interpreter)));
3915        LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeFilterDelete (interpreter)));
3916        LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeFilterList (interpreter)));
3917    }
3918
3919
3920    ~CommandObjectTypeFilter ()
3921    {
3922    }
3923};
3924
3925class CommandObjectTypeCategory : public CommandObjectMultiword
3926{
3927public:
3928    CommandObjectTypeCategory (CommandInterpreter &interpreter) :
3929    CommandObjectMultiword (interpreter,
3930                            "type category",
3931                            "A set of commands for operating on categories",
3932                            "type category [<sub-command-options>] ")
3933    {
3934        LoadSubCommand ("enable",        CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter)));
3935        LoadSubCommand ("disable",       CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter)));
3936        LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter)));
3937        LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeCategoryList (interpreter)));
3938    }
3939
3940
3941    ~CommandObjectTypeCategory ()
3942    {
3943    }
3944};
3945
3946class CommandObjectTypeSummary : public CommandObjectMultiword
3947{
3948public:
3949    CommandObjectTypeSummary (CommandInterpreter &interpreter) :
3950    CommandObjectMultiword (interpreter,
3951                            "type summary",
3952                            "A set of commands for editing variable summary display options",
3953                            "type summary [<sub-command-options>] ")
3954    {
3955        LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter)));
3956        LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));
3957        LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));
3958        LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSummaryList (interpreter)));
3959    }
3960
3961
3962    ~CommandObjectTypeSummary ()
3963    {
3964    }
3965};
3966
3967//-------------------------------------------------------------------------
3968// CommandObjectType
3969//-------------------------------------------------------------------------
3970
3971CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) :
3972    CommandObjectMultiword (interpreter,
3973                            "type",
3974                            "A set of commands for operating on the type system",
3975                            "type [<sub-command-options>]")
3976{
3977    LoadSubCommand ("category",  CommandObjectSP (new CommandObjectTypeCategory (interpreter)));
3978    LoadSubCommand ("filter",    CommandObjectSP (new CommandObjectTypeFilter (interpreter)));
3979    LoadSubCommand ("format",    CommandObjectSP (new CommandObjectTypeFormat (interpreter)));
3980    LoadSubCommand ("summary",   CommandObjectSP (new CommandObjectTypeSummary (interpreter)));
3981#ifndef LLDB_DISABLE_PYTHON
3982    LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter)));
3983#endif
3984}
3985
3986
3987CommandObjectType::~CommandObjectType ()
3988{
3989}
3990
3991
3992