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