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