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