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