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