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