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                     break;
1286                 case 'l':
1287                     error = m_category_language.SetValueFromString(option_arg);
1288                     break;
1289                 default:
1290                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1291                     break;
1292             }
1293 
1294             return error;
1295         }
1296 
1297         void
1298         OptionParsingStarting () override
1299         {
1300             m_category_regex.Clear();
1301             m_category_language.Clear();
1302         }
1303 
1304         const OptionDefinition*
1305         GetDefinitions () override
1306         {
1307             static OptionDefinition g_option_table[] =
1308             {
1309                 { LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
1310                 { LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,  "Only show the category for a specific language."},
1311                 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1312             };
1313 
1314             return g_option_table;
1315         }
1316 
1317         // Options table: Required for subclasses of Options.
1318 
1319         static OptionDefinition g_option_table[];
1320 
1321         // Instance variables to hold the values for command options.
1322 
1323         OptionValueString m_category_regex;
1324         OptionValueLanguage m_category_language;
1325     };
1326 
1327     CommandOptions m_options;
1328 
1329     Options *
1330     GetOptions () override
1331     {
1332         return &m_options;
1333     }
1334 
1335 public:
1336     CommandObjectTypeFormatterList (CommandInterpreter &interpreter,
1337                                     const char* name,
1338                                     const char* help) :
1339         CommandObjectParsed (interpreter,
1340                              name,
1341                              help,
1342                              NULL),
1343     m_options(interpreter)
1344     {
1345         CommandArgumentEntry type_arg;
1346         CommandArgumentData type_style_arg;
1347 
1348         type_style_arg.arg_type = eArgTypeName;
1349         type_style_arg.arg_repetition = eArgRepeatOptional;
1350 
1351         type_arg.push_back (type_style_arg);
1352 
1353         m_arguments.push_back (type_arg);
1354     }
1355 
1356     ~CommandObjectTypeFormatterList () override
1357     {
1358     }
1359 
1360 protected:
1361     virtual void
1362     FormatterSpecificList (CommandReturnObject &result)
1363     {
1364     }
1365 
1366     bool
1367     DoExecute (Args& command, CommandReturnObject &result) override
1368     {
1369         const size_t argc = command.GetArgumentCount();
1370 
1371         std::unique_ptr<RegularExpression> category_regex;
1372         std::unique_ptr<RegularExpression> formatter_regex;
1373 
1374         if (m_options.m_category_regex.OptionWasSet())
1375         {
1376             category_regex.reset(new RegularExpression());
1377             if (!category_regex->Compile(m_options.m_category_regex.GetCurrentValue()))
1378             {
1379                 result.AppendErrorWithFormat("syntax error in category regular expression '%s'", m_options.m_category_regex.GetCurrentValue());
1380                 result.SetStatus(eReturnStatusFailed);
1381                 return false;
1382             }
1383         }
1384 
1385         if (argc == 1)
1386         {
1387             const char* arg = command.GetArgumentAtIndex(1);
1388             formatter_regex.reset(new RegularExpression());
1389             if (!formatter_regex->Compile(arg))
1390             {
1391                 result.AppendErrorWithFormat("syntax error in regular expression '%s'", arg);
1392                 result.SetStatus(eReturnStatusFailed);
1393                 return false;
1394             }
1395         }
1396 
1397         auto category_closure = [&result, &formatter_regex] (const lldb::TypeCategoryImplSP& category) -> void {
1398             result.GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", category->GetName());
1399             TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach;
1400             foreach.SetExact([&result, &formatter_regex] (ConstString name, const FormatterSharedPointer& format_sp) -> bool {
1401                 if (formatter_regex)
1402                 {
1403                     bool escape = true;
1404                     if (0 == strcmp(name.AsCString(), formatter_regex->GetText()))
1405                     {
1406                         escape = false;
1407                     }
1408                     else if (formatter_regex->Execute(name.AsCString()))
1409                     {
1410                         escape = false;
1411                     }
1412 
1413                     if (escape)
1414                         return true;
1415                 }
1416 
1417                 result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), format_sp->GetDescription().c_str());
1418 
1419                 return true;
1420             });
1421 
1422             foreach.SetWithRegex( [&result, &formatter_regex] (RegularExpressionSP regex_sp, const FormatterSharedPointer& format_sp) -> bool {
1423                 if (formatter_regex)
1424                 {
1425                     bool escape = true;
1426                     if (0 == strcmp(regex_sp->GetText(), formatter_regex->GetText()))
1427                     {
1428                         escape = false;
1429                     }
1430                     else if (formatter_regex->Execute(regex_sp->GetText()))
1431                     {
1432                         escape = false;
1433                     }
1434 
1435                     if (escape)
1436                         return true;
1437                 }
1438 
1439                 result.GetOutputStream().Printf ("%s: %s\n", regex_sp->GetText(), format_sp->GetDescription().c_str());
1440 
1441                 return true;
1442             });
1443 
1444             category->ForEach(foreach);
1445         };
1446 
1447         if (m_options.m_category_language.OptionWasSet())
1448         {
1449             lldb::TypeCategoryImplSP category_sp;
1450             DataVisualization::Categories::GetCategory(m_options.m_category_language.GetCurrentValue(), category_sp);
1451             if (category_sp)
1452                 category_closure(category_sp);
1453         }
1454         else
1455         {
1456             DataVisualization::Categories::ForEach( [this, &command, &result, &category_regex, &formatter_regex, &category_closure] (const lldb::TypeCategoryImplSP& category) -> bool {
1457                 if (category_regex)
1458                 {
1459                     bool escape = true;
1460                     if (0 == strcmp(category->GetName(), category_regex->GetText()))
1461                     {
1462                         escape = false;
1463                     }
1464                     else if (category_regex->Execute(category->GetName()))
1465                     {
1466                         escape = false;
1467                     }
1468 
1469                     if (escape)
1470                         return true;
1471                 }
1472 
1473                 category_closure(category);
1474 
1475                 return true;
1476             });
1477 
1478             FormatterSpecificList(result);
1479         }
1480 
1481         result.SetStatus(eReturnStatusSuccessFinishResult);
1482         return result.Succeeded();
1483     }
1484 };
1485 
1486 //-------------------------------------------------------------------------
1487 // CommandObjectTypeFormatList
1488 //-------------------------------------------------------------------------
1489 
1490 class CommandObjectTypeFormatList : public CommandObjectTypeFormatterList<TypeFormatImpl>
1491 {
1492 public:
1493 
1494     CommandObjectTypeFormatList (CommandInterpreter &interpreter) :
1495         CommandObjectTypeFormatterList(interpreter,
1496                                        "type format list",
1497                                        "Show a list of current formats.")
1498     {
1499     }
1500 };
1501 
1502 #ifndef LLDB_DISABLE_PYTHON
1503 
1504 //-------------------------------------------------------------------------
1505 // CommandObjectTypeSummaryAdd
1506 //-------------------------------------------------------------------------
1507 
1508 #endif // #ifndef LLDB_DISABLE_PYTHON
1509 
1510 Error
1511 CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
1512 {
1513     Error error;
1514     const int short_option = m_getopt_table[option_idx].val;
1515     bool success;
1516 
1517     switch (short_option)
1518     {
1519         case 'C':
1520             m_flags.SetCascades(Args::StringToBoolean(option_arg, true, &success));
1521             if (!success)
1522                 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg);
1523             break;
1524         case 'e':
1525             m_flags.SetDontShowChildren(false);
1526             break;
1527         case 'h':
1528             m_flags.SetHideEmptyAggregates(true);
1529             break;
1530         case 'v':
1531             m_flags.SetDontShowValue(true);
1532             break;
1533         case 'c':
1534             m_flags.SetShowMembersOneLiner(true);
1535             break;
1536         case 's':
1537             m_format_string = std::string(option_arg);
1538             break;
1539         case 'p':
1540             m_flags.SetSkipPointers(true);
1541             break;
1542         case 'r':
1543             m_flags.SetSkipReferences(true);
1544             break;
1545         case 'x':
1546             m_regex = true;
1547             break;
1548         case 'n':
1549             m_name.SetCString(option_arg);
1550             break;
1551         case 'o':
1552             m_python_script = std::string(option_arg);
1553             m_is_add_script = true;
1554             break;
1555         case 'F':
1556             m_python_function = std::string(option_arg);
1557             m_is_add_script = true;
1558             break;
1559         case 'P':
1560             m_is_add_script = true;
1561             break;
1562         case 'w':
1563             m_category = std::string(option_arg);
1564             break;
1565         case 'O':
1566             m_flags.SetHideItemNames(true);
1567             break;
1568         default:
1569             error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1570             break;
1571     }
1572 
1573     return error;
1574 }
1575 
1576 void
1577 CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting ()
1578 {
1579     m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1580     m_flags.SetShowMembersOneLiner(false).SetSkipPointers(false).SetSkipReferences(false).SetHideItemNames(false);
1581 
1582     m_regex = false;
1583     m_name.Clear();
1584     m_python_script = "";
1585     m_python_function = "";
1586     m_format_string = "";
1587     m_is_add_script = false;
1588     m_category = "default";
1589 }
1590 
1591 
1592 
1593 #ifndef LLDB_DISABLE_PYTHON
1594 
1595 bool
1596 CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result)
1597 {
1598     const size_t argc = command.GetArgumentCount();
1599 
1600     if (argc < 1 && !m_options.m_name)
1601     {
1602         result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
1603         result.SetStatus(eReturnStatusFailed);
1604         return false;
1605     }
1606 
1607     TypeSummaryImplSP script_format;
1608 
1609     if (!m_options.m_python_function.empty()) // we have a Python function ready to use
1610     {
1611         const char *funct_name = m_options.m_python_function.c_str();
1612         if (!funct_name || !funct_name[0])
1613         {
1614             result.AppendError ("function name empty.\n");
1615             result.SetStatus (eReturnStatusFailed);
1616             return false;
1617         }
1618 
1619         std::string code = ("    " + m_options.m_python_function + "(valobj,internal_dict)");
1620 
1621         script_format.reset(new ScriptSummaryFormat(m_options.m_flags,
1622                                                     funct_name,
1623                                                     code.c_str()));
1624 
1625         ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1626 
1627         if (interpreter && interpreter->CheckObjectExists(funct_name) == false)
1628             result.AppendWarningWithFormat("The provided function \"%s\" does not exist - "
1629                                            "please define it before attempting to use this summary.\n",
1630                                            funct_name);
1631     }
1632     else if (!m_options.m_python_script.empty()) // we have a quick 1-line script, just use it
1633     {
1634         ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1635         if (!interpreter)
1636         {
1637             result.AppendError ("script interpreter missing - unable to generate function wrapper.\n");
1638             result.SetStatus (eReturnStatusFailed);
1639             return false;
1640         }
1641         StringList funct_sl;
1642         funct_sl << m_options.m_python_script.c_str();
1643         std::string funct_name_str;
1644         if (!interpreter->GenerateTypeScriptFunction (funct_sl,
1645                                                       funct_name_str))
1646         {
1647             result.AppendError ("unable to generate function wrapper.\n");
1648             result.SetStatus (eReturnStatusFailed);
1649             return false;
1650         }
1651         if (funct_name_str.empty())
1652         {
1653             result.AppendError ("script interpreter failed to generate a valid function name.\n");
1654             result.SetStatus (eReturnStatusFailed);
1655             return false;
1656         }
1657 
1658         std::string code = "    " + m_options.m_python_script;
1659 
1660         script_format.reset(new ScriptSummaryFormat(m_options.m_flags,
1661                                                     funct_name_str.c_str(),
1662                                                     code.c_str()));
1663     }
1664     else
1665     {
1666         // Use an IOHandler to grab Python code from the user
1667         ScriptAddOptions *options = new ScriptAddOptions(m_options.m_flags,
1668                                                          m_options.m_regex,
1669                                                          m_options.m_name,
1670                                                          m_options.m_category);
1671 
1672         for (size_t i = 0; i < argc; i++)
1673         {
1674             const char* typeA = command.GetArgumentAtIndex(i);
1675             if (typeA && *typeA)
1676                 options->m_target_types << typeA;
1677             else
1678             {
1679                 result.AppendError("empty typenames not allowed");
1680                 result.SetStatus(eReturnStatusFailed);
1681                 return false;
1682             }
1683         }
1684 
1685         m_interpreter.GetPythonCommandsFromIOHandler ("    ",   // Prompt
1686                                                       *this,    // IOHandlerDelegate
1687                                                       true,     // Run IOHandler in async mode
1688                                                       options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
1689         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1690 
1691         return result.Succeeded();
1692     }
1693 
1694     // if I am here, script_format must point to something good, so I can add that
1695     // as a script summary to all interested parties
1696 
1697     Error error;
1698 
1699     for (size_t i = 0; i < command.GetArgumentCount(); i++)
1700     {
1701         const char *type_name = command.GetArgumentAtIndex(i);
1702         CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
1703                                                 script_format,
1704                                                 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1705                                                 m_options.m_category,
1706                                                 &error);
1707         if (error.Fail())
1708         {
1709             result.AppendError(error.AsCString());
1710             result.SetStatus(eReturnStatusFailed);
1711             return false;
1712         }
1713     }
1714 
1715     if (m_options.m_name)
1716     {
1717         AddSummary(m_options.m_name, script_format, eNamedSummary, m_options.m_category, &error);
1718         if (error.Fail())
1719         {
1720             result.AppendError(error.AsCString());
1721             result.AppendError("added to types, but not given a name");
1722             result.SetStatus(eReturnStatusFailed);
1723             return false;
1724         }
1725     }
1726 
1727     return result.Succeeded();
1728 }
1729 
1730 #endif
1731 
1732 
1733 bool
1734 CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result)
1735 {
1736     const size_t argc = command.GetArgumentCount();
1737 
1738     if (argc < 1 && !m_options.m_name)
1739     {
1740         result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
1741         result.SetStatus(eReturnStatusFailed);
1742         return false;
1743     }
1744 
1745     if (!m_options.m_flags.GetShowMembersOneLiner() && m_options.m_format_string.empty())
1746     {
1747         result.AppendError("empty summary strings not allowed");
1748         result.SetStatus(eReturnStatusFailed);
1749         return false;
1750     }
1751 
1752     const char* format_cstr = (m_options.m_flags.GetShowMembersOneLiner() ? "" : m_options.m_format_string.c_str());
1753 
1754     // ${var%S} is an endless recursion, prevent it
1755     if (strcmp(format_cstr, "${var%S}") == 0)
1756     {
1757         result.AppendError("recursive summary not allowed");
1758         result.SetStatus(eReturnStatusFailed);
1759         return false;
1760     }
1761 
1762     Error error;
1763 
1764     lldb::TypeSummaryImplSP entry(new StringSummaryFormat(m_options.m_flags,
1765                                                         format_cstr));
1766 
1767     if (error.Fail())
1768     {
1769         result.AppendError(error.AsCString());
1770         result.SetStatus(eReturnStatusFailed);
1771         return false;
1772     }
1773 
1774     // now I have a valid format, let's add it to every type
1775 
1776     for (size_t i = 0; i < argc; i++)
1777     {
1778         const char* typeA = command.GetArgumentAtIndex(i);
1779         if (!typeA || typeA[0] == '\0')
1780         {
1781             result.AppendError("empty typenames not allowed");
1782             result.SetStatus(eReturnStatusFailed);
1783             return false;
1784         }
1785         ConstString typeCS(typeA);
1786 
1787         AddSummary(typeCS,
1788                    entry,
1789                    (m_options.m_regex ? eRegexSummary : eRegularSummary),
1790                    m_options.m_category,
1791                    &error);
1792 
1793         if (error.Fail())
1794         {
1795             result.AppendError(error.AsCString());
1796             result.SetStatus(eReturnStatusFailed);
1797             return false;
1798         }
1799     }
1800 
1801     if (m_options.m_name)
1802     {
1803         AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, &error);
1804         if (error.Fail())
1805         {
1806             result.AppendError(error.AsCString());
1807             result.AppendError("added to types, but not given a name");
1808             result.SetStatus(eReturnStatusFailed);
1809             return false;
1810         }
1811     }
1812 
1813     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1814     return result.Succeeded();
1815 }
1816 
1817 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) :
1818     CommandObjectParsed (interpreter,
1819                          "type summary add",
1820                          "Add a new summary style for a type.",
1821                          NULL),
1822     IOHandlerDelegateMultiline ("DONE"),
1823     m_options (interpreter)
1824 {
1825     CommandArgumentEntry type_arg;
1826     CommandArgumentData type_style_arg;
1827 
1828     type_style_arg.arg_type = eArgTypeName;
1829     type_style_arg.arg_repetition = eArgRepeatPlus;
1830 
1831     type_arg.push_back (type_style_arg);
1832 
1833     m_arguments.push_back (type_arg);
1834 
1835     SetHelpLong(
1836 R"(
1837 The following examples of 'type summary add' refer to this code snippet for context:
1838 
1839     struct JustADemo
1840     {
1841         int* ptr;
1842         float value;
1843         JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1844     };
1845     JustADemo demo_instance(42, 3.14);
1846 
1847     typedef JustADemo NewDemo;
1848     NewDemo new_demo_instance(42, 3.14);
1849 
1850 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1851 
1852     Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1853 
1854 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1855 
1856     Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1857 
1858 )" "Alternatively, you could define formatting for all pointers to integers and \
1859 rely on that when formatting JustADemo to obtain the same result:" R"(
1860 
1861 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1862 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1863 
1864 )" "Type summaries are automatically applied to derived typedefs, so the examples \
1865 above apply to both JustADemo and NewDemo.  The cascade option can be used to \
1866 suppress this behavior:" R"(
1867 
1868 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1869 
1870     The summary will now be used for values of JustADemo but not NewDemo.
1871 
1872 )" "By default summaries are shown for pointers and references to values of the \
1873 specified type.  To suppress formatting for pointers use the -p option, or apply \
1874 the corresponding -r option to suppress formatting for references:" R"(
1875 
1876 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1877 
1878 )" "One-line summaries including all fields in a type can be inferred without supplying an \
1879 explicit summary string by passing the -c option:" R"(
1880 
1881 (lldb) type summary add -c JustADemo
1882 (lldb) frame variable demo_instance
1883 (ptr=<address>, value=3.14)
1884 
1885 )" "Type summaries normally suppress the nested display of individual fields.  To \
1886 supply a summary to supplement the default structure add the -e option:" R"(
1887 
1888 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1889 
1890 )" "Now when displaying JustADemo values the int* is displayed, followed by the \
1891 standard LLDB sequence of children, one per line:" R"(
1892 
1893 *ptr = 42 {
1894   ptr = <address>
1895   value = 3.14
1896 }
1897 
1898 )" "You can also add summaries written in Python.  These scripts use lldb public API to \
1899 gather information from your variables and produce a meaningful summary.  To start a \
1900 multi-line script use the -P option.  The function declaration will be displayed along with \
1901 a comment describing the two arguments.  End your script with the  word 'DONE' on a line by \
1902 itself:" R"(
1903 
1904 (lldb) type summary add JustADemo -P
1905 def function (valobj,internal_dict):
1906 """valobj: an SBValue which you want to provide a summary for
1907 internal_dict: an LLDB support object not to be used"""
1908     value = valobj.GetChildMemberWithName('value');
1909     return 'My value is ' + value.GetValue();
1910     DONE
1911 
1912 Alternatively, the -o option can be used when providing a simple one-line Python script:
1913 
1914 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"
1915     );
1916 }
1917 
1918 bool
1919 CommandObjectTypeSummaryAdd::DoExecute (Args& command, CommandReturnObject &result)
1920 {
1921     WarnOnPotentialUnquotedUnsignedType(command, result);
1922 
1923     if (m_options.m_is_add_script)
1924     {
1925 #ifndef LLDB_DISABLE_PYTHON
1926         return Execute_ScriptSummary(command, result);
1927 #else
1928         result.AppendError ("python is disabled");
1929         result.SetStatus(eReturnStatusFailed);
1930         return false;
1931 #endif
1932     }
1933 
1934     return Execute_StringSummary(command, result);
1935 }
1936 
1937 static bool
1938 FixArrayTypeNameWithRegex (ConstString &type_name)
1939 {
1940     llvm::StringRef type_name_ref(type_name.GetStringRef());
1941 
1942     if (type_name_ref.endswith("[]"))
1943     {
1944         std::string type_name_str(type_name.GetCString());
1945         type_name_str.resize(type_name_str.length()-2);
1946         if (type_name_str.back() != ' ')
1947             type_name_str.append(" \\[[0-9]+\\]");
1948         else
1949             type_name_str.append("\\[[0-9]+\\]");
1950         type_name.SetCString(type_name_str.c_str());
1951         return true;
1952     }
1953     return false;
1954 }
1955 
1956 bool
1957 CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
1958                                         TypeSummaryImplSP entry,
1959                                         SummaryFormatType type,
1960                                         std::string category_name,
1961                                         Error* error)
1962 {
1963     lldb::TypeCategoryImplSP category;
1964     DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
1965 
1966     if (type == eRegularSummary)
1967     {
1968         if (FixArrayTypeNameWithRegex (type_name))
1969             type = eRegexSummary;
1970     }
1971 
1972     if (type == eRegexSummary)
1973     {
1974         RegularExpressionSP typeRX(new RegularExpression());
1975         if (!typeRX->Compile(type_name.GetCString()))
1976         {
1977             if (error)
1978                 error->SetErrorString("regex format error (maybe this is not really a regex?)");
1979             return false;
1980         }
1981 
1982         category->GetRegexTypeSummariesContainer()->Delete(type_name);
1983         category->GetRegexTypeSummariesContainer()->Add(typeRX, entry);
1984 
1985         return true;
1986     }
1987     else if (type == eNamedSummary)
1988     {
1989         // system named summaries do not exist (yet?)
1990         DataVisualization::NamedSummaryFormats::Add(type_name,entry);
1991         return true;
1992     }
1993     else
1994     {
1995         category->GetTypeSummariesContainer()->Add(type_name, entry);
1996         return true;
1997     }
1998 }
1999 
2000 OptionDefinition
2001 CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
2002 {
2003     { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,    "Add this to the given category instead of the default one."},
2004     { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,    "If true, cascade through typedef chains."},
2005     { 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."},
2006     { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
2007     { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
2008     { LLDB_OPT_SET_ALL, false,  "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
2009     { LLDB_OPT_SET_1  , true, "inline-children", 'c', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "If true, inline all child values into summary string."},
2010     { LLDB_OPT_SET_1  , false, "omit-names", 'O', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "If true, omit value names in the summary display."},
2011     { LLDB_OPT_SET_2  , true, "summary-string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeSummaryString,    "Summary string used to display text and object contents."},
2012     { 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."},
2013     { 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."},
2014     { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."},
2015     { 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."},
2016     { 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."},
2017     { LLDB_OPT_SET_2 | LLDB_OPT_SET_3,   false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,    "A name for this summary string."},
2018     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2019 };
2020 
2021 
2022 //-------------------------------------------------------------------------
2023 // CommandObjectTypeSummaryDelete
2024 //-------------------------------------------------------------------------
2025 
2026 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete
2027 {
2028 public:
2029     CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) :
2030     CommandObjectTypeFormatterDelete (interpreter,
2031                                       eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
2032                                       "type summary delete",
2033                                       "Delete an existing summary for a type.")
2034     {
2035     }
2036 
2037     ~CommandObjectTypeSummaryDelete () override
2038     {
2039     }
2040 
2041 protected:
2042     bool
2043     FormatterSpecificDeletion (ConstString typeCS) override
2044     {
2045         if (m_options.m_language != lldb::eLanguageTypeUnknown)
2046             return false;
2047         return DataVisualization::NamedSummaryFormats::Delete(typeCS);
2048     }
2049 };
2050 
2051 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear
2052 {
2053 public:
2054     CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) :
2055     CommandObjectTypeFormatterClear (interpreter,
2056                                      eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
2057                                      "type summary clear",
2058                                      "Delete all existing summaries.")
2059     {
2060     }
2061 
2062 protected:
2063     void
2064     FormatterSpecificDeletion () override
2065     {
2066         DataVisualization::NamedSummaryFormats::Clear();
2067     }
2068 };
2069 
2070 //-------------------------------------------------------------------------
2071 // CommandObjectTypeSummaryList
2072 //-------------------------------------------------------------------------
2073 
2074 class CommandObjectTypeSummaryList : public CommandObjectTypeFormatterList<TypeSummaryImpl>
2075 {
2076 public:
2077 
2078     CommandObjectTypeSummaryList (CommandInterpreter &interpreter) :
2079     CommandObjectTypeFormatterList(interpreter,
2080                                    "type summary list",
2081                                    "Show a list of current summaries.")
2082     {
2083     }
2084 
2085 protected:
2086     void
2087     FormatterSpecificList (CommandReturnObject &result) override
2088     {
2089         if (DataVisualization::NamedSummaryFormats::GetCount() > 0)
2090         {
2091             result.GetOutputStream().Printf("Named summaries:\n");
2092             DataVisualization::NamedSummaryFormats::ForEach( [&result] (ConstString name, const TypeSummaryImplSP& summary_sp) -> bool {
2093                 result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), summary_sp->GetDescription().c_str());
2094                 return true;
2095             });
2096         }
2097     }
2098 };
2099 
2100 //-------------------------------------------------------------------------
2101 // CommandObjectTypeCategoryDefine
2102 //-------------------------------------------------------------------------
2103 
2104 class CommandObjectTypeCategoryDefine : public CommandObjectParsed
2105 {
2106 
2107     class CommandOptions : public Options
2108     {
2109     public:
2110 
2111         CommandOptions (CommandInterpreter &interpreter) :
2112         Options (interpreter),
2113         m_define_enabled(false,false),
2114         m_cate_language(eLanguageTypeUnknown,eLanguageTypeUnknown)
2115         {
2116         }
2117 
2118         ~CommandOptions () override {}
2119 
2120         Error
2121         SetOptionValue (uint32_t option_idx, const char *option_arg) override
2122         {
2123             Error error;
2124             const int short_option = m_getopt_table[option_idx].val;
2125 
2126             switch (short_option)
2127             {
2128                 case 'e':
2129                     m_define_enabled.SetValueFromString("true");
2130                     break;
2131                 case 'l':
2132                     error = m_cate_language.SetValueFromString(option_arg);
2133                     break;
2134                 default:
2135                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2136                     break;
2137             }
2138 
2139             return error;
2140         }
2141 
2142         void
2143         OptionParsingStarting () override
2144         {
2145             m_define_enabled.Clear();
2146             m_cate_language.Clear();
2147         }
2148 
2149         const OptionDefinition*
2150         GetDefinitions () override
2151         {
2152             return g_option_table;
2153         }
2154 
2155         // Options table: Required for subclasses of Options.
2156 
2157         static OptionDefinition g_option_table[];
2158 
2159         // Instance variables to hold the values for command options.
2160 
2161         OptionValueBoolean m_define_enabled;
2162         OptionValueLanguage m_cate_language;
2163 
2164 
2165     };
2166 
2167     CommandOptions m_options;
2168 
2169     Options *
2170     GetOptions () override
2171     {
2172         return &m_options;
2173     }
2174 
2175 public:
2176     CommandObjectTypeCategoryDefine (CommandInterpreter &interpreter) :
2177     CommandObjectParsed (interpreter,
2178                          "type category define",
2179                          "Define a new category as a source of formatters.",
2180                          NULL),
2181     m_options(interpreter)
2182     {
2183         CommandArgumentEntry type_arg;
2184         CommandArgumentData type_style_arg;
2185 
2186         type_style_arg.arg_type = eArgTypeName;
2187         type_style_arg.arg_repetition = eArgRepeatPlus;
2188 
2189         type_arg.push_back (type_style_arg);
2190 
2191         m_arguments.push_back (type_arg);
2192 
2193     }
2194 
2195     ~CommandObjectTypeCategoryDefine () override
2196     {
2197     }
2198 
2199 protected:
2200     bool
2201     DoExecute (Args& command, CommandReturnObject &result) override
2202     {
2203         const size_t argc = command.GetArgumentCount();
2204 
2205         if (argc < 1)
2206         {
2207             result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
2208             result.SetStatus(eReturnStatusFailed);
2209             return false;
2210         }
2211 
2212         for (size_t i = 0; i < argc; i++)
2213         {
2214             const char* cateName = command.GetArgumentAtIndex(i);
2215             TypeCategoryImplSP category_sp;
2216             if (DataVisualization::Categories::GetCategory(ConstString(cateName), category_sp) && category_sp)
2217             {
2218                 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
2219                 if (m_options.m_define_enabled.GetCurrentValue())
2220                     DataVisualization::Categories::Enable(category_sp, TypeCategoryMap::Default);
2221             }
2222         }
2223 
2224         result.SetStatus(eReturnStatusSuccessFinishResult);
2225         return result.Succeeded();
2226     }
2227 
2228 };
2229 
2230 OptionDefinition
2231 CommandObjectTypeCategoryDefine::CommandOptions::g_option_table[] =
2232 {
2233     { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,  "If specified, this category will be created enabled."},
2234     { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,  "Specify the language that this category is supported for."},
2235     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2236 };
2237 
2238 //-------------------------------------------------------------------------
2239 // CommandObjectTypeCategoryEnable
2240 //-------------------------------------------------------------------------
2241 
2242 class CommandObjectTypeCategoryEnable : public CommandObjectParsed
2243 {
2244     class CommandOptions : public Options
2245     {
2246     public:
2247 
2248         CommandOptions (CommandInterpreter &interpreter) :
2249         Options (interpreter)
2250         {
2251         }
2252 
2253         ~CommandOptions () override {}
2254 
2255         Error
2256         SetOptionValue (uint32_t option_idx, const char *option_arg) override
2257         {
2258             Error error;
2259             const int short_option = m_getopt_table[option_idx].val;
2260 
2261             switch (short_option)
2262             {
2263                 case 'l':
2264                     if (option_arg)
2265                     {
2266                         m_language = Language::GetLanguageTypeFromString(option_arg);
2267                         if (m_language == lldb::eLanguageTypeUnknown)
2268                             error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg);
2269                     }
2270                     break;
2271                 default:
2272                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2273                     break;
2274             }
2275 
2276             return error;
2277         }
2278 
2279         void
2280         OptionParsingStarting () override
2281         {
2282             m_language = lldb::eLanguageTypeUnknown;
2283         }
2284 
2285         const OptionDefinition*
2286         GetDefinitions () override
2287         {
2288             return g_option_table;
2289         }
2290 
2291         // Options table: Required for subclasses of Options.
2292 
2293         static OptionDefinition g_option_table[];
2294 
2295         // Instance variables to hold the values for command options.
2296 
2297         lldb::LanguageType m_language;
2298 
2299     };
2300 
2301     CommandOptions m_options;
2302 
2303     Options *
2304     GetOptions () override
2305     {
2306         return &m_options;
2307     }
2308 
2309 public:
2310     CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) :
2311         CommandObjectParsed (interpreter,
2312                              "type category enable",
2313                              "Enable a category as a source of formatters.",
2314                              NULL),
2315         m_options(interpreter)
2316     {
2317         CommandArgumentEntry type_arg;
2318         CommandArgumentData type_style_arg;
2319 
2320         type_style_arg.arg_type = eArgTypeName;
2321         type_style_arg.arg_repetition = eArgRepeatPlus;
2322 
2323         type_arg.push_back (type_style_arg);
2324 
2325         m_arguments.push_back (type_arg);
2326 
2327     }
2328 
2329     ~CommandObjectTypeCategoryEnable () override
2330     {
2331     }
2332 
2333 protected:
2334     bool
2335     DoExecute (Args& command, CommandReturnObject &result) override
2336     {
2337         const size_t argc = command.GetArgumentCount();
2338 
2339         if (argc < 1 &&
2340             m_options.m_language == lldb::eLanguageTypeUnknown)
2341         {
2342             result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str());
2343             result.SetStatus(eReturnStatusFailed);
2344             return false;
2345         }
2346 
2347         if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)
2348         {
2349             DataVisualization::Categories::EnableStar();
2350         }
2351         else if (argc > 0)
2352         {
2353             for (int i = argc - 1; i >= 0; i--)
2354             {
2355                 const char* typeA = command.GetArgumentAtIndex(i);
2356                 ConstString typeCS(typeA);
2357 
2358                 if (!typeCS)
2359                 {
2360                     result.AppendError("empty category name not allowed");
2361                     result.SetStatus(eReturnStatusFailed);
2362                     return false;
2363                 }
2364                 DataVisualization::Categories::Enable(typeCS);
2365                 lldb::TypeCategoryImplSP cate;
2366                 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate.get())
2367                 {
2368                     if (cate->GetCount() == 0)
2369                     {
2370                         result.AppendWarning("empty category enabled (typo?)");
2371                     }
2372                 }
2373             }
2374         }
2375 
2376         if (m_options.m_language != lldb::eLanguageTypeUnknown)
2377             DataVisualization::Categories::Enable(m_options.m_language);
2378 
2379         result.SetStatus(eReturnStatusSuccessFinishResult);
2380         return result.Succeeded();
2381     }
2382 
2383 };
2384 
2385 OptionDefinition
2386 CommandObjectTypeCategoryEnable::CommandOptions::g_option_table[] =
2387 {
2388     { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,  "Enable the category for this language."},
2389     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2390 };
2391 
2392 //-------------------------------------------------------------------------
2393 // CommandObjectTypeCategoryDelete
2394 //-------------------------------------------------------------------------
2395 
2396 class CommandObjectTypeCategoryDelete : public CommandObjectParsed
2397 {
2398 public:
2399     CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) :
2400         CommandObjectParsed (interpreter,
2401                              "type category delete",
2402                              "Delete a category and all associated formatters.",
2403                              NULL)
2404     {
2405         CommandArgumentEntry type_arg;
2406         CommandArgumentData type_style_arg;
2407 
2408         type_style_arg.arg_type = eArgTypeName;
2409         type_style_arg.arg_repetition = eArgRepeatPlus;
2410 
2411         type_arg.push_back (type_style_arg);
2412 
2413         m_arguments.push_back (type_arg);
2414 
2415     }
2416 
2417     ~CommandObjectTypeCategoryDelete () override
2418     {
2419     }
2420 
2421 protected:
2422     bool
2423     DoExecute (Args& command, CommandReturnObject &result) override
2424     {
2425         const size_t argc = command.GetArgumentCount();
2426 
2427         if (argc < 1)
2428         {
2429             result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str());
2430             result.SetStatus(eReturnStatusFailed);
2431             return false;
2432         }
2433 
2434         bool success = true;
2435 
2436         // the order is not relevant here
2437         for (int i = argc - 1; i >= 0; i--)
2438         {
2439             const char* typeA = command.GetArgumentAtIndex(i);
2440             ConstString typeCS(typeA);
2441 
2442             if (!typeCS)
2443             {
2444                 result.AppendError("empty category name not allowed");
2445                 result.SetStatus(eReturnStatusFailed);
2446                 return false;
2447             }
2448             if (!DataVisualization::Categories::Delete(typeCS))
2449                 success = false; // keep deleting even if we hit an error
2450         }
2451         if (success)
2452         {
2453             result.SetStatus(eReturnStatusSuccessFinishResult);
2454             return result.Succeeded();
2455         }
2456         else
2457         {
2458             result.AppendError("cannot delete one or more categories\n");
2459             result.SetStatus(eReturnStatusFailed);
2460             return false;
2461         }
2462     }
2463 };
2464 
2465 //-------------------------------------------------------------------------
2466 // CommandObjectTypeCategoryDisable
2467 //-------------------------------------------------------------------------
2468 
2469 class CommandObjectTypeCategoryDisable : public CommandObjectParsed
2470 {
2471     class CommandOptions : public Options
2472     {
2473     public:
2474 
2475         CommandOptions (CommandInterpreter &interpreter) :
2476         Options (interpreter)
2477         {
2478         }
2479 
2480         ~CommandOptions () override {}
2481 
2482         Error
2483         SetOptionValue (uint32_t option_idx, const char *option_arg) override
2484         {
2485             Error error;
2486             const int short_option = m_getopt_table[option_idx].val;
2487 
2488             switch (short_option)
2489             {
2490                 case 'l':
2491                     if (option_arg)
2492                     {
2493                         m_language = Language::GetLanguageTypeFromString(option_arg);
2494                         if (m_language == lldb::eLanguageTypeUnknown)
2495                             error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg);
2496                     }
2497                     break;
2498                 default:
2499                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2500                     break;
2501             }
2502 
2503             return error;
2504         }
2505 
2506         void
2507         OptionParsingStarting () override
2508         {
2509             m_language = lldb::eLanguageTypeUnknown;
2510         }
2511 
2512         const OptionDefinition*
2513         GetDefinitions () override
2514         {
2515             return g_option_table;
2516         }
2517 
2518         // Options table: Required for subclasses of Options.
2519 
2520         static OptionDefinition g_option_table[];
2521 
2522         // Instance variables to hold the values for command options.
2523 
2524         lldb::LanguageType m_language;
2525 
2526     };
2527 
2528     CommandOptions m_options;
2529 
2530     Options *
2531     GetOptions () override
2532     {
2533         return &m_options;
2534     }
2535 
2536 public:
2537     CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) :
2538         CommandObjectParsed (interpreter,
2539                              "type category disable",
2540                              "Disable a category as a source of formatters.",
2541                              NULL),
2542         m_options(interpreter)
2543     {
2544         CommandArgumentEntry type_arg;
2545         CommandArgumentData type_style_arg;
2546 
2547         type_style_arg.arg_type = eArgTypeName;
2548         type_style_arg.arg_repetition = eArgRepeatPlus;
2549 
2550         type_arg.push_back (type_style_arg);
2551 
2552         m_arguments.push_back (type_arg);
2553 
2554     }
2555 
2556     ~CommandObjectTypeCategoryDisable () override
2557     {
2558     }
2559 
2560 protected:
2561     bool
2562     DoExecute (Args& command, CommandReturnObject &result) override
2563     {
2564         const size_t argc = command.GetArgumentCount();
2565 
2566         if (argc < 1 &&
2567             m_options.m_language == lldb::eLanguageTypeUnknown)
2568         {
2569             result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str());
2570             result.SetStatus(eReturnStatusFailed);
2571             return false;
2572         }
2573 
2574         if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)
2575         {
2576             DataVisualization::Categories::DisableStar();
2577         }
2578         else if (argc > 0)
2579         {
2580             // the order is not relevant here
2581             for (int i = argc - 1; i >= 0; i--)
2582             {
2583                 const char* typeA = command.GetArgumentAtIndex(i);
2584                 ConstString typeCS(typeA);
2585 
2586                 if (!typeCS)
2587                 {
2588                     result.AppendError("empty category name not allowed");
2589                     result.SetStatus(eReturnStatusFailed);
2590                     return false;
2591                 }
2592                 DataVisualization::Categories::Disable(typeCS);
2593             }
2594         }
2595 
2596         if (m_options.m_language != lldb::eLanguageTypeUnknown)
2597             DataVisualization::Categories::Disable(m_options.m_language);
2598 
2599         result.SetStatus(eReturnStatusSuccessFinishResult);
2600         return result.Succeeded();
2601     }
2602 
2603 };
2604 
2605 OptionDefinition
2606 CommandObjectTypeCategoryDisable::CommandOptions::g_option_table[] =
2607 {
2608     { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,  "Enable the category for this language."},
2609     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2610 };
2611 
2612 //-------------------------------------------------------------------------
2613 // CommandObjectTypeCategoryList
2614 //-------------------------------------------------------------------------
2615 
2616 class CommandObjectTypeCategoryList : public CommandObjectParsed
2617 {
2618 public:
2619     CommandObjectTypeCategoryList (CommandInterpreter &interpreter) :
2620         CommandObjectParsed (interpreter,
2621                              "type category list",
2622                              "Provide a list of all existing categories.",
2623                              NULL)
2624     {
2625         CommandArgumentEntry type_arg;
2626         CommandArgumentData type_style_arg;
2627 
2628         type_style_arg.arg_type = eArgTypeName;
2629         type_style_arg.arg_repetition = eArgRepeatOptional;
2630 
2631         type_arg.push_back (type_style_arg);
2632 
2633         m_arguments.push_back (type_arg);
2634     }
2635 
2636     ~CommandObjectTypeCategoryList () override
2637     {
2638     }
2639 
2640 protected:
2641     bool
2642     DoExecute (Args& command, CommandReturnObject &result) override
2643     {
2644         const size_t argc = command.GetArgumentCount();
2645 
2646         std::unique_ptr<RegularExpression> regex;
2647 
2648         if (argc == 1)
2649         {
2650             regex.reset(new RegularExpression());
2651             const char* arg = command.GetArgumentAtIndex(0);
2652             if (!regex->Compile(arg))
2653             {
2654                 result.AppendErrorWithFormat("syntax error in category regular expression '%s'", arg);
2655                 result.SetStatus(eReturnStatusFailed);
2656                 return false;
2657             }
2658         }
2659         else if (argc != 0)
2660         {
2661             result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str());
2662             result.SetStatus(eReturnStatusFailed);
2663             return false;
2664         }
2665 
2666         DataVisualization::Categories::ForEach( [&regex, &result] (const lldb::TypeCategoryImplSP& category_sp) -> bool {
2667             if (regex)
2668             {
2669                 bool escape = true;
2670                 if (0 == strcmp(category_sp->GetName(), regex->GetText()))
2671                 {
2672                     escape = false;
2673                 }
2674                 else if (regex->Execute(category_sp->GetName()))
2675                 {
2676                     escape = false;
2677                 }
2678 
2679                 if (escape)
2680                     return true;
2681             }
2682 
2683             result.GetOutputStream().Printf("Category: %s\n", category_sp->GetDescription().c_str());
2684 
2685             return true;
2686         });
2687 
2688         result.SetStatus(eReturnStatusSuccessFinishResult);
2689         return result.Succeeded();
2690     }
2691 
2692 };
2693 
2694 //-------------------------------------------------------------------------
2695 // CommandObjectTypeFilterList
2696 //-------------------------------------------------------------------------
2697 
2698 class CommandObjectTypeFilterList : public CommandObjectTypeFormatterList<TypeFilterImpl>
2699 {
2700 public:
2701 
2702     CommandObjectTypeFilterList (CommandInterpreter &interpreter) :
2703     CommandObjectTypeFormatterList(interpreter,
2704                                    "type filter list",
2705                                    "Show a list of current filters.")
2706     {
2707     }
2708 };
2709 
2710 #ifndef LLDB_DISABLE_PYTHON
2711 
2712 //-------------------------------------------------------------------------
2713 // CommandObjectTypeSynthList
2714 //-------------------------------------------------------------------------
2715 
2716 class CommandObjectTypeSynthList : public CommandObjectTypeFormatterList<SyntheticChildren>
2717 {
2718 public:
2719 
2720     CommandObjectTypeSynthList (CommandInterpreter &interpreter) :
2721     CommandObjectTypeFormatterList(interpreter,
2722                                    "type synthetic list",
2723                                    "Show a list of current synthetic providers.")
2724     {
2725     }
2726 };
2727 
2728 #endif // #ifndef LLDB_DISABLE_PYTHON
2729 //-------------------------------------------------------------------------
2730 // CommandObjectTypeFilterDelete
2731 //-------------------------------------------------------------------------
2732 
2733 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete
2734 {
2735 public:
2736     CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) :
2737     CommandObjectTypeFormatterDelete (interpreter,
2738                                       eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2739                                       "type filter delete",
2740                                       "Delete an existing filter for a type.")
2741     {
2742     }
2743 
2744     ~CommandObjectTypeFilterDelete () override
2745     {
2746     }
2747 };
2748 
2749 #ifndef LLDB_DISABLE_PYTHON
2750 
2751 //-------------------------------------------------------------------------
2752 // CommandObjectTypeSynthDelete
2753 //-------------------------------------------------------------------------
2754 
2755 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete
2756 {
2757 public:
2758     CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) :
2759     CommandObjectTypeFormatterDelete (interpreter,
2760                                       eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2761                                       "type synthetic delete",
2762                                       "Delete an existing synthetic provider for a type.")
2763     {
2764     }
2765 
2766     ~CommandObjectTypeSynthDelete () override
2767     {
2768     }
2769 };
2770 
2771 #endif // #ifndef LLDB_DISABLE_PYTHON
2772 
2773 //-------------------------------------------------------------------------
2774 // CommandObjectTypeFilterClear
2775 //-------------------------------------------------------------------------
2776 
2777 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear
2778 {
2779 public:
2780     CommandObjectTypeFilterClear (CommandInterpreter &interpreter) :
2781     CommandObjectTypeFormatterClear (interpreter,
2782                                      eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2783                                      "type filter clear",
2784                                      "Delete all existing filter.")
2785     {
2786     }
2787 };
2788 
2789 #ifndef LLDB_DISABLE_PYTHON
2790 //-------------------------------------------------------------------------
2791 // CommandObjectTypeSynthClear
2792 //-------------------------------------------------------------------------
2793 
2794 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear
2795 {
2796 public:
2797     CommandObjectTypeSynthClear (CommandInterpreter &interpreter) :
2798     CommandObjectTypeFormatterClear (interpreter,
2799                                      eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
2800                                      "type synthetic clear",
2801                                      "Delete all existing synthetic providers.")
2802     {
2803     }
2804 };
2805 
2806 bool
2807 CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result)
2808 {
2809     SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers,
2810                                                      m_options.m_skip_references,
2811                                                      m_options.m_cascade,
2812                                                      m_options.m_regex,
2813                                                      m_options.m_category);
2814 
2815     const size_t argc = command.GetArgumentCount();
2816 
2817     for (size_t i = 0; i < argc; i++)
2818     {
2819         const char* typeA = command.GetArgumentAtIndex(i);
2820         if (typeA && *typeA)
2821             options->m_target_types << typeA;
2822         else
2823         {
2824             result.AppendError("empty typenames not allowed");
2825             result.SetStatus(eReturnStatusFailed);
2826             return false;
2827         }
2828     }
2829 
2830     m_interpreter.GetPythonCommandsFromIOHandler ("    ",   // Prompt
2831                                                   *this,    // IOHandlerDelegate
2832                                                   true,     // Run IOHandler in async mode
2833                                                   options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
2834     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2835     return result.Succeeded();
2836 }
2837 
2838 bool
2839 CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result)
2840 {
2841     const size_t argc = command.GetArgumentCount();
2842 
2843     if (argc < 1)
2844     {
2845         result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
2846         result.SetStatus(eReturnStatusFailed);
2847         return false;
2848     }
2849 
2850     if (m_options.m_class_name.empty() && !m_options.m_input_python)
2851     {
2852         result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str());
2853         result.SetStatus(eReturnStatusFailed);
2854         return false;
2855     }
2856 
2857     SyntheticChildrenSP entry;
2858 
2859     ScriptedSyntheticChildren* impl = new ScriptedSyntheticChildren(SyntheticChildren::Flags().
2860                                                                     SetCascades(m_options.m_cascade).
2861                                                                     SetSkipPointers(m_options.m_skip_pointers).
2862                                                                     SetSkipReferences(m_options.m_skip_references),
2863                                                                     m_options.m_class_name.c_str());
2864 
2865     entry.reset(impl);
2866 
2867     ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
2868 
2869     if (interpreter && interpreter->CheckObjectExists(impl->GetPythonClassName()) == false)
2870         result.AppendWarning("The provided class does not exist - please define it before attempting to use this synthetic provider");
2871 
2872     // now I have a valid provider, let's add it to every type
2873 
2874     lldb::TypeCategoryImplSP category;
2875     DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
2876 
2877     Error error;
2878 
2879     for (size_t i = 0; i < argc; i++)
2880     {
2881         const char* typeA = command.GetArgumentAtIndex(i);
2882         ConstString typeCS(typeA);
2883         if (typeCS)
2884         {
2885             if (!AddSynth(typeCS,
2886                           entry,
2887                           m_options.m_regex ? eRegexSynth : eRegularSynth,
2888                           m_options.m_category,
2889                           &error))
2890             {
2891                 result.AppendError(error.AsCString());
2892                 result.SetStatus(eReturnStatusFailed);
2893                 return false;
2894             }
2895         }
2896         else
2897         {
2898             result.AppendError("empty typenames not allowed");
2899             result.SetStatus(eReturnStatusFailed);
2900             return false;
2901         }
2902     }
2903 
2904     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2905     return result.Succeeded();
2906 }
2907 
2908 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) :
2909     CommandObjectParsed (interpreter,
2910                          "type synthetic add",
2911                          "Add a new synthetic provider for a type.",
2912                          NULL),
2913     IOHandlerDelegateMultiline ("DONE"),
2914     m_options (interpreter)
2915 {
2916     CommandArgumentEntry type_arg;
2917     CommandArgumentData type_style_arg;
2918 
2919     type_style_arg.arg_type = eArgTypeName;
2920     type_style_arg.arg_repetition = eArgRepeatPlus;
2921 
2922     type_arg.push_back (type_style_arg);
2923 
2924     m_arguments.push_back (type_arg);
2925 
2926 }
2927 
2928 bool
2929 CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
2930                                     SyntheticChildrenSP entry,
2931                                     SynthFormatType type,
2932                                     std::string category_name,
2933                                     Error* error)
2934 {
2935     lldb::TypeCategoryImplSP category;
2936     DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
2937 
2938     if (type == eRegularSynth)
2939     {
2940         if (FixArrayTypeNameWithRegex (type_name))
2941             type = eRegexSynth;
2942     }
2943 
2944     if (category->AnyMatches(type_name,
2945                              eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
2946                              false))
2947     {
2948         if (error)
2949             error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString());
2950         return false;
2951     }
2952 
2953     if (type == eRegexSynth)
2954     {
2955         RegularExpressionSP typeRX(new RegularExpression());
2956         if (!typeRX->Compile(type_name.GetCString()))
2957         {
2958             if (error)
2959                 error->SetErrorString("regex format error (maybe this is not really a regex?)");
2960             return false;
2961         }
2962 
2963         category->GetRegexTypeSyntheticsContainer()->Delete(type_name);
2964         category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry);
2965 
2966         return true;
2967     }
2968     else
2969     {
2970         category->GetTypeSyntheticsContainer()->Add(type_name, entry);
2971         return true;
2972     }
2973 }
2974 
2975 OptionDefinition
2976 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
2977 {
2978     { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,    "If true, cascade through typedef chains."},
2979     { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
2980     { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
2981     { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,         "Add this to the given category instead of the default one."},
2982     { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass,    "Use this Python class to produce synthetic children."},
2983     { 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."},
2984     { LLDB_OPT_SET_ALL, false,  "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
2985     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2986 };
2987 
2988 #endif // #ifndef LLDB_DISABLE_PYTHON
2989 
2990 class CommandObjectTypeFilterAdd : public CommandObjectParsed
2991 {
2992 
2993 private:
2994 
2995     class CommandOptions : public Options
2996     {
2997         typedef std::vector<std::string> option_vector;
2998     public:
2999 
3000         CommandOptions (CommandInterpreter &interpreter) :
3001         Options (interpreter)
3002         {
3003         }
3004 
3005         ~CommandOptions () override {}
3006 
3007         Error
3008         SetOptionValue (uint32_t option_idx, const char *option_arg) override
3009         {
3010             Error error;
3011             const int short_option = m_getopt_table[option_idx].val;
3012             bool success;
3013 
3014             switch (short_option)
3015             {
3016                 case 'C':
3017                     m_cascade = Args::StringToBoolean(option_arg, true, &success);
3018                     if (!success)
3019                         error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg);
3020                     break;
3021                 case 'c':
3022                     m_expr_paths.push_back(option_arg);
3023                     has_child_list = true;
3024                     break;
3025                 case 'p':
3026                     m_skip_pointers = true;
3027                     break;
3028                 case 'r':
3029                     m_skip_references = true;
3030                     break;
3031                 case 'w':
3032                     m_category = std::string(option_arg);
3033                     break;
3034                 case 'x':
3035                     m_regex = true;
3036                     break;
3037                 default:
3038                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
3039                     break;
3040             }
3041 
3042             return error;
3043         }
3044 
3045         void
3046         OptionParsingStarting () override
3047         {
3048             m_cascade = true;
3049             m_skip_pointers = false;
3050             m_skip_references = false;
3051             m_category = "default";
3052             m_expr_paths.clear();
3053             has_child_list = false;
3054             m_regex = false;
3055         }
3056 
3057         const OptionDefinition*
3058         GetDefinitions () override
3059         {
3060             return g_option_table;
3061         }
3062 
3063         // Options table: Required for subclasses of Options.
3064 
3065         static OptionDefinition g_option_table[];
3066 
3067         // Instance variables to hold the values for command options.
3068 
3069         bool m_cascade;
3070         bool m_skip_references;
3071         bool m_skip_pointers;
3072         bool m_input_python;
3073         option_vector m_expr_paths;
3074         std::string m_category;
3075 
3076         bool has_child_list;
3077 
3078         bool m_regex;
3079 
3080         typedef option_vector::iterator ExpressionPathsIterator;
3081     };
3082 
3083     CommandOptions m_options;
3084 
3085     Options *
3086     GetOptions () override
3087     {
3088         return &m_options;
3089     }
3090 
3091     enum FilterFormatType
3092     {
3093         eRegularFilter,
3094         eRegexFilter
3095     };
3096 
3097     bool
3098     AddFilter(ConstString type_name,
3099               TypeFilterImplSP entry,
3100               FilterFormatType type,
3101               std::string category_name,
3102               Error* error)
3103     {
3104         lldb::TypeCategoryImplSP category;
3105         DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
3106 
3107         if (type == eRegularFilter)
3108         {
3109             if (FixArrayTypeNameWithRegex (type_name))
3110                 type = eRegexFilter;
3111         }
3112 
3113         if (category->AnyMatches(type_name,
3114                                  eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
3115                                  false))
3116         {
3117             if (error)
3118                 error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString());
3119             return false;
3120         }
3121 
3122         if (type == eRegexFilter)
3123         {
3124             RegularExpressionSP typeRX(new RegularExpression());
3125             if (!typeRX->Compile(type_name.GetCString()))
3126             {
3127                 if (error)
3128                     error->SetErrorString("regex format error (maybe this is not really a regex?)");
3129                 return false;
3130             }
3131 
3132             category->GetRegexTypeFiltersContainer()->Delete(type_name);
3133             category->GetRegexTypeFiltersContainer()->Add(typeRX, entry);
3134 
3135             return true;
3136         }
3137         else
3138         {
3139             category->GetTypeFiltersContainer()->Add(type_name, entry);
3140             return true;
3141         }
3142     }
3143 
3144 
3145 public:
3146 
3147     CommandObjectTypeFilterAdd (CommandInterpreter &interpreter) :
3148         CommandObjectParsed (interpreter,
3149                              "type filter add",
3150                              "Add a new filter for a type.",
3151                              NULL),
3152         m_options (interpreter)
3153     {
3154         CommandArgumentEntry type_arg;
3155         CommandArgumentData type_style_arg;
3156 
3157         type_style_arg.arg_type = eArgTypeName;
3158         type_style_arg.arg_repetition = eArgRepeatPlus;
3159 
3160         type_arg.push_back (type_style_arg);
3161 
3162         m_arguments.push_back (type_arg);
3163 
3164         SetHelpLong(
3165 R"(
3166 The following examples of 'type filter add' refer to this code snippet for context:
3167 
3168     class Foo {
3169         int a;
3170         int b;
3171         int c;
3172         int d;
3173         int e;
3174         int f;
3175         int g;
3176         int h;
3177         int i;
3178     }
3179     Foo my_foo;
3180 
3181 Adding a simple filter:
3182 
3183 (lldb) type filter add --child a --child g Foo
3184 (lldb) frame variable my_foo
3185 
3186 )" "Produces output where only a and g are displayed.  Other children of my_foo \
3187 (b, c, d, e, f, h and i) are available by asking for them explicitly:" R"(
3188 
3189 (lldb) frame variable my_foo.b my_foo.c my_foo.i
3190 
3191 )" "The formatting option --raw on frame variable bypasses the filter, showing \
3192 all children of my_foo as if no filter was defined:" R"(
3193 
3194 (lldb) frame variable my_foo --raw)"
3195         );
3196     }
3197 
3198     ~CommandObjectTypeFilterAdd () override
3199     {
3200     }
3201 
3202 protected:
3203     bool
3204     DoExecute (Args& command, CommandReturnObject &result) override
3205     {
3206         const size_t argc = command.GetArgumentCount();
3207 
3208         if (argc < 1)
3209         {
3210             result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
3211             result.SetStatus(eReturnStatusFailed);
3212             return false;
3213         }
3214 
3215         if (m_options.m_expr_paths.size() == 0)
3216         {
3217             result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
3218             result.SetStatus(eReturnStatusFailed);
3219             return false;
3220         }
3221 
3222         TypeFilterImplSP entry(new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade).
3223                                        SetSkipPointers(m_options.m_skip_pointers).
3224                                                   SetSkipReferences(m_options.m_skip_references)));
3225 
3226         // go through the expression paths
3227         CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
3228 
3229         for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
3230             entry->AddExpressionPath(*begin);
3231 
3232 
3233         // now I have a valid provider, let's add it to every type
3234 
3235         lldb::TypeCategoryImplSP category;
3236         DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
3237 
3238         Error error;
3239 
3240         WarnOnPotentialUnquotedUnsignedType(command, result);
3241 
3242         for (size_t i = 0; i < argc; i++)
3243         {
3244             const char* typeA = command.GetArgumentAtIndex(i);
3245             ConstString typeCS(typeA);
3246             if (typeCS)
3247             {
3248                 if (!AddFilter(typeCS,
3249                           entry,
3250                           m_options.m_regex ? eRegexFilter : eRegularFilter,
3251                           m_options.m_category,
3252                           &error))
3253                 {
3254                     result.AppendError(error.AsCString());
3255                     result.SetStatus(eReturnStatusFailed);
3256                     return false;
3257                 }
3258             }
3259             else
3260             {
3261                 result.AppendError("empty typenames not allowed");
3262                 result.SetStatus(eReturnStatusFailed);
3263                 return false;
3264             }
3265         }
3266 
3267         result.SetStatus(eReturnStatusSuccessFinishNoResult);
3268         return result.Succeeded();
3269     }
3270 
3271 };
3272 
3273 OptionDefinition
3274 CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] =
3275 {
3276     { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,    "If true, cascade through typedef chains."},
3277     { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
3278     { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
3279     { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,         "Add this to the given category instead of the default one."},
3280     { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpressionPath,    "Include this expression path in the synthetic view."},
3281     { LLDB_OPT_SET_ALL, false,  "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
3282     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3283 };
3284 
3285 //----------------------------------------------------------------------
3286 // "type lookup"
3287 //----------------------------------------------------------------------
3288 class CommandObjectTypeLookup : public CommandObjectRaw
3289 {
3290 protected:
3291 
3292     class CommandOptions : public OptionGroup
3293     {
3294     public:
3295 
3296         CommandOptions () :
3297         OptionGroup(),
3298         m_show_help(false),
3299         m_language(eLanguageTypeUnknown)
3300         {}
3301 
3302         ~CommandOptions () override {}
3303 
3304         uint32_t
3305         GetNumDefinitions () override
3306         {
3307             return 3;
3308         }
3309 
3310         const OptionDefinition*
3311         GetDefinitions () override
3312         {
3313             return g_option_table;
3314         }
3315 
3316         Error
3317         SetOptionValue (CommandInterpreter &interpreter,
3318                         uint32_t option_idx,
3319                         const char *option_value) override
3320         {
3321             Error error;
3322 
3323             const int short_option = g_option_table[option_idx].short_option;
3324 
3325             switch (short_option)
3326             {
3327                 case 'h':
3328                     m_show_help = true;
3329                     break;
3330 
3331                 case 'l':
3332                     m_language = Language::GetLanguageTypeFromString(option_value);
3333                     break;
3334 
3335                 default:
3336                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
3337                     break;
3338             }
3339 
3340             return error;
3341         }
3342 
3343         void
3344         OptionParsingStarting (CommandInterpreter &interpreter) override
3345         {
3346             m_show_help = false;
3347             m_language = eLanguageTypeUnknown;
3348         }
3349 
3350         // Options table: Required for subclasses of Options.
3351 
3352         static OptionDefinition g_option_table[];
3353         bool m_show_help;
3354         lldb::LanguageType m_language;
3355     };
3356 
3357     OptionGroupOptions m_option_group;
3358     CommandOptions m_command_options;
3359 
3360 public:
3361 
3362     CommandObjectTypeLookup (CommandInterpreter &interpreter) :
3363     CommandObjectRaw (interpreter,
3364                       "type lookup",
3365                       "Lookup a type by name in the select target.",
3366                       "type lookup <typename>",
3367                       eCommandRequiresTarget),
3368     m_option_group(interpreter),
3369     m_command_options()
3370     {
3371         m_option_group.Append(&m_command_options);
3372         m_option_group.Finalize();
3373     }
3374 
3375     ~CommandObjectTypeLookup () override
3376     {
3377     }
3378 
3379     Options *
3380     GetOptions () override
3381     {
3382         return &m_option_group;
3383     }
3384 
3385     bool
3386     DoExecute (const char *raw_command_line, CommandReturnObject &result) override
3387     {
3388         if (!raw_command_line || !raw_command_line[0])
3389         {
3390             result.SetError("type lookup cannot be invoked without a type name as argument");
3391             return false;
3392         }
3393 
3394         m_option_group.NotifyOptionParsingStarting();
3395 
3396         const char * name_of_type = NULL;
3397 
3398         if (raw_command_line[0] == '-')
3399         {
3400             // We have some options and these options MUST end with --.
3401             const char *end_options = NULL;
3402             const char *s = raw_command_line;
3403             while (s && s[0])
3404             {
3405                 end_options = ::strstr (s, "--");
3406                 if (end_options)
3407                 {
3408                     end_options += 2; // Get past the "--"
3409                     if (::isspace (end_options[0]))
3410                     {
3411                         name_of_type = end_options;
3412                         while (::isspace (*name_of_type))
3413                             ++name_of_type;
3414                         break;
3415                     }
3416                 }
3417                 s = end_options;
3418             }
3419 
3420             if (end_options)
3421             {
3422                 Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line));
3423                 if (!ParseOptions (args, result))
3424                     return false;
3425 
3426                 Error error (m_option_group.NotifyOptionParsingFinished());
3427                 if (error.Fail())
3428                 {
3429                     result.AppendError (error.AsCString());
3430                     result.SetStatus (eReturnStatusFailed);
3431                     return false;
3432                 }
3433             }
3434         }
3435         if (nullptr == name_of_type)
3436             name_of_type = raw_command_line;
3437 
3438         TargetSP target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());
3439         const bool fill_all_in = true;
3440         ExecutionContext exe_ctx(target_sp.get(), fill_all_in);
3441         ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
3442 
3443         bool any_found = false;
3444 
3445         std::vector<Language*> languages;
3446 
3447         if (m_command_options.m_language == eLanguageTypeUnknown)
3448         {
3449             // FIXME: hardcoding languages is not good
3450             languages.push_back(Language::FindPlugin(eLanguageTypeObjC));
3451             languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));
3452         }
3453         else
3454         {
3455             languages.push_back(Language::FindPlugin(m_command_options.m_language));
3456         }
3457 
3458         for (Language* language : languages)
3459         {
3460             if (!language)
3461                 continue;
3462 
3463             if (auto scavenger = language->GetTypeScavenger())
3464             {
3465                 Language::TypeScavenger::ResultSet search_results;
3466                 if (scavenger->Find(best_scope, name_of_type, search_results) > 0)
3467                 {
3468                     for (const auto& search_result : search_results)
3469                     {
3470                         if (search_result && search_result->IsValid())
3471                         {
3472                             any_found = true;
3473                             search_result->DumpToStream(result.GetOutputStream(), this->m_command_options.m_show_help);
3474                         }
3475                     }
3476                 }
3477             }
3478         }
3479 
3480         result.SetStatus (any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult);
3481         return true;
3482     }
3483 
3484 };
3485 
3486 OptionDefinition
3487 CommandObjectTypeLookup::CommandOptions::g_option_table[] =
3488 {
3489     { LLDB_OPT_SET_ALL, false, "show-help",        'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "Display available help for types"},
3490     { LLDB_OPT_SET_ALL, false, "language",         'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,    "Which language's types should the search scope be"},
3491     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3492 };
3493 
3494 template <typename FormatterType>
3495 class CommandObjectFormatterInfo : public CommandObjectRaw
3496 {
3497 public:
3498     typedef std::function<typename FormatterType::SharedPointer(ValueObject&)> DiscoveryFunction;
3499     CommandObjectFormatterInfo (CommandInterpreter &interpreter,
3500                                 const char* formatter_name,
3501                                 DiscoveryFunction discovery_func) :
3502     CommandObjectRaw(interpreter,
3503                      nullptr,
3504                      nullptr,
3505                      nullptr,
3506                      eCommandRequiresFrame),
3507     m_formatter_name(formatter_name ? formatter_name : ""),
3508     m_discovery_function(discovery_func)
3509     {
3510         StreamString name;
3511         name.Printf("type %s info", formatter_name);
3512         SetCommandName(name.GetData());
3513         StreamString help;
3514         help.Printf("This command evaluates the provided expression and shows which %s is applied to the resulting value (if any).", formatter_name);
3515         SetHelp(help.GetData());
3516         StreamString syntax;
3517         syntax.Printf("type %s info <expr>", formatter_name);
3518         SetSyntax(syntax.GetData());
3519     }
3520 
3521     ~CommandObjectFormatterInfo () override
3522     {
3523     }
3524 
3525 protected:
3526     bool
3527     DoExecute (const char *command, CommandReturnObject &result) override
3528     {
3529         auto target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
3530         auto frame_sp = target_sp->GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame();
3531         ValueObjectSP result_valobj_sp;
3532         EvaluateExpressionOptions options;
3533         lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(command, frame_sp.get(), result_valobj_sp, options);
3534         if (expr_result == eExpressionCompleted && result_valobj_sp)
3535         {
3536             result_valobj_sp = result_valobj_sp->GetQualifiedRepresentationIfAvailable(target_sp->GetPreferDynamicValue(), target_sp->GetEnableSyntheticValue());
3537             typename FormatterType::SharedPointer formatter_sp = m_discovery_function(*result_valobj_sp);
3538             if (formatter_sp)
3539             {
3540                 std::string description(formatter_sp->GetDescription());
3541                 result.AppendMessageWithFormat("%s applied to (%s) %s is: %s\n",
3542                                                m_formatter_name.c_str(),
3543                                                result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
3544                                                command,
3545                                                description.c_str());
3546                 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
3547             }
3548             else
3549             {
3550                 result.AppendMessageWithFormat("no %s applies to (%s) %s\n",
3551                                                m_formatter_name.c_str(),
3552                                                result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
3553                                                command);
3554                 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
3555             }
3556             return true;
3557         }
3558         else
3559         {
3560             result.AppendError("failed to evaluate expression");
3561             result.SetStatus(lldb::eReturnStatusFailed);
3562             return false;
3563         }
3564     }
3565 
3566 private:
3567     std::string m_formatter_name;
3568     DiscoveryFunction m_discovery_function;
3569 };
3570 
3571 class CommandObjectTypeFormat : public CommandObjectMultiword
3572 {
3573 public:
3574     CommandObjectTypeFormat (CommandInterpreter &interpreter) :
3575         CommandObjectMultiword (interpreter,
3576                                 "type format",
3577                                 "A set of commands for editing variable value display options",
3578                                 "type format [<sub-command-options>] ")
3579     {
3580         LoadSubCommand ("add",    CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter)));
3581         LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectTypeFormatClear (interpreter)));
3582         LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter)));
3583         LoadSubCommand ("list",   CommandObjectSP (new CommandObjectTypeFormatList (interpreter)));
3584         LoadSubCommand ("info",   CommandObjectSP (new CommandObjectFormatterInfo<TypeFormatImpl>(interpreter,
3585                                                                                                   "format",
3586                                                                                                   [](ValueObject& valobj) -> TypeFormatImpl::SharedPointer {
3587                                                                                                       return valobj.GetValueFormat();
3588                                                                                                   })));
3589     }
3590 
3591 
3592     ~CommandObjectTypeFormat () override
3593     {
3594     }
3595 };
3596 
3597 #ifndef LLDB_DISABLE_PYTHON
3598 
3599 class CommandObjectTypeSynth : public CommandObjectMultiword
3600 {
3601 public:
3602     CommandObjectTypeSynth (CommandInterpreter &interpreter) :
3603     CommandObjectMultiword (interpreter,
3604                             "type synthetic",
3605                             "A set of commands for operating on synthetic type representations",
3606                             "type synthetic [<sub-command-options>] ")
3607     {
3608         LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter)));
3609         LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSynthClear (interpreter)));
3610         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter)));
3611         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSynthList (interpreter)));
3612         LoadSubCommand ("info",          CommandObjectSP (new CommandObjectFormatterInfo<SyntheticChildren>(interpreter,
3613                                                                                                             "synthetic",
3614                                                                                                             [](ValueObject& valobj) -> SyntheticChildren::SharedPointer {
3615                                                                                                                 return valobj.GetSyntheticChildren();
3616                                                                                                             })));
3617     }
3618 
3619 
3620     ~CommandObjectTypeSynth () override
3621     {
3622     }
3623 };
3624 
3625 #endif // #ifndef LLDB_DISABLE_PYTHON
3626 
3627 class CommandObjectTypeFilter : public CommandObjectMultiword
3628 {
3629 public:
3630     CommandObjectTypeFilter (CommandInterpreter &interpreter) :
3631     CommandObjectMultiword (interpreter,
3632                             "type filter",
3633                             "A set of commands for operating on type filters",
3634                             "type synthetic [<sub-command-options>] ")
3635     {
3636         LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeFilterAdd (interpreter)));
3637         LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeFilterClear (interpreter)));
3638         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeFilterDelete (interpreter)));
3639         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeFilterList (interpreter)));
3640     }
3641 
3642 
3643     ~CommandObjectTypeFilter () override
3644     {
3645     }
3646 };
3647 
3648 class CommandObjectTypeCategory : public CommandObjectMultiword
3649 {
3650 public:
3651     CommandObjectTypeCategory (CommandInterpreter &interpreter) :
3652     CommandObjectMultiword (interpreter,
3653                             "type category",
3654                             "A set of commands for operating on categories",
3655                             "type category [<sub-command-options>] ")
3656     {
3657         LoadSubCommand ("define",        CommandObjectSP (new CommandObjectTypeCategoryDefine (interpreter)));
3658         LoadSubCommand ("enable",        CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter)));
3659         LoadSubCommand ("disable",       CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter)));
3660         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter)));
3661         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeCategoryList (interpreter)));
3662     }
3663 
3664 
3665     ~CommandObjectTypeCategory () override
3666     {
3667     }
3668 };
3669 
3670 class CommandObjectTypeSummary : public CommandObjectMultiword
3671 {
3672 public:
3673     CommandObjectTypeSummary (CommandInterpreter &interpreter) :
3674     CommandObjectMultiword (interpreter,
3675                             "type summary",
3676                             "A set of commands for editing variable summary display options",
3677                             "type summary [<sub-command-options>] ")
3678     {
3679         LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter)));
3680         LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));
3681         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));
3682         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSummaryList (interpreter)));
3683         LoadSubCommand ("info",          CommandObjectSP (new CommandObjectFormatterInfo<TypeSummaryImpl>(interpreter,
3684                                                                                                           "summary",
3685                                                                                                             [](ValueObject& valobj) -> TypeSummaryImpl::SharedPointer {
3686                                                                                                                 return valobj.GetSummaryFormat();
3687                                                                                                             })));
3688     }
3689 
3690 
3691     ~CommandObjectTypeSummary () override
3692     {
3693     }
3694 };
3695 
3696 //-------------------------------------------------------------------------
3697 // CommandObjectType
3698 //-------------------------------------------------------------------------
3699 
3700 CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) :
3701     CommandObjectMultiword (interpreter,
3702                             "type",
3703                             "A set of commands for operating on the type system",
3704                             "type [<sub-command-options>]")
3705 {
3706     LoadSubCommand ("category",  CommandObjectSP (new CommandObjectTypeCategory (interpreter)));
3707     LoadSubCommand ("filter",    CommandObjectSP (new CommandObjectTypeFilter (interpreter)));
3708     LoadSubCommand ("format",    CommandObjectSP (new CommandObjectTypeFormat (interpreter)));
3709     LoadSubCommand ("summary",   CommandObjectSP (new CommandObjectTypeSummary (interpreter)));
3710 #ifndef LLDB_DISABLE_PYTHON
3711     LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter)));
3712 #endif
3713     LoadSubCommand ("lookup",   CommandObjectSP (new CommandObjectTypeLookup (interpreter)));
3714 }
3715 
3716 
3717 CommandObjectType::~CommandObjectType ()
3718 {
3719 }
3720