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