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