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 = ConstString(option_arg).GetCString();
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 = NULL;
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                                         const char* category_name,
1040                                         Error* error)
1041 {
1042     lldb::FormatCategorySP category;
1043     Debugger::Formatting::Categories::Get(ConstString(category_name), 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 = ConstString(option_arg).GetCString();
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 = NULL;
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         const char* 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), 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 // CommandObjectTypeSynthList
1892 //-------------------------------------------------------------------------
1893 
1894 bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, const char* type, const SyntheticFilter::SharedPointer& entry);
1895 bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticFilter::SharedPointer& entry);
1896 
1897 class CommandObjectTypeSynthList;
1898 
1899 struct CommandObjectTypeSynthList_LoopCallbackParam {
1900     CommandObjectTypeSynthList* self;
1901     CommandReturnObject* result;
1902     RegularExpression* regex;
1903     RegularExpression* cate_regex;
1904     CommandObjectTypeSynthList_LoopCallbackParam(CommandObjectTypeSynthList* S, CommandReturnObject* R,
1905                                                  RegularExpression* X = NULL,
1906                                                  RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
1907 };
1908 
1909 class CommandObjectTypeSynthList : 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     CommandObjectTypeSynthList (CommandInterpreter &interpreter) :
1975     CommandObject (interpreter,
1976                    "type synthetic list",
1977                    "Show a list of current synthetic providers.",
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     ~CommandObjectTypeSynthList ()
1992     {
1993     }
1994 
1995     bool
1996     Execute (Args& command, CommandReturnObject &result)
1997     {
1998         const size_t argc = command.GetArgumentCount();
1999 
2000         CommandObjectTypeSynthList_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 CommandObjectTypeSynthList_LoopCallbackParam(this,&result,regex,cate_regex);
2009         }
2010         else
2011             param = new CommandObjectTypeSynthList_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         CommandObjectTypeSynthList_LoopCallbackParam* param =
2031         (CommandObjectTypeSynthList_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(CommandObjectTypeSynthList_LoopCallback, param_vp);
2047 
2048         if (cate->RegexFilter()->GetCount() > 0)
2049         {
2050             result->GetOutputStream().Printf("Regex-based filters (slower):\n");
2051             cate->RegexFilter()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp);
2052         }
2053 
2054         return true;
2055     }
2056 
2057     bool
2058     LoopCallback (const char* type,
2059                   const SyntheticFilter::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 CommandObjectTypeSynthList_LoopCallback(void* pt2self, const char* type, const SyntheticFilter::SharedPointer& entry);
2069     friend bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticFilter::SharedPointer& entry);
2070 };
2071 
2072 bool
2073 CommandObjectTypeSynthList_LoopCallback (void* pt2self,
2074                                          const char* type,
2075                                          const SyntheticFilter::SharedPointer& entry)
2076 {
2077     CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
2078     return param->self->LoopCallback(type, entry, param->regex, param->result);
2079 }
2080 
2081 bool
2082 CommandObjectTypeSynthRXList_LoopCallback (void* pt2self,
2083                                          lldb::RegularExpressionSP regex,
2084                                          const SyntheticFilter::SharedPointer& entry)
2085 {
2086     CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
2087     return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
2088 }
2089 
2090 
2091 OptionDefinition
2092 CommandObjectTypeSynthList::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 // CommandObjectTypeSynthDelete
2100 //-------------------------------------------------------------------------
2101 
2102 class CommandObjectTypeSynthDelete : public CommandObject
2103 {
2104 private:
2105     class CommandOptions : public Options
2106     {
2107     public:
2108 
2109         CommandOptions (CommandInterpreter &interpreter) :
2110         Options (interpreter)
2111         {
2112         }
2113 
2114         virtual
2115         ~CommandOptions (){}
2116 
2117         virtual Error
2118         SetOptionValue (uint32_t option_idx, const char *option_arg)
2119         {
2120             Error error;
2121             char short_option = (char) m_getopt_table[option_idx].val;
2122 
2123             switch (short_option)
2124             {
2125                 case 'a':
2126                     m_delete_all = true;
2127                     break;
2128                 case 'w':
2129                     m_category = ConstString(option_arg).GetCString();
2130                     break;
2131                 default:
2132                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
2133                     break;
2134             }
2135 
2136             return error;
2137         }
2138 
2139         void
2140         OptionParsingStarting ()
2141         {
2142             m_delete_all = false;
2143             m_category = NULL;
2144         }
2145 
2146         const OptionDefinition*
2147         GetDefinitions ()
2148         {
2149             return g_option_table;
2150         }
2151 
2152         // Options table: Required for subclasses of Options.
2153 
2154         static OptionDefinition g_option_table[];
2155 
2156         // Instance variables to hold the values for command options.
2157 
2158         bool m_delete_all;
2159         const char* m_category;
2160 
2161     };
2162 
2163     CommandOptions m_options;
2164 
2165     virtual Options *
2166     GetOptions ()
2167     {
2168         return &m_options;
2169     }
2170 
2171     static bool
2172     PerCategoryCallback(void* param,
2173                         const char* cate_name,
2174                         const FormatCategory::SharedPointer& cate)
2175     {
2176         const char* name = (const char*)param;
2177         return cate->Delete(name, FormatCategory::eFilter | FormatCategory::eRegexFilter);
2178     }
2179 
2180 public:
2181     CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) :
2182     CommandObject (interpreter,
2183                    "type synthetic delete",
2184                    "Delete an existing synthetic provider for a type.",
2185                    NULL), m_options(interpreter)
2186     {
2187         CommandArgumentEntry type_arg;
2188         CommandArgumentData type_style_arg;
2189 
2190         type_style_arg.arg_type = eArgTypeName;
2191         type_style_arg.arg_repetition = eArgRepeatPlain;
2192 
2193         type_arg.push_back (type_style_arg);
2194 
2195         m_arguments.push_back (type_arg);
2196 
2197     }
2198 
2199     ~CommandObjectTypeSynthDelete ()
2200     {
2201     }
2202 
2203     bool
2204     Execute (Args& command, CommandReturnObject &result)
2205     {
2206         const size_t argc = command.GetArgumentCount();
2207 
2208         if (argc != 1)
2209         {
2210             result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
2211             result.SetStatus(eReturnStatusFailed);
2212             return false;
2213         }
2214 
2215         const char* typeA = command.GetArgumentAtIndex(0);
2216         ConstString typeCS(typeA);
2217 
2218         if (!typeCS)
2219         {
2220             result.AppendError("empty typenames not allowed");
2221             result.SetStatus(eReturnStatusFailed);
2222             return false;
2223         }
2224 
2225         if (m_options.m_delete_all)
2226         {
2227             Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, (void*)typeCS.GetCString());
2228             result.SetStatus(eReturnStatusSuccessFinishNoResult);
2229             return result.Succeeded();
2230         }
2231 
2232         lldb::FormatCategorySP category;
2233         Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
2234 
2235         bool delete_category = category->Filter()->Delete(typeCS.GetCString());
2236         delete_category = category->RegexFilter()->Delete(typeCS.GetCString()) || delete_category;
2237 
2238         if (delete_category)
2239         {
2240             result.SetStatus(eReturnStatusSuccessFinishNoResult);
2241             return result.Succeeded();
2242         }
2243         else
2244         {
2245             result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA);
2246             result.SetStatus(eReturnStatusFailed);
2247             return false;
2248         }
2249 
2250     }
2251 };
2252 
2253 OptionDefinition
2254 CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] =
2255 {
2256     { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Delete from every category."},
2257     { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,  "Delete from given category."},
2258     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2259 };
2260 
2261 //-------------------------------------------------------------------------
2262 // CommandObjectTypeSynthClear
2263 //-------------------------------------------------------------------------
2264 
2265 class CommandObjectTypeSynthClear : public CommandObject
2266 {
2267 private:
2268 
2269     class CommandOptions : public Options
2270     {
2271     public:
2272 
2273         CommandOptions (CommandInterpreter &interpreter) :
2274         Options (interpreter)
2275         {
2276         }
2277 
2278         virtual
2279         ~CommandOptions (){}
2280 
2281         virtual Error
2282         SetOptionValue (uint32_t option_idx, const char *option_arg)
2283         {
2284             Error error;
2285             char short_option = (char) m_getopt_table[option_idx].val;
2286 
2287             switch (short_option)
2288             {
2289                 case 'a':
2290                     m_delete_all = true;
2291                     break;
2292                 default:
2293                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
2294                     break;
2295             }
2296 
2297             return error;
2298         }
2299 
2300         void
2301         OptionParsingStarting ()
2302         {
2303             m_delete_all = false;
2304         }
2305 
2306         const OptionDefinition*
2307         GetDefinitions ()
2308         {
2309             return g_option_table;
2310         }
2311 
2312         // Options table: Required for subclasses of Options.
2313 
2314         static OptionDefinition g_option_table[];
2315 
2316         // Instance variables to hold the values for command options.
2317 
2318         bool m_delete_all;
2319         bool m_delete_named;
2320     };
2321 
2322     CommandOptions m_options;
2323 
2324     virtual Options *
2325     GetOptions ()
2326     {
2327         return &m_options;
2328     }
2329 
2330     static bool
2331     PerCategoryCallback(void* param,
2332                         const char* cate_name,
2333                         const FormatCategory::SharedPointer& cate)
2334     {
2335         cate->Clear(FormatCategory::eFilter | FormatCategory::eRegexFilter);
2336         return true;
2337 
2338     }
2339 
2340 public:
2341     CommandObjectTypeSynthClear (CommandInterpreter &interpreter) :
2342     CommandObject (interpreter,
2343                    "type synthetic clear",
2344                    "Delete all existing synthetic providers.",
2345                    NULL), m_options(interpreter)
2346     {
2347     }
2348 
2349     ~CommandObjectTypeSynthClear ()
2350     {
2351     }
2352 
2353     bool
2354     Execute (Args& command, CommandReturnObject &result)
2355     {
2356 
2357         if (m_options.m_delete_all)
2358             Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, NULL);
2359 
2360         else
2361         {
2362             lldb::FormatCategorySP category;
2363             if (command.GetArgumentCount() > 0)
2364             {
2365                 const char* cat_name = command.GetArgumentAtIndex(0);
2366                 ConstString cat_nameCS(cat_name);
2367                 Debugger::Formatting::Categories::Get(cat_nameCS, category);
2368             }
2369             else
2370                 Debugger::Formatting::Categories::Get(ConstString(NULL), category);
2371             category->Filter()->Clear();
2372             category->RegexFilter()->Clear();
2373         }
2374 
2375         result.SetStatus(eReturnStatusSuccessFinishResult);
2376         return result.Succeeded();
2377     }
2378 
2379 };
2380 
2381 OptionDefinition
2382 CommandObjectTypeSynthClear::CommandOptions::g_option_table[] =
2383 {
2384     { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone,  "Clear every category."},
2385     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2386 };
2387 
2388 //-------------------------------------------------------------------------
2389 // CommandObjectTypeSynthAdd
2390 //-------------------------------------------------------------------------
2391 
2392 static const char *g_synth_addreader_instructions =   "Enter your Python command(s). Type 'DONE' to end.\n"
2393                                                       "You must define a Python class with these methods:\n"
2394                                                       "     def __init__(self, valobj, dict):\n"
2395                                                       "     def num_children(self):\n"
2396                                                       "     def get_child_at_index(self, index):\n"
2397                                                       "     def get_child_index(self, name):\n"
2398                                                       "Optionally, you can also define a method:\n"
2399                                                       "     def update(self):\n"
2400                                                       "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"
2401                                                       "class synthProvider:";
2402 
2403 class TypeSynthAddInputReader : public InputReaderEZ
2404 {
2405 private:
2406     DISALLOW_COPY_AND_ASSIGN (TypeSynthAddInputReader);
2407 public:
2408     TypeSynthAddInputReader(Debugger& debugger) :
2409     InputReaderEZ(debugger)
2410     {}
2411 
2412     virtual
2413     ~TypeSynthAddInputReader()
2414     {
2415     }
2416 
2417     virtual void ActivateHandler(HandlerData& data)
2418     {
2419         StreamSP out_stream = data.GetOutStream();
2420         bool batch_mode = data.GetBatchMode();
2421         if (!batch_mode)
2422         {
2423             out_stream->Printf ("%s\n", g_synth_addreader_instructions);
2424             if (data.reader.GetPrompt())
2425                 out_stream->Printf ("%s", data.reader.GetPrompt());
2426             out_stream->Flush();
2427         }
2428     }
2429 
2430     virtual void ReactivateHandler(HandlerData& data)
2431     {
2432         StreamSP out_stream = data.GetOutStream();
2433         bool batch_mode = data.GetBatchMode();
2434         if (data.reader.GetPrompt() && !batch_mode)
2435         {
2436             out_stream->Printf ("%s", data.reader.GetPrompt());
2437             out_stream->Flush();
2438         }
2439     }
2440     virtual void GotTokenHandler(HandlerData& data)
2441     {
2442         StreamSP out_stream = data.GetOutStream();
2443         bool batch_mode = data.GetBatchMode();
2444         if (data.bytes && data.bytes_len && data.baton)
2445         {
2446             ((SynthAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len);
2447         }
2448         if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
2449         {
2450             out_stream->Printf ("%s", data.reader.GetPrompt());
2451             out_stream->Flush();
2452         }
2453     }
2454     virtual void InterruptHandler(HandlerData& data)
2455     {
2456         StreamSP out_stream = data.GetOutStream();
2457         bool batch_mode = data.GetBatchMode();
2458         data.reader.SetIsDone (true);
2459         if (!batch_mode)
2460         {
2461             out_stream->Printf ("Warning: No command attached to breakpoint.\n");
2462             out_stream->Flush();
2463         }
2464     }
2465     virtual void EOFHandler(HandlerData& data)
2466     {
2467         data.reader.SetIsDone (true);
2468     }
2469     virtual void DoneHandler(HandlerData& data)
2470     {
2471         StreamSP out_stream = data.GetOutStream();
2472         SynthAddOptions *options_ptr = ((SynthAddOptions*)data.baton);
2473         if (!options_ptr)
2474         {
2475             out_stream->Printf ("Internal error #1: no script attached.\n");
2476             out_stream->Flush();
2477             return;
2478         }
2479 
2480         SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
2481 
2482         ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
2483         if (!interpreter)
2484         {
2485             out_stream->Printf ("Internal error #2: no script attached.\n");
2486             out_stream->Flush();
2487             return;
2488         }
2489         StringList class_name_sl;
2490         if (!interpreter->GenerateTypeSynthClass (options->m_user_source,
2491                                                   class_name_sl))
2492         {
2493             out_stream->Printf ("Internal error #3: no script attached.\n");
2494             out_stream->Flush();
2495             return;
2496         }
2497         if (class_name_sl.GetSize() == 0)
2498         {
2499             out_stream->Printf ("Internal error #4: no script attached.\n");
2500             out_stream->Flush();
2501             return;
2502         }
2503         const char *class_name = class_name_sl.GetStringAtIndex(0);
2504         if (!class_name || !class_name[0])
2505         {
2506             out_stream->Printf ("Internal error #5: no script attached.\n");
2507             out_stream->Flush();
2508             return;
2509         }
2510 
2511         // everything should be fine now, let's add the synth provider class
2512 
2513         SyntheticChildrenSP synth_provider;
2514         synth_provider.reset(new SyntheticScriptProvider(options->m_cascade,
2515                                                          options->m_skip_pointers,
2516                                                          options->m_skip_references,
2517                                                          std::string(class_name)));
2518 
2519 
2520         lldb::FormatCategorySP category;
2521         Debugger::Formatting::Categories::Get(ConstString(options->m_category), category);
2522 
2523         for (size_t i = 0; i < options->m_target_types.GetSize(); i++) {
2524             const char *type_name = options->m_target_types.GetStringAtIndex(i);
2525             ConstString typeCS(type_name);
2526             if (typeCS)
2527                 CommandObjectTypeSynthAdd::AddSynth(typeCS,
2528                                                     synth_provider,
2529                                                     options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth,
2530                                                     options->m_category,
2531                                                     NULL);
2532             else
2533             {
2534                 out_stream->Printf ("Internal error #6: no script attached.\n");
2535                 out_stream->Flush();
2536                 return;
2537             }
2538         }
2539     }
2540 };
2541 
2542 void
2543 CommandObjectTypeSynthAdd::CollectPythonScript (SynthAddOptions *options,
2544                                                 CommandReturnObject &result)
2545 {
2546     InputReaderSP reader_sp (new TypeSynthAddInputReader(m_interpreter.GetDebugger()));
2547     if (reader_sp && options)
2548     {
2549 
2550         InputReaderEZ::InitializationParameters ipr;
2551 
2552         Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt("     ")));
2553         if (err.Success())
2554         {
2555             m_interpreter.GetDebugger().PushInputReader (reader_sp);
2556             result.SetStatus (eReturnStatusSuccessFinishNoResult);
2557         }
2558         else
2559         {
2560             result.AppendError (err.AsCString());
2561             result.SetStatus (eReturnStatusFailed);
2562         }
2563     }
2564     else
2565     {
2566         result.AppendError("out of memory");
2567         result.SetStatus (eReturnStatusFailed);
2568     }
2569 }
2570 
2571 bool
2572 CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result)
2573 {
2574     SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers,
2575                                                      m_options.m_skip_references,
2576                                                      m_options.m_cascade,
2577                                                      m_options.m_regex,
2578                                                      m_options.m_category);
2579 
2580     const size_t argc = command.GetArgumentCount();
2581 
2582     for (size_t i = 0; i < argc; i++) {
2583         const char* typeA = command.GetArgumentAtIndex(i);
2584         if (typeA && *typeA)
2585             options->m_target_types << typeA;
2586         else
2587         {
2588             result.AppendError("empty typenames not allowed");
2589             result.SetStatus(eReturnStatusFailed);
2590             return false;
2591         }
2592     }
2593 
2594     CollectPythonScript(options,result);
2595     return result.Succeeded();
2596 }
2597 
2598 bool
2599 CommandObjectTypeSynthAdd::Execute_ChildrenList (Args& command, CommandReturnObject &result)
2600 {
2601     const size_t argc = command.GetArgumentCount();
2602 
2603     if (argc < 1)
2604     {
2605         result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
2606         result.SetStatus(eReturnStatusFailed);
2607         return false;
2608     }
2609 
2610     if (m_options.m_expr_paths.size() == 0)
2611     {
2612         result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
2613         result.SetStatus(eReturnStatusFailed);
2614         return false;
2615     }
2616 
2617     SyntheticChildrenSP entry;
2618 
2619     SyntheticFilter* impl = new SyntheticFilter(m_options.m_cascade,
2620                                                 m_options.m_skip_pointers,
2621                                                 m_options.m_skip_references);
2622 
2623     entry.reset(impl);
2624 
2625     // go through the expression paths
2626     CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
2627 
2628     for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2629         impl->AddExpressionPath(*begin);
2630 
2631 
2632     // now I have a valid provider, let's add it to every type
2633 
2634     lldb::FormatCategorySP category;
2635     Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
2636 
2637     for (size_t i = 0; i < argc; i++) {
2638         const char* typeA = command.GetArgumentAtIndex(i);
2639         ConstString typeCS(typeA);
2640         if (typeCS)
2641             AddSynth(typeCS,
2642                      entry,
2643                      m_options.m_regex ? eRegexSynth : eRegularSynth,
2644                      m_options.m_category,
2645                      NULL);
2646         else
2647         {
2648             result.AppendError("empty typenames not allowed");
2649             result.SetStatus(eReturnStatusFailed);
2650             return false;
2651         }
2652     }
2653 
2654     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2655     return result.Succeeded();
2656 }
2657 
2658 bool
2659 CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result)
2660 {
2661     const size_t argc = command.GetArgumentCount();
2662 
2663     if (argc < 1)
2664     {
2665         result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
2666         result.SetStatus(eReturnStatusFailed);
2667         return false;
2668     }
2669 
2670     if (m_options.m_class_name.empty() && !m_options.m_input_python)
2671     {
2672         result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str());
2673         result.SetStatus(eReturnStatusFailed);
2674         return false;
2675     }
2676 
2677     SyntheticChildrenSP entry;
2678 
2679     SyntheticScriptProvider* impl = new SyntheticScriptProvider(m_options.m_cascade,
2680                                                                 m_options.m_skip_pointers,
2681                                                                 m_options.m_skip_references,
2682                                                                 m_options.m_class_name);
2683 
2684     entry.reset(impl);
2685 
2686     // now I have a valid provider, let's add it to every type
2687 
2688     lldb::FormatCategorySP category;
2689     Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
2690 
2691     for (size_t i = 0; i < argc; i++) {
2692         const char* typeA = command.GetArgumentAtIndex(i);
2693         ConstString typeCS(typeA);
2694         if (typeCS)
2695             AddSynth(typeCS,
2696                      entry,
2697                      m_options.m_regex ? eRegexSynth : eRegularSynth,
2698                      m_options.m_category,
2699                      NULL);
2700         else
2701         {
2702             result.AppendError("empty typenames not allowed");
2703             result.SetStatus(eReturnStatusFailed);
2704             return false;
2705         }
2706     }
2707 
2708     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2709     return result.Succeeded();
2710 }
2711 
2712 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) :
2713 CommandObject (interpreter,
2714                "type synthetic add",
2715                "Add a new synthetic provider for a type.",
2716                NULL), m_options (interpreter)
2717 {
2718     CommandArgumentEntry type_arg;
2719     CommandArgumentData type_style_arg;
2720 
2721     type_style_arg.arg_type = eArgTypeName;
2722     type_style_arg.arg_repetition = eArgRepeatPlus;
2723 
2724     type_arg.push_back (type_style_arg);
2725 
2726     m_arguments.push_back (type_arg);
2727 
2728 }
2729 
2730 bool
2731 CommandObjectTypeSynthAdd::AddSynth(const ConstString& type_name,
2732          SyntheticChildrenSP entry,
2733          SynthFormatType type,
2734          const char* category_name,
2735          Error* error)
2736 {
2737     lldb::FormatCategorySP category;
2738     Debugger::Formatting::Categories::Get(ConstString(category_name), category);
2739 
2740     if (type == eRegexSynth)
2741     {
2742         RegularExpressionSP typeRX(new RegularExpression());
2743         if (!typeRX->Compile(type_name.GetCString()))
2744         {
2745             if (error)
2746                 error->SetErrorString("regex format error (maybe this is not really a regex?)");
2747             return false;
2748         }
2749 
2750         category->RegexFilter()->Delete(type_name.GetCString());
2751         category->RegexFilter()->Add(typeRX, entry);
2752 
2753         return true;
2754     }
2755     else
2756     {
2757         category->Filter()->Add(type_name.GetCString(), entry);
2758         return true;
2759     }
2760 }
2761 
2762 bool
2763 CommandObjectTypeSynthAdd::Execute (Args& command, CommandReturnObject &result)
2764 {
2765     if (m_options.handwrite_python)
2766         return Execute_HandwritePython(command, result);
2767     else if (m_options.is_class_based)
2768         return Execute_PythonClass(command, result);
2769     else if (m_options.has_child_list)
2770         return Execute_ChildrenList(command, result);
2771     else
2772     {
2773         result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line");
2774         result.SetStatus(eReturnStatusFailed);
2775         return false;
2776     }
2777 }
2778 
2779 OptionDefinition
2780 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
2781 {
2782     { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade to derived typedefs."},
2783     { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
2784     { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
2785     { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,         "Add this to the given category instead of the default one."},
2786     { LLDB_OPT_SET_1, false, "child", 'c', required_argument, NULL, 0, eArgTypeName,    "Include this expression path in the synthetic view."},
2787     { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypeName,    "Use this Python class to produce synthetic children."},
2788     { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone,    "Type Python code to generate a class that provides synthetic children."},
2789     { LLDB_OPT_SET_ALL, false,  "regex", 'x', no_argument, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
2790     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2791 };
2792 
2793 class CommandObjectTypeFormat : public CommandObjectMultiword
2794 {
2795 public:
2796     CommandObjectTypeFormat (CommandInterpreter &interpreter) :
2797         CommandObjectMultiword (interpreter,
2798                                 "type format",
2799                                 "A set of commands for editing variable value display options",
2800                                 "type format [<sub-command-options>] ")
2801     {
2802         LoadSubCommand ("add",    CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter)));
2803         LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectTypeFormatClear (interpreter)));
2804         LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter)));
2805         LoadSubCommand ("list",   CommandObjectSP (new CommandObjectTypeFormatList (interpreter)));
2806     }
2807 
2808 
2809     ~CommandObjectTypeFormat ()
2810     {
2811     }
2812 };
2813 
2814 class CommandObjectTypeSynth : public CommandObjectMultiword
2815 {
2816 public:
2817     CommandObjectTypeSynth (CommandInterpreter &interpreter) :
2818     CommandObjectMultiword (interpreter,
2819                             "type synthetic",
2820                             "A set of commands for operating on synthetic type representations",
2821                             "type synthetic [<sub-command-options>] ")
2822     {
2823         LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter)));
2824         LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSynthClear (interpreter)));
2825         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter)));
2826         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSynthList (interpreter)));
2827     }
2828 
2829 
2830     ~CommandObjectTypeSynth ()
2831     {
2832     }
2833 };
2834 
2835 class CommandObjectTypeCategory : public CommandObjectMultiword
2836 {
2837 public:
2838     CommandObjectTypeCategory (CommandInterpreter &interpreter) :
2839     CommandObjectMultiword (interpreter,
2840                             "type category",
2841                             "A set of commands for operating on categories",
2842                             "type category [<sub-command-options>] ")
2843     {
2844         LoadSubCommand ("enable",        CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter)));
2845         LoadSubCommand ("disable",       CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter)));
2846         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter)));
2847         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeCategoryList (interpreter)));
2848     }
2849 
2850 
2851     ~CommandObjectTypeCategory ()
2852     {
2853     }
2854 };
2855 
2856 class CommandObjectTypeSummary : public CommandObjectMultiword
2857 {
2858 public:
2859     CommandObjectTypeSummary (CommandInterpreter &interpreter) :
2860     CommandObjectMultiword (interpreter,
2861                             "type summary",
2862                             "A set of commands for editing variable summary display options",
2863                             "type summary [<sub-command-options>] ")
2864     {
2865         LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter)));
2866         LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));
2867         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));
2868         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSummaryList (interpreter)));
2869     }
2870 
2871 
2872     ~CommandObjectTypeSummary ()
2873     {
2874     }
2875 };
2876 
2877 //-------------------------------------------------------------------------
2878 // CommandObjectType
2879 //-------------------------------------------------------------------------
2880 
2881 CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) :
2882     CommandObjectMultiword (interpreter,
2883                             "type",
2884                             "A set of commands for operating on the type system",
2885                             "type [<sub-command-options>]")
2886 {
2887     LoadSubCommand ("category",  CommandObjectSP (new CommandObjectTypeCategory (interpreter)));
2888     LoadSubCommand ("format",    CommandObjectSP (new CommandObjectTypeFormat (interpreter)));
2889     LoadSubCommand ("summary",   CommandObjectSP (new CommandObjectTypeSummary (interpreter)));
2890     LoadSubCommand ("synthetic",     CommandObjectSP (new CommandObjectTypeSynth (interpreter)));
2891 }
2892 
2893 
2894 CommandObjectType::~CommandObjectType ()
2895 {
2896 }
2897 
2898 
2899