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,internal_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,internal_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         if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)
1960         {
1961             // we want to make sure to enable "system" last and "default" first
1962             DataVisualization::Categories::Enable(ConstString("default"), CategoryMap::First);
1963             uint32_t num_categories = DataVisualization::Categories::GetCount();
1964             for (uint32_t i = 0; i < num_categories; i++)
1965             {
1966                 lldb::TypeCategoryImplSP category_sp = DataVisualization::Categories::GetCategoryAtIndex(i);
1967                 if (category_sp)
1968                 {
1969                     if ( ::strcmp(category_sp->GetName(), "system") == 0 ||
1970                          ::strcmp(category_sp->GetName(), "default") == 0 )
1971                         continue;
1972                     else
1973                         DataVisualization::Categories::Enable(category_sp, CategoryMap::Default);
1974                 }
1975             }
1976             DataVisualization::Categories::Enable(ConstString("system"), CategoryMap::Last);
1977         }
1978         else
1979         {
1980             for (int i = argc - 1; i >= 0; i--)
1981             {
1982                 const char* typeA = command.GetArgumentAtIndex(i);
1983                 ConstString typeCS(typeA);
1984 
1985                 if (!typeCS)
1986                 {
1987                     result.AppendError("empty category name not allowed");
1988                     result.SetStatus(eReturnStatusFailed);
1989                     return false;
1990                 }
1991                 DataVisualization::Categories::Enable(typeCS);
1992                 lldb::TypeCategoryImplSP cate;
1993                 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate.get())
1994                 {
1995                     if (cate->GetCount() == 0)
1996                     {
1997                         result.AppendWarning("empty category enabled (typo?)");
1998                     }
1999                 }
2000             }
2001         }
2002 
2003         result.SetStatus(eReturnStatusSuccessFinishResult);
2004         return result.Succeeded();
2005     }
2006 
2007 };
2008 
2009 //-------------------------------------------------------------------------
2010 // CommandObjectTypeCategoryDelete
2011 //-------------------------------------------------------------------------
2012 
2013 class CommandObjectTypeCategoryDelete : public CommandObjectParsed
2014 {
2015 public:
2016     CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) :
2017         CommandObjectParsed (interpreter,
2018                              "type category delete",
2019                              "Delete a category and all associated formatters.",
2020                              NULL)
2021     {
2022         CommandArgumentEntry type_arg;
2023         CommandArgumentData type_style_arg;
2024 
2025         type_style_arg.arg_type = eArgTypeName;
2026         type_style_arg.arg_repetition = eArgRepeatPlus;
2027 
2028         type_arg.push_back (type_style_arg);
2029 
2030         m_arguments.push_back (type_arg);
2031 
2032     }
2033 
2034     ~CommandObjectTypeCategoryDelete ()
2035     {
2036     }
2037 
2038 protected:
2039     bool
2040     DoExecute (Args& command, CommandReturnObject &result)
2041     {
2042         const size_t argc = command.GetArgumentCount();
2043 
2044         if (argc < 1)
2045         {
2046             result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str());
2047             result.SetStatus(eReturnStatusFailed);
2048             return false;
2049         }
2050 
2051         bool success = true;
2052 
2053         // the order is not relevant here
2054         for (int i = argc - 1; i >= 0; i--)
2055         {
2056             const char* typeA = command.GetArgumentAtIndex(i);
2057             ConstString typeCS(typeA);
2058 
2059             if (!typeCS)
2060             {
2061                 result.AppendError("empty category name not allowed");
2062                 result.SetStatus(eReturnStatusFailed);
2063                 return false;
2064             }
2065             if (!DataVisualization::Categories::Delete(typeCS))
2066                 success = false; // keep deleting even if we hit an error
2067         }
2068         if (success)
2069         {
2070             result.SetStatus(eReturnStatusSuccessFinishResult);
2071             return result.Succeeded();
2072         }
2073         else
2074         {
2075             result.AppendError("cannot delete one or more categories\n");
2076             result.SetStatus(eReturnStatusFailed);
2077             return false;
2078         }
2079     }
2080 };
2081 
2082 //-------------------------------------------------------------------------
2083 // CommandObjectTypeCategoryDisable
2084 //-------------------------------------------------------------------------
2085 
2086 class CommandObjectTypeCategoryDisable : public CommandObjectParsed
2087 {
2088 public:
2089     CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) :
2090         CommandObjectParsed (interpreter,
2091                              "type category disable",
2092                              "Disable a category as a source of formatters.",
2093                              NULL)
2094     {
2095         CommandArgumentEntry type_arg;
2096         CommandArgumentData type_style_arg;
2097 
2098         type_style_arg.arg_type = eArgTypeName;
2099         type_style_arg.arg_repetition = eArgRepeatPlus;
2100 
2101         type_arg.push_back (type_style_arg);
2102 
2103         m_arguments.push_back (type_arg);
2104 
2105     }
2106 
2107     ~CommandObjectTypeCategoryDisable ()
2108     {
2109     }
2110 
2111 protected:
2112     bool
2113     DoExecute (Args& command, CommandReturnObject &result)
2114     {
2115         const size_t argc = command.GetArgumentCount();
2116 
2117         if (argc < 1)
2118         {
2119             result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
2120             result.SetStatus(eReturnStatusFailed);
2121             return false;
2122         }
2123 
2124         if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)
2125         {
2126             uint32_t num_categories = DataVisualization::Categories::GetCount();
2127             for (uint32_t i = 0; i < num_categories; i++)
2128             {
2129                 lldb::TypeCategoryImplSP category_sp = DataVisualization::Categories::GetCategoryAtIndex(i);
2130                 // no need to check if the category is enabled - disabling a disabled category has no effect
2131                 if (category_sp)
2132                     DataVisualization::Categories::Disable(category_sp);
2133             }
2134         }
2135         else
2136         {
2137             // the order is not relevant here
2138             for (int i = argc - 1; i >= 0; i--)
2139             {
2140                 const char* typeA = command.GetArgumentAtIndex(i);
2141                 ConstString typeCS(typeA);
2142 
2143                 if (!typeCS)
2144                 {
2145                     result.AppendError("empty category name not allowed");
2146                     result.SetStatus(eReturnStatusFailed);
2147                     return false;
2148                 }
2149                 DataVisualization::Categories::Disable(typeCS);
2150             }
2151         }
2152 
2153         result.SetStatus(eReturnStatusSuccessFinishResult);
2154         return result.Succeeded();
2155     }
2156 
2157 };
2158 
2159 //-------------------------------------------------------------------------
2160 // CommandObjectTypeCategoryList
2161 //-------------------------------------------------------------------------
2162 
2163 class CommandObjectTypeCategoryList : public CommandObjectParsed
2164 {
2165 private:
2166 
2167     struct CommandObjectTypeCategoryList_CallbackParam
2168     {
2169         CommandReturnObject* result;
2170         RegularExpression* regex;
2171 
2172         CommandObjectTypeCategoryList_CallbackParam(CommandReturnObject* res,
2173                                                     RegularExpression* rex = NULL) :
2174         result(res),
2175         regex(rex)
2176         {
2177         }
2178 
2179     };
2180 
2181     static bool
2182     PerCategoryCallback(void* param_vp,
2183                         const lldb::TypeCategoryImplSP& cate)
2184     {
2185         CommandObjectTypeCategoryList_CallbackParam* param =
2186             (CommandObjectTypeCategoryList_CallbackParam*)param_vp;
2187         CommandReturnObject* result = param->result;
2188         RegularExpression* regex = param->regex;
2189 
2190         const char* cate_name = cate->GetName();
2191 
2192         if (regex == NULL || regex->Execute(cate_name))
2193             result->GetOutputStream().Printf("Category %s is%s enabled\n",
2194                                        cate_name,
2195                                        (cate->IsEnabled() ? "" : " not"));
2196         return true;
2197     }
2198 public:
2199     CommandObjectTypeCategoryList (CommandInterpreter &interpreter) :
2200         CommandObjectParsed (interpreter,
2201                              "type category list",
2202                              "Provide a list of all existing categories.",
2203                              NULL)
2204     {
2205         CommandArgumentEntry type_arg;
2206         CommandArgumentData type_style_arg;
2207 
2208         type_style_arg.arg_type = eArgTypeName;
2209         type_style_arg.arg_repetition = eArgRepeatOptional;
2210 
2211         type_arg.push_back (type_style_arg);
2212 
2213         m_arguments.push_back (type_arg);
2214     }
2215 
2216     ~CommandObjectTypeCategoryList ()
2217     {
2218     }
2219 
2220 protected:
2221     bool
2222     DoExecute (Args& command, CommandReturnObject &result)
2223     {
2224         const size_t argc = command.GetArgumentCount();
2225         RegularExpression* regex = NULL;
2226 
2227         if (argc == 0)
2228             ;
2229         else if (argc == 1)
2230             regex = new RegularExpression(command.GetArgumentAtIndex(0));
2231         else
2232         {
2233             result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str());
2234             result.SetStatus(eReturnStatusFailed);
2235             return false;
2236         }
2237 
2238         CommandObjectTypeCategoryList_CallbackParam param(&result,
2239                                                           regex);
2240 
2241         DataVisualization::Categories::LoopThrough(PerCategoryCallback, &param);
2242 
2243         if (regex)
2244             delete regex;
2245 
2246         result.SetStatus(eReturnStatusSuccessFinishResult);
2247         return result.Succeeded();
2248     }
2249 
2250 };
2251 
2252 //-------------------------------------------------------------------------
2253 // CommandObjectTypeFilterList
2254 //-------------------------------------------------------------------------
2255 
2256 bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
2257 bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
2258 
2259 class CommandObjectTypeFilterList;
2260 
2261 struct CommandObjectTypeFilterList_LoopCallbackParam {
2262     CommandObjectTypeFilterList* self;
2263     CommandReturnObject* result;
2264     RegularExpression* regex;
2265     RegularExpression* cate_regex;
2266     CommandObjectTypeFilterList_LoopCallbackParam(CommandObjectTypeFilterList* S, CommandReturnObject* R,
2267                                                   RegularExpression* X = NULL,
2268                                                   RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
2269 };
2270 
2271 class CommandObjectTypeFilterList : public CommandObjectParsed
2272 {
2273 
2274     class CommandOptions : public Options
2275     {
2276     public:
2277 
2278         CommandOptions (CommandInterpreter &interpreter) :
2279         Options (interpreter)
2280         {
2281         }
2282 
2283         virtual
2284         ~CommandOptions (){}
2285 
2286         virtual Error
2287         SetOptionValue (uint32_t option_idx, const char *option_arg)
2288         {
2289             Error error;
2290             char short_option = (char) m_getopt_table[option_idx].val;
2291 
2292             switch (short_option)
2293             {
2294                 case 'w':
2295                     m_category_regex = std::string(option_arg);
2296                     break;
2297                 default:
2298                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2299                     break;
2300             }
2301 
2302             return error;
2303         }
2304 
2305         void
2306         OptionParsingStarting ()
2307         {
2308             m_category_regex = "";
2309         }
2310 
2311         const OptionDefinition*
2312         GetDefinitions ()
2313         {
2314             return g_option_table;
2315         }
2316 
2317         // Options table: Required for subclasses of Options.
2318 
2319         static OptionDefinition g_option_table[];
2320 
2321         // Instance variables to hold the values for command options.
2322 
2323         std::string m_category_regex;
2324 
2325     };
2326 
2327     CommandOptions m_options;
2328 
2329     virtual Options *
2330     GetOptions ()
2331     {
2332         return &m_options;
2333     }
2334 
2335 public:
2336     CommandObjectTypeFilterList (CommandInterpreter &interpreter) :
2337         CommandObjectParsed (interpreter,
2338                              "type filter list",
2339                              "Show a list of current filters.",
2340                              NULL),
2341         m_options(interpreter)
2342     {
2343         CommandArgumentEntry type_arg;
2344         CommandArgumentData type_style_arg;
2345 
2346         type_style_arg.arg_type = eArgTypeName;
2347         type_style_arg.arg_repetition = eArgRepeatOptional;
2348 
2349         type_arg.push_back (type_style_arg);
2350 
2351         m_arguments.push_back (type_arg);
2352     }
2353 
2354     ~CommandObjectTypeFilterList ()
2355     {
2356     }
2357 
2358 protected:
2359     bool
2360     DoExecute (Args& command, CommandReturnObject &result)
2361     {
2362         const size_t argc = command.GetArgumentCount();
2363 
2364         CommandObjectTypeFilterList_LoopCallbackParam *param;
2365         RegularExpression* cate_regex =
2366         m_options.m_category_regex.empty() ? NULL :
2367         new RegularExpression(m_options.m_category_regex.c_str());
2368 
2369         if (argc == 1)
2370         {
2371             RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
2372             regex->Compile(command.GetArgumentAtIndex(0));
2373             param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,regex,cate_regex);
2374         }
2375         else
2376             param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,NULL,cate_regex);
2377 
2378         DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
2379 
2380         if (cate_regex)
2381             delete cate_regex;
2382 
2383         result.SetStatus(eReturnStatusSuccessFinishResult);
2384         return result.Succeeded();
2385     }
2386 
2387 private:
2388 
2389     static bool
2390     PerCategoryCallback(void* param_vp,
2391                         const lldb::TypeCategoryImplSP& cate)
2392     {
2393 
2394         const char* cate_name = cate->GetName();
2395 
2396         CommandObjectTypeFilterList_LoopCallbackParam* param =
2397         (CommandObjectTypeFilterList_LoopCallbackParam*)param_vp;
2398         CommandReturnObject* result = param->result;
2399 
2400         // if the category is disabled or empty and there is no regex, just skip it
2401         if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter) == 0) && param->cate_regex == NULL)
2402             return true;
2403 
2404         // if we have a regex and this category does not match it, just skip it
2405         if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false)
2406             return true;
2407 
2408         result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
2409                                          cate_name,
2410                                          (cate->IsEnabled() ? "enabled" : "disabled"));
2411 
2412         cate->GetFilterNavigator()->LoopThrough(CommandObjectTypeFilterList_LoopCallback, param_vp);
2413 
2414         if (cate->GetRegexFilterNavigator()->GetCount() > 0)
2415         {
2416             result->GetOutputStream().Printf("Regex-based filters (slower):\n");
2417             cate->GetRegexFilterNavigator()->LoopThrough(CommandObjectTypeFilterRXList_LoopCallback, param_vp);
2418         }
2419 
2420         return true;
2421     }
2422 
2423     bool
2424     LoopCallback (const char* type,
2425                   const SyntheticChildren::SharedPointer& entry,
2426                   RegularExpression* regex,
2427                   CommandReturnObject *result)
2428     {
2429         if (regex == NULL || regex->Execute(type))
2430             result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
2431         return true;
2432     }
2433 
2434     friend bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
2435     friend bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
2436 };
2437 
2438 bool
2439 CommandObjectTypeFilterList_LoopCallback (void* pt2self,
2440                                          ConstString type,
2441                                          const SyntheticChildren::SharedPointer& entry)
2442 {
2443     CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self;
2444     return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
2445 }
2446 
2447 bool
2448 CommandObjectTypeFilterRXList_LoopCallback (void* pt2self,
2449                                            lldb::RegularExpressionSP regex,
2450                                            const SyntheticChildren::SharedPointer& entry)
2451 {
2452     CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self;
2453     return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
2454 }
2455 
2456 
2457 OptionDefinition
2458 CommandObjectTypeFilterList::CommandOptions::g_option_table[] =
2459 {
2460     { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
2461     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2462 };
2463 
2464 #ifndef LLDB_DISABLE_PYTHON
2465 
2466 //-------------------------------------------------------------------------
2467 // CommandObjectTypeSynthList
2468 //-------------------------------------------------------------------------
2469 
2470 bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
2471 bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
2472 
2473 class CommandObjectTypeSynthList;
2474 
2475 struct CommandObjectTypeSynthList_LoopCallbackParam {
2476     CommandObjectTypeSynthList* self;
2477     CommandReturnObject* result;
2478     RegularExpression* regex;
2479     RegularExpression* cate_regex;
2480     CommandObjectTypeSynthList_LoopCallbackParam(CommandObjectTypeSynthList* S, CommandReturnObject* R,
2481                                                  RegularExpression* X = NULL,
2482                                                  RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
2483 };
2484 
2485 class CommandObjectTypeSynthList : public CommandObjectParsed
2486 {
2487 
2488     class CommandOptions : public Options
2489     {
2490     public:
2491 
2492         CommandOptions (CommandInterpreter &interpreter) :
2493         Options (interpreter)
2494         {
2495         }
2496 
2497         virtual
2498         ~CommandOptions (){}
2499 
2500         virtual Error
2501         SetOptionValue (uint32_t option_idx, const char *option_arg)
2502         {
2503             Error error;
2504             char short_option = (char) m_getopt_table[option_idx].val;
2505 
2506             switch (short_option)
2507             {
2508                 case 'w':
2509                     m_category_regex = std::string(option_arg);
2510                     break;
2511                 default:
2512                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2513                     break;
2514             }
2515 
2516             return error;
2517         }
2518 
2519         void
2520         OptionParsingStarting ()
2521         {
2522             m_category_regex = "";
2523         }
2524 
2525         const OptionDefinition*
2526         GetDefinitions ()
2527         {
2528             return g_option_table;
2529         }
2530 
2531         // Options table: Required for subclasses of Options.
2532 
2533         static OptionDefinition g_option_table[];
2534 
2535         // Instance variables to hold the values for command options.
2536 
2537         std::string m_category_regex;
2538 
2539     };
2540 
2541     CommandOptions m_options;
2542 
2543     virtual Options *
2544     GetOptions ()
2545     {
2546         return &m_options;
2547     }
2548 
2549 public:
2550     CommandObjectTypeSynthList (CommandInterpreter &interpreter) :
2551         CommandObjectParsed (interpreter,
2552                              "type synthetic list",
2553                              "Show a list of current synthetic providers.",
2554                              NULL),
2555         m_options(interpreter)
2556     {
2557         CommandArgumentEntry type_arg;
2558         CommandArgumentData type_style_arg;
2559 
2560         type_style_arg.arg_type = eArgTypeName;
2561         type_style_arg.arg_repetition = eArgRepeatOptional;
2562 
2563         type_arg.push_back (type_style_arg);
2564 
2565         m_arguments.push_back (type_arg);
2566     }
2567 
2568     ~CommandObjectTypeSynthList ()
2569     {
2570     }
2571 
2572 protected:
2573     bool
2574     DoExecute (Args& command, CommandReturnObject &result)
2575     {
2576         const size_t argc = command.GetArgumentCount();
2577 
2578         CommandObjectTypeSynthList_LoopCallbackParam *param;
2579         RegularExpression* cate_regex =
2580         m_options.m_category_regex.empty() ? NULL :
2581         new RegularExpression(m_options.m_category_regex.c_str());
2582 
2583         if (argc == 1)
2584         {
2585             RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
2586             regex->Compile(command.GetArgumentAtIndex(0));
2587             param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,regex,cate_regex);
2588         }
2589         else
2590             param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,NULL,cate_regex);
2591 
2592         DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
2593 
2594         if (cate_regex)
2595             delete cate_regex;
2596 
2597         result.SetStatus(eReturnStatusSuccessFinishResult);
2598         return result.Succeeded();
2599     }
2600 
2601 private:
2602 
2603     static bool
2604     PerCategoryCallback(void* param_vp,
2605                         const lldb::TypeCategoryImplSP& cate)
2606     {
2607 
2608         CommandObjectTypeSynthList_LoopCallbackParam* param =
2609         (CommandObjectTypeSynthList_LoopCallbackParam*)param_vp;
2610         CommandReturnObject* result = param->result;
2611 
2612         const char* cate_name = cate->GetName();
2613 
2614         // if the category is disabled or empty and there is no regex, just skip it
2615         if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth) == 0) && param->cate_regex == NULL)
2616             return true;
2617 
2618         // if we have a regex and this category does not match it, just skip it
2619         if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false)
2620             return true;
2621 
2622         result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
2623                                          cate_name,
2624                                          (cate->IsEnabled() ? "enabled" : "disabled"));
2625 
2626         cate->GetSyntheticNavigator()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp);
2627 
2628         if (cate->GetRegexSyntheticNavigator()->GetCount() > 0)
2629         {
2630             result->GetOutputStream().Printf("Regex-based synthetic providers (slower):\n");
2631             cate->GetRegexSyntheticNavigator()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp);
2632         }
2633 
2634         return true;
2635     }
2636 
2637     bool
2638     LoopCallback (const char* type,
2639                   const SyntheticChildren::SharedPointer& entry,
2640                   RegularExpression* regex,
2641                   CommandReturnObject *result)
2642     {
2643         if (regex == NULL || regex->Execute(type))
2644             result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
2645         return true;
2646     }
2647 
2648     friend bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
2649     friend bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
2650 };
2651 
2652 bool
2653 CommandObjectTypeSynthList_LoopCallback (void* pt2self,
2654                                          ConstString type,
2655                                          const SyntheticChildren::SharedPointer& entry)
2656 {
2657     CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
2658     return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
2659 }
2660 
2661 bool
2662 CommandObjectTypeSynthRXList_LoopCallback (void* pt2self,
2663                                          lldb::RegularExpressionSP regex,
2664                                          const SyntheticChildren::SharedPointer& entry)
2665 {
2666     CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
2667     return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
2668 }
2669 
2670 
2671 OptionDefinition
2672 CommandObjectTypeSynthList::CommandOptions::g_option_table[] =
2673 {
2674     { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
2675     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2676 };
2677 
2678 #endif // #ifndef LLDB_DISABLE_PYTHON
2679 //-------------------------------------------------------------------------
2680 // CommandObjectTypeFilterDelete
2681 //-------------------------------------------------------------------------
2682 
2683 class CommandObjectTypeFilterDelete : public CommandObjectParsed
2684 {
2685 private:
2686     class CommandOptions : public Options
2687     {
2688     public:
2689 
2690         CommandOptions (CommandInterpreter &interpreter) :
2691         Options (interpreter)
2692         {
2693         }
2694 
2695         virtual
2696         ~CommandOptions (){}
2697 
2698         virtual Error
2699         SetOptionValue (uint32_t option_idx, const char *option_arg)
2700         {
2701             Error error;
2702             char short_option = (char) m_getopt_table[option_idx].val;
2703 
2704             switch (short_option)
2705             {
2706                 case 'a':
2707                     m_delete_all = true;
2708                     break;
2709                 case 'w':
2710                     m_category = std::string(option_arg);
2711                     break;
2712                 default:
2713                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2714                     break;
2715             }
2716 
2717             return error;
2718         }
2719 
2720         void
2721         OptionParsingStarting ()
2722         {
2723             m_delete_all = false;
2724             m_category = "default";
2725         }
2726 
2727         const OptionDefinition*
2728         GetDefinitions ()
2729         {
2730             return g_option_table;
2731         }
2732 
2733         // Options table: Required for subclasses of Options.
2734 
2735         static OptionDefinition g_option_table[];
2736 
2737         // Instance variables to hold the values for command options.
2738 
2739         bool m_delete_all;
2740         std::string m_category;
2741 
2742     };
2743 
2744     CommandOptions m_options;
2745 
2746     virtual Options *
2747     GetOptions ()
2748     {
2749         return &m_options;
2750     }
2751 
2752     static bool
2753     PerCategoryCallback(void* param,
2754                         const lldb::TypeCategoryImplSP& cate)
2755     {
2756         ConstString *name = (ConstString*)param;
2757         return cate->Delete(*name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter);
2758     }
2759 
2760 public:
2761     CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) :
2762         CommandObjectParsed (interpreter,
2763                              "type filter delete",
2764                              "Delete an existing filter for a type.",
2765                              NULL),
2766         m_options(interpreter)
2767     {
2768         CommandArgumentEntry type_arg;
2769         CommandArgumentData type_style_arg;
2770 
2771         type_style_arg.arg_type = eArgTypeName;
2772         type_style_arg.arg_repetition = eArgRepeatPlain;
2773 
2774         type_arg.push_back (type_style_arg);
2775 
2776         m_arguments.push_back (type_arg);
2777 
2778     }
2779 
2780     ~CommandObjectTypeFilterDelete ()
2781     {
2782     }
2783 
2784 protected:
2785     bool
2786     DoExecute (Args& command, CommandReturnObject &result)
2787     {
2788         const size_t argc = command.GetArgumentCount();
2789 
2790         if (argc != 1)
2791         {
2792             result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
2793             result.SetStatus(eReturnStatusFailed);
2794             return false;
2795         }
2796 
2797         const char* typeA = command.GetArgumentAtIndex(0);
2798         ConstString typeCS(typeA);
2799 
2800         if (!typeCS)
2801         {
2802             result.AppendError("empty typenames not allowed");
2803             result.SetStatus(eReturnStatusFailed);
2804             return false;
2805         }
2806 
2807         if (m_options.m_delete_all)
2808         {
2809             DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS);
2810             result.SetStatus(eReturnStatusSuccessFinishNoResult);
2811             return result.Succeeded();
2812         }
2813 
2814         lldb::TypeCategoryImplSP category;
2815         DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
2816 
2817         bool delete_category = category->GetFilterNavigator()->Delete(typeCS);
2818         delete_category = category->GetRegexFilterNavigator()->Delete(typeCS) || delete_category;
2819 
2820         if (delete_category)
2821         {
2822             result.SetStatus(eReturnStatusSuccessFinishNoResult);
2823             return result.Succeeded();
2824         }
2825         else
2826         {
2827             result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA);
2828             result.SetStatus(eReturnStatusFailed);
2829             return false;
2830         }
2831 
2832     }
2833 };
2834 
2835 OptionDefinition
2836 CommandObjectTypeFilterDelete::CommandOptions::g_option_table[] =
2837 {
2838     { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Delete from every category."},
2839     { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,  "Delete from given category."},
2840     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2841 };
2842 
2843 #ifndef LLDB_DISABLE_PYTHON
2844 
2845 //-------------------------------------------------------------------------
2846 // CommandObjectTypeSynthDelete
2847 //-------------------------------------------------------------------------
2848 
2849 class CommandObjectTypeSynthDelete : public CommandObjectParsed
2850 {
2851 private:
2852     class CommandOptions : public Options
2853     {
2854     public:
2855 
2856         CommandOptions (CommandInterpreter &interpreter) :
2857         Options (interpreter)
2858         {
2859         }
2860 
2861         virtual
2862         ~CommandOptions (){}
2863 
2864         virtual Error
2865         SetOptionValue (uint32_t option_idx, const char *option_arg)
2866         {
2867             Error error;
2868             char short_option = (char) m_getopt_table[option_idx].val;
2869 
2870             switch (short_option)
2871             {
2872                 case 'a':
2873                     m_delete_all = true;
2874                     break;
2875                 case 'w':
2876                     m_category = std::string(option_arg);
2877                     break;
2878                 default:
2879                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2880                     break;
2881             }
2882 
2883             return error;
2884         }
2885 
2886         void
2887         OptionParsingStarting ()
2888         {
2889             m_delete_all = false;
2890             m_category = "default";
2891         }
2892 
2893         const OptionDefinition*
2894         GetDefinitions ()
2895         {
2896             return g_option_table;
2897         }
2898 
2899         // Options table: Required for subclasses of Options.
2900 
2901         static OptionDefinition g_option_table[];
2902 
2903         // Instance variables to hold the values for command options.
2904 
2905         bool m_delete_all;
2906         std::string m_category;
2907 
2908     };
2909 
2910     CommandOptions m_options;
2911 
2912     virtual Options *
2913     GetOptions ()
2914     {
2915         return &m_options;
2916     }
2917 
2918     static bool
2919     PerCategoryCallback(void* param,
2920                         const lldb::TypeCategoryImplSP& cate)
2921     {
2922         ConstString* name = (ConstString*)param;
2923         return cate->Delete(*name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth);
2924     }
2925 
2926 public:
2927     CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) :
2928         CommandObjectParsed (interpreter,
2929                              "type synthetic delete",
2930                              "Delete an existing synthetic provider for a type.",
2931                              NULL),
2932         m_options(interpreter)
2933     {
2934         CommandArgumentEntry type_arg;
2935         CommandArgumentData type_style_arg;
2936 
2937         type_style_arg.arg_type = eArgTypeName;
2938         type_style_arg.arg_repetition = eArgRepeatPlain;
2939 
2940         type_arg.push_back (type_style_arg);
2941 
2942         m_arguments.push_back (type_arg);
2943 
2944     }
2945 
2946     ~CommandObjectTypeSynthDelete ()
2947     {
2948     }
2949 
2950 protected:
2951     bool
2952     DoExecute (Args& command, CommandReturnObject &result)
2953     {
2954         const size_t argc = command.GetArgumentCount();
2955 
2956         if (argc != 1)
2957         {
2958             result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
2959             result.SetStatus(eReturnStatusFailed);
2960             return false;
2961         }
2962 
2963         const char* typeA = command.GetArgumentAtIndex(0);
2964         ConstString typeCS(typeA);
2965 
2966         if (!typeCS)
2967         {
2968             result.AppendError("empty typenames not allowed");
2969             result.SetStatus(eReturnStatusFailed);
2970             return false;
2971         }
2972 
2973         if (m_options.m_delete_all)
2974         {
2975             DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS);
2976             result.SetStatus(eReturnStatusSuccessFinishNoResult);
2977             return result.Succeeded();
2978         }
2979 
2980         lldb::TypeCategoryImplSP category;
2981         DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
2982 
2983         bool delete_category = category->GetSyntheticNavigator()->Delete(typeCS);
2984         delete_category = category->GetRegexSyntheticNavigator()->Delete(typeCS) || delete_category;
2985 
2986         if (delete_category)
2987         {
2988             result.SetStatus(eReturnStatusSuccessFinishNoResult);
2989             return result.Succeeded();
2990         }
2991         else
2992         {
2993             result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA);
2994             result.SetStatus(eReturnStatusFailed);
2995             return false;
2996         }
2997 
2998     }
2999 };
3000 
3001 OptionDefinition
3002 CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] =
3003 {
3004     { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Delete from every category."},
3005     { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,  "Delete from given category."},
3006     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
3007 };
3008 
3009 #endif // #ifndef LLDB_DISABLE_PYTHON
3010 
3011 //-------------------------------------------------------------------------
3012 // CommandObjectTypeFilterClear
3013 //-------------------------------------------------------------------------
3014 
3015 class CommandObjectTypeFilterClear : public CommandObjectParsed
3016 {
3017 private:
3018 
3019     class CommandOptions : public Options
3020     {
3021     public:
3022 
3023         CommandOptions (CommandInterpreter &interpreter) :
3024         Options (interpreter)
3025         {
3026         }
3027 
3028         virtual
3029         ~CommandOptions (){}
3030 
3031         virtual Error
3032         SetOptionValue (uint32_t option_idx, const char *option_arg)
3033         {
3034             Error error;
3035             char short_option = (char) m_getopt_table[option_idx].val;
3036 
3037             switch (short_option)
3038             {
3039                 case 'a':
3040                     m_delete_all = true;
3041                     break;
3042                 default:
3043                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
3044                     break;
3045             }
3046 
3047             return error;
3048         }
3049 
3050         void
3051         OptionParsingStarting ()
3052         {
3053             m_delete_all = false;
3054         }
3055 
3056         const OptionDefinition*
3057         GetDefinitions ()
3058         {
3059             return g_option_table;
3060         }
3061 
3062         // Options table: Required for subclasses of Options.
3063 
3064         static OptionDefinition g_option_table[];
3065 
3066         // Instance variables to hold the values for command options.
3067 
3068         bool m_delete_all;
3069         bool m_delete_named;
3070     };
3071 
3072     CommandOptions m_options;
3073 
3074     virtual Options *
3075     GetOptions ()
3076     {
3077         return &m_options;
3078     }
3079 
3080     static bool
3081     PerCategoryCallback(void* param,
3082                         const lldb::TypeCategoryImplSP& cate)
3083     {
3084         cate->Clear(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter);
3085         return true;
3086 
3087     }
3088 
3089 public:
3090     CommandObjectTypeFilterClear (CommandInterpreter &interpreter) :
3091         CommandObjectParsed (interpreter,
3092                              "type filter clear",
3093                              "Delete all existing filters.",
3094                              NULL),
3095         m_options(interpreter)
3096     {
3097     }
3098 
3099     ~CommandObjectTypeFilterClear ()
3100     {
3101     }
3102 
3103 protected:
3104     bool
3105     DoExecute (Args& command, CommandReturnObject &result)
3106     {
3107 
3108         if (m_options.m_delete_all)
3109             DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL);
3110 
3111         else
3112         {
3113             lldb::TypeCategoryImplSP category;
3114             if (command.GetArgumentCount() > 0)
3115             {
3116                 const char* cat_name = command.GetArgumentAtIndex(0);
3117                 ConstString cat_nameCS(cat_name);
3118                 DataVisualization::Categories::GetCategory(cat_nameCS, category);
3119             }
3120             else
3121                 DataVisualization::Categories::GetCategory(ConstString(NULL), category);
3122             category->GetFilterNavigator()->Clear();
3123             category->GetRegexFilterNavigator()->Clear();
3124         }
3125 
3126         result.SetStatus(eReturnStatusSuccessFinishResult);
3127         return result.Succeeded();
3128     }
3129 
3130 };
3131 
3132 OptionDefinition
3133 CommandObjectTypeFilterClear::CommandOptions::g_option_table[] =
3134 {
3135     { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Clear every category."},
3136     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
3137 };
3138 
3139 #ifndef LLDB_DISABLE_PYTHON
3140 //-------------------------------------------------------------------------
3141 // CommandObjectTypeSynthClear
3142 //-------------------------------------------------------------------------
3143 
3144 class CommandObjectTypeSynthClear : public CommandObjectParsed
3145 {
3146 private:
3147 
3148     class CommandOptions : public Options
3149     {
3150     public:
3151 
3152         CommandOptions (CommandInterpreter &interpreter) :
3153         Options (interpreter)
3154         {
3155         }
3156 
3157         virtual
3158         ~CommandOptions (){}
3159 
3160         virtual Error
3161         SetOptionValue (uint32_t option_idx, const char *option_arg)
3162         {
3163             Error error;
3164             char short_option = (char) m_getopt_table[option_idx].val;
3165 
3166             switch (short_option)
3167             {
3168                 case 'a':
3169                     m_delete_all = true;
3170                     break;
3171                 default:
3172                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
3173                     break;
3174             }
3175 
3176             return error;
3177         }
3178 
3179         void
3180         OptionParsingStarting ()
3181         {
3182             m_delete_all = false;
3183         }
3184 
3185         const OptionDefinition*
3186         GetDefinitions ()
3187         {
3188             return g_option_table;
3189         }
3190 
3191         // Options table: Required for subclasses of Options.
3192 
3193         static OptionDefinition g_option_table[];
3194 
3195         // Instance variables to hold the values for command options.
3196 
3197         bool m_delete_all;
3198         bool m_delete_named;
3199     };
3200 
3201     CommandOptions m_options;
3202 
3203     virtual Options *
3204     GetOptions ()
3205     {
3206         return &m_options;
3207     }
3208 
3209     static bool
3210     PerCategoryCallback(void* param,
3211                         const lldb::TypeCategoryImplSP& cate)
3212     {
3213         cate->Clear(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth);
3214         return true;
3215 
3216     }
3217 
3218 public:
3219     CommandObjectTypeSynthClear (CommandInterpreter &interpreter) :
3220         CommandObjectParsed (interpreter,
3221                              "type synthetic clear",
3222                              "Delete all existing synthetic providers.",
3223                              NULL),
3224         m_options(interpreter)
3225     {
3226     }
3227 
3228     ~CommandObjectTypeSynthClear ()
3229     {
3230     }
3231 
3232 protected:
3233     bool
3234     DoExecute (Args& command, CommandReturnObject &result)
3235     {
3236 
3237         if (m_options.m_delete_all)
3238             DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL);
3239 
3240         else
3241         {
3242             lldb::TypeCategoryImplSP category;
3243             if (command.GetArgumentCount() > 0)
3244             {
3245                 const char* cat_name = command.GetArgumentAtIndex(0);
3246                 ConstString cat_nameCS(cat_name);
3247                 DataVisualization::Categories::GetCategory(cat_nameCS, category);
3248             }
3249             else
3250                 DataVisualization::Categories::GetCategory(ConstString(NULL), category);
3251             category->GetSyntheticNavigator()->Clear();
3252             category->GetRegexSyntheticNavigator()->Clear();
3253         }
3254 
3255         result.SetStatus(eReturnStatusSuccessFinishResult);
3256         return result.Succeeded();
3257     }
3258 
3259 };
3260 
3261 OptionDefinition
3262 CommandObjectTypeSynthClear::CommandOptions::g_option_table[] =
3263 {
3264     { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Clear every category."},
3265     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
3266 };
3267 
3268 
3269 //-------------------------------------------------------------------------
3270 // TypeSynthAddInputReader
3271 //-------------------------------------------------------------------------
3272 
3273 static const char *g_synth_addreader_instructions =   "Enter your Python command(s). Type 'DONE' to end.\n"
3274                                                       "You must define a Python class with these methods:\n"
3275                                                       "     def __init__(self, valobj, dict):\n"
3276                                                       "     def num_children(self):\n"
3277                                                       "     def get_child_at_index(self, index):\n"
3278                                                       "     def get_child_index(self, name):\n"
3279                                                       "Optionally, you can also define a method:\n"
3280                                                       "     def update(self):\n"
3281                                                       "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"
3282                                                       "class synthProvider:";
3283 
3284 class TypeSynthAddInputReader : public InputReaderEZ
3285 {
3286 public:
3287     TypeSynthAddInputReader(Debugger& debugger) :
3288         InputReaderEZ(debugger)
3289     {}
3290 
3291     virtual
3292     ~TypeSynthAddInputReader()
3293     {
3294     }
3295 
3296     virtual void ActivateHandler(HandlerData& data)
3297     {
3298         StreamSP out_stream = data.GetOutStream();
3299         bool batch_mode = data.GetBatchMode();
3300         if (!batch_mode)
3301         {
3302             out_stream->Printf ("%s\n", g_synth_addreader_instructions);
3303             if (data.reader.GetPrompt())
3304                 out_stream->Printf ("%s", data.reader.GetPrompt());
3305             out_stream->Flush();
3306         }
3307     }
3308 
3309     virtual void ReactivateHandler(HandlerData& data)
3310     {
3311         StreamSP out_stream = data.GetOutStream();
3312         bool batch_mode = data.GetBatchMode();
3313         if (data.reader.GetPrompt() && !batch_mode)
3314         {
3315             out_stream->Printf ("%s", data.reader.GetPrompt());
3316             out_stream->Flush();
3317         }
3318     }
3319     virtual void GotTokenHandler(HandlerData& data)
3320     {
3321         StreamSP out_stream = data.GetOutStream();
3322         bool batch_mode = data.GetBatchMode();
3323         if (data.bytes && data.bytes_len && data.baton)
3324         {
3325             ((SynthAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len);
3326         }
3327         if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
3328         {
3329             out_stream->Printf ("%s", data.reader.GetPrompt());
3330             out_stream->Flush();
3331         }
3332     }
3333     virtual void InterruptHandler(HandlerData& data)
3334     {
3335         StreamSP out_stream = data.GetOutStream();
3336         bool batch_mode = data.GetBatchMode();
3337         data.reader.SetIsDone (true);
3338         if (!batch_mode)
3339         {
3340             out_stream->Printf ("Warning: No command attached to breakpoint.\n");
3341             out_stream->Flush();
3342         }
3343     }
3344     virtual void EOFHandler(HandlerData& data)
3345     {
3346         data.reader.SetIsDone (true);
3347     }
3348     virtual void DoneHandler(HandlerData& data)
3349     {
3350         StreamSP out_stream = data.GetOutStream();
3351         SynthAddOptions *options_ptr = ((SynthAddOptions*)data.baton);
3352         if (!options_ptr)
3353         {
3354             out_stream->Printf ("Internal error #1: no script attached.\n");
3355             out_stream->Flush();
3356             return;
3357         }
3358 
3359         SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
3360 
3361         ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
3362         if (!interpreter)
3363         {
3364             out_stream->Printf ("Internal error #2: no script attached.\n");
3365             out_stream->Flush();
3366             return;
3367         }
3368         std::string class_name_str;
3369         if (!interpreter->GenerateTypeSynthClass (options->m_user_source,
3370                                                   class_name_str))
3371         {
3372             out_stream->Printf ("Internal error #3: no script attached.\n");
3373             out_stream->Flush();
3374             return;
3375         }
3376         if (class_name_str.empty())
3377         {
3378             out_stream->Printf ("Internal error #4: no script attached.\n");
3379             out_stream->Flush();
3380             return;
3381         }
3382 
3383         // everything should be fine now, let's add the synth provider class
3384 
3385         SyntheticChildrenSP synth_provider;
3386         synth_provider.reset(new TypeSyntheticImpl(SyntheticChildren::Flags().SetCascades(options->m_cascade).
3387                                                          SetSkipPointers(options->m_skip_pointers).
3388                                                          SetSkipReferences(options->m_skip_references),
3389                                                          class_name_str.c_str()));
3390 
3391 
3392         lldb::TypeCategoryImplSP category;
3393         DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category);
3394 
3395         Error error;
3396 
3397         for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
3398         {
3399             const char *type_name = options->m_target_types.GetStringAtIndex(i);
3400             ConstString typeCS(type_name);
3401             if (typeCS)
3402             {
3403                 if (!CommandObjectTypeSynthAdd::AddSynth(typeCS,
3404                                                         synth_provider,
3405                                                         options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth,
3406                                                         options->m_category,
3407                                                         &error))
3408                 {
3409                     out_stream->Printf("%s\n", error.AsCString());
3410                     out_stream->Flush();
3411                     return;
3412                 }
3413             }
3414             else
3415             {
3416                 out_stream->Printf ("Internal error #6: no script attached.\n");
3417                 out_stream->Flush();
3418                 return;
3419             }
3420         }
3421     }
3422 
3423 private:
3424     DISALLOW_COPY_AND_ASSIGN (TypeSynthAddInputReader);
3425 };
3426 
3427 void
3428 CommandObjectTypeSynthAdd::CollectPythonScript (SynthAddOptions *options,
3429                                                 CommandReturnObject &result)
3430 {
3431     InputReaderSP reader_sp (new TypeSynthAddInputReader(m_interpreter.GetDebugger()));
3432     if (reader_sp && options)
3433     {
3434 
3435         InputReaderEZ::InitializationParameters ipr;
3436 
3437         Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt("     ")));
3438         if (err.Success())
3439         {
3440             m_interpreter.GetDebugger().PushInputReader (reader_sp);
3441             result.SetStatus (eReturnStatusSuccessFinishNoResult);
3442         }
3443         else
3444         {
3445             result.AppendError (err.AsCString());
3446             result.SetStatus (eReturnStatusFailed);
3447         }
3448     }
3449     else
3450     {
3451         result.AppendError("out of memory");
3452         result.SetStatus (eReturnStatusFailed);
3453     }
3454 }
3455 
3456 bool
3457 CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result)
3458 {
3459     SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers,
3460                                                      m_options.m_skip_references,
3461                                                      m_options.m_cascade,
3462                                                      m_options.m_regex,
3463                                                      m_options.m_category);
3464 
3465     const size_t argc = command.GetArgumentCount();
3466 
3467     for (size_t i = 0; i < argc; i++)
3468     {
3469         const char* typeA = command.GetArgumentAtIndex(i);
3470         if (typeA && *typeA)
3471             options->m_target_types << typeA;
3472         else
3473         {
3474             result.AppendError("empty typenames not allowed");
3475             result.SetStatus(eReturnStatusFailed);
3476             return false;
3477         }
3478     }
3479 
3480     CollectPythonScript(options,result);
3481     return result.Succeeded();
3482 }
3483 
3484 bool
3485 CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result)
3486 {
3487     const size_t argc = command.GetArgumentCount();
3488 
3489     if (argc < 1)
3490     {
3491         result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
3492         result.SetStatus(eReturnStatusFailed);
3493         return false;
3494     }
3495 
3496     if (m_options.m_class_name.empty() && !m_options.m_input_python)
3497     {
3498         result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str());
3499         result.SetStatus(eReturnStatusFailed);
3500         return false;
3501     }
3502 
3503     SyntheticChildrenSP entry;
3504 
3505     TypeSyntheticImpl* impl = new TypeSyntheticImpl(SyntheticChildren::Flags().
3506                                                     SetCascades(m_options.m_cascade).
3507                                                     SetSkipPointers(m_options.m_skip_pointers).
3508                                                     SetSkipReferences(m_options.m_skip_references),
3509                                                     m_options.m_class_name.c_str());
3510 
3511     entry.reset(impl);
3512 
3513     // now I have a valid provider, let's add it to every type
3514 
3515     lldb::TypeCategoryImplSP category;
3516     DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
3517 
3518     Error error;
3519 
3520     for (size_t i = 0; i < argc; i++)
3521     {
3522         const char* typeA = command.GetArgumentAtIndex(i);
3523         ConstString typeCS(typeA);
3524         if (typeCS)
3525         {
3526             if (!AddSynth(typeCS,
3527                           entry,
3528                           m_options.m_regex ? eRegexSynth : eRegularSynth,
3529                           m_options.m_category,
3530                           &error))
3531             {
3532                 result.AppendError(error.AsCString());
3533                 result.SetStatus(eReturnStatusFailed);
3534                 return false;
3535             }
3536         }
3537         else
3538         {
3539             result.AppendError("empty typenames not allowed");
3540             result.SetStatus(eReturnStatusFailed);
3541             return false;
3542         }
3543     }
3544 
3545     result.SetStatus(eReturnStatusSuccessFinishNoResult);
3546     return result.Succeeded();
3547 }
3548 
3549 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) :
3550     CommandObjectParsed (interpreter,
3551                          "type synthetic add",
3552                          "Add a new synthetic provider for a type.",
3553                          NULL),
3554     m_options (interpreter)
3555 {
3556     CommandArgumentEntry type_arg;
3557     CommandArgumentData type_style_arg;
3558 
3559     type_style_arg.arg_type = eArgTypeName;
3560     type_style_arg.arg_repetition = eArgRepeatPlus;
3561 
3562     type_arg.push_back (type_style_arg);
3563 
3564     m_arguments.push_back (type_arg);
3565 
3566 }
3567 
3568 bool
3569 CommandObjectTypeSynthAdd::AddSynth(const ConstString& type_name,
3570          SyntheticChildrenSP entry,
3571          SynthFormatType type,
3572          std::string category_name,
3573          Error* error)
3574 {
3575     lldb::TypeCategoryImplSP category;
3576     DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
3577 
3578     if (category->AnyMatches(type_name,
3579                              eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
3580                              false))
3581     {
3582         if (error)
3583             error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString());
3584         return false;
3585     }
3586 
3587     if (type == eRegexSynth)
3588     {
3589         RegularExpressionSP typeRX(new RegularExpression());
3590         if (!typeRX->Compile(type_name.GetCString()))
3591         {
3592             if (error)
3593                 error->SetErrorString("regex format error (maybe this is not really a regex?)");
3594             return false;
3595         }
3596 
3597         category->GetRegexSyntheticNavigator()->Delete(type_name);
3598         category->GetRegexSyntheticNavigator()->Add(typeRX, entry);
3599 
3600         return true;
3601     }
3602     else
3603     {
3604         category->GetSyntheticNavigator()->Add(type_name, entry);
3605         return true;
3606     }
3607 }
3608 
3609 bool
3610 CommandObjectTypeSynthAdd::DoExecute (Args& command, CommandReturnObject &result)
3611 {
3612     if (m_options.handwrite_python)
3613         return Execute_HandwritePython(command, result);
3614     else if (m_options.is_class_based)
3615         return Execute_PythonClass(command, result);
3616     else
3617     {
3618         result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line");
3619         result.SetStatus(eReturnStatusFailed);
3620         return false;
3621     }
3622 }
3623 
3624 OptionDefinition
3625 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
3626 {
3627     { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade through typedef chains."},
3628     { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
3629     { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
3630     { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,         "Add this to the given category instead of the default one."},
3631     { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypePythonClass,    "Use this Python class to produce synthetic children."},
3632     { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone,    "Type Python code to generate a class that provides synthetic children."},
3633     { LLDB_OPT_SET_ALL, false,  "regex", 'x', no_argument, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
3634     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
3635 };
3636 
3637 #endif // #ifndef LLDB_DISABLE_PYTHON
3638 
3639 class CommandObjectTypeFilterAdd : public CommandObjectParsed
3640 {
3641 
3642 private:
3643 
3644     class CommandOptions : public Options
3645     {
3646         typedef std::vector<std::string> option_vector;
3647     public:
3648 
3649         CommandOptions (CommandInterpreter &interpreter) :
3650         Options (interpreter)
3651         {
3652         }
3653 
3654         virtual
3655         ~CommandOptions (){}
3656 
3657         virtual Error
3658         SetOptionValue (uint32_t option_idx, const char *option_arg)
3659         {
3660             Error error;
3661             char short_option = (char) m_getopt_table[option_idx].val;
3662             bool success;
3663 
3664             switch (short_option)
3665             {
3666                 case 'C':
3667                     m_cascade = Args::StringToBoolean(option_arg, true, &success);
3668                     if (!success)
3669                         error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg);
3670                     break;
3671                 case 'c':
3672                     m_expr_paths.push_back(option_arg);
3673                     has_child_list = true;
3674                     break;
3675                 case 'p':
3676                     m_skip_pointers = true;
3677                     break;
3678                 case 'r':
3679                     m_skip_references = true;
3680                     break;
3681                 case 'w':
3682                     m_category = std::string(option_arg);
3683                     break;
3684                 case 'x':
3685                     m_regex = true;
3686                     break;
3687                 default:
3688                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
3689                     break;
3690             }
3691 
3692             return error;
3693         }
3694 
3695         void
3696         OptionParsingStarting ()
3697         {
3698             m_cascade = true;
3699             m_skip_pointers = false;
3700             m_skip_references = false;
3701             m_category = "default";
3702             m_expr_paths.clear();
3703             has_child_list = false;
3704             m_regex = false;
3705         }
3706 
3707         const OptionDefinition*
3708         GetDefinitions ()
3709         {
3710             return g_option_table;
3711         }
3712 
3713         // Options table: Required for subclasses of Options.
3714 
3715         static OptionDefinition g_option_table[];
3716 
3717         // Instance variables to hold the values for command options.
3718 
3719         bool m_cascade;
3720         bool m_skip_references;
3721         bool m_skip_pointers;
3722         bool m_input_python;
3723         option_vector m_expr_paths;
3724         std::string m_category;
3725 
3726         bool has_child_list;
3727 
3728         bool m_regex;
3729 
3730         typedef option_vector::iterator ExpressionPathsIterator;
3731     };
3732 
3733     CommandOptions m_options;
3734 
3735     virtual Options *
3736     GetOptions ()
3737     {
3738         return &m_options;
3739     }
3740 
3741     enum FilterFormatType
3742     {
3743         eRegularFilter,
3744         eRegexFilter
3745     };
3746 
3747     bool
3748     AddFilter(const ConstString& type_name,
3749               SyntheticChildrenSP entry,
3750               FilterFormatType type,
3751               std::string category_name,
3752               Error* error)
3753     {
3754         lldb::TypeCategoryImplSP category;
3755         DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
3756 
3757         if (category->AnyMatches(type_name,
3758                                  eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
3759                                  false))
3760         {
3761             if (error)
3762                 error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString());
3763             return false;
3764         }
3765 
3766         if (type == eRegexFilter)
3767         {
3768             RegularExpressionSP typeRX(new RegularExpression());
3769             if (!typeRX->Compile(type_name.GetCString()))
3770             {
3771                 if (error)
3772                     error->SetErrorString("regex format error (maybe this is not really a regex?)");
3773                 return false;
3774             }
3775 
3776             category->GetRegexFilterNavigator()->Delete(type_name);
3777             category->GetRegexFilterNavigator()->Add(typeRX, entry);
3778 
3779             return true;
3780         }
3781         else
3782         {
3783             category->GetFilterNavigator()->Add(type_name, entry);
3784             return true;
3785         }
3786     }
3787 
3788 
3789 public:
3790 
3791     CommandObjectTypeFilterAdd (CommandInterpreter &interpreter) :
3792         CommandObjectParsed (interpreter,
3793                              "type filter add",
3794                              "Add a new filter for a type.",
3795                              NULL),
3796         m_options (interpreter)
3797     {
3798         CommandArgumentEntry type_arg;
3799         CommandArgumentData type_style_arg;
3800 
3801         type_style_arg.arg_type = eArgTypeName;
3802         type_style_arg.arg_repetition = eArgRepeatPlus;
3803 
3804         type_arg.push_back (type_style_arg);
3805 
3806         m_arguments.push_back (type_arg);
3807 
3808         SetHelpLong(
3809                     "Some examples of using this command.\n"
3810                     "We use as reference the following snippet of code:\n"
3811                     "\n"
3812                     "class Foo {;\n"
3813                     "    int a;\n"
3814                     "    int b;\n"
3815                     "    int c;\n"
3816                     "    int d;\n"
3817                     "    int e;\n"
3818                     "    int f;\n"
3819                     "    int g;\n"
3820                     "    int h;\n"
3821                     "    int i;\n"
3822                     "} \n"
3823                     "Typing:\n"
3824                     "type filter add --child a --child g Foo\n"
3825                     "frame variable a_foo\n"
3826                     "will produce an output where only a and g are displayed\n"
3827                     "Other children of a_foo (b,c,d,e,f,h and i) are available by asking for them, as in:\n"
3828                     "frame variable a_foo.b a_foo.c ... a_foo.i\n"
3829                     "\n"
3830                     "Use option --raw to frame variable prevails on the filter\n"
3831                     "frame variable a_foo --raw\n"
3832                     "shows all the children of a_foo (a thru i) as if no filter was defined\n"
3833                     );
3834     }
3835 
3836     ~CommandObjectTypeFilterAdd ()
3837     {
3838     }
3839 
3840 protected:
3841     bool
3842     DoExecute (Args& command, CommandReturnObject &result)
3843     {
3844         const size_t argc = command.GetArgumentCount();
3845 
3846         if (argc < 1)
3847         {
3848             result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
3849             result.SetStatus(eReturnStatusFailed);
3850             return false;
3851         }
3852 
3853         if (m_options.m_expr_paths.size() == 0)
3854         {
3855             result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
3856             result.SetStatus(eReturnStatusFailed);
3857             return false;
3858         }
3859 
3860         SyntheticChildrenSP entry;
3861 
3862         TypeFilterImpl* impl = new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade).
3863                                                     SetSkipPointers(m_options.m_skip_pointers).
3864                                                     SetSkipReferences(m_options.m_skip_references));
3865 
3866         entry.reset(impl);
3867 
3868         // go through the expression paths
3869         CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
3870 
3871         for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
3872             impl->AddExpressionPath(*begin);
3873 
3874 
3875         // now I have a valid provider, let's add it to every type
3876 
3877         lldb::TypeCategoryImplSP category;
3878         DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
3879 
3880         Error error;
3881 
3882         for (size_t i = 0; i < argc; i++)
3883         {
3884             const char* typeA = command.GetArgumentAtIndex(i);
3885             ConstString typeCS(typeA);
3886             if (typeCS)
3887             {
3888                 if (!AddFilter(typeCS,
3889                           entry,
3890                           m_options.m_regex ? eRegexFilter : eRegularFilter,
3891                           m_options.m_category,
3892                           &error))
3893                 {
3894                     result.AppendError(error.AsCString());
3895                     result.SetStatus(eReturnStatusFailed);
3896                     return false;
3897                 }
3898             }
3899             else
3900             {
3901                 result.AppendError("empty typenames not allowed");
3902                 result.SetStatus(eReturnStatusFailed);
3903                 return false;
3904             }
3905         }
3906 
3907         result.SetStatus(eReturnStatusSuccessFinishNoResult);
3908         return result.Succeeded();
3909     }
3910 
3911 };
3912 
3913 OptionDefinition
3914 CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] =
3915 {
3916     { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade through typedef chains."},
3917     { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
3918     { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
3919     { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,         "Add this to the given category instead of the default one."},
3920     { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeExpressionPath,    "Include this expression path in the synthetic view."},
3921     { LLDB_OPT_SET_ALL, false,  "regex", 'x', no_argument, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
3922     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
3923 };
3924 
3925 class CommandObjectTypeFormat : public CommandObjectMultiword
3926 {
3927 public:
3928     CommandObjectTypeFormat (CommandInterpreter &interpreter) :
3929         CommandObjectMultiword (interpreter,
3930                                 "type format",
3931                                 "A set of commands for editing variable value display options",
3932                                 "type format [<sub-command-options>] ")
3933     {
3934         LoadSubCommand ("add",    CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter)));
3935         LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectTypeFormatClear (interpreter)));
3936         LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter)));
3937         LoadSubCommand ("list",   CommandObjectSP (new CommandObjectTypeFormatList (interpreter)));
3938     }
3939 
3940 
3941     ~CommandObjectTypeFormat ()
3942     {
3943     }
3944 };
3945 
3946 #ifndef LLDB_DISABLE_PYTHON
3947 
3948 class CommandObjectTypeSynth : public CommandObjectMultiword
3949 {
3950 public:
3951     CommandObjectTypeSynth (CommandInterpreter &interpreter) :
3952     CommandObjectMultiword (interpreter,
3953                             "type synthetic",
3954                             "A set of commands for operating on synthetic type representations",
3955                             "type synthetic [<sub-command-options>] ")
3956     {
3957         LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter)));
3958         LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSynthClear (interpreter)));
3959         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter)));
3960         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSynthList (interpreter)));
3961     }
3962 
3963 
3964     ~CommandObjectTypeSynth ()
3965     {
3966     }
3967 };
3968 
3969 #endif // #ifndef LLDB_DISABLE_PYTHON
3970 
3971 class CommandObjectTypeFilter : public CommandObjectMultiword
3972 {
3973 public:
3974     CommandObjectTypeFilter (CommandInterpreter &interpreter) :
3975     CommandObjectMultiword (interpreter,
3976                             "type filter",
3977                             "A set of commands for operating on type filters",
3978                             "type synthetic [<sub-command-options>] ")
3979     {
3980         LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeFilterAdd (interpreter)));
3981         LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeFilterClear (interpreter)));
3982         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeFilterDelete (interpreter)));
3983         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeFilterList (interpreter)));
3984     }
3985 
3986 
3987     ~CommandObjectTypeFilter ()
3988     {
3989     }
3990 };
3991 
3992 class CommandObjectTypeCategory : public CommandObjectMultiword
3993 {
3994 public:
3995     CommandObjectTypeCategory (CommandInterpreter &interpreter) :
3996     CommandObjectMultiword (interpreter,
3997                             "type category",
3998                             "A set of commands for operating on categories",
3999                             "type category [<sub-command-options>] ")
4000     {
4001         LoadSubCommand ("enable",        CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter)));
4002         LoadSubCommand ("disable",       CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter)));
4003         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter)));
4004         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeCategoryList (interpreter)));
4005     }
4006 
4007 
4008     ~CommandObjectTypeCategory ()
4009     {
4010     }
4011 };
4012 
4013 class CommandObjectTypeSummary : public CommandObjectMultiword
4014 {
4015 public:
4016     CommandObjectTypeSummary (CommandInterpreter &interpreter) :
4017     CommandObjectMultiword (interpreter,
4018                             "type summary",
4019                             "A set of commands for editing variable summary display options",
4020                             "type summary [<sub-command-options>] ")
4021     {
4022         LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter)));
4023         LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));
4024         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));
4025         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSummaryList (interpreter)));
4026     }
4027 
4028 
4029     ~CommandObjectTypeSummary ()
4030     {
4031     }
4032 };
4033 
4034 //-------------------------------------------------------------------------
4035 // CommandObjectType
4036 //-------------------------------------------------------------------------
4037 
4038 CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) :
4039     CommandObjectMultiword (interpreter,
4040                             "type",
4041                             "A set of commands for operating on the type system",
4042                             "type [<sub-command-options>]")
4043 {
4044     LoadSubCommand ("category",  CommandObjectSP (new CommandObjectTypeCategory (interpreter)));
4045     LoadSubCommand ("filter",    CommandObjectSP (new CommandObjectTypeFilter (interpreter)));
4046     LoadSubCommand ("format",    CommandObjectSP (new CommandObjectTypeFormat (interpreter)));
4047     LoadSubCommand ("summary",   CommandObjectSP (new CommandObjectTypeSummary (interpreter)));
4048 #ifndef LLDB_DISABLE_PYTHON
4049     LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter)));
4050 #endif
4051 }
4052 
4053 
4054 CommandObjectType::~CommandObjectType ()
4055 {
4056 }
4057 
4058 
4059