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