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