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