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