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