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