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 
1093 
1094 
1095 
1096 
1097 //-------------------------------------------------------------------------
1098 // CommandObjectTypeFormatDelete
1099 //-------------------------------------------------------------------------
1100 
1101 class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete
1102 {
1103 public:
1104     CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) :
1105         CommandObjectTypeFormatterDelete (interpreter,
1106                                           eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
1107                                           "type format delete",
1108                                           "Delete an existing formatting style for a type.")
1109     {
1110     }
1111 
1112     ~CommandObjectTypeFormatDelete () override
1113     {
1114     }
1115 };
1116 
1117 //-------------------------------------------------------------------------
1118 // CommandObjectTypeFormatClear
1119 //-------------------------------------------------------------------------
1120 
1121 class CommandObjectTypeFormatClear : public CommandObjectParsed
1122 {
1123 private:
1124 
1125     class CommandOptions : public Options
1126     {
1127     public:
1128 
1129         CommandOptions (CommandInterpreter &interpreter) :
1130         Options (interpreter)
1131         {
1132         }
1133 
1134         ~CommandOptions () override {}
1135 
1136         Error
1137         SetOptionValue (uint32_t option_idx, const char *option_arg) override
1138         {
1139             Error error;
1140             const int short_option = m_getopt_table[option_idx].val;
1141 
1142             switch (short_option)
1143             {
1144                 case 'a':
1145                     m_delete_all = true;
1146                     break;
1147                 default:
1148                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1149                     break;
1150             }
1151 
1152             return error;
1153         }
1154 
1155         void
1156         OptionParsingStarting () override
1157         {
1158             m_delete_all = false;
1159         }
1160 
1161         const OptionDefinition*
1162         GetDefinitions () override
1163         {
1164             return g_option_table;
1165         }
1166 
1167         // Options table: Required for subclasses of Options.
1168 
1169         static OptionDefinition g_option_table[];
1170 
1171         // Instance variables to hold the values for command options.
1172 
1173         bool m_delete_all;
1174         bool m_delete_named;
1175     };
1176 
1177     CommandOptions m_options;
1178 
1179     Options *
1180     GetOptions () override
1181     {
1182         return &m_options;
1183     }
1184 
1185 public:
1186     CommandObjectTypeFormatClear (CommandInterpreter &interpreter) :
1187         CommandObjectParsed (interpreter,
1188                              "type format clear",
1189                              "Delete all existing format styles.",
1190                              NULL),
1191     m_options(interpreter)
1192     {
1193     }
1194 
1195     ~CommandObjectTypeFormatClear () override
1196     {
1197     }
1198 
1199 protected:
1200     bool
1201     DoExecute (Args& command, CommandReturnObject &result) override
1202     {
1203         if (m_options.m_delete_all)
1204         {
1205             DataVisualization::Categories::ForEach( [] (const TypeCategoryImplSP& category_sp) -> bool {
1206                 category_sp->Clear(eFormatCategoryItemValue | eFormatCategoryItemRegexValue);
1207                 return true;
1208             });
1209         }
1210         else
1211         {
1212             lldb::TypeCategoryImplSP category;
1213             if (command.GetArgumentCount() > 0)
1214             {
1215                 const char* cat_name = command.GetArgumentAtIndex(0);
1216                 ConstString cat_nameCS(cat_name);
1217                 DataVisualization::Categories::GetCategory(cat_nameCS, category);
1218             }
1219             else
1220                 DataVisualization::Categories::GetCategory(ConstString(NULL), category);
1221             category->Clear(eFormatCategoryItemValue | eFormatCategoryItemRegexValue);
1222         }
1223 
1224         result.SetStatus(eReturnStatusSuccessFinishResult);
1225         return result.Succeeded();
1226     }
1227 
1228 };
1229 
1230 OptionDefinition
1231 CommandObjectTypeFormatClear::CommandOptions::g_option_table[] =
1232 {
1233     { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,  "Clear every category."},
1234     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1235 };
1236 
1237 //-------------------------------------------------------------------------
1238 // CommandObjectTypeFormatList
1239 //-------------------------------------------------------------------------
1240 
1241 bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry);
1242 bool CommandObjectTypeRXFormatList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeFormatImplSP& entry);
1243 
1244 class CommandObjectTypeFormatList;
1245 
1246 struct CommandObjectTypeFormatList_LoopCallbackParam {
1247     CommandObjectTypeFormatList* self;
1248     CommandReturnObject* result;
1249     RegularExpression* regex;
1250     RegularExpression* cate_regex;
1251     CommandObjectTypeFormatList_LoopCallbackParam(CommandObjectTypeFormatList* S, CommandReturnObject* R,
1252                                             RegularExpression* X = NULL, RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
1253 };
1254 
1255 class CommandObjectTypeFormatList : public CommandObjectParsed
1256 {
1257     class CommandOptions : public Options
1258     {
1259     public:
1260 
1261         CommandOptions (CommandInterpreter &interpreter) :
1262         Options (interpreter)
1263         {
1264         }
1265 
1266         ~CommandOptions () override {}
1267 
1268         Error
1269         SetOptionValue (uint32_t option_idx, const char *option_arg) override
1270         {
1271             Error error;
1272             const int short_option = m_getopt_table[option_idx].val;
1273 
1274             switch (short_option)
1275             {
1276                 case 'w':
1277                     m_category_regex = std::string(option_arg);
1278                     break;
1279                 default:
1280                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1281                     break;
1282             }
1283 
1284             return error;
1285         }
1286 
1287         void
1288         OptionParsingStarting () override
1289         {
1290             m_category_regex = "";
1291         }
1292 
1293         const OptionDefinition*
1294         GetDefinitions () override
1295         {
1296             return g_option_table;
1297         }
1298 
1299         // Options table: Required for subclasses of Options.
1300 
1301         static OptionDefinition g_option_table[];
1302 
1303         // Instance variables to hold the values for command options.
1304 
1305         std::string m_category_regex;
1306 
1307     };
1308 
1309     CommandOptions m_options;
1310 
1311     Options *
1312     GetOptions () override
1313     {
1314         return &m_options;
1315     }
1316 
1317 public:
1318     CommandObjectTypeFormatList (CommandInterpreter &interpreter) :
1319         CommandObjectParsed (interpreter,
1320                              "type format list",
1321                              "Show a list of current formatting styles.",
1322                              NULL),
1323     m_options(interpreter)
1324     {
1325         CommandArgumentEntry type_arg;
1326         CommandArgumentData type_style_arg;
1327 
1328         type_style_arg.arg_type = eArgTypeName;
1329         type_style_arg.arg_repetition = eArgRepeatOptional;
1330 
1331         type_arg.push_back (type_style_arg);
1332 
1333         m_arguments.push_back (type_arg);
1334     }
1335 
1336     ~CommandObjectTypeFormatList () override
1337     {
1338     }
1339 
1340 protected:
1341     bool
1342     DoExecute (Args& command, CommandReturnObject &result) override
1343     {
1344         const size_t argc = command.GetArgumentCount();
1345 
1346         CommandObjectTypeFormatList_LoopCallbackParam *param;
1347         RegularExpression* cate_regex =
1348         m_options.m_category_regex.empty() ? NULL :
1349         new RegularExpression(m_options.m_category_regex.c_str());
1350 
1351         if (argc == 1)
1352         {
1353             RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
1354             regex->Compile(command.GetArgumentAtIndex(0));
1355             param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,regex,cate_regex);
1356         }
1357         else
1358             param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,NULL,cate_regex);
1359 
1360         DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
1361         delete param;
1362 
1363         if (cate_regex)
1364             delete cate_regex;
1365 
1366         result.SetStatus(eReturnStatusSuccessFinishResult);
1367         return result.Succeeded();
1368     }
1369 
1370 private:
1371 
1372     static bool
1373     PerCategoryCallback(void* param_vp,
1374                         const lldb::TypeCategoryImplSP& cate)
1375     {
1376 
1377         CommandObjectTypeFormatList_LoopCallbackParam* param =
1378         (CommandObjectTypeFormatList_LoopCallbackParam*)param_vp;
1379         CommandReturnObject* result = param->result;
1380 
1381         const char* cate_name = cate->GetName();
1382 
1383         // if the category is disabled or empty and there is no regex, just skip it
1384         if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemValue | eFormatCategoryItemRegexValue) == 0) && param->cate_regex == NULL)
1385             return true;
1386 
1387         // if we have a regex and this category does not match it, just skip it
1388         if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false)
1389             return true;
1390 
1391         result->GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", cate->GetDescription().c_str());
1392 
1393         cate->GetTypeFormatsContainer()->LoopThrough(CommandObjectTypeFormatList_LoopCallback, param_vp);
1394 
1395         if (cate->GetRegexTypeFormatsContainer()->GetCount() > 0)
1396         {
1397             result->GetOutputStream().Printf("Regex-based formats (slower):\n");
1398             cate->GetRegexTypeFormatsContainer()->LoopThrough(CommandObjectTypeRXFormatList_LoopCallback, param_vp);
1399         }
1400         return true;
1401     }
1402 
1403 
1404     bool
1405     LoopCallback (const char* type,
1406                   const lldb::TypeFormatImplSP& entry,
1407                   RegularExpression* regex,
1408                   CommandReturnObject *result)
1409     {
1410         if (regex == NULL || strcmp(type,regex->GetText()) == 0 || regex->Execute(type))
1411             result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
1412         return true;
1413     }
1414 
1415     friend bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry);
1416     friend bool CommandObjectTypeRXFormatList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeFormatImplSP& entry);
1417 
1418 };
1419 
1420 bool
1421 CommandObjectTypeFormatList_LoopCallback (
1422                                     void* pt2self,
1423                                     ConstString type,
1424                                     const lldb::TypeFormatImplSP& entry)
1425 {
1426     CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self;
1427     return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
1428 }
1429 
1430 bool
1431 CommandObjectTypeRXFormatList_LoopCallback (
1432                                              void* pt2self,
1433                                              lldb::RegularExpressionSP regex,
1434                                              const lldb::TypeFormatImplSP& entry)
1435 {
1436     CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self;
1437     return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
1438 }
1439 
1440 OptionDefinition
1441 CommandObjectTypeFormatList::CommandOptions::g_option_table[] =
1442 {
1443     { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
1444     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1445 };
1446 
1447 #ifndef LLDB_DISABLE_PYTHON
1448 
1449 //-------------------------------------------------------------------------
1450 // CommandObjectTypeSummaryAdd
1451 //-------------------------------------------------------------------------
1452 
1453 #endif // #ifndef LLDB_DISABLE_PYTHON
1454 
1455 Error
1456 CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
1457 {
1458     Error error;
1459     const int short_option = m_getopt_table[option_idx].val;
1460     bool success;
1461 
1462     switch (short_option)
1463     {
1464         case 'C':
1465             m_flags.SetCascades(Args::StringToBoolean(option_arg, true, &success));
1466             if (!success)
1467                 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg);
1468             break;
1469         case 'e':
1470             m_flags.SetDontShowChildren(false);
1471             break;
1472         case 'h':
1473             m_flags.SetHideEmptyAggregates(true);
1474             break;
1475         case 'v':
1476             m_flags.SetDontShowValue(true);
1477             break;
1478         case 'c':
1479             m_flags.SetShowMembersOneLiner(true);
1480             break;
1481         case 's':
1482             m_format_string = std::string(option_arg);
1483             break;
1484         case 'p':
1485             m_flags.SetSkipPointers(true);
1486             break;
1487         case 'r':
1488             m_flags.SetSkipReferences(true);
1489             break;
1490         case 'x':
1491             m_regex = true;
1492             break;
1493         case 'n':
1494             m_name.SetCString(option_arg);
1495             break;
1496         case 'o':
1497             m_python_script = std::string(option_arg);
1498             m_is_add_script = true;
1499             break;
1500         case 'F':
1501             m_python_function = std::string(option_arg);
1502             m_is_add_script = true;
1503             break;
1504         case 'P':
1505             m_is_add_script = true;
1506             break;
1507         case 'w':
1508             m_category = std::string(option_arg);
1509             break;
1510         case 'O':
1511             m_flags.SetHideItemNames(true);
1512             break;
1513         default:
1514             error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1515             break;
1516     }
1517 
1518     return error;
1519 }
1520 
1521 void
1522 CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting ()
1523 {
1524     m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1525     m_flags.SetShowMembersOneLiner(false).SetSkipPointers(false).SetSkipReferences(false).SetHideItemNames(false);
1526 
1527     m_regex = false;
1528     m_name.Clear();
1529     m_python_script = "";
1530     m_python_function = "";
1531     m_format_string = "";
1532     m_is_add_script = false;
1533     m_category = "default";
1534 }
1535 
1536 
1537 
1538 #ifndef LLDB_DISABLE_PYTHON
1539 
1540 bool
1541 CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result)
1542 {
1543     const size_t argc = command.GetArgumentCount();
1544 
1545     if (argc < 1 && !m_options.m_name)
1546     {
1547         result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
1548         result.SetStatus(eReturnStatusFailed);
1549         return false;
1550     }
1551 
1552     TypeSummaryImplSP script_format;
1553 
1554     if (!m_options.m_python_function.empty()) // we have a Python function ready to use
1555     {
1556         const char *funct_name = m_options.m_python_function.c_str();
1557         if (!funct_name || !funct_name[0])
1558         {
1559             result.AppendError ("function name empty.\n");
1560             result.SetStatus (eReturnStatusFailed);
1561             return false;
1562         }
1563 
1564         std::string code = ("    " + m_options.m_python_function + "(valobj,internal_dict)");
1565 
1566         script_format.reset(new ScriptSummaryFormat(m_options.m_flags,
1567                                                     funct_name,
1568                                                     code.c_str()));
1569 
1570         ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1571 
1572         if (interpreter && interpreter->CheckObjectExists(funct_name) == false)
1573             result.AppendWarningWithFormat("The provided function \"%s\" does not exist - "
1574                                            "please define it before attempting to use this summary.\n",
1575                                            funct_name);
1576     }
1577     else if (!m_options.m_python_script.empty()) // we have a quick 1-line script, just use it
1578     {
1579         ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1580         if (!interpreter)
1581         {
1582             result.AppendError ("script interpreter missing - unable to generate function wrapper.\n");
1583             result.SetStatus (eReturnStatusFailed);
1584             return false;
1585         }
1586         StringList funct_sl;
1587         funct_sl << m_options.m_python_script.c_str();
1588         std::string funct_name_str;
1589         if (!interpreter->GenerateTypeScriptFunction (funct_sl,
1590                                                       funct_name_str))
1591         {
1592             result.AppendError ("unable to generate function wrapper.\n");
1593             result.SetStatus (eReturnStatusFailed);
1594             return false;
1595         }
1596         if (funct_name_str.empty())
1597         {
1598             result.AppendError ("script interpreter failed to generate a valid function name.\n");
1599             result.SetStatus (eReturnStatusFailed);
1600             return false;
1601         }
1602 
1603         std::string code = "    " + m_options.m_python_script;
1604 
1605         script_format.reset(new ScriptSummaryFormat(m_options.m_flags,
1606                                                     funct_name_str.c_str(),
1607                                                     code.c_str()));
1608     }
1609     else
1610     {
1611         // Use an IOHandler to grab Python code from the user
1612         ScriptAddOptions *options = new ScriptAddOptions(m_options.m_flags,
1613                                                          m_options.m_regex,
1614                                                          m_options.m_name,
1615                                                          m_options.m_category);
1616 
1617         for (size_t i = 0; i < argc; i++)
1618         {
1619             const char* typeA = command.GetArgumentAtIndex(i);
1620             if (typeA && *typeA)
1621                 options->m_target_types << typeA;
1622             else
1623             {
1624                 result.AppendError("empty typenames not allowed");
1625                 result.SetStatus(eReturnStatusFailed);
1626                 return false;
1627             }
1628         }
1629 
1630         m_interpreter.GetPythonCommandsFromIOHandler ("    ",   // Prompt
1631                                                       *this,    // IOHandlerDelegate
1632                                                       true,     // Run IOHandler in async mode
1633                                                       options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
1634         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1635 
1636         return result.Succeeded();
1637     }
1638 
1639     // if I am here, script_format must point to something good, so I can add that
1640     // as a script summary to all interested parties
1641 
1642     Error error;
1643 
1644     for (size_t i = 0; i < command.GetArgumentCount(); i++)
1645     {
1646         const char *type_name = command.GetArgumentAtIndex(i);
1647         CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
1648                                                 script_format,
1649                                                 (m_options.m_regex ? eRegexSummary : eRegularSummary),
1650                                                 m_options.m_category,
1651                                                 &error);
1652         if (error.Fail())
1653         {
1654             result.AppendError(error.AsCString());
1655             result.SetStatus(eReturnStatusFailed);
1656             return false;
1657         }
1658     }
1659 
1660     if (m_options.m_name)
1661     {
1662         AddSummary(m_options.m_name, script_format, eNamedSummary, m_options.m_category, &error);
1663         if (error.Fail())
1664         {
1665             result.AppendError(error.AsCString());
1666             result.AppendError("added to types, but not given a name");
1667             result.SetStatus(eReturnStatusFailed);
1668             return false;
1669         }
1670     }
1671 
1672     return result.Succeeded();
1673 }
1674 
1675 #endif
1676 
1677 
1678 bool
1679 CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result)
1680 {
1681     const size_t argc = command.GetArgumentCount();
1682 
1683     if (argc < 1 && !m_options.m_name)
1684     {
1685         result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
1686         result.SetStatus(eReturnStatusFailed);
1687         return false;
1688     }
1689 
1690     if (!m_options.m_flags.GetShowMembersOneLiner() && m_options.m_format_string.empty())
1691     {
1692         result.AppendError("empty summary strings not allowed");
1693         result.SetStatus(eReturnStatusFailed);
1694         return false;
1695     }
1696 
1697     const char* format_cstr = (m_options.m_flags.GetShowMembersOneLiner() ? "" : m_options.m_format_string.c_str());
1698 
1699     // ${var%S} is an endless recursion, prevent it
1700     if (strcmp(format_cstr, "${var%S}") == 0)
1701     {
1702         result.AppendError("recursive summary not allowed");
1703         result.SetStatus(eReturnStatusFailed);
1704         return false;
1705     }
1706 
1707     Error error;
1708 
1709     lldb::TypeSummaryImplSP entry(new StringSummaryFormat(m_options.m_flags,
1710                                                         format_cstr));
1711 
1712     if (error.Fail())
1713     {
1714         result.AppendError(error.AsCString());
1715         result.SetStatus(eReturnStatusFailed);
1716         return false;
1717     }
1718 
1719     // now I have a valid format, let's add it to every type
1720 
1721     for (size_t i = 0; i < argc; i++)
1722     {
1723         const char* typeA = command.GetArgumentAtIndex(i);
1724         if (!typeA || typeA[0] == '\0')
1725         {
1726             result.AppendError("empty typenames not allowed");
1727             result.SetStatus(eReturnStatusFailed);
1728             return false;
1729         }
1730         ConstString typeCS(typeA);
1731 
1732         AddSummary(typeCS,
1733                    entry,
1734                    (m_options.m_regex ? eRegexSummary : eRegularSummary),
1735                    m_options.m_category,
1736                    &error);
1737 
1738         if (error.Fail())
1739         {
1740             result.AppendError(error.AsCString());
1741             result.SetStatus(eReturnStatusFailed);
1742             return false;
1743         }
1744     }
1745 
1746     if (m_options.m_name)
1747     {
1748         AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, &error);
1749         if (error.Fail())
1750         {
1751             result.AppendError(error.AsCString());
1752             result.AppendError("added to types, but not given a name");
1753             result.SetStatus(eReturnStatusFailed);
1754             return false;
1755         }
1756     }
1757 
1758     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1759     return result.Succeeded();
1760 }
1761 
1762 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) :
1763     CommandObjectParsed (interpreter,
1764                          "type summary add",
1765                          "Add a new summary style for a type.",
1766                          NULL),
1767     IOHandlerDelegateMultiline ("DONE"),
1768     m_options (interpreter)
1769 {
1770     CommandArgumentEntry type_arg;
1771     CommandArgumentData type_style_arg;
1772 
1773     type_style_arg.arg_type = eArgTypeName;
1774     type_style_arg.arg_repetition = eArgRepeatPlus;
1775 
1776     type_arg.push_back (type_style_arg);
1777 
1778     m_arguments.push_back (type_arg);
1779 
1780     SetHelpLong(
1781 R"(
1782 The following examples of 'type summary add' refer to this code snippet for context:
1783 
1784     struct JustADemo
1785     {
1786         int* ptr;
1787         float value;
1788         JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1789     };
1790     JustADemo demo_instance(42, 3.14);
1791 
1792     typedef JustADemo NewDemo;
1793     NewDemo new_demo_instance(42, 3.14);
1794 
1795 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1796 
1797     Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1798 
1799 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1800 
1801     Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1802 
1803 )" "Alternatively, you could define formatting for all pointers to integers and \
1804 rely on that when formatting JustADemo to obtain the same result:" R"(
1805 
1806 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1807 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1808 
1809 )" "Type summaries are automatically applied to derived typedefs, so the examples \
1810 above apply to both JustADemo and NewDemo.  The cascade option can be used to \
1811 suppress this behavior:" R"(
1812 
1813 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1814 
1815     The summary will now be used for values of JustADemo but not NewDemo.
1816 
1817 )" "By default summaries are shown for pointers and references to values of the \
1818 specified type.  To suppress formatting for pointers use the -p option, or apply \
1819 the corresponding -r option to suppress formatting for references:" R"(
1820 
1821 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1822 
1823 )" "One-line summaries including all fields in a type can be inferred without supplying an \
1824 explicit summary string by passing the -c option:" R"(
1825 
1826 (lldb) type summary add -c JustADemo
1827 (lldb) frame variable demo_instance
1828 (ptr=<address>, value=3.14)
1829 
1830 )" "Type summaries normally suppress the nested display of individual fields.  To \
1831 supply a summary to supplement the default structure add the -e option:" R"(
1832 
1833 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1834 
1835 )" "Now when displaying JustADemo values the int* is displayed, followed by the \
1836 standard LLDB sequence of children, one per line:" R"(
1837 
1838 *ptr = 42 {
1839   ptr = <address>
1840   value = 3.14
1841 }
1842 
1843 )" "You can also add summaries written in Python.  These scripts use lldb public API to \
1844 gather information from your variables and produce a meaningful summary.  To start a \
1845 multi-line script use the -P option.  The function declaration will be displayed along with \
1846 a comment describing the two arguments.  End your script with the  word 'DONE' on a line by \
1847 itself:" R"(
1848 
1849 (lldb) type summary add JustADemo -P
1850 def function (valobj,internal_dict):
1851 """valobj: an SBValue which you want to provide a summary for
1852 internal_dict: an LLDB support object not to be used"""
1853     value = valobj.GetChildMemberWithName('value');
1854     return 'My value is ' + value.GetValue();
1855     DONE
1856 
1857 Alternatively, the -o option can be used when providing a simple one-line Python script:
1858 
1859 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"
1860     );
1861 }
1862 
1863 bool
1864 CommandObjectTypeSummaryAdd::DoExecute (Args& command, CommandReturnObject &result)
1865 {
1866     WarnOnPotentialUnquotedUnsignedType(command, result);
1867 
1868     if (m_options.m_is_add_script)
1869     {
1870 #ifndef LLDB_DISABLE_PYTHON
1871         return Execute_ScriptSummary(command, result);
1872 #else
1873         result.AppendError ("python is disabled");
1874         result.SetStatus(eReturnStatusFailed);
1875         return false;
1876 #endif
1877     }
1878 
1879     return Execute_StringSummary(command, result);
1880 }
1881 
1882 static bool
1883 FixArrayTypeNameWithRegex (ConstString &type_name)
1884 {
1885     llvm::StringRef type_name_ref(type_name.GetStringRef());
1886 
1887     if (type_name_ref.endswith("[]"))
1888     {
1889         std::string type_name_str(type_name.GetCString());
1890         type_name_str.resize(type_name_str.length()-2);
1891         if (type_name_str.back() != ' ')
1892             type_name_str.append(" \\[[0-9]+\\]");
1893         else
1894             type_name_str.append("\\[[0-9]+\\]");
1895         type_name.SetCString(type_name_str.c_str());
1896         return true;
1897     }
1898     return false;
1899 }
1900 
1901 bool
1902 CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
1903                                         TypeSummaryImplSP entry,
1904                                         SummaryFormatType type,
1905                                         std::string category_name,
1906                                         Error* error)
1907 {
1908     lldb::TypeCategoryImplSP category;
1909     DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
1910 
1911     if (type == eRegularSummary)
1912     {
1913         if (FixArrayTypeNameWithRegex (type_name))
1914             type = eRegexSummary;
1915     }
1916 
1917     if (type == eRegexSummary)
1918     {
1919         RegularExpressionSP typeRX(new RegularExpression());
1920         if (!typeRX->Compile(type_name.GetCString()))
1921         {
1922             if (error)
1923                 error->SetErrorString("regex format error (maybe this is not really a regex?)");
1924             return false;
1925         }
1926 
1927         category->GetRegexTypeSummariesContainer()->Delete(type_name);
1928         category->GetRegexTypeSummariesContainer()->Add(typeRX, entry);
1929 
1930         return true;
1931     }
1932     else if (type == eNamedSummary)
1933     {
1934         // system named summaries do not exist (yet?)
1935         DataVisualization::NamedSummaryFormats::Add(type_name,entry);
1936         return true;
1937     }
1938     else
1939     {
1940         category->GetTypeSummariesContainer()->Add(type_name, entry);
1941         return true;
1942     }
1943 }
1944 
1945 OptionDefinition
1946 CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
1947 {
1948     { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,    "Add this to the given category instead of the default one."},
1949     { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,    "If true, cascade through typedef chains."},
1950     { 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."},
1951     { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
1952     { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
1953     { LLDB_OPT_SET_ALL, false,  "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
1954     { LLDB_OPT_SET_1  , true, "inline-children", 'c', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "If true, inline all child values into summary string."},
1955     { LLDB_OPT_SET_1  , false, "omit-names", 'O', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "If true, omit value names in the summary display."},
1956     { LLDB_OPT_SET_2  , true, "summary-string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeSummaryString,    "Summary string used to display text and object contents."},
1957     { 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."},
1958     { 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."},
1959     { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."},
1960     { 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."},
1961     { 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."},
1962     { LLDB_OPT_SET_2 | LLDB_OPT_SET_3,   false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,    "A name for this summary string."},
1963     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1964 };
1965 
1966 
1967 //-------------------------------------------------------------------------
1968 // CommandObjectTypeSummaryDelete
1969 //-------------------------------------------------------------------------
1970 
1971 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete
1972 {
1973 public:
1974     CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) :
1975     CommandObjectTypeFormatterDelete (interpreter,
1976                                       eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
1977                                       "type summary delete",
1978                                       "Delete an existing summary for a type.")
1979     {
1980     }
1981 
1982     ~CommandObjectTypeSummaryDelete () override
1983     {
1984     }
1985 
1986 protected:
1987     bool
1988     FormatterSpecificDeletion (ConstString typeCS) override
1989     {
1990         if (m_options.m_language != lldb::eLanguageTypeUnknown)
1991             return false;
1992         return DataVisualization::NamedSummaryFormats::Delete(typeCS);
1993     }
1994 };
1995 
1996 class CommandObjectTypeSummaryClear : public CommandObjectParsed
1997 {
1998 private:
1999 
2000     class CommandOptions : public Options
2001     {
2002     public:
2003 
2004         CommandOptions (CommandInterpreter &interpreter) :
2005         Options (interpreter)
2006         {
2007         }
2008 
2009         ~CommandOptions () override {}
2010 
2011         Error
2012         SetOptionValue (uint32_t option_idx, const char *option_arg) override
2013         {
2014             Error error;
2015             const int short_option = m_getopt_table[option_idx].val;
2016 
2017             switch (short_option)
2018             {
2019                 case 'a':
2020                     m_delete_all = true;
2021                     break;
2022                 default:
2023                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2024                     break;
2025             }
2026 
2027             return error;
2028         }
2029 
2030         void
2031         OptionParsingStarting () override
2032         {
2033             m_delete_all = false;
2034         }
2035 
2036         const OptionDefinition*
2037         GetDefinitions () override
2038         {
2039             return g_option_table;
2040         }
2041 
2042         // Options table: Required for subclasses of Options.
2043 
2044         static OptionDefinition g_option_table[];
2045 
2046         // Instance variables to hold the values for command options.
2047 
2048         bool m_delete_all;
2049         bool m_delete_named;
2050     };
2051 
2052     CommandOptions m_options;
2053 
2054     Options *
2055     GetOptions () override
2056     {
2057         return &m_options;
2058     }
2059 
2060 public:
2061     CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) :
2062         CommandObjectParsed (interpreter,
2063                              "type summary clear",
2064                              "Delete all existing summary styles.",
2065                              NULL),
2066         m_options(interpreter)
2067     {
2068     }
2069 
2070     ~CommandObjectTypeSummaryClear () override
2071     {
2072     }
2073 
2074 protected:
2075     bool
2076     DoExecute (Args& command, CommandReturnObject &result) override
2077     {
2078 
2079         if (m_options.m_delete_all)
2080         {
2081             DataVisualization::Categories::ForEach( [] (const TypeCategoryImplSP& category_sp) -> bool {
2082                 category_sp->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary);
2083                 return true;
2084             });
2085         }
2086         else
2087         {
2088             lldb::TypeCategoryImplSP category;
2089             if (command.GetArgumentCount() > 0)
2090             {
2091                 const char* cat_name = command.GetArgumentAtIndex(0);
2092                 ConstString cat_nameCS(cat_name);
2093                 DataVisualization::Categories::GetCategory(cat_nameCS, category);
2094             }
2095             else
2096                 DataVisualization::Categories::GetCategory(ConstString(NULL), category);
2097             category->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary);
2098         }
2099 
2100         DataVisualization::NamedSummaryFormats::Clear();
2101 
2102         result.SetStatus(eReturnStatusSuccessFinishResult);
2103         return result.Succeeded();
2104     }
2105 
2106 };
2107 
2108 OptionDefinition
2109 CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] =
2110 {
2111     { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,  "Clear every category."},
2112     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2113 };
2114 
2115 //-------------------------------------------------------------------------
2116 // CommandObjectTypeSummaryList
2117 //-------------------------------------------------------------------------
2118 
2119 bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const StringSummaryFormat::SharedPointer& entry);
2120 bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry);
2121 
2122 class CommandObjectTypeSummaryList;
2123 
2124 struct CommandObjectTypeSummaryList_LoopCallbackParam {
2125     CommandObjectTypeSummaryList* self;
2126     CommandReturnObject* result;
2127     RegularExpression* regex;
2128     RegularExpression* cate_regex;
2129     CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R,
2130                                                   RegularExpression* X = NULL,
2131                                                   RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
2132 };
2133 
2134 class CommandObjectTypeSummaryList : public CommandObjectParsed
2135 {
2136 
2137     class CommandOptions : public Options
2138     {
2139     public:
2140 
2141         CommandOptions (CommandInterpreter &interpreter) :
2142         Options (interpreter)
2143         {
2144         }
2145 
2146         ~CommandOptions () override {}
2147 
2148         Error
2149         SetOptionValue (uint32_t option_idx, const char *option_arg) override
2150         {
2151             Error error;
2152             const int short_option = m_getopt_table[option_idx].val;
2153 
2154             switch (short_option)
2155             {
2156                 case 'w':
2157                     m_category_regex = std::string(option_arg);
2158                     break;
2159                 default:
2160                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2161                     break;
2162             }
2163 
2164             return error;
2165         }
2166 
2167         void
2168         OptionParsingStarting () override
2169         {
2170             m_category_regex = "";
2171         }
2172 
2173         const OptionDefinition*
2174         GetDefinitions () override
2175         {
2176             return g_option_table;
2177         }
2178 
2179         // Options table: Required for subclasses of Options.
2180 
2181         static OptionDefinition g_option_table[];
2182 
2183         // Instance variables to hold the values for command options.
2184 
2185         std::string m_category_regex;
2186 
2187     };
2188 
2189     CommandOptions m_options;
2190 
2191     Options *
2192     GetOptions () override
2193     {
2194         return &m_options;
2195     }
2196 
2197 public:
2198     CommandObjectTypeSummaryList (CommandInterpreter &interpreter) :
2199         CommandObjectParsed (interpreter,
2200                              "type summary list",
2201                              "Show a list of current summary styles.",
2202                              NULL),
2203         m_options(interpreter)
2204     {
2205         CommandArgumentEntry type_arg;
2206         CommandArgumentData type_style_arg;
2207 
2208         type_style_arg.arg_type = eArgTypeName;
2209         type_style_arg.arg_repetition = eArgRepeatOptional;
2210 
2211         type_arg.push_back (type_style_arg);
2212 
2213         m_arguments.push_back (type_arg);
2214     }
2215 
2216     ~CommandObjectTypeSummaryList () override
2217     {
2218     }
2219 
2220 protected:
2221     bool
2222     DoExecute (Args& command, CommandReturnObject &result) override
2223     {
2224         const size_t argc = command.GetArgumentCount();
2225 
2226         CommandObjectTypeSummaryList_LoopCallbackParam *param;
2227         RegularExpression* cate_regex =
2228         m_options.m_category_regex.empty() ? NULL :
2229         new RegularExpression(m_options.m_category_regex.c_str());
2230 
2231         if (argc == 1)
2232         {
2233             RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
2234             regex->Compile(command.GetArgumentAtIndex(0));
2235             param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex,cate_regex);
2236         }
2237         else
2238             param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,NULL,cate_regex);
2239 
2240         DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
2241         delete param;
2242 
2243         if (DataVisualization::NamedSummaryFormats::GetCount() > 0)
2244         {
2245             result.GetOutputStream().Printf("Named summaries:\n");
2246             if (argc == 1)
2247             {
2248                 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
2249                 regex->Compile(command.GetArgumentAtIndex(0));
2250                 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex);
2251             }
2252             else
2253                 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result);
2254             DataVisualization::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
2255             delete param;
2256         }
2257 
2258         if (cate_regex)
2259             delete cate_regex;
2260 
2261         result.SetStatus(eReturnStatusSuccessFinishResult);
2262         return result.Succeeded();
2263     }
2264 
2265 private:
2266 
2267     static bool
2268     PerCategoryCallback(void* param_vp,
2269                         const lldb::TypeCategoryImplSP& cate)
2270     {
2271 
2272         CommandObjectTypeSummaryList_LoopCallbackParam* param =
2273             (CommandObjectTypeSummaryList_LoopCallbackParam*)param_vp;
2274         CommandReturnObject* result = param->result;
2275 
2276         const char* cate_name = cate->GetName();
2277 
2278         // if the category is disabled or empty and there is no regex, just skip it
2279         if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary) == 0) && param->cate_regex == NULL)
2280             return true;
2281 
2282         // if we have a regex and this category does not match it, just skip it
2283         if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false)
2284             return true;
2285 
2286         result->GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", cate->GetDescription().c_str());
2287 
2288         cate->GetTypeSummariesContainer()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param_vp);
2289 
2290         if (cate->GetRegexTypeSummariesContainer()->GetCount() > 0)
2291         {
2292             result->GetOutputStream().Printf("Regex-based summaries (slower):\n");
2293             cate->GetRegexTypeSummariesContainer()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param_vp);
2294         }
2295         return true;
2296     }
2297 
2298 
2299     bool
2300     LoopCallback (const char* type,
2301                   const lldb::TypeSummaryImplSP& entry,
2302                   RegularExpression* regex,
2303                   CommandReturnObject *result)
2304     {
2305         if (regex == NULL || strcmp(type,regex->GetText()) == 0 || regex->Execute(type))
2306                 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
2307         return true;
2308     }
2309 
2310     friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeSummaryImplSP& entry);
2311     friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeSummaryImplSP& entry);
2312 };
2313 
2314 bool
2315 CommandObjectTypeSummaryList_LoopCallback (
2316                                           void* pt2self,
2317                                           ConstString type,
2318                                           const lldb::TypeSummaryImplSP& entry)
2319 {
2320     CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
2321     return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
2322 }
2323 
2324 bool
2325 CommandObjectTypeRXSummaryList_LoopCallback (
2326                                            void* pt2self,
2327                                            lldb::RegularExpressionSP regex,
2328                                            const lldb::TypeSummaryImplSP& entry)
2329 {
2330     CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
2331     return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
2332 }
2333 
2334 OptionDefinition
2335 CommandObjectTypeSummaryList::CommandOptions::g_option_table[] =
2336 {
2337     { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
2338     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2339 };
2340 
2341 //-------------------------------------------------------------------------
2342 // CommandObjectTypeCategoryDefine
2343 //-------------------------------------------------------------------------
2344 
2345 class CommandObjectTypeCategoryDefine : public CommandObjectParsed
2346 {
2347 
2348     class CommandOptions : public Options
2349     {
2350     public:
2351 
2352         CommandOptions (CommandInterpreter &interpreter) :
2353         Options (interpreter),
2354         m_define_enabled(false,false),
2355         m_cate_language(eLanguageTypeUnknown,eLanguageTypeUnknown)
2356         {
2357         }
2358 
2359         ~CommandOptions () override {}
2360 
2361         Error
2362         SetOptionValue (uint32_t option_idx, const char *option_arg) override
2363         {
2364             Error error;
2365             const int short_option = m_getopt_table[option_idx].val;
2366 
2367             switch (short_option)
2368             {
2369                 case 'e':
2370                     m_define_enabled.SetValueFromString("true");
2371                     break;
2372                 case 'l':
2373                     error = m_cate_language.SetValueFromString(option_arg);
2374                     break;
2375                 default:
2376                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2377                     break;
2378             }
2379 
2380             return error;
2381         }
2382 
2383         void
2384         OptionParsingStarting () override
2385         {
2386             m_define_enabled.Clear();
2387             m_cate_language.Clear();
2388         }
2389 
2390         const OptionDefinition*
2391         GetDefinitions () override
2392         {
2393             return g_option_table;
2394         }
2395 
2396         // Options table: Required for subclasses of Options.
2397 
2398         static OptionDefinition g_option_table[];
2399 
2400         // Instance variables to hold the values for command options.
2401 
2402         OptionValueBoolean m_define_enabled;
2403         OptionValueLanguage m_cate_language;
2404 
2405 
2406     };
2407 
2408     CommandOptions m_options;
2409 
2410     Options *
2411     GetOptions () override
2412     {
2413         return &m_options;
2414     }
2415 
2416 public:
2417     CommandObjectTypeCategoryDefine (CommandInterpreter &interpreter) :
2418     CommandObjectParsed (interpreter,
2419                          "type category define",
2420                          "Define a new category as a source of formatters.",
2421                          NULL),
2422     m_options(interpreter)
2423     {
2424         CommandArgumentEntry type_arg;
2425         CommandArgumentData type_style_arg;
2426 
2427         type_style_arg.arg_type = eArgTypeName;
2428         type_style_arg.arg_repetition = eArgRepeatPlus;
2429 
2430         type_arg.push_back (type_style_arg);
2431 
2432         m_arguments.push_back (type_arg);
2433 
2434     }
2435 
2436     ~CommandObjectTypeCategoryDefine () override
2437     {
2438     }
2439 
2440 protected:
2441     bool
2442     DoExecute (Args& command, CommandReturnObject &result) override
2443     {
2444         const size_t argc = command.GetArgumentCount();
2445 
2446         if (argc < 1)
2447         {
2448             result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
2449             result.SetStatus(eReturnStatusFailed);
2450             return false;
2451         }
2452 
2453         for (size_t i = 0; i < argc; i++)
2454         {
2455             const char* cateName = command.GetArgumentAtIndex(i);
2456             TypeCategoryImplSP category_sp;
2457             if (DataVisualization::Categories::GetCategory(ConstString(cateName), category_sp) && category_sp)
2458             {
2459                 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
2460                 if (m_options.m_define_enabled.GetCurrentValue())
2461                     DataVisualization::Categories::Enable(category_sp, TypeCategoryMap::Default);
2462             }
2463         }
2464 
2465         result.SetStatus(eReturnStatusSuccessFinishResult);
2466         return result.Succeeded();
2467     }
2468 
2469 };
2470 
2471 OptionDefinition
2472 CommandObjectTypeCategoryDefine::CommandOptions::g_option_table[] =
2473 {
2474     { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,  "If specified, this category will be created enabled."},
2475     { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,  "Specify the language that this category is supported for."},
2476     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2477 };
2478 
2479 //-------------------------------------------------------------------------
2480 // CommandObjectTypeCategoryEnable
2481 //-------------------------------------------------------------------------
2482 
2483 class CommandObjectTypeCategoryEnable : public CommandObjectParsed
2484 {
2485     class CommandOptions : public Options
2486     {
2487     public:
2488 
2489         CommandOptions (CommandInterpreter &interpreter) :
2490         Options (interpreter)
2491         {
2492         }
2493 
2494         ~CommandOptions () override {}
2495 
2496         Error
2497         SetOptionValue (uint32_t option_idx, const char *option_arg) override
2498         {
2499             Error error;
2500             const int short_option = m_getopt_table[option_idx].val;
2501 
2502             switch (short_option)
2503             {
2504                 case 'l':
2505                     if (option_arg)
2506                     {
2507                         m_language = Language::GetLanguageTypeFromString(option_arg);
2508                         if (m_language == lldb::eLanguageTypeUnknown)
2509                             error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg);
2510                     }
2511                     break;
2512                 default:
2513                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2514                     break;
2515             }
2516 
2517             return error;
2518         }
2519 
2520         void
2521         OptionParsingStarting () override
2522         {
2523             m_language = lldb::eLanguageTypeUnknown;
2524         }
2525 
2526         const OptionDefinition*
2527         GetDefinitions () override
2528         {
2529             return g_option_table;
2530         }
2531 
2532         // Options table: Required for subclasses of Options.
2533 
2534         static OptionDefinition g_option_table[];
2535 
2536         // Instance variables to hold the values for command options.
2537 
2538         lldb::LanguageType m_language;
2539 
2540     };
2541 
2542     CommandOptions m_options;
2543 
2544     Options *
2545     GetOptions () override
2546     {
2547         return &m_options;
2548     }
2549 
2550 public:
2551     CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) :
2552         CommandObjectParsed (interpreter,
2553                              "type category enable",
2554                              "Enable a category as a source of formatters.",
2555                              NULL),
2556         m_options(interpreter)
2557     {
2558         CommandArgumentEntry type_arg;
2559         CommandArgumentData type_style_arg;
2560 
2561         type_style_arg.arg_type = eArgTypeName;
2562         type_style_arg.arg_repetition = eArgRepeatPlus;
2563 
2564         type_arg.push_back (type_style_arg);
2565 
2566         m_arguments.push_back (type_arg);
2567 
2568     }
2569 
2570     ~CommandObjectTypeCategoryEnable () override
2571     {
2572     }
2573 
2574 protected:
2575     bool
2576     DoExecute (Args& command, CommandReturnObject &result) override
2577     {
2578         const size_t argc = command.GetArgumentCount();
2579 
2580         if (argc < 1 &&
2581             m_options.m_language == lldb::eLanguageTypeUnknown)
2582         {
2583             result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str());
2584             result.SetStatus(eReturnStatusFailed);
2585             return false;
2586         }
2587 
2588         if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)
2589         {
2590             DataVisualization::Categories::EnableStar();
2591         }
2592         else if (argc > 0)
2593         {
2594             for (int i = argc - 1; i >= 0; i--)
2595             {
2596                 const char* typeA = command.GetArgumentAtIndex(i);
2597                 ConstString typeCS(typeA);
2598 
2599                 if (!typeCS)
2600                 {
2601                     result.AppendError("empty category name not allowed");
2602                     result.SetStatus(eReturnStatusFailed);
2603                     return false;
2604                 }
2605                 DataVisualization::Categories::Enable(typeCS);
2606                 lldb::TypeCategoryImplSP cate;
2607                 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate.get())
2608                 {
2609                     if (cate->GetCount() == 0)
2610                     {
2611                         result.AppendWarning("empty category enabled (typo?)");
2612                     }
2613                 }
2614             }
2615         }
2616 
2617         if (m_options.m_language != lldb::eLanguageTypeUnknown)
2618             DataVisualization::Categories::Enable(m_options.m_language);
2619 
2620         result.SetStatus(eReturnStatusSuccessFinishResult);
2621         return result.Succeeded();
2622     }
2623 
2624 };
2625 
2626 OptionDefinition
2627 CommandObjectTypeCategoryEnable::CommandOptions::g_option_table[] =
2628 {
2629     { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,  "Enable the category for this language."},
2630     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2631 };
2632 
2633 //-------------------------------------------------------------------------
2634 // CommandObjectTypeCategoryDelete
2635 //-------------------------------------------------------------------------
2636 
2637 class CommandObjectTypeCategoryDelete : public CommandObjectParsed
2638 {
2639 public:
2640     CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) :
2641         CommandObjectParsed (interpreter,
2642                              "type category delete",
2643                              "Delete a category and all associated formatters.",
2644                              NULL)
2645     {
2646         CommandArgumentEntry type_arg;
2647         CommandArgumentData type_style_arg;
2648 
2649         type_style_arg.arg_type = eArgTypeName;
2650         type_style_arg.arg_repetition = eArgRepeatPlus;
2651 
2652         type_arg.push_back (type_style_arg);
2653 
2654         m_arguments.push_back (type_arg);
2655 
2656     }
2657 
2658     ~CommandObjectTypeCategoryDelete () override
2659     {
2660     }
2661 
2662 protected:
2663     bool
2664     DoExecute (Args& command, CommandReturnObject &result) override
2665     {
2666         const size_t argc = command.GetArgumentCount();
2667 
2668         if (argc < 1)
2669         {
2670             result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str());
2671             result.SetStatus(eReturnStatusFailed);
2672             return false;
2673         }
2674 
2675         bool success = true;
2676 
2677         // the order is not relevant here
2678         for (int i = argc - 1; i >= 0; i--)
2679         {
2680             const char* typeA = command.GetArgumentAtIndex(i);
2681             ConstString typeCS(typeA);
2682 
2683             if (!typeCS)
2684             {
2685                 result.AppendError("empty category name not allowed");
2686                 result.SetStatus(eReturnStatusFailed);
2687                 return false;
2688             }
2689             if (!DataVisualization::Categories::Delete(typeCS))
2690                 success = false; // keep deleting even if we hit an error
2691         }
2692         if (success)
2693         {
2694             result.SetStatus(eReturnStatusSuccessFinishResult);
2695             return result.Succeeded();
2696         }
2697         else
2698         {
2699             result.AppendError("cannot delete one or more categories\n");
2700             result.SetStatus(eReturnStatusFailed);
2701             return false;
2702         }
2703     }
2704 };
2705 
2706 //-------------------------------------------------------------------------
2707 // CommandObjectTypeCategoryDisable
2708 //-------------------------------------------------------------------------
2709 
2710 class CommandObjectTypeCategoryDisable : public CommandObjectParsed
2711 {
2712     class CommandOptions : public Options
2713     {
2714     public:
2715 
2716         CommandOptions (CommandInterpreter &interpreter) :
2717         Options (interpreter)
2718         {
2719         }
2720 
2721         ~CommandOptions () override {}
2722 
2723         Error
2724         SetOptionValue (uint32_t option_idx, const char *option_arg) override
2725         {
2726             Error error;
2727             const int short_option = m_getopt_table[option_idx].val;
2728 
2729             switch (short_option)
2730             {
2731                 case 'l':
2732                     if (option_arg)
2733                     {
2734                         m_language = Language::GetLanguageTypeFromString(option_arg);
2735                         if (m_language == lldb::eLanguageTypeUnknown)
2736                             error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg);
2737                     }
2738                     break;
2739                 default:
2740                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2741                     break;
2742             }
2743 
2744             return error;
2745         }
2746 
2747         void
2748         OptionParsingStarting () override
2749         {
2750             m_language = lldb::eLanguageTypeUnknown;
2751         }
2752 
2753         const OptionDefinition*
2754         GetDefinitions () override
2755         {
2756             return g_option_table;
2757         }
2758 
2759         // Options table: Required for subclasses of Options.
2760 
2761         static OptionDefinition g_option_table[];
2762 
2763         // Instance variables to hold the values for command options.
2764 
2765         lldb::LanguageType m_language;
2766 
2767     };
2768 
2769     CommandOptions m_options;
2770 
2771     Options *
2772     GetOptions () override
2773     {
2774         return &m_options;
2775     }
2776 
2777 public:
2778     CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) :
2779         CommandObjectParsed (interpreter,
2780                              "type category disable",
2781                              "Disable a category as a source of formatters.",
2782                              NULL),
2783         m_options(interpreter)
2784     {
2785         CommandArgumentEntry type_arg;
2786         CommandArgumentData type_style_arg;
2787 
2788         type_style_arg.arg_type = eArgTypeName;
2789         type_style_arg.arg_repetition = eArgRepeatPlus;
2790 
2791         type_arg.push_back (type_style_arg);
2792 
2793         m_arguments.push_back (type_arg);
2794 
2795     }
2796 
2797     ~CommandObjectTypeCategoryDisable () override
2798     {
2799     }
2800 
2801 protected:
2802     bool
2803     DoExecute (Args& command, CommandReturnObject &result) override
2804     {
2805         const size_t argc = command.GetArgumentCount();
2806 
2807         if (argc < 1 &&
2808             m_options.m_language == lldb::eLanguageTypeUnknown)
2809         {
2810             result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str());
2811             result.SetStatus(eReturnStatusFailed);
2812             return false;
2813         }
2814 
2815         if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)
2816         {
2817             DataVisualization::Categories::DisableStar();
2818         }
2819         else if (argc > 0)
2820         {
2821             // the order is not relevant here
2822             for (int i = argc - 1; i >= 0; i--)
2823             {
2824                 const char* typeA = command.GetArgumentAtIndex(i);
2825                 ConstString typeCS(typeA);
2826 
2827                 if (!typeCS)
2828                 {
2829                     result.AppendError("empty category name not allowed");
2830                     result.SetStatus(eReturnStatusFailed);
2831                     return false;
2832                 }
2833                 DataVisualization::Categories::Disable(typeCS);
2834             }
2835         }
2836 
2837         if (m_options.m_language != lldb::eLanguageTypeUnknown)
2838             DataVisualization::Categories::Disable(m_options.m_language);
2839 
2840         result.SetStatus(eReturnStatusSuccessFinishResult);
2841         return result.Succeeded();
2842     }
2843 
2844 };
2845 
2846 OptionDefinition
2847 CommandObjectTypeCategoryDisable::CommandOptions::g_option_table[] =
2848 {
2849     { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,  "Enable the category for this language."},
2850     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2851 };
2852 
2853 //-------------------------------------------------------------------------
2854 // CommandObjectTypeCategoryList
2855 //-------------------------------------------------------------------------
2856 
2857 class CommandObjectTypeCategoryList : public CommandObjectParsed
2858 {
2859 private:
2860 
2861     struct CommandObjectTypeCategoryList_CallbackParam
2862     {
2863         CommandReturnObject* result;
2864         RegularExpression* regex;
2865 
2866         CommandObjectTypeCategoryList_CallbackParam(CommandReturnObject* res,
2867                                                     RegularExpression* rex = NULL) :
2868         result(res),
2869         regex(rex)
2870         {
2871         }
2872 
2873     };
2874 
2875     static bool
2876     PerCategoryCallback(void* param_vp,
2877                         const lldb::TypeCategoryImplSP& cate)
2878     {
2879         CommandObjectTypeCategoryList_CallbackParam* param =
2880             (CommandObjectTypeCategoryList_CallbackParam*)param_vp;
2881         CommandReturnObject* result = param->result;
2882         RegularExpression* regex = param->regex;
2883 
2884         const char* cate_name = cate->GetName();
2885 
2886         if (regex == NULL || strcmp(cate_name, regex->GetText()) == 0 || regex->Execute(cate_name))
2887             result->GetOutputStream().Printf("Category: %s\n", cate->GetDescription().c_str());
2888         return true;
2889     }
2890 public:
2891     CommandObjectTypeCategoryList (CommandInterpreter &interpreter) :
2892         CommandObjectParsed (interpreter,
2893                              "type category list",
2894                              "Provide a list of all existing categories.",
2895                              NULL)
2896     {
2897         CommandArgumentEntry type_arg;
2898         CommandArgumentData type_style_arg;
2899 
2900         type_style_arg.arg_type = eArgTypeName;
2901         type_style_arg.arg_repetition = eArgRepeatOptional;
2902 
2903         type_arg.push_back (type_style_arg);
2904 
2905         m_arguments.push_back (type_arg);
2906     }
2907 
2908     ~CommandObjectTypeCategoryList () override
2909     {
2910     }
2911 
2912 protected:
2913     bool
2914     DoExecute (Args& command, CommandReturnObject &result) override
2915     {
2916         const size_t argc = command.GetArgumentCount();
2917         RegularExpression* regex = NULL;
2918 
2919         if (argc == 0)
2920             ;
2921         else if (argc == 1)
2922             regex = new RegularExpression(command.GetArgumentAtIndex(0));
2923         else
2924         {
2925             result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str());
2926             result.SetStatus(eReturnStatusFailed);
2927             return false;
2928         }
2929 
2930         CommandObjectTypeCategoryList_CallbackParam param(&result,
2931                                                           regex);
2932 
2933         DataVisualization::Categories::LoopThrough(PerCategoryCallback, &param);
2934 
2935         if (regex)
2936             delete regex;
2937 
2938         result.SetStatus(eReturnStatusSuccessFinishResult);
2939         return result.Succeeded();
2940     }
2941 
2942 };
2943 
2944 //-------------------------------------------------------------------------
2945 // CommandObjectTypeFilterList
2946 //-------------------------------------------------------------------------
2947 
2948 bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
2949 bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
2950 
2951 class CommandObjectTypeFilterList;
2952 
2953 struct CommandObjectTypeFilterList_LoopCallbackParam {
2954     CommandObjectTypeFilterList* self;
2955     CommandReturnObject* result;
2956     RegularExpression* regex;
2957     RegularExpression* cate_regex;
2958     CommandObjectTypeFilterList_LoopCallbackParam(CommandObjectTypeFilterList* S, CommandReturnObject* R,
2959                                                   RegularExpression* X = NULL,
2960                                                   RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
2961 };
2962 
2963 class CommandObjectTypeFilterList : public CommandObjectParsed
2964 {
2965 
2966     class CommandOptions : public Options
2967     {
2968     public:
2969 
2970         CommandOptions (CommandInterpreter &interpreter) :
2971         Options (interpreter)
2972         {
2973         }
2974 
2975         ~CommandOptions () override {}
2976 
2977         Error
2978         SetOptionValue (uint32_t option_idx, const char *option_arg) override
2979         {
2980             Error error;
2981             const int short_option = m_getopt_table[option_idx].val;
2982 
2983             switch (short_option)
2984             {
2985                 case 'w':
2986                     m_category_regex = std::string(option_arg);
2987                     break;
2988                 default:
2989                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
2990                     break;
2991             }
2992 
2993             return error;
2994         }
2995 
2996         void
2997         OptionParsingStarting () override
2998         {
2999             m_category_regex = "";
3000         }
3001 
3002         const OptionDefinition*
3003         GetDefinitions () override
3004         {
3005             return g_option_table;
3006         }
3007 
3008         // Options table: Required for subclasses of Options.
3009 
3010         static OptionDefinition g_option_table[];
3011 
3012         // Instance variables to hold the values for command options.
3013 
3014         std::string m_category_regex;
3015 
3016     };
3017 
3018     CommandOptions m_options;
3019 
3020     Options *
3021     GetOptions () override
3022     {
3023         return &m_options;
3024     }
3025 
3026 public:
3027     CommandObjectTypeFilterList (CommandInterpreter &interpreter) :
3028         CommandObjectParsed (interpreter,
3029                              "type filter list",
3030                              "Show a list of current filters.",
3031                              NULL),
3032         m_options(interpreter)
3033     {
3034         CommandArgumentEntry type_arg;
3035         CommandArgumentData type_style_arg;
3036 
3037         type_style_arg.arg_type = eArgTypeName;
3038         type_style_arg.arg_repetition = eArgRepeatOptional;
3039 
3040         type_arg.push_back (type_style_arg);
3041 
3042         m_arguments.push_back (type_arg);
3043     }
3044 
3045     ~CommandObjectTypeFilterList () override
3046     {
3047     }
3048 
3049 protected:
3050     bool
3051     DoExecute (Args& command, CommandReturnObject &result) override
3052     {
3053         const size_t argc = command.GetArgumentCount();
3054 
3055         CommandObjectTypeFilterList_LoopCallbackParam *param;
3056         RegularExpression* cate_regex =
3057         m_options.m_category_regex.empty() ? NULL :
3058         new RegularExpression(m_options.m_category_regex.c_str());
3059 
3060         if (argc == 1)
3061         {
3062             RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
3063             regex->Compile(command.GetArgumentAtIndex(0));
3064             param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,regex,cate_regex);
3065         }
3066         else
3067             param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,NULL,cate_regex);
3068 
3069         DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
3070         delete param;
3071 
3072         if (cate_regex)
3073             delete cate_regex;
3074 
3075         result.SetStatus(eReturnStatusSuccessFinishResult);
3076         return result.Succeeded();
3077     }
3078 
3079 private:
3080 
3081     static bool
3082     PerCategoryCallback(void* param_vp,
3083                         const lldb::TypeCategoryImplSP& cate)
3084     {
3085 
3086         const char* cate_name = cate->GetName();
3087 
3088         CommandObjectTypeFilterList_LoopCallbackParam* param =
3089         (CommandObjectTypeFilterList_LoopCallbackParam*)param_vp;
3090         CommandReturnObject* result = param->result;
3091 
3092         // if the category is disabled or empty and there is no regex, just skip it
3093         if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter) == 0) && param->cate_regex == NULL)
3094             return true;
3095 
3096         // if we have a regex and this category does not match it, just skip it
3097         if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false)
3098             return true;
3099 
3100         result->GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", cate->GetDescription().c_str());
3101 
3102         cate->GetTypeFiltersContainer()->LoopThrough(CommandObjectTypeFilterList_LoopCallback, param_vp);
3103 
3104         if (cate->GetRegexTypeFiltersContainer()->GetCount() > 0)
3105         {
3106             result->GetOutputStream().Printf("Regex-based filters (slower):\n");
3107             cate->GetRegexTypeFiltersContainer()->LoopThrough(CommandObjectTypeFilterRXList_LoopCallback, param_vp);
3108         }
3109 
3110         return true;
3111     }
3112 
3113     bool
3114     LoopCallback (const char* type,
3115                   const SyntheticChildren::SharedPointer& entry,
3116                   RegularExpression* regex,
3117                   CommandReturnObject *result)
3118     {
3119         if (regex == NULL || regex->Execute(type))
3120             result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
3121         return true;
3122     }
3123 
3124     friend bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
3125     friend bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
3126 };
3127 
3128 bool
3129 CommandObjectTypeFilterList_LoopCallback (void* pt2self,
3130                                          ConstString type,
3131                                          const SyntheticChildren::SharedPointer& entry)
3132 {
3133     CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self;
3134     return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
3135 }
3136 
3137 bool
3138 CommandObjectTypeFilterRXList_LoopCallback (void* pt2self,
3139                                            lldb::RegularExpressionSP regex,
3140                                            const SyntheticChildren::SharedPointer& entry)
3141 {
3142     CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self;
3143     return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
3144 }
3145 
3146 
3147 OptionDefinition
3148 CommandObjectTypeFilterList::CommandOptions::g_option_table[] =
3149 {
3150     { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
3151     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3152 };
3153 
3154 #ifndef LLDB_DISABLE_PYTHON
3155 
3156 //-------------------------------------------------------------------------
3157 // CommandObjectTypeSynthList
3158 //-------------------------------------------------------------------------
3159 
3160 bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
3161 bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
3162 
3163 class CommandObjectTypeSynthList;
3164 
3165 struct CommandObjectTypeSynthList_LoopCallbackParam {
3166     CommandObjectTypeSynthList* self;
3167     CommandReturnObject* result;
3168     RegularExpression* regex;
3169     RegularExpression* cate_regex;
3170     CommandObjectTypeSynthList_LoopCallbackParam(CommandObjectTypeSynthList* S, CommandReturnObject* R,
3171                                                  RegularExpression* X = NULL,
3172                                                  RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
3173 };
3174 
3175 class CommandObjectTypeSynthList : public CommandObjectParsed
3176 {
3177 
3178     class CommandOptions : public Options
3179     {
3180     public:
3181 
3182         CommandOptions (CommandInterpreter &interpreter) :
3183         Options (interpreter)
3184         {
3185         }
3186 
3187         ~CommandOptions () override {}
3188 
3189         Error
3190         SetOptionValue (uint32_t option_idx, const char *option_arg) override
3191         {
3192             Error error;
3193             const int short_option = m_getopt_table[option_idx].val;
3194 
3195             switch (short_option)
3196             {
3197                 case 'w':
3198                     m_category_regex = std::string(option_arg);
3199                     break;
3200                 default:
3201                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
3202                     break;
3203             }
3204 
3205             return error;
3206         }
3207 
3208         void
3209         OptionParsingStarting () override
3210         {
3211             m_category_regex = "";
3212         }
3213 
3214         const OptionDefinition*
3215         GetDefinitions () override
3216         {
3217             return g_option_table;
3218         }
3219 
3220         // Options table: Required for subclasses of Options.
3221 
3222         static OptionDefinition g_option_table[];
3223 
3224         // Instance variables to hold the values for command options.
3225 
3226         std::string m_category_regex;
3227 
3228     };
3229 
3230     CommandOptions m_options;
3231 
3232     Options *
3233     GetOptions () override
3234     {
3235         return &m_options;
3236     }
3237 
3238 public:
3239     CommandObjectTypeSynthList (CommandInterpreter &interpreter) :
3240         CommandObjectParsed (interpreter,
3241                              "type synthetic list",
3242                              "Show a list of current synthetic providers.",
3243                              NULL),
3244         m_options(interpreter)
3245     {
3246         CommandArgumentEntry type_arg;
3247         CommandArgumentData type_style_arg;
3248 
3249         type_style_arg.arg_type = eArgTypeName;
3250         type_style_arg.arg_repetition = eArgRepeatOptional;
3251 
3252         type_arg.push_back (type_style_arg);
3253 
3254         m_arguments.push_back (type_arg);
3255     }
3256 
3257     ~CommandObjectTypeSynthList () override
3258     {
3259     }
3260 
3261 protected:
3262     bool
3263     DoExecute (Args& command, CommandReturnObject &result) override
3264     {
3265         const size_t argc = command.GetArgumentCount();
3266 
3267         CommandObjectTypeSynthList_LoopCallbackParam *param;
3268         RegularExpression* cate_regex =
3269         m_options.m_category_regex.empty() ? NULL :
3270         new RegularExpression(m_options.m_category_regex.c_str());
3271 
3272         if (argc == 1)
3273         {
3274             RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
3275             regex->Compile(command.GetArgumentAtIndex(0));
3276             param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,regex,cate_regex);
3277         }
3278         else
3279             param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,NULL,cate_regex);
3280 
3281         DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
3282         delete param;
3283 
3284         if (cate_regex)
3285             delete cate_regex;
3286 
3287         result.SetStatus(eReturnStatusSuccessFinishResult);
3288         return result.Succeeded();
3289     }
3290 
3291 private:
3292 
3293     static bool
3294     PerCategoryCallback(void* param_vp,
3295                         const lldb::TypeCategoryImplSP& cate)
3296     {
3297 
3298         CommandObjectTypeSynthList_LoopCallbackParam* param =
3299         (CommandObjectTypeSynthList_LoopCallbackParam*)param_vp;
3300         CommandReturnObject* result = param->result;
3301 
3302         const char* cate_name = cate->GetName();
3303 
3304         // if the category is disabled or empty and there is no regex, just skip it
3305         if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth) == 0) && param->cate_regex == NULL)
3306             return true;
3307 
3308         // if we have a regex and this category does not match it, just skip it
3309         if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false)
3310             return true;
3311 
3312         result->GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", cate->GetDescription().c_str());
3313 
3314         cate->GetTypeSyntheticsContainer()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp);
3315 
3316         if (cate->GetRegexTypeSyntheticsContainer()->GetCount() > 0)
3317         {
3318             result->GetOutputStream().Printf("Regex-based synthetic providers (slower):\n");
3319             cate->GetRegexTypeSyntheticsContainer()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp);
3320         }
3321 
3322         return true;
3323     }
3324 
3325     bool
3326     LoopCallback (const char* type,
3327                   const SyntheticChildren::SharedPointer& entry,
3328                   RegularExpression* regex,
3329                   CommandReturnObject *result)
3330     {
3331         if (regex == NULL || regex->Execute(type))
3332             result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
3333         return true;
3334     }
3335 
3336     friend bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
3337     friend bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
3338 };
3339 
3340 bool
3341 CommandObjectTypeSynthList_LoopCallback (void* pt2self,
3342                                          ConstString type,
3343                                          const SyntheticChildren::SharedPointer& entry)
3344 {
3345     CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
3346     return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
3347 }
3348 
3349 bool
3350 CommandObjectTypeSynthRXList_LoopCallback (void* pt2self,
3351                                          lldb::RegularExpressionSP regex,
3352                                          const SyntheticChildren::SharedPointer& entry)
3353 {
3354     CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
3355     return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
3356 }
3357 
3358 
3359 OptionDefinition
3360 CommandObjectTypeSynthList::CommandOptions::g_option_table[] =
3361 {
3362     { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,  "Only show categories matching this filter."},
3363     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3364 };
3365 
3366 #endif // #ifndef LLDB_DISABLE_PYTHON
3367 //-------------------------------------------------------------------------
3368 // CommandObjectTypeFilterDelete
3369 //-------------------------------------------------------------------------
3370 
3371 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete
3372 {
3373 public:
3374     CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) :
3375     CommandObjectTypeFormatterDelete (interpreter,
3376                                       eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
3377                                       "type filter delete",
3378                                       "Delete an existing filter for a type.")
3379     {
3380     }
3381 
3382     ~CommandObjectTypeFilterDelete () override
3383     {
3384     }
3385 };
3386 
3387 #ifndef LLDB_DISABLE_PYTHON
3388 
3389 //-------------------------------------------------------------------------
3390 // CommandObjectTypeSynthDelete
3391 //-------------------------------------------------------------------------
3392 
3393 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete
3394 {
3395 public:
3396     CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) :
3397     CommandObjectTypeFormatterDelete (interpreter,
3398                                       eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
3399                                       "type synthetic delete",
3400                                       "Delete an existing synthetic provider for a type.")
3401     {
3402     }
3403 
3404     ~CommandObjectTypeSynthDelete () override
3405     {
3406     }
3407 };
3408 
3409 #endif // #ifndef LLDB_DISABLE_PYTHON
3410 
3411 //-------------------------------------------------------------------------
3412 // CommandObjectTypeFilterClear
3413 //-------------------------------------------------------------------------
3414 
3415 class CommandObjectTypeFilterClear : public CommandObjectParsed
3416 {
3417 private:
3418 
3419     class CommandOptions : public Options
3420     {
3421     public:
3422 
3423         CommandOptions (CommandInterpreter &interpreter) :
3424         Options (interpreter)
3425         {
3426         }
3427 
3428         ~CommandOptions () override {}
3429 
3430         Error
3431         SetOptionValue (uint32_t option_idx, const char *option_arg) override
3432         {
3433             Error error;
3434             const int short_option = m_getopt_table[option_idx].val;
3435 
3436             switch (short_option)
3437             {
3438                 case 'a':
3439                     m_delete_all = true;
3440                     break;
3441                 default:
3442                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
3443                     break;
3444             }
3445 
3446             return error;
3447         }
3448 
3449         void
3450         OptionParsingStarting () override
3451         {
3452             m_delete_all = false;
3453         }
3454 
3455         const OptionDefinition*
3456         GetDefinitions () override
3457         {
3458             return g_option_table;
3459         }
3460 
3461         // Options table: Required for subclasses of Options.
3462 
3463         static OptionDefinition g_option_table[];
3464 
3465         // Instance variables to hold the values for command options.
3466 
3467         bool m_delete_all;
3468         bool m_delete_named;
3469     };
3470 
3471     CommandOptions m_options;
3472 
3473     Options *
3474     GetOptions () override
3475     {
3476         return &m_options;
3477     }
3478 
3479 public:
3480     CommandObjectTypeFilterClear (CommandInterpreter &interpreter) :
3481         CommandObjectParsed (interpreter,
3482                              "type filter clear",
3483                              "Delete all existing filters.",
3484                              NULL),
3485         m_options(interpreter)
3486     {
3487     }
3488 
3489     ~CommandObjectTypeFilterClear () override
3490     {
3491     }
3492 
3493 protected:
3494     bool
3495     DoExecute (Args& command, CommandReturnObject &result) override
3496     {
3497 
3498         if (m_options.m_delete_all)
3499         {
3500             DataVisualization::Categories::ForEach( [] (const TypeCategoryImplSP& category_sp) -> bool {
3501                 category_sp->Clear(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter);
3502                 return true;
3503             });
3504         }
3505         else
3506         {
3507             lldb::TypeCategoryImplSP category;
3508             if (command.GetArgumentCount() > 0)
3509             {
3510                 const char* cat_name = command.GetArgumentAtIndex(0);
3511                 ConstString cat_nameCS(cat_name);
3512                 DataVisualization::Categories::GetCategory(cat_nameCS, category);
3513             }
3514             else
3515                 DataVisualization::Categories::GetCategory(ConstString(NULL), category);
3516             category->Clear(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter);
3517         }
3518 
3519         result.SetStatus(eReturnStatusSuccessFinishResult);
3520         return result.Succeeded();
3521     }
3522 
3523 };
3524 
3525 OptionDefinition
3526 CommandObjectTypeFilterClear::CommandOptions::g_option_table[] =
3527 {
3528     { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,  "Clear every category."},
3529     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3530 };
3531 
3532 #ifndef LLDB_DISABLE_PYTHON
3533 //-------------------------------------------------------------------------
3534 // CommandObjectTypeSynthClear
3535 //-------------------------------------------------------------------------
3536 
3537 class CommandObjectTypeSynthClear : public CommandObjectParsed
3538 {
3539 private:
3540 
3541     class CommandOptions : public Options
3542     {
3543     public:
3544 
3545         CommandOptions (CommandInterpreter &interpreter) :
3546         Options (interpreter)
3547         {
3548         }
3549 
3550         ~CommandOptions () override {}
3551 
3552         Error
3553         SetOptionValue (uint32_t option_idx, const char *option_arg) override
3554         {
3555             Error error;
3556             const int short_option = m_getopt_table[option_idx].val;
3557 
3558             switch (short_option)
3559             {
3560                 case 'a':
3561                     m_delete_all = true;
3562                     break;
3563                 default:
3564                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
3565                     break;
3566             }
3567 
3568             return error;
3569         }
3570 
3571         void
3572         OptionParsingStarting () override
3573         {
3574             m_delete_all = false;
3575         }
3576 
3577         const OptionDefinition*
3578         GetDefinitions () override
3579         {
3580             return g_option_table;
3581         }
3582 
3583         // Options table: Required for subclasses of Options.
3584 
3585         static OptionDefinition g_option_table[];
3586 
3587         // Instance variables to hold the values for command options.
3588 
3589         bool m_delete_all;
3590         bool m_delete_named;
3591     };
3592 
3593     CommandOptions m_options;
3594 
3595     Options *
3596     GetOptions () override
3597     {
3598         return &m_options;
3599     }
3600 
3601 public:
3602     CommandObjectTypeSynthClear (CommandInterpreter &interpreter) :
3603         CommandObjectParsed (interpreter,
3604                              "type synthetic clear",
3605                              "Delete all existing synthetic providers.",
3606                              NULL),
3607         m_options(interpreter)
3608     {
3609     }
3610 
3611     ~CommandObjectTypeSynthClear () override
3612     {
3613     }
3614 
3615 protected:
3616     bool
3617     DoExecute (Args& command, CommandReturnObject &result) override
3618     {
3619 
3620         if (m_options.m_delete_all)
3621         {
3622             DataVisualization::Categories::ForEach( [] (const TypeCategoryImplSP& category_sp) -> bool {
3623                 category_sp->Clear(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth);
3624                 return true;
3625             });
3626         }
3627         else
3628         {
3629             lldb::TypeCategoryImplSP category;
3630             if (command.GetArgumentCount() > 0)
3631             {
3632                 const char* cat_name = command.GetArgumentAtIndex(0);
3633                 ConstString cat_nameCS(cat_name);
3634                 DataVisualization::Categories::GetCategory(cat_nameCS, category);
3635             }
3636             else
3637                 DataVisualization::Categories::GetCategory(ConstString(NULL), category);
3638             category->Clear(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth);
3639         }
3640 
3641         result.SetStatus(eReturnStatusSuccessFinishResult);
3642         return result.Succeeded();
3643     }
3644 
3645 };
3646 
3647 OptionDefinition
3648 CommandObjectTypeSynthClear::CommandOptions::g_option_table[] =
3649 {
3650     { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,  "Clear every category."},
3651     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3652 };
3653 
3654 
3655 bool
3656 CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result)
3657 {
3658     SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers,
3659                                                      m_options.m_skip_references,
3660                                                      m_options.m_cascade,
3661                                                      m_options.m_regex,
3662                                                      m_options.m_category);
3663 
3664     const size_t argc = command.GetArgumentCount();
3665 
3666     for (size_t i = 0; i < argc; i++)
3667     {
3668         const char* typeA = command.GetArgumentAtIndex(i);
3669         if (typeA && *typeA)
3670             options->m_target_types << typeA;
3671         else
3672         {
3673             result.AppendError("empty typenames not allowed");
3674             result.SetStatus(eReturnStatusFailed);
3675             return false;
3676         }
3677     }
3678 
3679     m_interpreter.GetPythonCommandsFromIOHandler ("    ",   // Prompt
3680                                                   *this,    // IOHandlerDelegate
3681                                                   true,     // Run IOHandler in async mode
3682                                                   options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
3683     result.SetStatus(eReturnStatusSuccessFinishNoResult);
3684     return result.Succeeded();
3685 }
3686 
3687 bool
3688 CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result)
3689 {
3690     const size_t argc = command.GetArgumentCount();
3691 
3692     if (argc < 1)
3693     {
3694         result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
3695         result.SetStatus(eReturnStatusFailed);
3696         return false;
3697     }
3698 
3699     if (m_options.m_class_name.empty() && !m_options.m_input_python)
3700     {
3701         result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str());
3702         result.SetStatus(eReturnStatusFailed);
3703         return false;
3704     }
3705 
3706     SyntheticChildrenSP entry;
3707 
3708     ScriptedSyntheticChildren* impl = new ScriptedSyntheticChildren(SyntheticChildren::Flags().
3709                                                                     SetCascades(m_options.m_cascade).
3710                                                                     SetSkipPointers(m_options.m_skip_pointers).
3711                                                                     SetSkipReferences(m_options.m_skip_references),
3712                                                                     m_options.m_class_name.c_str());
3713 
3714     entry.reset(impl);
3715 
3716     ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
3717 
3718     if (interpreter && interpreter->CheckObjectExists(impl->GetPythonClassName()) == false)
3719         result.AppendWarning("The provided class does not exist - please define it before attempting to use this synthetic provider");
3720 
3721     // now I have a valid provider, let's add it to every type
3722 
3723     lldb::TypeCategoryImplSP category;
3724     DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
3725 
3726     Error error;
3727 
3728     for (size_t i = 0; i < argc; i++)
3729     {
3730         const char* typeA = command.GetArgumentAtIndex(i);
3731         ConstString typeCS(typeA);
3732         if (typeCS)
3733         {
3734             if (!AddSynth(typeCS,
3735                           entry,
3736                           m_options.m_regex ? eRegexSynth : eRegularSynth,
3737                           m_options.m_category,
3738                           &error))
3739             {
3740                 result.AppendError(error.AsCString());
3741                 result.SetStatus(eReturnStatusFailed);
3742                 return false;
3743             }
3744         }
3745         else
3746         {
3747             result.AppendError("empty typenames not allowed");
3748             result.SetStatus(eReturnStatusFailed);
3749             return false;
3750         }
3751     }
3752 
3753     result.SetStatus(eReturnStatusSuccessFinishNoResult);
3754     return result.Succeeded();
3755 }
3756 
3757 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) :
3758     CommandObjectParsed (interpreter,
3759                          "type synthetic add",
3760                          "Add a new synthetic provider for a type.",
3761                          NULL),
3762     IOHandlerDelegateMultiline ("DONE"),
3763     m_options (interpreter)
3764 {
3765     CommandArgumentEntry type_arg;
3766     CommandArgumentData type_style_arg;
3767 
3768     type_style_arg.arg_type = eArgTypeName;
3769     type_style_arg.arg_repetition = eArgRepeatPlus;
3770 
3771     type_arg.push_back (type_style_arg);
3772 
3773     m_arguments.push_back (type_arg);
3774 
3775 }
3776 
3777 bool
3778 CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
3779                                     SyntheticChildrenSP entry,
3780                                     SynthFormatType type,
3781                                     std::string category_name,
3782                                     Error* error)
3783 {
3784     lldb::TypeCategoryImplSP category;
3785     DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
3786 
3787     if (type == eRegularSynth)
3788     {
3789         if (FixArrayTypeNameWithRegex (type_name))
3790             type = eRegexSynth;
3791     }
3792 
3793     if (category->AnyMatches(type_name,
3794                              eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
3795                              false))
3796     {
3797         if (error)
3798             error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString());
3799         return false;
3800     }
3801 
3802     if (type == eRegexSynth)
3803     {
3804         RegularExpressionSP typeRX(new RegularExpression());
3805         if (!typeRX->Compile(type_name.GetCString()))
3806         {
3807             if (error)
3808                 error->SetErrorString("regex format error (maybe this is not really a regex?)");
3809             return false;
3810         }
3811 
3812         category->GetRegexTypeSyntheticsContainer()->Delete(type_name);
3813         category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry);
3814 
3815         return true;
3816     }
3817     else
3818     {
3819         category->GetTypeSyntheticsContainer()->Add(type_name, entry);
3820         return true;
3821     }
3822 }
3823 
3824 OptionDefinition
3825 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
3826 {
3827     { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,    "If true, cascade through typedef chains."},
3828     { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
3829     { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
3830     { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,         "Add this to the given category instead of the default one."},
3831     { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass,    "Use this Python class to produce synthetic children."},
3832     { 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."},
3833     { LLDB_OPT_SET_ALL, false,  "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
3834     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3835 };
3836 
3837 #endif // #ifndef LLDB_DISABLE_PYTHON
3838 
3839 class CommandObjectTypeFilterAdd : public CommandObjectParsed
3840 {
3841 
3842 private:
3843 
3844     class CommandOptions : public Options
3845     {
3846         typedef std::vector<std::string> option_vector;
3847     public:
3848 
3849         CommandOptions (CommandInterpreter &interpreter) :
3850         Options (interpreter)
3851         {
3852         }
3853 
3854         ~CommandOptions () override {}
3855 
3856         Error
3857         SetOptionValue (uint32_t option_idx, const char *option_arg) override
3858         {
3859             Error error;
3860             const int short_option = m_getopt_table[option_idx].val;
3861             bool success;
3862 
3863             switch (short_option)
3864             {
3865                 case 'C':
3866                     m_cascade = Args::StringToBoolean(option_arg, true, &success);
3867                     if (!success)
3868                         error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg);
3869                     break;
3870                 case 'c':
3871                     m_expr_paths.push_back(option_arg);
3872                     has_child_list = true;
3873                     break;
3874                 case 'p':
3875                     m_skip_pointers = true;
3876                     break;
3877                 case 'r':
3878                     m_skip_references = true;
3879                     break;
3880                 case 'w':
3881                     m_category = std::string(option_arg);
3882                     break;
3883                 case 'x':
3884                     m_regex = true;
3885                     break;
3886                 default:
3887                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
3888                     break;
3889             }
3890 
3891             return error;
3892         }
3893 
3894         void
3895         OptionParsingStarting () override
3896         {
3897             m_cascade = true;
3898             m_skip_pointers = false;
3899             m_skip_references = false;
3900             m_category = "default";
3901             m_expr_paths.clear();
3902             has_child_list = false;
3903             m_regex = false;
3904         }
3905 
3906         const OptionDefinition*
3907         GetDefinitions () override
3908         {
3909             return g_option_table;
3910         }
3911 
3912         // Options table: Required for subclasses of Options.
3913 
3914         static OptionDefinition g_option_table[];
3915 
3916         // Instance variables to hold the values for command options.
3917 
3918         bool m_cascade;
3919         bool m_skip_references;
3920         bool m_skip_pointers;
3921         bool m_input_python;
3922         option_vector m_expr_paths;
3923         std::string m_category;
3924 
3925         bool has_child_list;
3926 
3927         bool m_regex;
3928 
3929         typedef option_vector::iterator ExpressionPathsIterator;
3930     };
3931 
3932     CommandOptions m_options;
3933 
3934     Options *
3935     GetOptions () override
3936     {
3937         return &m_options;
3938     }
3939 
3940     enum FilterFormatType
3941     {
3942         eRegularFilter,
3943         eRegexFilter
3944     };
3945 
3946     bool
3947     AddFilter(ConstString type_name,
3948               SyntheticChildrenSP entry,
3949               FilterFormatType type,
3950               std::string category_name,
3951               Error* error)
3952     {
3953         lldb::TypeCategoryImplSP category;
3954         DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
3955 
3956         if (type == eRegularFilter)
3957         {
3958             if (FixArrayTypeNameWithRegex (type_name))
3959                 type = eRegexFilter;
3960         }
3961 
3962         if (category->AnyMatches(type_name,
3963                                  eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
3964                                  false))
3965         {
3966             if (error)
3967                 error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString());
3968             return false;
3969         }
3970 
3971         if (type == eRegexFilter)
3972         {
3973             RegularExpressionSP typeRX(new RegularExpression());
3974             if (!typeRX->Compile(type_name.GetCString()))
3975             {
3976                 if (error)
3977                     error->SetErrorString("regex format error (maybe this is not really a regex?)");
3978                 return false;
3979             }
3980 
3981             category->GetRegexTypeFiltersContainer()->Delete(type_name);
3982             category->GetRegexTypeFiltersContainer()->Add(typeRX, entry);
3983 
3984             return true;
3985         }
3986         else
3987         {
3988             category->GetTypeFiltersContainer()->Add(type_name, entry);
3989             return true;
3990         }
3991     }
3992 
3993 
3994 public:
3995 
3996     CommandObjectTypeFilterAdd (CommandInterpreter &interpreter) :
3997         CommandObjectParsed (interpreter,
3998                              "type filter add",
3999                              "Add a new filter for a type.",
4000                              NULL),
4001         m_options (interpreter)
4002     {
4003         CommandArgumentEntry type_arg;
4004         CommandArgumentData type_style_arg;
4005 
4006         type_style_arg.arg_type = eArgTypeName;
4007         type_style_arg.arg_repetition = eArgRepeatPlus;
4008 
4009         type_arg.push_back (type_style_arg);
4010 
4011         m_arguments.push_back (type_arg);
4012 
4013         SetHelpLong(
4014 R"(
4015 The following examples of 'type filter add' refer to this code snippet for context:
4016 
4017     class Foo {
4018         int a;
4019         int b;
4020         int c;
4021         int d;
4022         int e;
4023         int f;
4024         int g;
4025         int h;
4026         int i;
4027     }
4028     Foo my_foo;
4029 
4030 Adding a simple filter:
4031 
4032 (lldb) type filter add --child a --child g Foo
4033 (lldb) frame variable my_foo
4034 
4035 )" "Produces output where only a and g are displayed.  Other children of my_foo \
4036 (b, c, d, e, f, h and i) are available by asking for them explicitly:" R"(
4037 
4038 (lldb) frame variable my_foo.b my_foo.c my_foo.i
4039 
4040 )" "The formatting option --raw on frame variable bypasses the filter, showing \
4041 all children of my_foo as if no filter was defined:" R"(
4042 
4043 (lldb) frame variable my_foo --raw)"
4044         );
4045     }
4046 
4047     ~CommandObjectTypeFilterAdd () override
4048     {
4049     }
4050 
4051 protected:
4052     bool
4053     DoExecute (Args& command, CommandReturnObject &result) override
4054     {
4055         const size_t argc = command.GetArgumentCount();
4056 
4057         if (argc < 1)
4058         {
4059             result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
4060             result.SetStatus(eReturnStatusFailed);
4061             return false;
4062         }
4063 
4064         if (m_options.m_expr_paths.size() == 0)
4065         {
4066             result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
4067             result.SetStatus(eReturnStatusFailed);
4068             return false;
4069         }
4070 
4071         SyntheticChildrenSP entry;
4072 
4073         TypeFilterImpl* impl = new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade).
4074                                                     SetSkipPointers(m_options.m_skip_pointers).
4075                                                     SetSkipReferences(m_options.m_skip_references));
4076 
4077         entry.reset(impl);
4078 
4079         // go through the expression paths
4080         CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
4081 
4082         for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
4083             impl->AddExpressionPath(*begin);
4084 
4085 
4086         // now I have a valid provider, let's add it to every type
4087 
4088         lldb::TypeCategoryImplSP category;
4089         DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
4090 
4091         Error error;
4092 
4093         WarnOnPotentialUnquotedUnsignedType(command, result);
4094 
4095         for (size_t i = 0; i < argc; i++)
4096         {
4097             const char* typeA = command.GetArgumentAtIndex(i);
4098             ConstString typeCS(typeA);
4099             if (typeCS)
4100             {
4101                 if (!AddFilter(typeCS,
4102                           entry,
4103                           m_options.m_regex ? eRegexFilter : eRegularFilter,
4104                           m_options.m_category,
4105                           &error))
4106                 {
4107                     result.AppendError(error.AsCString());
4108                     result.SetStatus(eReturnStatusFailed);
4109                     return false;
4110                 }
4111             }
4112             else
4113             {
4114                 result.AppendError("empty typenames not allowed");
4115                 result.SetStatus(eReturnStatusFailed);
4116                 return false;
4117             }
4118         }
4119 
4120         result.SetStatus(eReturnStatusSuccessFinishNoResult);
4121         return result.Succeeded();
4122     }
4123 
4124 };
4125 
4126 OptionDefinition
4127 CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] =
4128 {
4129     { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,    "If true, cascade through typedef chains."},
4130     { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for pointers-to-type objects."},
4131     { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,         "Don't use this format for references-to-type objects."},
4132     { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName,         "Add this to the given category instead of the default one."},
4133     { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpressionPath,    "Include this expression path in the synthetic view."},
4134     { LLDB_OPT_SET_ALL, false,  "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "Type names are actually regular expressions."},
4135     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
4136 };
4137 
4138 //----------------------------------------------------------------------
4139 // "type lookup"
4140 //----------------------------------------------------------------------
4141 class CommandObjectTypeLookup : public CommandObjectRaw
4142 {
4143 protected:
4144 
4145     class CommandOptions : public OptionGroup
4146     {
4147     public:
4148 
4149         CommandOptions () :
4150         OptionGroup(),
4151         m_show_help(false),
4152         m_language(eLanguageTypeUnknown)
4153         {}
4154 
4155         ~CommandOptions () override {}
4156 
4157         uint32_t
4158         GetNumDefinitions () override
4159         {
4160             return 3;
4161         }
4162 
4163         const OptionDefinition*
4164         GetDefinitions () override
4165         {
4166             return g_option_table;
4167         }
4168 
4169         Error
4170         SetOptionValue (CommandInterpreter &interpreter,
4171                         uint32_t option_idx,
4172                         const char *option_value) override
4173         {
4174             Error error;
4175 
4176             const int short_option = g_option_table[option_idx].short_option;
4177 
4178             switch (short_option)
4179             {
4180                 case 'h':
4181                     m_show_help = true;
4182                     break;
4183 
4184                 case 'l':
4185                     m_language = Language::GetLanguageTypeFromString(option_value);
4186                     break;
4187 
4188                 default:
4189                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
4190                     break;
4191             }
4192 
4193             return error;
4194         }
4195 
4196         void
4197         OptionParsingStarting (CommandInterpreter &interpreter) override
4198         {
4199             m_show_help = false;
4200             m_language = eLanguageTypeUnknown;
4201         }
4202 
4203         // Options table: Required for subclasses of Options.
4204 
4205         static OptionDefinition g_option_table[];
4206         bool m_show_help;
4207         lldb::LanguageType m_language;
4208     };
4209 
4210     OptionGroupOptions m_option_group;
4211     CommandOptions m_command_options;
4212 
4213 public:
4214 
4215     CommandObjectTypeLookup (CommandInterpreter &interpreter) :
4216     CommandObjectRaw (interpreter,
4217                       "type lookup",
4218                       "Lookup a type by name in the select target.",
4219                       "type lookup <typename>",
4220                       eCommandRequiresTarget),
4221     m_option_group(interpreter),
4222     m_command_options()
4223     {
4224         m_option_group.Append(&m_command_options);
4225         m_option_group.Finalize();
4226     }
4227 
4228     ~CommandObjectTypeLookup () override
4229     {
4230     }
4231 
4232     Options *
4233     GetOptions () override
4234     {
4235         return &m_option_group;
4236     }
4237 
4238     bool
4239     DoExecute (const char *raw_command_line, CommandReturnObject &result) override
4240     {
4241         if (!raw_command_line || !raw_command_line[0])
4242         {
4243             result.SetError("type lookup cannot be invoked without a type name as argument");
4244             return false;
4245         }
4246 
4247         m_option_group.NotifyOptionParsingStarting();
4248 
4249         const char * name_of_type = NULL;
4250 
4251         if (raw_command_line[0] == '-')
4252         {
4253             // We have some options and these options MUST end with --.
4254             const char *end_options = NULL;
4255             const char *s = raw_command_line;
4256             while (s && s[0])
4257             {
4258                 end_options = ::strstr (s, "--");
4259                 if (end_options)
4260                 {
4261                     end_options += 2; // Get past the "--"
4262                     if (::isspace (end_options[0]))
4263                     {
4264                         name_of_type = end_options;
4265                         while (::isspace (*name_of_type))
4266                             ++name_of_type;
4267                         break;
4268                     }
4269                 }
4270                 s = end_options;
4271             }
4272 
4273             if (end_options)
4274             {
4275                 Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line));
4276                 if (!ParseOptions (args, result))
4277                     return false;
4278 
4279                 Error error (m_option_group.NotifyOptionParsingFinished());
4280                 if (error.Fail())
4281                 {
4282                     result.AppendError (error.AsCString());
4283                     result.SetStatus (eReturnStatusFailed);
4284                     return false;
4285                 }
4286             }
4287         }
4288         if (nullptr == name_of_type)
4289             name_of_type = raw_command_line;
4290 
4291         TargetSP target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());
4292         const bool fill_all_in = true;
4293         ExecutionContext exe_ctx(target_sp.get(), fill_all_in);
4294         ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
4295 
4296         bool any_found = false;
4297 
4298         std::vector<Language*> languages;
4299 
4300         if (m_command_options.m_language == eLanguageTypeUnknown)
4301         {
4302             // FIXME: hardcoding languages is not good
4303             languages.push_back(Language::FindPlugin(eLanguageTypeObjC));
4304             languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));
4305         }
4306         else
4307         {
4308             languages.push_back(Language::FindPlugin(m_command_options.m_language));
4309         }
4310 
4311         for (Language* language : languages)
4312         {
4313             if (!language)
4314                 continue;
4315 
4316             if (auto scavenger = language->GetTypeScavenger())
4317             {
4318                 Language::TypeScavenger::ResultSet search_results;
4319                 if (scavenger->Find(best_scope, name_of_type, search_results) > 0)
4320                 {
4321                     for (const auto& search_result : search_results)
4322                     {
4323                         if (search_result && search_result->IsValid())
4324                         {
4325                             any_found = true;
4326                             search_result->DumpToStream(result.GetOutputStream(), this->m_command_options.m_show_help);
4327                         }
4328                     }
4329                 }
4330             }
4331         }
4332 
4333         result.SetStatus (any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult);
4334         return true;
4335     }
4336 
4337 };
4338 
4339 OptionDefinition
4340 CommandObjectTypeLookup::CommandOptions::g_option_table[] =
4341 {
4342     { LLDB_OPT_SET_ALL, false, "show-help",        'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "Display available help for types"},
4343     { LLDB_OPT_SET_ALL, false, "language",         'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,    "Which language's types should the search scope be"},
4344     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
4345 };
4346 
4347 template <typename FormatterType>
4348 class CommandObjectFormatterInfo : public CommandObjectRaw
4349 {
4350 public:
4351     typedef std::function<typename FormatterType::SharedPointer(ValueObject&)> DiscoveryFunction;
4352     CommandObjectFormatterInfo (CommandInterpreter &interpreter,
4353                                 const char* formatter_name,
4354                                 DiscoveryFunction discovery_func) :
4355     CommandObjectRaw(interpreter,
4356                      nullptr,
4357                      nullptr,
4358                      nullptr,
4359                      eCommandRequiresFrame),
4360     m_formatter_name(formatter_name ? formatter_name : ""),
4361     m_discovery_function(discovery_func)
4362     {
4363         StreamString name;
4364         name.Printf("type %s info", formatter_name);
4365         SetCommandName(name.GetData());
4366         StreamString help;
4367         help.Printf("This command evaluates the provided expression and shows which %s is applied to the resulting value (if any).", formatter_name);
4368         SetHelp(help.GetData());
4369         StreamString syntax;
4370         syntax.Printf("type %s info <expr>", formatter_name);
4371         SetSyntax(syntax.GetData());
4372     }
4373 
4374     ~CommandObjectFormatterInfo () override
4375     {
4376     }
4377 
4378 protected:
4379     bool
4380     DoExecute (const char *command, CommandReturnObject &result) override
4381     {
4382         auto target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
4383         auto frame_sp = target_sp->GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame();
4384         ValueObjectSP result_valobj_sp;
4385         EvaluateExpressionOptions options;
4386         lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(command, frame_sp.get(), result_valobj_sp, options);
4387         if (expr_result == eExpressionCompleted && result_valobj_sp)
4388         {
4389             result_valobj_sp = result_valobj_sp->GetQualifiedRepresentationIfAvailable(target_sp->GetPreferDynamicValue(), target_sp->GetEnableSyntheticValue());
4390             typename FormatterType::SharedPointer formatter_sp = m_discovery_function(*result_valobj_sp);
4391             if (formatter_sp)
4392             {
4393                 std::string description(formatter_sp->GetDescription());
4394                 result.AppendMessageWithFormat("%s applied to (%s) %s is: %s\n",
4395                                                m_formatter_name.c_str(),
4396                                                result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
4397                                                command,
4398                                                description.c_str());
4399                 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
4400             }
4401             else
4402             {
4403                 result.AppendMessageWithFormat("no %s applies to (%s) %s\n",
4404                                                m_formatter_name.c_str(),
4405                                                result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"),
4406                                                command);
4407                 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
4408             }
4409             return true;
4410         }
4411         else
4412         {
4413             result.AppendError("failed to evaluate expression");
4414             result.SetStatus(lldb::eReturnStatusFailed);
4415             return false;
4416         }
4417     }
4418 
4419 private:
4420     std::string m_formatter_name;
4421     DiscoveryFunction m_discovery_function;
4422 };
4423 
4424 class CommandObjectTypeFormat : public CommandObjectMultiword
4425 {
4426 public:
4427     CommandObjectTypeFormat (CommandInterpreter &interpreter) :
4428         CommandObjectMultiword (interpreter,
4429                                 "type format",
4430                                 "A set of commands for editing variable value display options",
4431                                 "type format [<sub-command-options>] ")
4432     {
4433         LoadSubCommand ("add",    CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter)));
4434         LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectTypeFormatClear (interpreter)));
4435         LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter)));
4436         LoadSubCommand ("list",   CommandObjectSP (new CommandObjectTypeFormatList (interpreter)));
4437         LoadSubCommand ("info",   CommandObjectSP (new CommandObjectFormatterInfo<TypeFormatImpl>(interpreter,
4438                                                                                                   "format",
4439                                                                                                   [](ValueObject& valobj) -> TypeFormatImpl::SharedPointer {
4440                                                                                                       return valobj.GetValueFormat();
4441                                                                                                   })));
4442     }
4443 
4444 
4445     ~CommandObjectTypeFormat () override
4446     {
4447     }
4448 };
4449 
4450 #ifndef LLDB_DISABLE_PYTHON
4451 
4452 class CommandObjectTypeSynth : public CommandObjectMultiword
4453 {
4454 public:
4455     CommandObjectTypeSynth (CommandInterpreter &interpreter) :
4456     CommandObjectMultiword (interpreter,
4457                             "type synthetic",
4458                             "A set of commands for operating on synthetic type representations",
4459                             "type synthetic [<sub-command-options>] ")
4460     {
4461         LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter)));
4462         LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSynthClear (interpreter)));
4463         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter)));
4464         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSynthList (interpreter)));
4465         LoadSubCommand ("info",          CommandObjectSP (new CommandObjectFormatterInfo<SyntheticChildren>(interpreter,
4466                                                                                                             "synthetic",
4467                                                                                                             [](ValueObject& valobj) -> SyntheticChildren::SharedPointer {
4468                                                                                                                 return valobj.GetSyntheticChildren();
4469                                                                                                             })));
4470     }
4471 
4472 
4473     ~CommandObjectTypeSynth () override
4474     {
4475     }
4476 };
4477 
4478 #endif // #ifndef LLDB_DISABLE_PYTHON
4479 
4480 class CommandObjectTypeFilter : public CommandObjectMultiword
4481 {
4482 public:
4483     CommandObjectTypeFilter (CommandInterpreter &interpreter) :
4484     CommandObjectMultiword (interpreter,
4485                             "type filter",
4486                             "A set of commands for operating on type filters",
4487                             "type synthetic [<sub-command-options>] ")
4488     {
4489         LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeFilterAdd (interpreter)));
4490         LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeFilterClear (interpreter)));
4491         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeFilterDelete (interpreter)));
4492         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeFilterList (interpreter)));
4493     }
4494 
4495 
4496     ~CommandObjectTypeFilter () override
4497     {
4498     }
4499 };
4500 
4501 class CommandObjectTypeCategory : public CommandObjectMultiword
4502 {
4503 public:
4504     CommandObjectTypeCategory (CommandInterpreter &interpreter) :
4505     CommandObjectMultiword (interpreter,
4506                             "type category",
4507                             "A set of commands for operating on categories",
4508                             "type category [<sub-command-options>] ")
4509     {
4510         LoadSubCommand ("define",        CommandObjectSP (new CommandObjectTypeCategoryDefine (interpreter)));
4511         LoadSubCommand ("enable",        CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter)));
4512         LoadSubCommand ("disable",       CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter)));
4513         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter)));
4514         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeCategoryList (interpreter)));
4515     }
4516 
4517 
4518     ~CommandObjectTypeCategory () override
4519     {
4520     }
4521 };
4522 
4523 class CommandObjectTypeSummary : public CommandObjectMultiword
4524 {
4525 public:
4526     CommandObjectTypeSummary (CommandInterpreter &interpreter) :
4527     CommandObjectMultiword (interpreter,
4528                             "type summary",
4529                             "A set of commands for editing variable summary display options",
4530                             "type summary [<sub-command-options>] ")
4531     {
4532         LoadSubCommand ("add",           CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter)));
4533         LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter)));
4534         LoadSubCommand ("delete",        CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter)));
4535         LoadSubCommand ("list",          CommandObjectSP (new CommandObjectTypeSummaryList (interpreter)));
4536         LoadSubCommand ("info",          CommandObjectSP (new CommandObjectFormatterInfo<TypeSummaryImpl>(interpreter,
4537                                                                                                           "summary",
4538                                                                                                             [](ValueObject& valobj) -> TypeSummaryImpl::SharedPointer {
4539                                                                                                                 return valobj.GetSummaryFormat();
4540                                                                                                             })));
4541     }
4542 
4543 
4544     ~CommandObjectTypeSummary () override
4545     {
4546     }
4547 };
4548 
4549 //-------------------------------------------------------------------------
4550 // CommandObjectType
4551 //-------------------------------------------------------------------------
4552 
4553 CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) :
4554     CommandObjectMultiword (interpreter,
4555                             "type",
4556                             "A set of commands for operating on the type system",
4557                             "type [<sub-command-options>]")
4558 {
4559     LoadSubCommand ("category",  CommandObjectSP (new CommandObjectTypeCategory (interpreter)));
4560     LoadSubCommand ("filter",    CommandObjectSP (new CommandObjectTypeFilter (interpreter)));
4561     LoadSubCommand ("format",    CommandObjectSP (new CommandObjectTypeFormat (interpreter)));
4562     LoadSubCommand ("summary",   CommandObjectSP (new CommandObjectTypeSummary (interpreter)));
4563 #ifndef LLDB_DISABLE_PYTHON
4564     LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter)));
4565 #endif
4566     LoadSubCommand ("lookup",   CommandObjectSP (new CommandObjectTypeLookup (interpreter)));
4567 }
4568 
4569 
4570 CommandObjectType::~CommandObjectType ()
4571 {
4572 }
4573 
4574 
4575