CommandObjectType.cpp revision 2bc9eb3ba78efc64a273729b480bafc3bbaa433a
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    CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R,
1394                                                  RegularExpression* X = NULL) : self(S), result(R), regex(X) {}
1395};
1396
1397class CommandObjectTypeSummaryList : public CommandObject
1398{
1399public:
1400    CommandObjectTypeSummaryList (CommandInterpreter &interpreter) :
1401    CommandObject (interpreter,
1402                   "type summary list",
1403                   "Show a list of current summary styles.",
1404                   NULL)
1405    {
1406        CommandArgumentEntry type_arg;
1407        CommandArgumentData type_style_arg;
1408
1409        type_style_arg.arg_type = eArgTypeName;
1410        type_style_arg.arg_repetition = eArgRepeatOptional;
1411
1412        type_arg.push_back (type_style_arg);
1413
1414        m_arguments.push_back (type_arg);
1415    }
1416
1417    ~CommandObjectTypeSummaryList ()
1418    {
1419    }
1420
1421    bool
1422    Execute (Args& command, CommandReturnObject &result)
1423    {
1424        const size_t argc = command.GetArgumentCount();
1425
1426        CommandObjectTypeSummaryList_LoopCallbackParam *param;
1427
1428        if (argc == 1) {
1429            RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
1430            regex->Compile(command.GetArgumentAtIndex(0));
1431            param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex);
1432        }
1433        else
1434            param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result);
1435
1436        Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback,param);
1437
1438        if (Debugger::Formatting::NamedSummaryFormats::GetCount() > 0)
1439        {
1440            result.GetOutputStream().Printf("Named summaries:\n");
1441            if (argc == 1) {
1442                RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
1443                regex->Compile(command.GetArgumentAtIndex(0));
1444                param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex);
1445            }
1446            else
1447                param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result);
1448            Debugger::Formatting::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
1449            delete param;
1450        }
1451
1452        result.SetStatus(eReturnStatusSuccessFinishResult);
1453        return result.Succeeded();
1454    }
1455
1456private:
1457
1458    static bool
1459    PerCategoryCallback(void* param,
1460                        const char* cate_name,
1461                        const FormatCategory::SharedPointer& cate)
1462    {
1463
1464        CommandReturnObject* result = ((CommandObjectTypeSummaryList_LoopCallbackParam*)param)->result;
1465
1466        result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
1467                                         cate_name,
1468                                         (cate->IsEnabled() ? "enabled" : "disabled"));
1469
1470        cate->Summary()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
1471
1472        if (cate->RegexSummary()->GetCount() > 0)
1473        {
1474            result->GetOutputStream().Printf("Regex-based summaries (slower):\n");
1475            cate->RegexSummary()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param);
1476        }
1477        return true;
1478    }
1479
1480    bool
1481    LoopCallback (const char* type,
1482                  const SummaryFormat::SharedPointer& entry,
1483                  RegularExpression* regex,
1484                  CommandReturnObject *result)
1485    {
1486        if (regex == NULL || regex->Execute(type))
1487                result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
1488        return true;
1489    }
1490
1491    friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const SummaryFormat::SharedPointer& entry);
1492    friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SummaryFormat::SharedPointer& entry);
1493};
1494
1495bool
1496CommandObjectTypeSummaryList_LoopCallback (
1497                                          void* pt2self,
1498                                          const char* type,
1499                                          const SummaryFormat::SharedPointer& entry)
1500{
1501    CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
1502    return param->self->LoopCallback(type, entry, param->regex, param->result);
1503}
1504
1505bool
1506CommandObjectTypeRXSummaryList_LoopCallback (
1507                                           void* pt2self,
1508                                           lldb::RegularExpressionSP regex,
1509                                           const SummaryFormat::SharedPointer& entry)
1510{
1511    CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
1512    return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
1513}
1514
1515//-------------------------------------------------------------------------
1516// CommandObjectTypeCategoryEnable
1517//-------------------------------------------------------------------------
1518
1519class CommandObjectTypeCategoryEnable : public CommandObject
1520{
1521public:
1522    CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) :
1523    CommandObject (interpreter,
1524                   "type category enable",
1525                   "Enable a category as a source of summaries.",
1526                   NULL)
1527    {
1528        CommandArgumentEntry type_arg;
1529        CommandArgumentData type_style_arg;
1530
1531        type_style_arg.arg_type = eArgTypeName;
1532        type_style_arg.arg_repetition = eArgRepeatPlus;
1533
1534        type_arg.push_back (type_style_arg);
1535
1536        m_arguments.push_back (type_arg);
1537
1538    }
1539
1540    ~CommandObjectTypeCategoryEnable ()
1541    {
1542    }
1543
1544    bool
1545    Execute (Args& command, CommandReturnObject &result)
1546    {
1547        const size_t argc = command.GetArgumentCount();
1548
1549        if (argc < 1)
1550        {
1551            result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
1552            result.SetStatus(eReturnStatusFailed);
1553            return false;
1554        }
1555
1556        for (int i = argc - 1; i >= 0; i--)
1557        {
1558            const char* typeA = command.GetArgumentAtIndex(i);
1559            ConstString typeCS(typeA);
1560
1561            if (!typeCS)
1562            {
1563                result.AppendError("empty category name not allowed");
1564                result.SetStatus(eReturnStatusFailed);
1565                return false;
1566            }
1567            Debugger::Formatting::Categories::Enable(typeCS);
1568        }
1569
1570        result.SetStatus(eReturnStatusSuccessFinishResult);
1571        return result.Succeeded();
1572    }
1573
1574};
1575
1576//-------------------------------------------------------------------------
1577// CommandObjectTypeCategoryDelete
1578//-------------------------------------------------------------------------
1579
1580class CommandObjectTypeCategoryDelete : public CommandObject
1581{
1582public:
1583    CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) :
1584    CommandObject (interpreter,
1585                   "type category delete",
1586                   "Delete a category and all associated summaries.",
1587                   NULL)
1588    {
1589        CommandArgumentEntry type_arg;
1590        CommandArgumentData type_style_arg;
1591
1592        type_style_arg.arg_type = eArgTypeName;
1593        type_style_arg.arg_repetition = eArgRepeatPlus;
1594
1595        type_arg.push_back (type_style_arg);
1596
1597        m_arguments.push_back (type_arg);
1598
1599    }
1600
1601    ~CommandObjectTypeCategoryDelete ()
1602    {
1603    }
1604
1605    bool
1606    Execute (Args& command, CommandReturnObject &result)
1607    {
1608        const size_t argc = command.GetArgumentCount();
1609
1610        if (argc < 1)
1611        {
1612            result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str());
1613            result.SetStatus(eReturnStatusFailed);
1614            return false;
1615        }
1616
1617        bool success = true;
1618
1619        // the order is not relevant here
1620        for (int i = argc - 1; i >= 0; i--)
1621        {
1622            const char* typeA = command.GetArgumentAtIndex(i);
1623            ConstString typeCS(typeA);
1624
1625            if (!typeCS)
1626            {
1627                result.AppendError("empty category name not allowed");
1628                result.SetStatus(eReturnStatusFailed);
1629                return false;
1630            }
1631            if (!Debugger::Formatting::Categories::Delete(typeCS))
1632                success = false; // keep deleting even if we hit an error
1633        }
1634        if (success)
1635        {
1636            result.SetStatus(eReturnStatusSuccessFinishResult);
1637            return result.Succeeded();
1638        }
1639        else
1640        {
1641            result.AppendError("cannot delete one or more categories\n");
1642            result.SetStatus(eReturnStatusFailed);
1643            return false;
1644        }
1645    }
1646};
1647
1648//-------------------------------------------------------------------------
1649// CommandObjectTypeCategoryDisable
1650//-------------------------------------------------------------------------
1651
1652class CommandObjectTypeCategoryDisable : public CommandObject
1653{
1654public:
1655    CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) :
1656    CommandObject (interpreter,
1657                   "type category disable",
1658                   "Disable a category as a source of summaries.",
1659                   NULL)
1660    {
1661        CommandArgumentEntry type_arg;
1662        CommandArgumentData type_style_arg;
1663
1664        type_style_arg.arg_type = eArgTypeName;
1665        type_style_arg.arg_repetition = eArgRepeatPlus;
1666
1667        type_arg.push_back (type_style_arg);
1668
1669        m_arguments.push_back (type_arg);
1670
1671    }
1672
1673    ~CommandObjectTypeCategoryDisable ()
1674    {
1675    }
1676
1677    bool
1678    Execute (Args& command, CommandReturnObject &result)
1679    {
1680        const size_t argc = command.GetArgumentCount();
1681
1682        if (argc < 1)
1683        {
1684            result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
1685            result.SetStatus(eReturnStatusFailed);
1686            return false;
1687        }
1688
1689        // the order is not relevant here
1690        for (int i = argc - 1; i >= 0; i--)
1691        {
1692            const char* typeA = command.GetArgumentAtIndex(i);
1693            ConstString typeCS(typeA);
1694
1695            if (!typeCS)
1696            {
1697                result.AppendError("empty category name not allowed");
1698                result.SetStatus(eReturnStatusFailed);
1699                return false;
1700            }
1701            Debugger::Formatting::Categories::Disable(typeCS);
1702        }
1703
1704        result.SetStatus(eReturnStatusSuccessFinishResult);
1705        return result.Succeeded();
1706    }
1707
1708};
1709
1710//-------------------------------------------------------------------------
1711// CommandObjectTypeCategoryList
1712//-------------------------------------------------------------------------
1713
1714class CommandObjectTypeCategoryList : public CommandObject
1715{
1716private:
1717    static bool
1718    PerCategoryCallback(void* param,
1719                        const char* cate_name,
1720                        const FormatCategory::SharedPointer& cate)
1721    {
1722        CommandReturnObject* result = (CommandReturnObject*)param;
1723        result->GetOutputStream().Printf("Category %s is%s enabled\n",
1724                                       cate_name,
1725                                       (cate->IsEnabled() ? "" : " not"));
1726        return true;
1727    }
1728public:
1729    CommandObjectTypeCategoryList (CommandInterpreter &interpreter) :
1730    CommandObject (interpreter,
1731                   "type category list",
1732                   "Provide a list of all existing categories.",
1733                   NULL)
1734    {
1735    }
1736
1737    ~CommandObjectTypeCategoryList ()
1738    {
1739    }
1740
1741    bool
1742    Execute (Args& command, CommandReturnObject &result)
1743    {
1744        Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, (void*)&result);
1745        result.SetStatus(eReturnStatusSuccessFinishResult);
1746        return result.Succeeded();
1747    }
1748
1749};
1750
1751class CommandObjectTypeFormat : public CommandObjectMultiword
1752{
1753public:
1754    CommandObjectTypeFormat (CommandInterpreter &interpreter) :
1755        CommandObjectMultiword (interpreter,
1756                                "type format",
1757                                "A set of commands for editing variable value display options",
1758                                "type format [<sub-command-options>] ")
1759    {
1760        LoadSubCommand ("add",    CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter)));
1761        LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectTypeFormatClear (interpreter)));
1762        LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter)));
1763        LoadSubCommand ("list",   CommandObjectSP (new CommandObjectTypeFormatList (interpreter)));
1764    }
1765
1766
1767    ~CommandObjectTypeFormat ()
1768    {
1769    }
1770};
1771
1772class CommandObjectTypeCategory : public CommandObjectMultiword
1773{
1774public:
1775    CommandObjectTypeCategory (CommandInterpreter &interpreter) :
1776    CommandObjectMultiword (interpreter,
1777                            "type category",
1778                            "A set of commands for operating on categories",
1779                            "type category [<sub-command-options>] ")
1780    {
1781        LoadSubCommand ("enable",        CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter)));
1782        LoadSubCommand ("disable",       CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter)));
1783        LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter)));
1784        LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeCategoryList (interpreter)));
1785    }
1786
1787
1788    ~CommandObjectTypeCategory ()
1789    {
1790    }
1791};
1792
1793class CommandObjectTypeSummary : public CommandObjectMultiword
1794{
1795public:
1796    CommandObjectTypeSummary (CommandInterpreter &interpreter) :
1797    CommandObjectMultiword (interpreter,
1798                            "type summary",
1799                            "A set of commands for editing variable summary display options",
1800                            "type summary [<sub-command-options>] ")
1801    {
1802        LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter)));
1803        LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));
1804        LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));
1805        LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSummaryList (interpreter)));
1806    }
1807
1808
1809    ~CommandObjectTypeSummary ()
1810    {
1811    }
1812};
1813
1814//-------------------------------------------------------------------------
1815// CommandObjectType
1816//-------------------------------------------------------------------------
1817
1818CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) :
1819    CommandObjectMultiword (interpreter,
1820                            "type",
1821                            "A set of commands for operating on the type system",
1822                            "type [<sub-command-options>]")
1823{
1824    LoadSubCommand ("category",  CommandObjectSP (new CommandObjectTypeCategory (interpreter)));
1825    LoadSubCommand ("format",    CommandObjectSP (new CommandObjectTypeFormat (interpreter)));
1826    LoadSubCommand ("summary",   CommandObjectSP (new CommandObjectTypeSummary (interpreter)));
1827}
1828
1829
1830CommandObjectType::~CommandObjectType ()
1831{
1832}
1833
1834
1835