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