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