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