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