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