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