CommandObjectType.cpp revision 1e620f0c6b953f86436a97fdd1d728648b4cdab1
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// C++ Includes
14
15#include "lldb/Core/ConstString.h"
16#include "lldb/Core/Debugger.h"
17#include "lldb/Core/FormatManager.h"
18#include "lldb/Core/InputReaderEZ.h"
19#include "lldb/Core/RegularExpression.h"
20#include "lldb/Core/State.h"
21#include "lldb/Core/StringList.h"
22#include "lldb/Interpreter/CommandInterpreter.h"
23#include "lldb/Interpreter/CommandObject.h"
24#include "lldb/Interpreter/CommandReturnObject.h"
25#include "lldb/Interpreter/Options.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30//-------------------------------------------------------------------------
31// CommandObjectTypeFormatAdd
32//-------------------------------------------------------------------------
33
34class CommandObjectTypeFormatAdd : public CommandObject
35{
36
37private:
38
39    class CommandOptions : public Options
40    {
41    public:
42
43        CommandOptions (CommandInterpreter &interpreter) :
44        Options (interpreter)
45        {
46        }
47
48        virtual
49        ~CommandOptions (){}
50
51        virtual Error
52        SetOptionValue (uint32_t option_idx, const char *option_arg)
53        {
54            Error error;
55            char short_option = (char) m_getopt_table[option_idx].val;
56            bool success;
57
58            switch (short_option)
59            {
60                case 'C':
61                    m_cascade = Args::StringToBoolean(option_arg, true, &success);
62                    if (!success)
63                        error.SetErrorStringWithFormat("Invalid value for cascade: %s.\n", option_arg);
64                    break;
65                case 'f':
66                    error = Args::StringToFormat(option_arg, m_format, NULL);
67                    break;
68                case 'p':
69                    m_skip_pointers = true;
70                    break;
71                case 'r':
72                    m_skip_references = true;
73                    break;
74                default:
75                    error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
76                    break;
77            }
78
79            return error;
80        }
81
82        void
83        OptionParsingStarting ()
84        {
85            m_cascade = true;
86            m_format = eFormatInvalid;
87            m_skip_pointers = false;
88            m_skip_references = false;
89        }
90
91        const OptionDefinition*
92        GetDefinitions ()
93        {
94            return g_option_table;
95        }
96
97        // Options table: Required for subclasses of Options.
98
99        static OptionDefinition g_option_table[];
100
101        // Instance variables to hold the values for command options.
102
103        bool m_cascade;
104        lldb::Format m_format;
105        bool m_skip_references;
106        bool m_skip_pointers;
107    };
108
109    CommandOptions m_options;
110
111    virtual Options *
112    GetOptions ()
113    {
114        return &m_options;
115    }
116
117public:
118    CommandObjectTypeFormatAdd (CommandInterpreter &interpreter) :
119    CommandObject (interpreter,
120                   "type format add",
121                   "Add a new formatting style for a type.",
122                   NULL), m_options (interpreter)
123    {
124        CommandArgumentEntry type_arg;
125        CommandArgumentData type_style_arg;
126
127        type_style_arg.arg_type = eArgTypeName;
128        type_style_arg.arg_repetition = eArgRepeatPlus;
129
130        type_arg.push_back (type_style_arg);
131
132        m_arguments.push_back (type_arg);
133
134        SetHelpLong(
135                    "Some examples of using this command.\n"
136                    "We use as reference the following snippet of code:\n"
137                    "\n"
138                    "typedef int Aint;\n"
139                    "typedef float Afloat;\n"
140                    "typedef Aint Bint;\n"
141                    "typedef Afloat Bfloat;\n"
142                    "\n"
143                    "Aint ix = 5;\n"
144                    "Bint iy = 5;\n"
145                    "\n"
146                    "Afloat fx = 3.14;\n"
147                    "BFloat fy = 3.14;\n"
148                    "\n"
149                    "Typing:\n"
150                    "type format add -f hex AInt\n"
151                    "frame variable iy\n"
152                    "will produce an hex display of iy, because no formatter is available for Bint and the one for Aint is used instead\n"
153                    "To prevent this type\n"
154                    "type format add -f hex -C no AInt\n"
155                    "\n"
156                    "A similar reasoning applies to\n"
157                    "type format add -f hex -C no float -p\n"
158                    "which now prints all floats and float&s as hexadecimal, but does not format float*s\n"
159                    "and does not change the default display for Afloat and Bfloat objects.\n"
160                    );
161    }
162
163    ~CommandObjectTypeFormatAdd ()
164    {
165    }
166
167    bool
168    Execute (Args& command, CommandReturnObject &result)
169    {
170        const size_t argc = command.GetArgumentCount();
171
172        if (argc < 1)
173        {
174            result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
175            result.SetStatus(eReturnStatusFailed);
176            return false;
177        }
178
179        if (m_options.m_format == eFormatInvalid)
180        {
181            result.AppendErrorWithFormat ("%s needs a valid format.\n", m_cmd_name.c_str());
182            result.SetStatus(eReturnStatusFailed);
183            return false;
184        }
185
186        ValueFormatSP entry;
187
188        entry.reset(new ValueFormat(m_options.m_format,
189                                    m_options.m_cascade,
190                                    m_options.m_skip_pointers,
191                                    m_options.m_skip_references));
192
193        // now I have a valid format, let's add it to every type
194
195        for (size_t i = 0; i < argc; i++) {
196            const char* typeA = command.GetArgumentAtIndex(i);
197            ConstString typeCS(typeA);
198            if (typeCS)
199                Debugger::Formatting::ValueFormats::Add(typeCS, entry);
200            else
201            {
202                result.AppendError("empty typenames not allowed");
203                result.SetStatus(eReturnStatusFailed);
204                return false;
205            }
206        }
207
208        result.SetStatus(eReturnStatusSuccessFinishNoResult);
209        return result.Succeeded();
210    }
211};
212
213OptionDefinition
214CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] =
215{
216    { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade to derived typedefs."},
217    { LLDB_OPT_SET_ALL, false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat,    "The format to use to display this type."},
218    { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean,         "Don't use this format for pointers-to-type objects."},
219    { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean,         "Don't use this format for references-to-type objects."},
220    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
221};
222
223
224//-------------------------------------------------------------------------
225// CommandObjectTypeFormatDelete
226//-------------------------------------------------------------------------
227
228class CommandObjectTypeFormatDelete : public CommandObject
229{
230public:
231    CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) :
232    CommandObject (interpreter,
233                   "type format delete",
234                   "Delete an existing formatting style for a type.",
235                   NULL)
236    {
237        CommandArgumentEntry type_arg;
238        CommandArgumentData type_style_arg;
239
240        type_style_arg.arg_type = eArgTypeName;
241        type_style_arg.arg_repetition = eArgRepeatPlain;
242
243        type_arg.push_back (type_style_arg);
244
245        m_arguments.push_back (type_arg);
246
247    }
248
249    ~CommandObjectTypeFormatDelete ()
250    {
251    }
252
253    bool
254    Execute (Args& command, CommandReturnObject &result)
255    {
256        const size_t argc = command.GetArgumentCount();
257
258        if (argc != 1)
259        {
260            result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
261            result.SetStatus(eReturnStatusFailed);
262            return false;
263        }
264
265        const char* typeA = command.GetArgumentAtIndex(0);
266        ConstString typeCS(typeA);
267
268        if (!typeCS)
269        {
270            result.AppendError("empty typenames not allowed");
271            result.SetStatus(eReturnStatusFailed);
272            return false;
273        }
274
275
276        if (Debugger::Formatting::ValueFormats::Delete(typeCS))
277        {
278            result.SetStatus(eReturnStatusSuccessFinishNoResult);
279            return result.Succeeded();
280        }
281        else
282        {
283            result.AppendErrorWithFormat ("no custom format for %s.\n", typeA);
284            result.SetStatus(eReturnStatusFailed);
285            return false;
286        }
287
288    }
289
290};
291
292//-------------------------------------------------------------------------
293// CommandObjectTypeFormatClear
294//-------------------------------------------------------------------------
295
296class CommandObjectTypeFormatClear : public CommandObject
297{
298public:
299    CommandObjectTypeFormatClear (CommandInterpreter &interpreter) :
300    CommandObject (interpreter,
301                   "type format clear",
302                   "Delete all existing format styles.",
303                   NULL)
304    {
305    }
306
307    ~CommandObjectTypeFormatClear ()
308    {
309    }
310
311    bool
312    Execute (Args& command, CommandReturnObject &result)
313    {
314        Debugger::Formatting::ValueFormats::Clear();
315        result.SetStatus(eReturnStatusSuccessFinishResult);
316        return result.Succeeded();
317    }
318
319};
320
321//-------------------------------------------------------------------------
322// CommandObjectTypeFormatList
323//-------------------------------------------------------------------------
324
325bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, const char* type, const ValueFormat::SharedPointer& entry);
326
327class CommandObjectTypeFormatList;
328
329struct CommandObjectTypeFormatList_LoopCallbackParam {
330    CommandObjectTypeFormatList* self;
331    CommandReturnObject* result;
332    RegularExpression* regex;
333    CommandObjectTypeFormatList_LoopCallbackParam(CommandObjectTypeFormatList* S, CommandReturnObject* R,
334                                            RegularExpression* X = NULL) : self(S), result(R), regex(X) {}
335};
336
337class CommandObjectTypeFormatList : public CommandObject
338{
339public:
340    CommandObjectTypeFormatList (CommandInterpreter &interpreter) :
341    CommandObject (interpreter,
342                   "type format list",
343                   "Show a list of current formatting styles.",
344                   NULL)
345    {
346        CommandArgumentEntry type_arg;
347        CommandArgumentData type_style_arg;
348
349        type_style_arg.arg_type = eArgTypeName;
350        type_style_arg.arg_repetition = eArgRepeatOptional;
351
352        type_arg.push_back (type_style_arg);
353
354        m_arguments.push_back (type_arg);
355    }
356
357    ~CommandObjectTypeFormatList ()
358    {
359    }
360
361    bool
362    Execute (Args& command, CommandReturnObject &result)
363    {
364        const size_t argc = command.GetArgumentCount();
365
366        CommandObjectTypeFormatList_LoopCallbackParam *param;
367
368        if (argc == 1) {
369            RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
370            regex->Compile(command.GetArgumentAtIndex(0));
371            param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,regex);
372        }
373        else
374            param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result);
375        Debugger::Formatting::ValueFormats::LoopThrough(CommandObjectTypeFormatList_LoopCallback, param);
376        delete param;
377        result.SetStatus(eReturnStatusSuccessFinishResult);
378        return result.Succeeded();
379    }
380
381private:
382
383    bool
384    LoopCallback (const char* type,
385                  const ValueFormat::SharedPointer& entry,
386                  RegularExpression* regex,
387                  CommandReturnObject *result)
388    {
389        if (regex == NULL || regex->Execute(type))
390        {
391            result->GetOutputStream().Printf ("%s: %s%s%s%s\n", type,
392                                              FormatManager::GetFormatAsCString (entry->m_format),
393                                              entry->m_cascades ? "" : " (not cascading)",
394                                              entry->m_skip_pointers ? " (skip pointers)" : "",
395                                              entry->m_skip_references ? " (skip references)" : "");
396        }
397        return true;
398    }
399
400    friend bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, const char* type, const ValueFormat::SharedPointer& entry);
401
402};
403
404bool
405CommandObjectTypeFormatList_LoopCallback (
406                                    void* pt2self,
407                                    const char* type,
408                                    const ValueFormat::SharedPointer& entry)
409{
410    CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self;
411    return param->self->LoopCallback(type, entry, param->regex, param->result);
412}
413
414
415
416
417//-------------------------------------------------------------------------
418// CommandObjectTypeSummaryAdd
419//-------------------------------------------------------------------------
420
421static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
422                                           "def function (valobj,dict):";
423
424class TypeScriptAddInputReader : public InputReaderEZ
425{
426private:
427    DISALLOW_COPY_AND_ASSIGN (TypeScriptAddInputReader);
428public:
429    TypeScriptAddInputReader(Debugger& debugger) :
430    InputReaderEZ(debugger)
431    {}
432
433    virtual
434    ~TypeScriptAddInputReader()
435    {
436    }
437
438    virtual void ActivateHandler(HandlerData& data)
439    {
440        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
441        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
442        if (!batch_mode)
443        {
444            out_stream->Printf ("%s\n", g_reader_instructions);
445            if (data.reader.GetPrompt())
446                out_stream->Printf ("%s", data.reader.GetPrompt());
447            out_stream->Flush();
448        }
449    }
450
451    virtual void ReactivateHandler(HandlerData& data)
452    {
453        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
454        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
455        if (data.reader.GetPrompt() && !batch_mode)
456        {
457            out_stream->Printf ("%s", data.reader.GetPrompt());
458            out_stream->Flush();
459        }
460    }
461    virtual void GotTokenHandler(HandlerData& data)
462    {
463        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
464        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
465        if (data.bytes && data.bytes_len && data.baton)
466        {
467            ((ScriptAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len);
468        }
469        if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
470        {
471            out_stream->Printf ("%s", data.reader.GetPrompt());
472            out_stream->Flush();
473        }
474    }
475    virtual void InterruptHandler(HandlerData& data)
476    {
477        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
478        bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
479        data.reader.SetIsDone (true);
480        if (!batch_mode)
481        {
482            out_stream->Printf ("Warning: No command attached to breakpoint.\n");
483            out_stream->Flush();
484        }
485    }
486    virtual void EOFHandler(HandlerData& data)
487    {
488        data.reader.SetIsDone (true);
489    }
490    virtual void DoneHandler(HandlerData& data)
491    {
492        StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
493        ScriptAddOptions *options_ptr = ((ScriptAddOptions*)data.baton);
494        if (!options_ptr)
495        {
496            out_stream->Printf ("Internal error #1: no script attached.\n");
497            out_stream->Flush();
498            return;
499        }
500
501        ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
502
503        ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
504        if (!interpreter)
505        {
506            out_stream->Printf ("Internal error #2: no script attached.\n");
507            out_stream->Flush();
508            return;
509        }
510        StringList funct_name_sl;
511        if (!interpreter->GenerateTypeScriptFunction (options->m_user_source,
512                                                      funct_name_sl))
513        {
514            out_stream->Printf ("Internal error #3: no script attached.\n");
515            out_stream->Flush();
516            return;
517        }
518        if (funct_name_sl.GetSize() == 0)
519        {
520            out_stream->Printf ("Internal error #4: no script attached.\n");
521            out_stream->Flush();
522            return;
523        }
524        const char *funct_name = funct_name_sl.GetStringAtIndex(0);
525        if (!funct_name || !funct_name[0])
526        {
527            out_stream->Printf ("Internal error #5: no script attached.\n");
528            out_stream->Flush();
529            return;
530        }
531        // now I have a valid function name, let's add this as script for every type in the list
532
533        SummaryFormatSP script_format;
534        script_format.reset(new ScriptSummaryFormat(options->m_cascade,
535                                                    options->m_skip_pointers,
536                                                    options->m_skip_references,
537                                                    options->m_no_children,
538                                                    options->m_no_value,
539                                                    options->m_one_liner,
540                                                    std::string(funct_name),
541                                                    options->m_user_source.CopyList("     ")));
542
543        Error error;
544
545        for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
546        {
547            const char *type_name = options->m_target_types.GetStringAtIndex(i);
548            CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
549                                                    script_format,
550                                                    (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary),
551                                                    options->m_category,
552                                                    &error);
553            if (error.Fail())
554            {
555                out_stream->Printf (error.AsCString());
556                out_stream->Flush();
557                return;
558            }
559        }
560
561        if (options->m_name)
562        {
563            if ( (bool)(*(options->m_name)) )
564            {
565                CommandObjectTypeSummaryAdd::AddSummary(*(options->m_name),
566                                                                  script_format,
567                                                                  CommandObjectTypeSummaryAdd::eNamedSummary,
568                                                                  options->m_category,
569                                                                  &error);
570                if (error.Fail())
571                {
572                    out_stream->Printf (error.AsCString());
573                    out_stream->Flush();
574                    return;
575                }
576            }
577            else
578            {
579                out_stream->Printf (error.AsCString());
580                out_stream->Flush();
581                return;
582            }
583        }
584    }
585};
586
587Error
588CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
589{
590    Error error;
591    char short_option = (char) m_getopt_table[option_idx].val;
592    bool success;
593
594    switch (short_option)
595    {
596        case 'C':
597            m_cascade = Args::StringToBoolean(option_arg, true, &success);
598            if (!success)
599                error.SetErrorStringWithFormat("Invalid value for cascade: %s.\n", option_arg);
600            break;
601        case 'e':
602            m_no_children = false;
603            break;
604        case 'v':
605            m_no_value = true;
606            break;
607        case 'c':
608            m_one_liner = true;
609            break;
610        case 'f':
611            m_format_string = std::string(option_arg);
612            break;
613        case 'p':
614            m_skip_pointers = true;
615            break;
616        case 'r':
617            m_skip_references = true;
618            break;
619        case 'x':
620            m_regex = true;
621            break;
622        case 'n':
623            m_name = new ConstString(option_arg);
624            break;
625        case 's':
626            m_python_script = std::string(option_arg);
627            m_is_add_script = true;
628            break;
629        case 'F':
630            m_python_function = std::string(option_arg);
631            m_is_add_script = true;
632            break;
633        case 'P':
634            m_is_add_script = true;
635            break;
636        case 'w':
637            m_category = ConstString(option_arg).GetCString();
638            break;
639        default:
640            error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
641            break;
642    }
643
644    return error;
645}
646
647void
648CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting ()
649{
650    m_cascade = true;
651    m_no_children = true;
652    m_no_value = false;
653    m_one_liner = false;
654    m_skip_references = false;
655    m_skip_pointers = false;
656    m_regex = false;
657    m_name = NULL;
658    m_python_script = "";
659    m_python_function = "";
660    m_is_add_script = false;
661    m_category = NULL;
662}
663
664void
665CommandObjectTypeSummaryAdd::CollectPythonScript (ScriptAddOptions *options,
666                                                  CommandReturnObject &result)
667{
668    InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger()));
669    if (reader_sp && options)
670    {
671
672        InputReaderEZ::InitializationParameters ipr;
673
674        Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt("     ")));
675        if (err.Success())
676        {
677            m_interpreter.GetDebugger().PushInputReader (reader_sp);
678            result.SetStatus (eReturnStatusSuccessFinishNoResult);
679        }
680        else
681        {
682            result.AppendError (err.AsCString());
683            result.SetStatus (eReturnStatusFailed);
684        }
685    }
686    else
687    {
688        result.AppendError("out of memory");
689        result.SetStatus (eReturnStatusFailed);
690    }
691
692}
693
694bool
695CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result)
696{
697    const size_t argc = command.GetArgumentCount();
698
699    if (argc < 1 && !m_options.m_name)
700    {
701        result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
702        result.SetStatus(eReturnStatusFailed);
703        return false;
704    }
705
706    SummaryFormatSP script_format;
707
708    if (!m_options.m_python_function.empty()) // we have a Python function ready to use
709    {
710        ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
711        if (!interpreter)
712        {
713            result.AppendError ("Internal error #1N: no script attached.\n");
714            result.SetStatus (eReturnStatusFailed);
715            return false;
716        }
717        const char *funct_name = m_options.m_python_function.c_str();
718        if (!funct_name || !funct_name[0])
719        {
720            result.AppendError ("Internal error #2N: no script attached.\n");
721            result.SetStatus (eReturnStatusFailed);
722            return false;
723        }
724
725        script_format.reset(new ScriptSummaryFormat(m_options.m_cascade,
726                                                    m_options.m_skip_pointers,
727                                                    m_options.m_skip_references,
728                                                    m_options.m_no_children,
729                                                    m_options.m_no_value,
730                                                    m_options.m_one_liner,
731                                                    std::string(funct_name),
732                                                    "     " + m_options.m_python_function + "(valobj,dict)"));
733    }
734    else if (!m_options.m_python_script.empty()) // we have a quick 1-line script, just use it
735    {
736        ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
737        if (!interpreter)
738        {
739            result.AppendError ("Internal error #1Q: no script attached.\n");
740            result.SetStatus (eReturnStatusFailed);
741            return false;
742        }
743        StringList funct_sl;
744        funct_sl << m_options.m_python_script.c_str();
745        StringList funct_name_sl;
746        if (!interpreter->GenerateTypeScriptFunction (funct_sl,
747                                                      funct_name_sl))
748        {
749            result.AppendError ("Internal error #2Q: no script attached.\n");
750            result.SetStatus (eReturnStatusFailed);
751            return false;
752        }
753        if (funct_name_sl.GetSize() == 0)
754        {
755            result.AppendError ("Internal error #3Q: no script attached.\n");
756            result.SetStatus (eReturnStatusFailed);
757            return false;
758        }
759        const char *funct_name = funct_name_sl.GetStringAtIndex(0);
760        if (!funct_name || !funct_name[0])
761        {
762            result.AppendError ("Internal error #4Q: no script attached.\n");
763            result.SetStatus (eReturnStatusFailed);
764            return false;
765        }
766
767        script_format.reset(new ScriptSummaryFormat(m_options.m_cascade,
768                                                    m_options.m_skip_pointers,
769                                                    m_options.m_skip_references,
770                                                    m_options.m_no_children,
771                                                    m_options.m_no_value,
772                                                    m_options.m_one_liner,
773                                                    std::string(funct_name),
774                                                    "     " + m_options.m_python_script));
775    }
776    else // use an InputReader to grab Python code from the user
777    {
778        ScriptAddOptions *options = new ScriptAddOptions(m_options.m_skip_pointers,
779                                                         m_options.m_skip_references,
780                                                         m_options.m_cascade,
781                                                         m_options.m_no_children,
782                                                         m_options.m_no_value,
783                                                         m_options.m_one_liner,
784                                                         m_options.m_regex,
785                                                         m_options.m_name,
786                                                         m_options.m_category);
787
788        for (size_t i = 0; i < argc; i++) {
789            const char* typeA = command.GetArgumentAtIndex(i);
790            if (typeA && *typeA)
791                options->m_target_types << typeA;
792            else
793            {
794                result.AppendError("empty typenames not allowed");
795                result.SetStatus(eReturnStatusFailed);
796                return false;
797            }
798        }
799
800        CollectPythonScript(options,result);
801        return result.Succeeded();
802    }
803
804    // if I am here, script_format must point to something good, so I can add that
805    // as a script summary to all interested parties
806
807    Error error;
808
809    for (size_t i = 0; i < command.GetArgumentCount(); i++)
810    {
811        const char *type_name = command.GetArgumentAtIndex(i);
812        CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
813                                                script_format,
814                                                (m_options.m_regex ? eRegexSummary : eRegularSummary),
815                                                m_options.m_category,
816                                                &error);
817        if (error.Fail())
818        {
819            result.AppendError(error.AsCString());
820            result.SetStatus(eReturnStatusFailed);
821            return false;
822        }
823    }
824
825    if (m_options.m_name)
826    {
827        if ( (bool)(*(m_options.m_name)) )
828        {
829            AddSummary(*(m_options.m_name), script_format, eNamedSummary, m_options.m_category, &error);
830            if (error.Fail())
831            {
832                result.AppendError(error.AsCString());
833                result.AppendError("added to types, but not given a name");
834                result.SetStatus(eReturnStatusFailed);
835                return false;
836            }
837        }
838        else
839        {
840            result.AppendError("added to types, but not given a name");
841            result.SetStatus(eReturnStatusFailed);
842            return false;
843        }
844    }
845
846    return result.Succeeded();
847}
848
849bool
850CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result)
851{
852    const size_t argc = command.GetArgumentCount();
853
854    if (argc < 1 && !m_options.m_name)
855    {
856        result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
857        result.SetStatus(eReturnStatusFailed);
858        return false;
859    }
860
861    if (!m_options.m_one_liner && m_options.m_format_string.empty())
862    {
863        result.AppendError("empty summary strings not allowed");
864        result.SetStatus(eReturnStatusFailed);
865        return false;
866    }
867
868    const char* format_cstr = (m_options.m_one_liner ? "" : m_options.m_format_string.c_str());
869
870    Error error;
871
872    SummaryFormat::SharedPointer entry(new StringSummaryFormat(m_options.m_cascade,
873                                                               m_options.m_skip_pointers,
874                                                               m_options.m_skip_references,
875                                                               m_options.m_no_children,
876                                                               m_options.m_no_value,
877                                                               m_options.m_one_liner,
878                                                               format_cstr));
879
880    if (error.Fail())
881    {
882        result.AppendError(error.AsCString());
883        result.SetStatus(eReturnStatusFailed);
884        return false;
885    }
886
887    // now I have a valid format, let's add it to every type
888
889    for (size_t i = 0; i < argc; i++) {
890        const char* typeA = command.GetArgumentAtIndex(i);
891        if (!typeA || typeA[0] == '\0')
892        {
893            result.AppendError("empty typenames not allowed");
894            result.SetStatus(eReturnStatusFailed);
895            return false;
896        }
897        ConstString typeCS(typeA);
898
899        AddSummary(typeCS,
900                   entry,
901                   (m_options.m_regex ? eRegexSummary : eRegularSummary),
902                   m_options.m_category,
903                   &error);
904
905        if (error.Fail())
906        {
907            result.AppendError(error.AsCString());
908            result.SetStatus(eReturnStatusFailed);
909            return false;
910        }
911    }
912
913    if (m_options.m_name)
914    {
915        if ( (bool)(*(m_options.m_name)) )
916        {
917            AddSummary(*(m_options.m_name), entry, eNamedSummary, m_options.m_category, &error);
918            if (error.Fail())
919            {
920                result.AppendError(error.AsCString());
921                result.AppendError("added to types, but not given a name");
922                result.SetStatus(eReturnStatusFailed);
923                return false;
924            }
925        }
926        else
927        {
928            result.AppendError("added to types, but not given a name");
929            result.SetStatus(eReturnStatusFailed);
930            return false;
931        }
932    }
933
934    result.SetStatus(eReturnStatusSuccessFinishNoResult);
935    return result.Succeeded();
936}
937
938CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) :
939CommandObject (interpreter,
940               "type summary add",
941               "Add a new summary style for a type.",
942               NULL), m_options (interpreter)
943{
944    CommandArgumentEntry type_arg;
945    CommandArgumentData type_style_arg;
946
947    type_style_arg.arg_type = eArgTypeName;
948    type_style_arg.arg_repetition = eArgRepeatPlus;
949
950    type_arg.push_back (type_style_arg);
951
952    m_arguments.push_back (type_arg);
953
954    SetHelpLong(
955                "Some examples of using this command.\n"
956                "We use as reference the following snippet of code:\n"
957                "struct JustADemo\n"
958                "{\n"
959                "int* ptr;\n"
960                "float value;\n"
961                "JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n"
962                "};\n"
963                "JustADemo object(42,3.14);\n"
964                "struct AnotherDemo : public JustADemo\n"
965                "{\n"
966                "uint8_t byte;\n"
967                "AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n"
968                "};\n"
969                "AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n"
970                "\n"
971                "type summary add -f \"the answer is ${*var.ptr}\" JustADemo\n"
972                "when typing frame variable object you will get \"the answer is 42\"\n"
973                "type summary add -f \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n"
974                "when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n"
975                "\n"
976                "Alternatively, you could also say\n"
977                "type summary add -f \"${var%V} -> ${*var}\" \"int *\"\n"
978                "and replace the above summary string with\n"
979                "type summary add -f \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n"
980                "to obtain a similar result\n"
981                "\n"
982                "To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n"
983                "type summary add -f \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n"
984                "\n"
985                "This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n"
986                "If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n"
987                "type summary add -f \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n"
988                "A similar option -r exists for references.\n"
989                "\n"
990                "If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n"
991                "you can use the -c option, without giving any summary string:\n"
992                "type summary add -c JustADemo\n"
993                "frame variable object\n"
994                "the output being similar to (ptr=0xsomeaddress, value=3.14)\n"
995                "\n"
996                "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"
997                "type summary add -e -f \"*ptr = ${*var.ptr}\" JustADemo\n"
998                "Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n"
999                "to get an output like:\n"
1000                "\n"
1001                "*ptr = 42 {\n"
1002                " ptr = 0xsomeaddress\n"
1003                " value = 3.14\n"
1004                "}\n"
1005                "\n"
1006                "A command you may definitely want to try if you're doing C++ debugging is:\n"
1007                "type summary add -f \"${var._M_dataplus._M_p}\" std::string\n"
1008                "\n"
1009                "You can also add Python summaries, in which case you will use lldb public API to gather information from your variables"
1010                "and elaborate them to a meaningful summary inside a script written in Python. The variable object will be passed to your"
1011                "script as an SBValue object. The following example might help you when starting to use the Python summaries feature:\n"
1012                "type summary add JustADemo -s \"value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();\"\n"
1013                "If you prefer to type your scripts on multiple lines, you will use the -P option and then type your script, ending it with "
1014                "the word DONE on a line by itself to mark you're finished editing your code:\n"
1015                "(lldb)type summary add JustADemo -P\n"
1016                "     value = valobj.GetChildMemberWithName('value');\n"
1017                "     return 'My value is ' + value.GetValue();\n"
1018                "DONE\n"
1019                "(lldb)"
1020                );
1021}
1022
1023bool
1024CommandObjectTypeSummaryAdd::Execute (Args& command, CommandReturnObject &result)
1025{
1026    if (m_options.m_is_add_script)
1027        return Execute_ScriptSummary(command, result);
1028    else
1029        return Execute_StringSummary(command, result);
1030}
1031
1032bool
1033CommandObjectTypeSummaryAdd::AddSummary(const ConstString& type_name,
1034                                        SummaryFormatSP entry,
1035                                        SummaryFormatType type,
1036                                        const char* category_name,
1037                                        Error* error)
1038{
1039    lldb::FormatCategorySP category;
1040    Debugger::Formatting::Categories::Get(ConstString(category_name), category);
1041
1042    if (type == eRegexSummary)
1043    {
1044        RegularExpressionSP typeRX(new RegularExpression());
1045        if (!typeRX->Compile(type_name.GetCString()))
1046        {
1047            if (error)
1048                error->SetErrorString("regex format error (maybe this is not really a regex?)");
1049            return false;
1050        }
1051
1052        category->RegexSummary()->Delete(type_name.GetCString());
1053        category->RegexSummary()->Add(typeRX, entry);
1054
1055        return true;
1056    }
1057    else if (type == eNamedSummary)
1058    {
1059        // system named summaries do not exist (yet?)
1060        Debugger::Formatting::NamedSummaryFormats::Add(type_name,entry);
1061        return true;
1062    }
1063    else
1064    {
1065        category->Summary()->Add(type_name.GetCString(), entry);
1066        return true;
1067    }
1068}
1069
1070OptionDefinition
1071CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
1072{
1073    { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,    "Add this to the given category instead of the default one."},
1074    { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade to derived typedefs."},
1075    { LLDB_OPT_SET_ALL, false, "no-value", 'v', no_argument, NULL, 0, eArgTypeBoolean,         "Don't show the value, just show the summary, for this type."},
1076    { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean,         "Don't use this format for pointers-to-type objects."},
1077    { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean,         "Don't use this format for references-to-type objects."},
1078    { LLDB_OPT_SET_ALL, false,  "regex", 'x', no_argument, NULL, 0, eArgTypeBoolean,    "Type names are actually regular expressions."},
1079    { LLDB_OPT_SET_1  , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeBoolean,    "If true, inline all child values into summary string."},
1080    { LLDB_OPT_SET_2  , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeSummaryString,    "Format string used to display text and object contents."},
1081    { LLDB_OPT_SET_3, false, "python-script", 's', required_argument, NULL, 0, eArgTypeName, "Give a one-liner Python script as part of the command."},
1082    { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypeName, "Give the name of a Python function to use for this type."},
1083    { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeName, "Input Python code to use for this type manually."},
1084    { LLDB_OPT_SET_2 | LLDB_OPT_SET_3,   false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean,    "Expand aggregate data types to show children on separate lines."},
1085    { LLDB_OPT_SET_2 | LLDB_OPT_SET_3,   false, "name", 'n', required_argument, NULL, 0, eArgTypeName,    "A name for this summary string."},
1086    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1087};
1088
1089
1090//-------------------------------------------------------------------------
1091// CommandObjectTypeSummaryDelete
1092//-------------------------------------------------------------------------
1093
1094class CommandObjectTypeSummaryDelete : public CommandObject
1095{
1096private:
1097    class CommandOptions : public Options
1098    {
1099    public:
1100
1101        CommandOptions (CommandInterpreter &interpreter) :
1102        Options (interpreter)
1103        {
1104        }
1105
1106        virtual
1107        ~CommandOptions (){}
1108
1109        virtual Error
1110        SetOptionValue (uint32_t option_idx, const char *option_arg)
1111        {
1112            Error error;
1113            char short_option = (char) m_getopt_table[option_idx].val;
1114
1115            switch (short_option)
1116            {
1117                case 'a':
1118                    m_delete_all = true;
1119                    break;
1120                case 'w':
1121                    m_category = ConstString(option_arg).GetCString();
1122                    break;
1123                default:
1124                    error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1125                    break;
1126            }
1127
1128            return error;
1129        }
1130
1131        void
1132        OptionParsingStarting ()
1133        {
1134            m_delete_all = false;
1135            m_category = NULL;
1136        }
1137
1138        const OptionDefinition*
1139        GetDefinitions ()
1140        {
1141            return g_option_table;
1142        }
1143
1144        // Options table: Required for subclasses of Options.
1145
1146        static OptionDefinition g_option_table[];
1147
1148        // Instance variables to hold the values for command options.
1149
1150        bool m_delete_all;
1151        const char* m_category;
1152
1153    };
1154
1155    CommandOptions m_options;
1156
1157    virtual Options *
1158    GetOptions ()
1159    {
1160        return &m_options;
1161    }
1162
1163    static bool
1164    PerCategoryCallback(void* param,
1165                        const char* cate_name,
1166                        const FormatCategory::SharedPointer& cate)
1167    {
1168        const char* name = (const char*)param;
1169        cate->Summary()->Delete(name);
1170        cate->RegexSummary()->Delete(name);
1171        return true;
1172    }
1173
1174public:
1175    CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) :
1176    CommandObject (interpreter,
1177                   "type summary delete",
1178                   "Delete an existing summary style for a type.",
1179                   NULL), m_options(interpreter)
1180    {
1181        CommandArgumentEntry type_arg;
1182        CommandArgumentData type_style_arg;
1183
1184        type_style_arg.arg_type = eArgTypeName;
1185        type_style_arg.arg_repetition = eArgRepeatPlain;
1186
1187        type_arg.push_back (type_style_arg);
1188
1189        m_arguments.push_back (type_arg);
1190
1191    }
1192
1193    ~CommandObjectTypeSummaryDelete ()
1194    {
1195    }
1196
1197    bool
1198    Execute (Args& command, CommandReturnObject &result)
1199    {
1200        const size_t argc = command.GetArgumentCount();
1201
1202        if (argc != 1)
1203        {
1204            result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
1205            result.SetStatus(eReturnStatusFailed);
1206            return false;
1207        }
1208
1209        const char* typeA = command.GetArgumentAtIndex(0);
1210        ConstString typeCS(typeA);
1211
1212        if (!typeCS)
1213        {
1214            result.AppendError("empty typenames not allowed");
1215            result.SetStatus(eReturnStatusFailed);
1216            return false;
1217        }
1218
1219        if (m_options.m_delete_all)
1220        {
1221            Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, (void*)typeCS.GetCString());
1222            result.SetStatus(eReturnStatusSuccessFinishNoResult);
1223            return result.Succeeded();
1224        }
1225
1226        lldb::FormatCategorySP category;
1227        Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
1228
1229        bool delete_category = category->Delete(typeCS.GetCString());
1230        bool delete_named = Debugger::Formatting::NamedSummaryFormats::Delete(typeCS);
1231
1232        if (delete_category || delete_named)
1233        {
1234            result.SetStatus(eReturnStatusSuccessFinishNoResult);
1235            return result.Succeeded();
1236        }
1237        else
1238        {
1239            result.AppendErrorWithFormat ("no custom summary for %s.\n", typeA);
1240            result.SetStatus(eReturnStatusFailed);
1241            return false;
1242        }
1243
1244    }
1245};
1246
1247OptionDefinition
1248CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] =
1249{
1250    { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean,  "Delete from every category."},
1251    { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,  "Delete from given category."},
1252    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1253};
1254
1255class CommandObjectTypeSummaryClear : public CommandObject
1256{
1257private:
1258
1259    class CommandOptions : public Options
1260    {
1261    public:
1262
1263        CommandOptions (CommandInterpreter &interpreter) :
1264        Options (interpreter)
1265        {
1266        }
1267
1268        virtual
1269        ~CommandOptions (){}
1270
1271        virtual Error
1272        SetOptionValue (uint32_t option_idx, const char *option_arg)
1273        {
1274            Error error;
1275            char short_option = (char) m_getopt_table[option_idx].val;
1276
1277            switch (short_option)
1278            {
1279                case 'a':
1280                    m_delete_all = true;
1281                    break;
1282                default:
1283                    error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1284                    break;
1285            }
1286
1287            return error;
1288        }
1289
1290        void
1291        OptionParsingStarting ()
1292        {
1293            m_delete_all = false;
1294        }
1295
1296        const OptionDefinition*
1297        GetDefinitions ()
1298        {
1299            return g_option_table;
1300        }
1301
1302        // Options table: Required for subclasses of Options.
1303
1304        static OptionDefinition g_option_table[];
1305
1306        // Instance variables to hold the values for command options.
1307
1308        bool m_delete_all;
1309        bool m_delete_named;
1310    };
1311
1312    CommandOptions m_options;
1313
1314    virtual Options *
1315    GetOptions ()
1316    {
1317        return &m_options;
1318    }
1319
1320    static bool
1321    PerCategoryCallback(void* param,
1322                        const char* cate_name,
1323                        const FormatCategory::SharedPointer& cate)
1324    {
1325        cate->Summary()->Clear();
1326        cate->RegexSummary()->Clear();
1327        return true;
1328
1329    }
1330
1331public:
1332    CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) :
1333    CommandObject (interpreter,
1334                   "type summary clear",
1335                   "Delete all existing summary styles.",
1336                   NULL), m_options(interpreter)
1337    {
1338    }
1339
1340    ~CommandObjectTypeSummaryClear ()
1341    {
1342    }
1343
1344    bool
1345    Execute (Args& command, CommandReturnObject &result)
1346    {
1347
1348        if (m_options.m_delete_all)
1349            Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, NULL);
1350
1351        else
1352        {
1353            lldb::FormatCategorySP category;
1354            if (command.GetArgumentCount() > 0)
1355            {
1356                const char* cat_name = command.GetArgumentAtIndex(0);
1357                ConstString cat_nameCS(cat_name);
1358                Debugger::Formatting::Categories::Get(cat_nameCS, category);
1359            }
1360            else
1361                Debugger::Formatting::Categories::Get(ConstString(NULL), category);
1362            category->Clear();
1363        }
1364
1365        Debugger::Formatting::NamedSummaryFormats::Clear();
1366
1367        result.SetStatus(eReturnStatusSuccessFinishResult);
1368        return result.Succeeded();
1369    }
1370
1371};
1372
1373OptionDefinition
1374CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] =
1375{
1376    { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean,  "Clear every category."},
1377    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1378};
1379
1380//-------------------------------------------------------------------------
1381// CommandObjectTypeSummaryList
1382//-------------------------------------------------------------------------
1383
1384bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const StringSummaryFormat::SharedPointer& entry);
1385bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry);
1386
1387class CommandObjectTypeSummaryList;
1388
1389struct CommandObjectTypeSummaryList_LoopCallbackParam {
1390    CommandObjectTypeSummaryList* self;
1391    CommandReturnObject* result;
1392    RegularExpression* regex;
1393    RegularExpression* cate_regex;
1394    CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R,
1395                                                  RegularExpression* X = NULL,
1396                                                  RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
1397};
1398
1399class CommandObjectTypeSummaryList : public CommandObject
1400{
1401
1402    class CommandOptions : public Options
1403    {
1404    public:
1405
1406        CommandOptions (CommandInterpreter &interpreter) :
1407        Options (interpreter)
1408        {
1409        }
1410
1411        virtual
1412        ~CommandOptions (){}
1413
1414        virtual Error
1415        SetOptionValue (uint32_t option_idx, const char *option_arg)
1416        {
1417            Error error;
1418            char short_option = (char) m_getopt_table[option_idx].val;
1419
1420            switch (short_option)
1421            {
1422                case 'w':
1423                    m_category_regex = std::string(option_arg);
1424                    break;
1425                default:
1426                    error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1427                    break;
1428            }
1429
1430            return error;
1431        }
1432
1433        void
1434        OptionParsingStarting ()
1435        {
1436            m_category_regex = "";
1437        }
1438
1439        const OptionDefinition*
1440        GetDefinitions ()
1441        {
1442            return g_option_table;
1443        }
1444
1445        // Options table: Required for subclasses of Options.
1446
1447        static OptionDefinition g_option_table[];
1448
1449        // Instance variables to hold the values for command options.
1450
1451        std::string m_category_regex;
1452
1453    };
1454
1455    CommandOptions m_options;
1456
1457    virtual Options *
1458    GetOptions ()
1459    {
1460        return &m_options;
1461    }
1462
1463public:
1464    CommandObjectTypeSummaryList (CommandInterpreter &interpreter) :
1465    CommandObject (interpreter,
1466                   "type summary list",
1467                   "Show a list of current summary styles.",
1468                   NULL), m_options(interpreter)
1469    {
1470        CommandArgumentEntry type_arg;
1471        CommandArgumentData type_style_arg;
1472
1473        type_style_arg.arg_type = eArgTypeName;
1474        type_style_arg.arg_repetition = eArgRepeatOptional;
1475
1476        type_arg.push_back (type_style_arg);
1477
1478        m_arguments.push_back (type_arg);
1479    }
1480
1481    ~CommandObjectTypeSummaryList ()
1482    {
1483    }
1484
1485    bool
1486    Execute (Args& command, CommandReturnObject &result)
1487    {
1488        const size_t argc = command.GetArgumentCount();
1489
1490        CommandObjectTypeSummaryList_LoopCallbackParam *param;
1491        RegularExpression* cate_regex =
1492        m_options.m_category_regex.empty() ? NULL :
1493        new RegularExpression(m_options.m_category_regex.c_str());
1494
1495        if (argc == 1) {
1496            RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
1497            regex->Compile(command.GetArgumentAtIndex(0));
1498            param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex,cate_regex);
1499        }
1500        else
1501            param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,NULL,cate_regex);
1502
1503        Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback,param);
1504
1505        if (Debugger::Formatting::NamedSummaryFormats::GetCount() > 0)
1506        {
1507            result.GetOutputStream().Printf("Named summaries:\n");
1508            if (argc == 1) {
1509                RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
1510                regex->Compile(command.GetArgumentAtIndex(0));
1511                param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex);
1512            }
1513            else
1514                param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result);
1515            Debugger::Formatting::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
1516            delete param;
1517        }
1518
1519        if (cate_regex)
1520            delete cate_regex;
1521
1522        result.SetStatus(eReturnStatusSuccessFinishResult);
1523        return result.Succeeded();
1524    }
1525
1526private:
1527
1528    static bool
1529    PerCategoryCallback(void* param_vp,
1530                        const char* cate_name,
1531                        const FormatCategory::SharedPointer& cate)
1532    {
1533
1534        CommandObjectTypeSummaryList_LoopCallbackParam* param =
1535            (CommandObjectTypeSummaryList_LoopCallbackParam*)param_vp;
1536        CommandReturnObject* result = param->result;
1537
1538        // if the category is disabled or empty and there is no regex, just skip it
1539        if ((cate->IsEnabled() == false || cate->GetCount() == 0) && param->cate_regex == NULL)
1540            return true;
1541
1542        // if we have a regex and this category does not match it, just skip it
1543        if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false)
1544            return true;
1545
1546        result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
1547                                         cate_name,
1548                                         (cate->IsEnabled() ? "enabled" : "disabled"));
1549
1550        cate->Summary()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param_vp);
1551
1552        if (cate->RegexSummary()->GetCount() > 0)
1553        {
1554            result->GetOutputStream().Printf("Regex-based summaries (slower):\n");
1555            cate->RegexSummary()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param_vp);
1556        }
1557        return true;
1558    }
1559
1560    bool
1561    LoopCallback (const char* type,
1562                  const SummaryFormat::SharedPointer& entry,
1563                  RegularExpression* regex,
1564                  CommandReturnObject *result)
1565    {
1566        if (regex == NULL || regex->Execute(type))
1567                result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
1568        return true;
1569    }
1570
1571    friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const SummaryFormat::SharedPointer& entry);
1572    friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SummaryFormat::SharedPointer& entry);
1573};
1574
1575bool
1576CommandObjectTypeSummaryList_LoopCallback (
1577                                          void* pt2self,
1578                                          const char* type,
1579                                          const SummaryFormat::SharedPointer& entry)
1580{
1581    CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
1582    return param->self->LoopCallback(type, entry, param->regex, param->result);
1583}
1584
1585bool
1586CommandObjectTypeRXSummaryList_LoopCallback (
1587                                           void* pt2self,
1588                                           lldb::RegularExpressionSP regex,
1589                                           const SummaryFormat::SharedPointer& entry)
1590{
1591    CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
1592    return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
1593}
1594
1595OptionDefinition
1596CommandObjectTypeSummaryList::CommandOptions::g_option_table[] =
1597{
1598    { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
1599    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1600};
1601
1602//-------------------------------------------------------------------------
1603// CommandObjectTypeCategoryEnable
1604//-------------------------------------------------------------------------
1605
1606class CommandObjectTypeCategoryEnable : public CommandObject
1607{
1608public:
1609    CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) :
1610    CommandObject (interpreter,
1611                   "type category enable",
1612                   "Enable a category as a source of summaries.",
1613                   NULL)
1614    {
1615        CommandArgumentEntry type_arg;
1616        CommandArgumentData type_style_arg;
1617
1618        type_style_arg.arg_type = eArgTypeName;
1619        type_style_arg.arg_repetition = eArgRepeatPlus;
1620
1621        type_arg.push_back (type_style_arg);
1622
1623        m_arguments.push_back (type_arg);
1624
1625    }
1626
1627    ~CommandObjectTypeCategoryEnable ()
1628    {
1629    }
1630
1631    bool
1632    Execute (Args& command, CommandReturnObject &result)
1633    {
1634        const size_t argc = command.GetArgumentCount();
1635
1636        if (argc < 1)
1637        {
1638            result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
1639            result.SetStatus(eReturnStatusFailed);
1640            return false;
1641        }
1642
1643        for (int i = argc - 1; i >= 0; i--)
1644        {
1645            const char* typeA = command.GetArgumentAtIndex(i);
1646            ConstString typeCS(typeA);
1647
1648            if (!typeCS)
1649            {
1650                result.AppendError("empty category name not allowed");
1651                result.SetStatus(eReturnStatusFailed);
1652                return false;
1653            }
1654            Debugger::Formatting::Categories::Enable(typeCS);
1655        }
1656
1657        result.SetStatus(eReturnStatusSuccessFinishResult);
1658        return result.Succeeded();
1659    }
1660
1661};
1662
1663//-------------------------------------------------------------------------
1664// CommandObjectTypeCategoryDelete
1665//-------------------------------------------------------------------------
1666
1667class CommandObjectTypeCategoryDelete : public CommandObject
1668{
1669public:
1670    CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) :
1671    CommandObject (interpreter,
1672                   "type category delete",
1673                   "Delete a category and all associated summaries.",
1674                   NULL)
1675    {
1676        CommandArgumentEntry type_arg;
1677        CommandArgumentData type_style_arg;
1678
1679        type_style_arg.arg_type = eArgTypeName;
1680        type_style_arg.arg_repetition = eArgRepeatPlus;
1681
1682        type_arg.push_back (type_style_arg);
1683
1684        m_arguments.push_back (type_arg);
1685
1686    }
1687
1688    ~CommandObjectTypeCategoryDelete ()
1689    {
1690    }
1691
1692    bool
1693    Execute (Args& command, CommandReturnObject &result)
1694    {
1695        const size_t argc = command.GetArgumentCount();
1696
1697        if (argc < 1)
1698        {
1699            result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str());
1700            result.SetStatus(eReturnStatusFailed);
1701            return false;
1702        }
1703
1704        bool success = true;
1705
1706        // the order is not relevant here
1707        for (int i = argc - 1; i >= 0; i--)
1708        {
1709            const char* typeA = command.GetArgumentAtIndex(i);
1710            ConstString typeCS(typeA);
1711
1712            if (!typeCS)
1713            {
1714                result.AppendError("empty category name not allowed");
1715                result.SetStatus(eReturnStatusFailed);
1716                return false;
1717            }
1718            if (!Debugger::Formatting::Categories::Delete(typeCS))
1719                success = false; // keep deleting even if we hit an error
1720        }
1721        if (success)
1722        {
1723            result.SetStatus(eReturnStatusSuccessFinishResult);
1724            return result.Succeeded();
1725        }
1726        else
1727        {
1728            result.AppendError("cannot delete one or more categories\n");
1729            result.SetStatus(eReturnStatusFailed);
1730            return false;
1731        }
1732    }
1733};
1734
1735//-------------------------------------------------------------------------
1736// CommandObjectTypeCategoryDisable
1737//-------------------------------------------------------------------------
1738
1739class CommandObjectTypeCategoryDisable : public CommandObject
1740{
1741public:
1742    CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) :
1743    CommandObject (interpreter,
1744                   "type category disable",
1745                   "Disable a category as a source of summaries.",
1746                   NULL)
1747    {
1748        CommandArgumentEntry type_arg;
1749        CommandArgumentData type_style_arg;
1750
1751        type_style_arg.arg_type = eArgTypeName;
1752        type_style_arg.arg_repetition = eArgRepeatPlus;
1753
1754        type_arg.push_back (type_style_arg);
1755
1756        m_arguments.push_back (type_arg);
1757
1758    }
1759
1760    ~CommandObjectTypeCategoryDisable ()
1761    {
1762    }
1763
1764    bool
1765    Execute (Args& command, CommandReturnObject &result)
1766    {
1767        const size_t argc = command.GetArgumentCount();
1768
1769        if (argc < 1)
1770        {
1771            result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
1772            result.SetStatus(eReturnStatusFailed);
1773            return false;
1774        }
1775
1776        // the order is not relevant here
1777        for (int i = argc - 1; i >= 0; i--)
1778        {
1779            const char* typeA = command.GetArgumentAtIndex(i);
1780            ConstString typeCS(typeA);
1781
1782            if (!typeCS)
1783            {
1784                result.AppendError("empty category name not allowed");
1785                result.SetStatus(eReturnStatusFailed);
1786                return false;
1787            }
1788            Debugger::Formatting::Categories::Disable(typeCS);
1789        }
1790
1791        result.SetStatus(eReturnStatusSuccessFinishResult);
1792        return result.Succeeded();
1793    }
1794
1795};
1796
1797//-------------------------------------------------------------------------
1798// CommandObjectTypeCategoryList
1799//-------------------------------------------------------------------------
1800
1801class CommandObjectTypeCategoryList : public CommandObject
1802{
1803private:
1804
1805    struct CommandObjectTypeCategoryList_CallbackParam
1806    {
1807        CommandReturnObject* result;
1808        RegularExpression* regex;
1809
1810        CommandObjectTypeCategoryList_CallbackParam(CommandReturnObject* res,
1811                                                    RegularExpression* rex = NULL) :
1812        result(res),
1813        regex(rex)
1814        {
1815        }
1816
1817    };
1818
1819    static bool
1820    PerCategoryCallback(void* param_vp,
1821                        const char* cate_name,
1822                        const FormatCategory::SharedPointer& cate)
1823    {
1824        CommandObjectTypeCategoryList_CallbackParam* param =
1825            (CommandObjectTypeCategoryList_CallbackParam*)param_vp;
1826        CommandReturnObject* result = param->result;
1827        RegularExpression* regex = param->regex;
1828
1829        if (regex == NULL || regex->Execute(cate_name))
1830            result->GetOutputStream().Printf("Category %s is%s enabled\n",
1831                                       cate_name,
1832                                       (cate->IsEnabled() ? "" : " not"));
1833        return true;
1834    }
1835public:
1836    CommandObjectTypeCategoryList (CommandInterpreter &interpreter) :
1837    CommandObject (interpreter,
1838                   "type category list",
1839                   "Provide a list of all existing categories.",
1840                   NULL)
1841    {
1842        CommandArgumentEntry type_arg;
1843        CommandArgumentData type_style_arg;
1844
1845        type_style_arg.arg_type = eArgTypeName;
1846        type_style_arg.arg_repetition = eArgRepeatOptional;
1847
1848        type_arg.push_back (type_style_arg);
1849
1850        m_arguments.push_back (type_arg);
1851    }
1852
1853    ~CommandObjectTypeCategoryList ()
1854    {
1855    }
1856
1857    bool
1858    Execute (Args& command, CommandReturnObject &result)
1859    {
1860        const size_t argc = command.GetArgumentCount();
1861        RegularExpression* regex = NULL;
1862
1863        if (argc == 0)
1864            ;
1865        else if (argc == 1)
1866            regex = new RegularExpression(command.GetArgumentAtIndex(0));
1867        else
1868        {
1869            result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str());
1870            result.SetStatus(eReturnStatusFailed);
1871            return false;
1872        }
1873
1874        CommandObjectTypeCategoryList_CallbackParam param(&result,
1875                                                          regex);
1876
1877        Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, &param);
1878
1879        if (regex)
1880            delete regex;
1881
1882        result.SetStatus(eReturnStatusSuccessFinishResult);
1883        return result.Succeeded();
1884    }
1885
1886};
1887
1888class CommandObjectTypeFormat : public CommandObjectMultiword
1889{
1890public:
1891    CommandObjectTypeFormat (CommandInterpreter &interpreter) :
1892        CommandObjectMultiword (interpreter,
1893                                "type format",
1894                                "A set of commands for editing variable value display options",
1895                                "type format [<sub-command-options>] ")
1896    {
1897        LoadSubCommand ("add",    CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter)));
1898        LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectTypeFormatClear (interpreter)));
1899        LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter)));
1900        LoadSubCommand ("list",   CommandObjectSP (new CommandObjectTypeFormatList (interpreter)));
1901    }
1902
1903
1904    ~CommandObjectTypeFormat ()
1905    {
1906    }
1907};
1908
1909class CommandObjectTypeCategory : public CommandObjectMultiword
1910{
1911public:
1912    CommandObjectTypeCategory (CommandInterpreter &interpreter) :
1913    CommandObjectMultiword (interpreter,
1914                            "type category",
1915                            "A set of commands for operating on categories",
1916                            "type category [<sub-command-options>] ")
1917    {
1918        LoadSubCommand ("enable",        CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter)));
1919        LoadSubCommand ("disable",       CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter)));
1920        LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter)));
1921        LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeCategoryList (interpreter)));
1922    }
1923
1924
1925    ~CommandObjectTypeCategory ()
1926    {
1927    }
1928};
1929
1930class CommandObjectTypeSummary : public CommandObjectMultiword
1931{
1932public:
1933    CommandObjectTypeSummary (CommandInterpreter &interpreter) :
1934    CommandObjectMultiword (interpreter,
1935                            "type summary",
1936                            "A set of commands for editing variable summary display options",
1937                            "type summary [<sub-command-options>] ")
1938    {
1939        LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter)));
1940        LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));
1941        LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));
1942        LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSummaryList (interpreter)));
1943    }
1944
1945
1946    ~CommandObjectTypeSummary ()
1947    {
1948    }
1949};
1950
1951//-------------------------------------------------------------------------
1952// CommandObjectType
1953//-------------------------------------------------------------------------
1954
1955CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) :
1956    CommandObjectMultiword (interpreter,
1957                            "type",
1958                            "A set of commands for operating on the type system",
1959                            "type [<sub-command-options>]")
1960{
1961    LoadSubCommand ("category",  CommandObjectSP (new CommandObjectTypeCategory (interpreter)));
1962    LoadSubCommand ("format",    CommandObjectSP (new CommandObjectTypeFormat (interpreter)));
1963    LoadSubCommand ("summary",   CommandObjectSP (new CommandObjectTypeSummary (interpreter)));
1964}
1965
1966
1967CommandObjectType::~CommandObjectType ()
1968{
1969}
1970
1971
1972