2016-07-23 16:50:09 -04:00
//===-- CommandObjectType.cpp -----------------------------------*- C++ -*-===//
2013-08-23 13:46:38 -04:00
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "CommandObjectType.h"
// C Includes
// C++ Includes
2016-07-23 16:50:09 -04:00
# include <algorithm>
# include <cctype>
2015-02-06 16:38:51 -05:00
# include <functional>
2013-08-23 13:46:38 -04:00
2016-07-23 16:50:09 -04:00
// Project includes
2013-08-23 13:46:38 -04:00
# include "lldb/Core/Debugger.h"
2014-02-18 11:23:10 -05:00
# include "lldb/Core/IOHandler.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Core/State.h"
# include "lldb/DataFormatters/DataVisualization.h"
2017-04-16 12:04:10 -04:00
# include "lldb/Host/OptionParser.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandObject.h"
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Interpreter/OptionGroupFormat.h"
2015-12-30 06:55:28 -05:00
# include "lldb/Interpreter/OptionValueBoolean.h"
# include "lldb/Interpreter/OptionValueLanguage.h"
# include "lldb/Interpreter/OptionValueString.h"
2017-01-02 14:26:05 -05:00
# include "lldb/Interpreter/Options.h"
2016-07-23 16:50:09 -04:00
# include "lldb/Symbol/Symbol.h"
2015-12-30 06:55:28 -05:00
# include "lldb/Target/Language.h"
2015-02-06 16:38:51 -05:00
# include "lldb/Target/Process.h"
# include "lldb/Target/StackFrame.h"
# include "lldb/Target/Target.h"
# include "lldb/Target/Thread.h"
# include "lldb/Target/ThreadList.h"
2017-04-16 12:04:10 -04:00
# include "lldb/Utility/ConstString.h"
# include "lldb/Utility/RegularExpression.h"
# include "lldb/Utility/StringList.h"
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Other libraries and framework includes
# include "llvm/ADT/STLExtras.h"
2013-08-23 13:46:38 -04:00
using namespace lldb ;
using namespace lldb_private ;
2017-01-02 14:26:05 -05:00
class ScriptAddOptions {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
TypeSummaryImpl : : Flags m_flags ;
StringList m_target_types ;
bool m_regex ;
ConstString m_name ;
std : : string m_category ;
ScriptAddOptions ( const TypeSummaryImpl : : Flags & flags , bool regx ,
const ConstString & name , std : : string catg )
: m_flags ( flags ) , m_regex ( regx ) , m_name ( name ) , m_category ( catg ) { }
typedef std : : shared_ptr < ScriptAddOptions > SharedPointer ;
2013-08-23 13:46:38 -04:00
} ;
2017-01-02 14:26:05 -05:00
class SynthAddOptions {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
bool m_skip_pointers ;
bool m_skip_references ;
bool m_cascade ;
bool m_regex ;
StringList m_target_types ;
std : : string m_category ;
SynthAddOptions ( bool sptr , bool sref , bool casc , bool regx , std : : string catg )
: m_skip_pointers ( sptr ) , m_skip_references ( sref ) , m_cascade ( casc ) ,
m_regex ( regx ) , m_target_types ( ) , m_category ( catg ) { }
typedef std : : shared_ptr < SynthAddOptions > SharedPointer ;
2013-08-23 13:46:38 -04:00
} ;
2017-01-02 14:26:05 -05:00
static bool WarnOnPotentialUnquotedUnsignedType ( Args & command ,
CommandReturnObject & result ) {
if ( command . empty ( ) )
2014-02-18 11:23:10 -05:00
return false ;
2017-01-02 14:26:05 -05:00
for ( auto entry : llvm : : enumerate ( command . entries ( ) . drop_back ( ) ) ) {
2017-04-16 12:04:10 -04:00
if ( entry . value ( ) . ref ! = " unsigned " )
2017-01-02 14:26:05 -05:00
continue ;
2017-04-16 12:04:10 -04:00
auto next = command . entries ( ) [ entry . index ( ) + 1 ] . ref ;
2017-01-02 14:26:05 -05:00
if ( next = = " int " | | next = = " short " | | next = = " char " | | next = = " long " ) {
result . AppendWarningWithFormat (
" unsigned %s being treated as two types. if you meant the combined "
" type "
" name use quotes, as in \" unsigned %s \" \n " ,
next . str ( ) . c_str ( ) , next . str ( ) . c_str ( ) ) ;
return true ;
}
}
return false ;
2014-02-18 11:23:10 -05:00
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
static OptionDefinition g_type_summary_add_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " category " , ' w ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeName , " Add this to the given category instead of the default one. " } ,
{ LLDB_OPT_SET_ALL , false , " cascade " , ' C ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " If true, cascade through typedef chains. " } ,
{ LLDB_OPT_SET_ALL , false , " no-value " , ' v ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Don't show the value, just show the summary, for this type. " } ,
{ LLDB_OPT_SET_ALL , false , " skip-pointers " , ' p ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Don't use this format for pointers-to-type objects. " } ,
{ LLDB_OPT_SET_ALL , false , " skip-references " , ' r ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Don't use this format for references-to-type objects. " } ,
{ LLDB_OPT_SET_ALL , false , " regex " , ' x ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Type names are actually regular expressions. " } ,
{ LLDB_OPT_SET_1 , true , " inline-children " , ' c ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " If true, inline all child values into summary string. " } ,
{ LLDB_OPT_SET_1 , false , " omit-names " , ' O ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " If true, omit value names in the summary display. " } ,
{ LLDB_OPT_SET_2 , true , " summary-string " , ' s ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeSummaryString , " Summary string used to display text and object contents. " } ,
{ LLDB_OPT_SET_3 , false , " python-script " , ' o ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypePythonScript , " Give a one-liner Python script as part of the command. " } ,
{ LLDB_OPT_SET_3 , false , " python-function " , ' F ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypePythonFunction , " Give the name of a Python function to use for this type. " } ,
{ LLDB_OPT_SET_3 , false , " input-python " , ' P ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Input Python code to use for this type manually. " } ,
{ LLDB_OPT_SET_2 | LLDB_OPT_SET_3 , false , " expand " , ' e ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Expand aggregate data types to show children on separate lines. " } ,
{ LLDB_OPT_SET_2 | LLDB_OPT_SET_3 , false , " hide-empty " , ' h ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Do not expand aggregate data types with no children. " } ,
{ LLDB_OPT_SET_2 | LLDB_OPT_SET_3 , false , " name " , ' n ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeName , " A name for this summary string. " }
// clang-format on
} ;
class CommandObjectTypeSummaryAdd : public CommandObjectParsed ,
public IOHandlerDelegateMultiline {
2013-08-23 13:46:38 -04:00
private :
2017-01-02 14:26:05 -05:00
class CommandOptions : public Options {
public :
CommandOptions ( CommandInterpreter & interpreter ) : Options ( ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override ;
void OptionParsingStarting ( ExecutionContext * execution_context ) override ;
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_type_summary_add_options ) ;
}
// Instance variables to hold the values for command options.
TypeSummaryImpl : : Flags m_flags ;
bool m_regex ;
std : : string m_format_string ;
ConstString m_name ;
std : : string m_python_script ;
std : : string m_python_function ;
bool m_is_add_script ;
std : : string m_category ;
} ;
CommandOptions m_options ;
Options * GetOptions ( ) override { return & m_options ; }
bool Execute_ScriptSummary ( Args & command , CommandReturnObject & result ) ;
bool Execute_StringSummary ( Args & command , CommandReturnObject & result ) ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
enum SummaryFormatType { eRegularSummary , eRegexSummary , eNamedSummary } ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
CommandObjectTypeSummaryAdd ( CommandInterpreter & interpreter ) ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTypeSummaryAdd ( ) override = default ;
void IOHandlerActivated ( IOHandler & io_handler ) override {
static const char * g_summary_addreader_instructions =
" Enter your Python command(s). Type 'DONE' to end. \n "
2014-02-18 11:23:10 -05:00
" def function (valobj,internal_dict): \n "
2017-01-02 14:26:05 -05:00
" \" \" \" valobj: an SBValue which you want to provide a summary "
" for \n "
2014-11-25 16:00:58 -05:00
" internal_dict: an LLDB support object not to be used \" \" \" \n " ;
2014-02-18 11:23:10 -05:00
2017-01-02 14:26:05 -05:00
StreamFileSP output_sp ( io_handler . GetOutputStreamFile ( ) ) ;
if ( output_sp ) {
output_sp - > PutCString ( g_summary_addreader_instructions ) ;
output_sp - > Flush ( ) ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
}
void IOHandlerInputComplete ( IOHandler & io_handler ,
std : : string & data ) override {
StreamFileSP error_sp = io_handler . GetErrorStreamFile ( ) ;
2016-07-23 16:50:09 -04:00
2014-02-18 11:23:10 -05:00
# ifndef LLDB_DISABLE_PYTHON
2017-01-02 14:26:05 -05:00
ScriptInterpreter * interpreter = m_interpreter . GetScriptInterpreter ( ) ;
if ( interpreter ) {
StringList lines ;
lines . SplitIntoLines ( data ) ;
if ( lines . GetSize ( ) > 0 ) {
ScriptAddOptions * options_ptr =
( ( ScriptAddOptions * ) io_handler . GetUserData ( ) ) ;
if ( options_ptr ) {
ScriptAddOptions : : SharedPointer options (
options_ptr ) ; // this will ensure that we get rid of the pointer
// when going out of scope
ScriptInterpreter * interpreter = m_interpreter . GetScriptInterpreter ( ) ;
if ( interpreter ) {
std : : string funct_name_str ;
if ( interpreter - > GenerateTypeScriptFunction ( lines ,
funct_name_str ) ) {
if ( funct_name_str . empty ( ) ) {
error_sp - > Printf ( " unable to obtain a valid function name from "
" the script interpreter. \n " ) ;
error_sp - > Flush ( ) ;
} else {
// now I have a valid function name, let's add this as script
// for every type in the list
TypeSummaryImplSP script_format ;
script_format . reset ( new ScriptSummaryFormat (
options - > m_flags , funct_name_str . c_str ( ) ,
lines . CopyList ( " " ) . c_str ( ) ) ) ;
Error error ;
for ( size_t i = 0 ; i < options - > m_target_types . GetSize ( ) ; i + + ) {
const char * type_name =
options - > m_target_types . GetStringAtIndex ( i ) ;
CommandObjectTypeSummaryAdd : : AddSummary (
ConstString ( type_name ) , script_format ,
( options - > m_regex
? CommandObjectTypeSummaryAdd : : eRegexSummary
: CommandObjectTypeSummaryAdd : : eRegularSummary ) ,
options - > m_category , & error ) ;
if ( error . Fail ( ) ) {
error_sp - > Printf ( " error: %s " , error . AsCString ( ) ) ;
error_sp - > Flush ( ) ;
}
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
if ( options - > m_name ) {
CommandObjectTypeSummaryAdd : : AddSummary (
options - > m_name , script_format ,
CommandObjectTypeSummaryAdd : : eNamedSummary ,
options - > m_category , & error ) ;
if ( error . Fail ( ) ) {
CommandObjectTypeSummaryAdd : : AddSummary (
options - > m_name , script_format ,
CommandObjectTypeSummaryAdd : : eNamedSummary ,
options - > m_category , & error ) ;
if ( error . Fail ( ) ) {
error_sp - > Printf ( " error: %s " , error . AsCString ( ) ) ;
error_sp - > Flush ( ) ;
}
} else {
error_sp - > Printf ( " error: %s " , error . AsCString ( ) ) ;
error_sp - > Flush ( ) ;
}
} else {
if ( error . AsCString ( ) ) {
error_sp - > Printf ( " error: %s " , error . AsCString ( ) ) ;
2014-02-18 11:23:10 -05:00
error_sp - > Flush ( ) ;
2017-01-02 14:26:05 -05:00
}
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
}
} else {
error_sp - > Printf ( " error: unable to generate a function. \n " ) ;
error_sp - > Flush ( ) ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
} else {
error_sp - > Printf ( " error: no script interpreter. \n " ) ;
2014-02-18 11:23:10 -05:00
error_sp - > Flush ( ) ;
2017-01-02 14:26:05 -05:00
}
} else {
error_sp - > Printf ( " error: internal synchronization information "
" missing or invalid. \n " ) ;
error_sp - > Flush ( ) ;
}
} else {
error_sp - > Printf ( " error: empty function, didn't add python command. \n " ) ;
error_sp - > Flush ( ) ;
}
} else {
error_sp - > Printf (
" error: script interpreter missing, didn't add python command. \n " ) ;
error_sp - > Flush ( ) ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
# endif // LLDB_DISABLE_PYTHON
io_handler . SetIsDone ( true ) ;
}
static bool AddSummary ( ConstString type_name , lldb : : TypeSummaryImplSP entry ,
SummaryFormatType type , std : : string category ,
Error * error = nullptr ) ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override ;
} ;
static const char * g_synth_addreader_instructions =
" Enter your Python command(s). Type 'DONE' to end. \n "
" You must define a Python class with these methods: \n "
" def __init__(self, valobj, dict): \n "
" def num_children(self): \n "
" def get_child_at_index(self, index): \n "
" def get_child_index(self, name): \n "
" def update(self): \n "
" '''Optional''' \n "
" class synthProvider: \n " ;
static OptionDefinition g_type_synth_add_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " cascade " , ' C ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " If true, cascade through typedef chains. " } ,
{ LLDB_OPT_SET_ALL , false , " skip-pointers " , ' p ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Don't use this format for pointers-to-type objects. " } ,
{ LLDB_OPT_SET_ALL , false , " skip-references " , ' r ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Don't use this format for references-to-type objects. " } ,
{ LLDB_OPT_SET_ALL , false , " category " , ' w ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeName , " Add this to the given category instead of the default one. " } ,
{ LLDB_OPT_SET_2 , false , " python-class " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypePythonClass , " Use this Python class to produce synthetic children. " } ,
{ LLDB_OPT_SET_3 , false , " input-python " , ' P ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Type Python code to generate a class that provides synthetic children. " } ,
{ LLDB_OPT_SET_ALL , false , " regex " , ' x ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Type names are actually regular expressions. " }
// clang-format on
2013-08-23 13:46:38 -04:00
} ;
2017-01-02 14:26:05 -05:00
class CommandObjectTypeSynthAdd : public CommandObjectParsed ,
public IOHandlerDelegateMultiline {
2013-08-23 13:46:38 -04:00
private :
2017-01-02 14:26:05 -05:00
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
bool success ;
switch ( short_option ) {
case ' C ' :
m_cascade = Args : : StringToBoolean ( option_arg , true , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " invalid value for cascade: %s " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' P ' :
handwrite_python = true ;
break ;
case ' l ' :
m_class_name = std : : string ( option_arg ) ;
is_class_based = true ;
break ;
case ' p ' :
m_skip_pointers = true ;
break ;
case ' r ' :
m_skip_references = true ;
break ;
case ' w ' :
m_category = std : : string ( option_arg ) ;
break ;
case ' x ' :
m_regex = true ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
}
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_cascade = true ;
m_class_name = " " ;
m_skip_pointers = false ;
m_skip_references = false ;
m_category = " default " ;
is_class_based = false ;
handwrite_python = false ;
m_regex = false ;
}
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_type_synth_add_options ) ;
}
// Instance variables to hold the values for command options.
bool m_cascade ;
bool m_skip_references ;
bool m_skip_pointers ;
std : : string m_class_name ;
bool m_input_python ;
std : : string m_category ;
bool is_class_based ;
bool handwrite_python ;
bool m_regex ;
} ;
CommandOptions m_options ;
Options * GetOptions ( ) override { return & m_options ; }
bool Execute_HandwritePython ( Args & command , CommandReturnObject & result ) ;
bool Execute_PythonClass ( Args & command , CommandReturnObject & result ) ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
WarnOnPotentialUnquotedUnsignedType ( command , result ) ;
if ( m_options . handwrite_python )
return Execute_HandwritePython ( command , result ) ;
else if ( m_options . is_class_based )
return Execute_PythonClass ( command , result ) ;
else {
result . AppendError ( " must either provide a children list, a Python class "
" name, or use -P and type a Python class "
" line-by-line " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
}
void IOHandlerActivated ( IOHandler & io_handler ) override {
StreamFileSP output_sp ( io_handler . GetOutputStreamFile ( ) ) ;
if ( output_sp ) {
output_sp - > PutCString ( g_synth_addreader_instructions ) ;
output_sp - > Flush ( ) ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
}
void IOHandlerInputComplete ( IOHandler & io_handler ,
std : : string & data ) override {
StreamFileSP error_sp = io_handler . GetErrorStreamFile ( ) ;
2016-07-23 16:50:09 -04:00
2014-02-18 11:23:10 -05:00
# ifndef LLDB_DISABLE_PYTHON
2017-01-02 14:26:05 -05:00
ScriptInterpreter * interpreter = m_interpreter . GetScriptInterpreter ( ) ;
if ( interpreter ) {
StringList lines ;
lines . SplitIntoLines ( data ) ;
if ( lines . GetSize ( ) > 0 ) {
SynthAddOptions * options_ptr =
( ( SynthAddOptions * ) io_handler . GetUserData ( ) ) ;
if ( options_ptr ) {
SynthAddOptions : : SharedPointer options (
options_ptr ) ; // this will ensure that we get rid of the pointer
// when going out of scope
ScriptInterpreter * interpreter = m_interpreter . GetScriptInterpreter ( ) ;
if ( interpreter ) {
std : : string class_name_str ;
if ( interpreter - > GenerateTypeSynthClass ( lines , class_name_str ) ) {
if ( class_name_str . empty ( ) ) {
error_sp - > Printf (
" error: unable to obtain a proper name for the class. \n " ) ;
error_sp - > Flush ( ) ;
} else {
// everything should be fine now, let's add the synth provider
// class
SyntheticChildrenSP synth_provider ;
synth_provider . reset ( new ScriptedSyntheticChildren (
SyntheticChildren : : Flags ( )
. SetCascades ( options - > m_cascade )
. SetSkipPointers ( options - > m_skip_pointers )
. SetSkipReferences ( options - > m_skip_references ) ,
class_name_str . c_str ( ) ) ) ;
lldb : : TypeCategoryImplSP category ;
DataVisualization : : Categories : : GetCategory (
ConstString ( options - > m_category . c_str ( ) ) , category ) ;
Error error ;
for ( size_t i = 0 ; i < options - > m_target_types . GetSize ( ) ; i + + ) {
const char * type_name =
options - > m_target_types . GetStringAtIndex ( i ) ;
ConstString const_type_name ( type_name ) ;
if ( const_type_name ) {
if ( ! CommandObjectTypeSynthAdd : : AddSynth (
const_type_name , synth_provider ,
options - > m_regex
? CommandObjectTypeSynthAdd : : eRegexSynth
: CommandObjectTypeSynthAdd : : eRegularSynth ,
options - > m_category , & error ) ) {
error_sp - > Printf ( " error: %s \n " , error . AsCString ( ) ) ;
error_sp - > Flush ( ) ;
break ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
} else {
error_sp - > Printf ( " error: invalid type name. \n " ) ;
2014-02-18 11:23:10 -05:00
error_sp - > Flush ( ) ;
2017-01-02 14:26:05 -05:00
break ;
}
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
}
} else {
error_sp - > Printf ( " error: unable to generate a class. \n " ) ;
error_sp - > Flush ( ) ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
} else {
error_sp - > Printf ( " error: no script interpreter. \n " ) ;
2014-02-18 11:23:10 -05:00
error_sp - > Flush ( ) ;
2017-01-02 14:26:05 -05:00
}
} else {
error_sp - > Printf ( " error: internal synchronization data missing. \n " ) ;
error_sp - > Flush ( ) ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
} else {
error_sp - > Printf ( " error: empty function, didn't add python command. \n " ) ;
error_sp - > Flush ( ) ;
}
} else {
error_sp - > Printf (
" error: script interpreter missing, didn't add python command. \n " ) ;
error_sp - > Flush ( ) ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
# endif // LLDB_DISABLE_PYTHON
io_handler . SetIsDone ( true ) ;
}
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
enum SynthFormatType { eRegularSynth , eRegexSynth } ;
CommandObjectTypeSynthAdd ( CommandInterpreter & interpreter ) ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTypeSynthAdd ( ) override = default ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
static bool AddSynth ( ConstString type_name , lldb : : SyntheticChildrenSP entry ,
SynthFormatType type , std : : string category_name ,
Error * error ) ;
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectTypeFormatAdd
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
static OptionDefinition g_type_format_add_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " category " , ' w ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeName , " Add this to the given category instead of the default one. " } ,
{ LLDB_OPT_SET_ALL , false , " cascade " , ' C ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " If true, cascade through typedef chains. " } ,
{ LLDB_OPT_SET_ALL , false , " skip-pointers " , ' p ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Don't use this format for pointers-to-type objects. " } ,
{ LLDB_OPT_SET_ALL , false , " skip-references " , ' r ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Don't use this format for references-to-type objects. " } ,
{ LLDB_OPT_SET_ALL , false , " regex " , ' x ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Type names are actually regular expressions. " } ,
{ LLDB_OPT_SET_2 , false , " type " , ' t ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeName , " Format variables as if they were of this type. " }
// clang-format on
} ;
class CommandObjectTypeFormatAdd : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
private :
2017-01-02 14:26:05 -05:00
class CommandOptions : public OptionGroup {
public :
CommandOptions ( ) : OptionGroup ( ) { }
~ CommandOptions ( ) override = default ;
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_type_format_add_options ) ;
}
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_cascade = true ;
m_skip_pointers = false ;
m_skip_references = false ;
m_regex = false ;
m_category . assign ( " default " ) ;
m_custom_type_name . clear ( ) ;
}
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_value ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option =
g_type_format_add_options [ option_idx ] . short_option ;
bool success ;
switch ( short_option ) {
case ' C ' :
m_cascade = Args : : StringToBoolean ( option_value , true , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " invalid value for cascade: %s " ,
option_value . str ( ) . c_str ( ) ) ;
break ;
case ' p ' :
m_skip_pointers = true ;
break ;
case ' w ' :
m_category . assign ( option_value ) ;
break ;
case ' r ' :
m_skip_references = true ;
break ;
case ' x ' :
m_regex = true ;
break ;
case ' t ' :
m_custom_type_name . assign ( option_value ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
}
// Instance variables to hold the values for command options.
bool m_cascade ;
bool m_skip_references ;
bool m_skip_pointers ;
bool m_regex ;
std : : string m_category ;
std : : string m_custom_type_name ;
} ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_option_group ;
OptionGroupFormat m_format_options ;
CommandOptions m_command_options ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
Options * GetOptions ( ) override { return & m_option_group ; }
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeFormatAdd ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " type format add " ,
" Add a new formatting style for a type. " , nullptr ) ,
m_option_group ( ) , m_format_options ( eFormatInvalid ) ,
m_command_options ( ) {
CommandArgumentEntry type_arg ;
CommandArgumentData type_style_arg ;
type_style_arg . arg_type = eArgTypeName ;
type_style_arg . arg_repetition = eArgRepeatPlus ;
type_arg . push_back ( type_style_arg ) ;
m_arguments . push_back ( type_arg ) ;
SetHelpLong (
R " (
2015-09-06 10:32:30 -04:00
The following examples of ' type format add ' refer to this code snippet for context :
typedef int Aint ;
typedef float Afloat ;
typedef Aint Bint ;
typedef Afloat Bfloat ;
Aint ix = 5 ;
Bint iy = 5 ;
Afloat fx = 3.14 ;
BFloat fy = 3.14 ;
Adding default formatting :
( lldb ) type format add - f hex AInt
( lldb ) frame variable iy
2017-01-02 14:26:05 -05:00
) "
" Produces hexadecimal display of iy, because no formatter is available for Bint and \
the one for Aint is used instead . "
R " (
2015-09-06 10:32:30 -04:00
To prevent this use the cascade option ' - C no ' to prevent evaluation of typedef chains :
( lldb ) type format add - f hex - C no AInt
Similar reasoning applies to this :
( lldb ) type format add - f hex - C no float - p
2017-01-02 14:26:05 -05:00
) "
" All float values and float references are now formatted as hexadecimal, but not \
pointers to floats . Nor will it change the default display for Afloat and Bfloat objects . " );
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
// Add the "--format" to all options groups
m_option_group . Append ( & m_format_options ,
OptionGroupFormat : : OPTION_GROUP_FORMAT ,
LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_command_options ) ;
m_option_group . Finalize ( ) ;
}
~ CommandObjectTypeFormatAdd ( ) override = default ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc < 1 ) {
result . AppendErrorWithFormat ( " %s takes one or more args. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
const Format format = m_format_options . GetFormat ( ) ;
if ( format = = eFormatInvalid & &
m_command_options . m_custom_type_name . empty ( ) ) {
result . AppendErrorWithFormat ( " %s needs a valid format. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
TypeFormatImplSP entry ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( m_command_options . m_custom_type_name . empty ( ) )
entry . reset ( new TypeFormatImpl_Format (
format , TypeFormatImpl : : Flags ( )
. SetCascades ( m_command_options . m_cascade )
. SetSkipPointers ( m_command_options . m_skip_pointers )
. SetSkipReferences ( m_command_options . m_skip_references ) ) ) ;
else
entry . reset ( new TypeFormatImpl_EnumType (
ConstString ( m_command_options . m_custom_type_name . c_str ( ) ) ,
TypeFormatImpl : : Flags ( )
. SetCascades ( m_command_options . m_cascade )
. SetSkipPointers ( m_command_options . m_skip_pointers )
. SetSkipReferences ( m_command_options . m_skip_references ) ) ) ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
// now I have a valid format, let's add it to every type
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
TypeCategoryImplSP category_sp ;
DataVisualization : : Categories : : GetCategory (
ConstString ( m_command_options . m_category ) , category_sp ) ;
if ( ! category_sp )
return false ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
WarnOnPotentialUnquotedUnsignedType ( command , result ) ;
for ( auto & arg_entry : command . entries ( ) ) {
if ( arg_entry . ref . empty ( ) ) {
result . AppendError ( " empty typenames not allowed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2015-12-30 06:55:28 -05:00
return false ;
2017-01-02 14:26:05 -05:00
}
ConstString typeCS ( arg_entry . ref ) ;
if ( m_command_options . m_regex ) {
RegularExpressionSP typeRX ( new RegularExpression ( ) ) ;
if ( ! typeRX - > Compile ( arg_entry . ref ) ) {
result . AppendError (
" regex format error (maybe this is not really a regex?) " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
category_sp - > GetRegexTypeSummariesContainer ( ) - > Delete ( typeCS ) ;
category_sp - > GetRegexTypeFormatsContainer ( ) - > Add ( typeRX , entry ) ;
} else
category_sp - > GetTypeFormatsContainer ( ) - > Add ( typeCS , entry ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
2017-01-02 14:26:05 -05:00
static OptionDefinition g_type_formatter_delete_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 , false , " all " , ' a ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Delete from every category. " } ,
{ LLDB_OPT_SET_2 , false , " category " , ' w ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeName , " Delete from given category. " } ,
{ LLDB_OPT_SET_3 , false , " language " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLanguage , " Delete from given language's category. " }
// clang-format on
2013-11-06 11:48:53 -05:00
} ;
2017-01-02 14:26:05 -05:00
class CommandObjectTypeFormatterDelete : public CommandObjectParsed {
protected :
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) { }
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandOptions ( ) override = default ;
2015-12-30 06:55:28 -05:00
2017-01-02 14:26:05 -05:00
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
switch ( short_option ) {
case ' a ' :
m_delete_all = true ;
break ;
case ' w ' :
m_category = std : : string ( option_arg ) ;
break ;
case ' l ' :
m_language = Language : : GetLanguageTypeFromString ( option_arg ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
return error ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_delete_all = false ;
m_category = " default " ;
m_language = lldb : : eLanguageTypeUnknown ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_type_formatter_delete_options ) ;
}
2013-11-06 11:48:53 -05:00
2017-01-02 14:26:05 -05:00
// Instance variables to hold the values for command options.
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
bool m_delete_all ;
std : : string m_category ;
lldb : : LanguageType m_language ;
} ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
CommandOptions m_options ;
uint32_t m_formatter_kind_mask ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
Options * GetOptions ( ) override { return & m_options ; }
2013-08-23 13:46:38 -04:00
2015-12-30 06:55:28 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeFormatterDelete ( CommandInterpreter & interpreter ,
uint32_t formatter_kind_mask ,
const char * name , const char * help )
: CommandObjectParsed ( interpreter , name , help , nullptr ) , m_options ( ) ,
m_formatter_kind_mask ( formatter_kind_mask ) {
CommandArgumentEntry type_arg ;
CommandArgumentData type_style_arg ;
type_style_arg . arg_type = eArgTypeName ;
type_style_arg . arg_repetition = eArgRepeatPlain ;
type_arg . push_back ( type_style_arg ) ;
m_arguments . push_back ( type_arg ) ;
}
~ CommandObjectTypeFormatterDelete ( ) override = default ;
protected :
virtual bool FormatterSpecificDeletion ( ConstString typeCS ) { return false ; }
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc ! = 1 ) {
result . AppendErrorWithFormat ( " %s takes 1 arg. \n " , m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
const char * typeA = command . GetArgumentAtIndex ( 0 ) ;
ConstString typeCS ( typeA ) ;
if ( ! typeCS ) {
result . AppendError ( " empty typenames not allowed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2015-12-30 06:55:28 -05:00
}
2017-01-02 14:26:05 -05:00
if ( m_options . m_delete_all ) {
DataVisualization : : Categories : : ForEach (
[ this , typeCS ] ( const lldb : : TypeCategoryImplSP & category_sp ) - > bool {
category_sp - > Delete ( typeCS , m_formatter_kind_mask ) ;
return true ;
} ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return result . Succeeded ( ) ;
}
bool delete_category = false ;
bool extra_deletion = false ;
if ( m_options . m_language ! = lldb : : eLanguageTypeUnknown ) {
lldb : : TypeCategoryImplSP category ;
DataVisualization : : Categories : : GetCategory ( m_options . m_language ,
category ) ;
if ( category )
delete_category = category - > Delete ( typeCS , m_formatter_kind_mask ) ;
extra_deletion = FormatterSpecificDeletion ( typeCS ) ;
} else {
lldb : : TypeCategoryImplSP category ;
DataVisualization : : Categories : : GetCategory (
ConstString ( m_options . m_category . c_str ( ) ) , category ) ;
if ( category )
delete_category = category - > Delete ( typeCS , m_formatter_kind_mask ) ;
extra_deletion = FormatterSpecificDeletion ( typeCS ) ;
}
if ( delete_category | | extra_deletion ) {
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return result . Succeeded ( ) ;
} else {
result . AppendErrorWithFormat ( " no custom formatter for %s. \n " , typeA ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
2013-08-23 13:46:38 -04:00
} ;
2017-01-02 14:26:05 -05:00
static OptionDefinition g_type_formatter_clear_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " all " , ' a ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Clear every category. " }
// clang-format on
} ;
2015-12-30 06:55:28 -05:00
2017-01-02 14:26:05 -05:00
class CommandObjectTypeFormatterClear : public CommandObjectParsed {
private :
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) { }
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' a ' :
m_delete_all = true ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
2013-11-06 11:48:53 -05:00
}
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_delete_all = false ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_type_formatter_clear_options ) ;
}
// Instance variables to hold the values for command options.
bool m_delete_all ;
} ;
CommandOptions m_options ;
uint32_t m_formatter_kind_mask ;
Options * GetOptions ( ) override { return & m_options ; }
public :
CommandObjectTypeFormatterClear ( CommandInterpreter & interpreter ,
uint32_t formatter_kind_mask ,
const char * name , const char * help )
: CommandObjectParsed ( interpreter , name , help , nullptr ) , m_options ( ) ,
m_formatter_kind_mask ( formatter_kind_mask ) { }
~ CommandObjectTypeFormatterClear ( ) override = default ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
virtual void FormatterSpecificDeletion ( ) { }
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
if ( m_options . m_delete_all ) {
DataVisualization : : Categories : : ForEach (
[ this ] ( const TypeCategoryImplSP & category_sp ) - > bool {
category_sp - > Clear ( m_formatter_kind_mask ) ;
return true ;
} ) ;
} else {
lldb : : TypeCategoryImplSP category ;
if ( command . GetArgumentCount ( ) > 0 ) {
const char * cat_name = command . GetArgumentAtIndex ( 0 ) ;
ConstString cat_nameCS ( cat_name ) ;
DataVisualization : : Categories : : GetCategory ( cat_nameCS , category ) ;
} else {
DataVisualization : : Categories : : GetCategory ( ConstString ( nullptr ) ,
category ) ;
}
category - > Clear ( m_formatter_kind_mask ) ;
}
FormatterSpecificDeletion ( ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return result . Succeeded ( ) ;
}
} ;
//-------------------------------------------------------------------------
// CommandObjectTypeFormatDelete
//-------------------------------------------------------------------------
class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete {
public :
CommandObjectTypeFormatDelete ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterDelete (
interpreter ,
eFormatCategoryItemValue | eFormatCategoryItemRegexValue ,
" type format delete " ,
" Delete an existing formatting style for a type. " ) { }
~ CommandObjectTypeFormatDelete ( ) override = default ;
} ;
//-------------------------------------------------------------------------
// CommandObjectTypeFormatClear
//-------------------------------------------------------------------------
class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear {
public :
CommandObjectTypeFormatClear ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterClear (
interpreter ,
eFormatCategoryItemValue | eFormatCategoryItemRegexValue ,
" type format clear " , " Delete all existing format styles. " ) { }
} ;
template < typename FormatterType >
class CommandObjectTypeFormatterList : public CommandObjectParsed {
typedef typename FormatterType : : SharedPointer FormatterSharedPointer ;
class CommandOptions : public Options {
public :
CommandOptions ( )
: Options ( ) , m_category_regex ( " " , " " ) ,
m_category_language ( lldb : : eLanguageTypeUnknown ,
lldb : : eLanguageTypeUnknown ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' w ' :
m_category_regex . SetCurrentValue ( option_arg ) ;
m_category_regex . SetOptionWasSet ( ) ;
break ;
case ' l ' :
error = m_category_language . SetValueFromString ( option_arg ) ;
if ( error . Success ( ) )
m_category_language . SetOptionWasSet ( ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
}
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_category_regex . Clear ( ) ;
m_category_language . Clear ( ) ;
}
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
static OptionDefinition g_option_table [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 , false , " category-regex " , ' w ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeName , " Only show categories matching this filter. " } ,
{ LLDB_OPT_SET_2 , false , " language " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLanguage , " Only show the category for a specific language. " }
// clang-format on
} ;
return llvm : : ArrayRef < OptionDefinition > ( g_option_table ) ;
}
// Instance variables to hold the values for command options.
OptionValueString m_category_regex ;
OptionValueLanguage m_category_language ;
} ;
CommandOptions m_options ;
Options * GetOptions ( ) override { return & m_options ; }
public :
CommandObjectTypeFormatterList ( CommandInterpreter & interpreter ,
const char * name , const char * help )
: CommandObjectParsed ( interpreter , name , help , nullptr ) , m_options ( ) {
CommandArgumentEntry type_arg ;
CommandArgumentData type_style_arg ;
type_style_arg . arg_type = eArgTypeName ;
type_style_arg . arg_repetition = eArgRepeatOptional ;
type_arg . push_back ( type_style_arg ) ;
m_arguments . push_back ( type_arg ) ;
}
~ CommandObjectTypeFormatterList ( ) override = default ;
protected :
virtual bool FormatterSpecificList ( CommandReturnObject & result ) {
return false ;
}
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
const size_t argc = command . GetArgumentCount ( ) ;
std : : unique_ptr < RegularExpression > category_regex ;
std : : unique_ptr < RegularExpression > formatter_regex ;
if ( m_options . m_category_regex . OptionWasSet ( ) ) {
category_regex . reset ( new RegularExpression ( ) ) ;
if ( ! category_regex - > Compile (
m_options . m_category_regex . GetCurrentValueAsRef ( ) ) ) {
result . AppendErrorWithFormat (
" syntax error in category regular expression '%s' " ,
m_options . m_category_regex . GetCurrentValueAsRef ( ) . str ( ) . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2016-07-23 16:50:09 -04:00
return false ;
2017-01-02 14:26:05 -05:00
}
2015-12-30 06:55:28 -05:00
}
2017-01-02 14:26:05 -05:00
if ( argc = = 1 ) {
const char * arg = command . GetArgumentAtIndex ( 0 ) ;
formatter_regex . reset ( new RegularExpression ( ) ) ;
if ( ! formatter_regex - > Compile ( llvm : : StringRef : : withNullAsEmpty ( arg ) ) ) {
result . AppendErrorWithFormat ( " syntax error in regular expression '%s' " ,
arg ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
bool any_printed = false ;
auto category_closure = [ & result , & formatter_regex , & any_printed ] (
const lldb : : TypeCategoryImplSP & category ) - > void {
result . GetOutputStream ( ) . Printf (
" ----------------------- \n Category: %s%s \n ----------------------- \n " ,
category - > GetName ( ) , category - > IsEnabled ( ) ? " " : " (disabled) " ) ;
TypeCategoryImpl : : ForEachCallbacks < FormatterType > foreach ;
foreach
. SetExact ( [ & result , & formatter_regex , & any_printed ] (
ConstString name ,
const FormatterSharedPointer & format_sp ) - > bool {
if ( formatter_regex ) {
bool escape = true ;
if ( name . GetStringRef ( ) = = formatter_regex - > GetText ( ) ) {
escape = false ;
} else if ( formatter_regex - > Execute ( name . GetStringRef ( ) ) ) {
escape = false ;
2015-12-30 06:55:28 -05:00
}
2017-01-02 14:26:05 -05:00
if ( escape )
return true ;
}
any_printed = true ;
result . GetOutputStream ( ) . Printf ( " %s: %s \n " , name . AsCString ( ) ,
format_sp - > GetDescription ( ) . c_str ( ) ) ;
return true ;
} ) ;
foreach
. SetWithRegex ( [ & result , & formatter_regex , & any_printed ] (
RegularExpressionSP regex_sp ,
const FormatterSharedPointer & format_sp ) - > bool {
if ( formatter_regex ) {
bool escape = true ;
if ( regex_sp - > GetText ( ) = = formatter_regex - > GetText ( ) ) {
escape = false ;
} else if ( formatter_regex - > Execute ( regex_sp - > GetText ( ) ) ) {
escape = false ;
2015-12-30 06:55:28 -05:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
if ( escape )
return true ;
}
any_printed = true ;
result . GetOutputStream ( ) . Printf ( " %s: %s \n " ,
regex_sp - > GetText ( ) . str ( ) . c_str ( ) ,
format_sp - > GetDescription ( ) . c_str ( ) ) ;
return true ;
} ) ;
category - > ForEach ( foreach ) ;
} ;
if ( m_options . m_category_language . OptionWasSet ( ) ) {
lldb : : TypeCategoryImplSP category_sp ;
DataVisualization : : Categories : : GetCategory (
m_options . m_category_language . GetCurrentValue ( ) , category_sp ) ;
if ( category_sp )
category_closure ( category_sp ) ;
} else {
DataVisualization : : Categories : : ForEach (
2017-04-16 12:04:10 -04:00
[ & category_regex , & category_closure ] (
2017-01-02 14:26:05 -05:00
const lldb : : TypeCategoryImplSP & category ) - > bool {
if ( category_regex ) {
bool escape = true ;
if ( category - > GetName ( ) = = category_regex - > GetText ( ) ) {
escape = false ;
} else if ( category_regex - > Execute (
llvm : : StringRef : : withNullAsEmpty (
category - > GetName ( ) ) ) ) {
escape = false ;
}
if ( escape )
2015-12-30 06:55:28 -05:00
return true ;
2017-01-02 14:26:05 -05:00
}
category_closure ( category ) ;
return true ;
} ) ;
any_printed = FormatterSpecificList ( result ) | any_printed ;
}
if ( any_printed )
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
else {
result . GetOutputStream ( ) . PutCString ( " no matching results found. \n " ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
2015-12-30 06:55:28 -05:00
//-------------------------------------------------------------------------
// CommandObjectTypeFormatList
//-------------------------------------------------------------------------
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
class CommandObjectTypeFormatList
: public CommandObjectTypeFormatterList < TypeFormatImpl > {
2015-12-30 06:55:28 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeFormatList ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterList ( interpreter , " type format list " ,
" Show a list of current formats. " ) { }
2013-11-06 11:48:53 -05:00
} ;
2013-08-23 13:46:38 -04:00
# ifndef LLDB_DISABLE_PYTHON
//-------------------------------------------------------------------------
// CommandObjectTypeSummaryAdd
//-------------------------------------------------------------------------
2016-07-23 16:50:09 -04:00
# endif // LLDB_DISABLE_PYTHON
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
Error CommandObjectTypeSummaryAdd : : CommandOptions : : SetOptionValue (
uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
bool success ;
switch ( short_option ) {
case ' C ' :
m_flags . SetCascades ( Args : : StringToBoolean ( option_arg , true , & success ) ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " invalid value for cascade: %s " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' e ' :
m_flags . SetDontShowChildren ( false ) ;
break ;
case ' h ' :
m_flags . SetHideEmptyAggregates ( true ) ;
break ;
case ' v ' :
m_flags . SetDontShowValue ( true ) ;
break ;
case ' c ' :
m_flags . SetShowMembersOneLiner ( true ) ;
break ;
case ' s ' :
m_format_string = std : : string ( option_arg ) ;
break ;
case ' p ' :
m_flags . SetSkipPointers ( true ) ;
break ;
case ' r ' :
m_flags . SetSkipReferences ( true ) ;
break ;
case ' x ' :
m_regex = true ;
break ;
case ' n ' :
m_name . SetString ( option_arg ) ;
break ;
case ' o ' :
m_python_script = option_arg ;
m_is_add_script = true ;
break ;
case ' F ' :
m_python_function = option_arg ;
m_is_add_script = true ;
break ;
case ' P ' :
m_is_add_script = true ;
break ;
case ' w ' :
m_category = std : : string ( option_arg ) ;
break ;
case ' O ' :
m_flags . SetHideItemNames ( true ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " , short_option ) ;
break ;
}
return error ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
void CommandObjectTypeSummaryAdd : : CommandOptions : : OptionParsingStarting (
ExecutionContext * execution_context ) {
m_flags . Clear ( ) . SetCascades ( ) . SetDontShowChildren ( ) . SetDontShowValue ( false ) ;
m_flags . SetShowMembersOneLiner ( false )
. SetSkipPointers ( false )
. SetSkipReferences ( false )
. SetHideItemNames ( false ) ;
m_regex = false ;
m_name . Clear ( ) ;
m_python_script = " " ;
m_python_function = " " ;
m_format_string = " " ;
m_is_add_script = false ;
m_category = " default " ;
2013-08-23 13:46:38 -04:00
}
# ifndef LLDB_DISABLE_PYTHON
2017-01-02 14:26:05 -05:00
bool CommandObjectTypeSummaryAdd : : Execute_ScriptSummary (
Args & command , CommandReturnObject & result ) {
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc < 1 & & ! m_options . m_name ) {
result . AppendErrorWithFormat ( " %s takes one or more args. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
TypeSummaryImplSP script_format ;
if ( ! m_options . m_python_function
. empty ( ) ) // we have a Python function ready to use
{
const char * funct_name = m_options . m_python_function . c_str ( ) ;
if ( ! funct_name | | ! funct_name [ 0 ] ) {
result . AppendError ( " function name empty. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
std : : string code =
( " " + m_options . m_python_function + " (valobj,internal_dict) " ) ;
script_format . reset (
new ScriptSummaryFormat ( m_options . m_flags , funct_name , code . c_str ( ) ) ) ;
ScriptInterpreter * interpreter = m_interpreter . GetScriptInterpreter ( ) ;
if ( interpreter & & ! interpreter - > CheckObjectExists ( funct_name ) )
result . AppendWarningWithFormat (
" The provided function \" %s \" does not exist - "
" please define it before attempting to use this summary. \n " ,
funct_name ) ;
} else if ( ! m_options . m_python_script
. empty ( ) ) // we have a quick 1-line script, just use it
{
ScriptInterpreter * interpreter = m_interpreter . GetScriptInterpreter ( ) ;
if ( ! interpreter ) {
result . AppendError ( " script interpreter missing - unable to generate "
" function wrapper. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
StringList funct_sl ;
funct_sl < < m_options . m_python_script . c_str ( ) ;
std : : string funct_name_str ;
if ( ! interpreter - > GenerateTypeScriptFunction ( funct_sl , funct_name_str ) ) {
result . AppendError ( " unable to generate function wrapper. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( funct_name_str . empty ( ) ) {
result . AppendError (
" script interpreter failed to generate a valid function name. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
std : : string code = " " + m_options . m_python_script ;
script_format . reset ( new ScriptSummaryFormat (
m_options . m_flags , funct_name_str . c_str ( ) , code . c_str ( ) ) ) ;
} else {
// Use an IOHandler to grab Python code from the user
ScriptAddOptions * options =
new ScriptAddOptions ( m_options . m_flags , m_options . m_regex ,
m_options . m_name , m_options . m_category ) ;
for ( auto & entry : command . entries ( ) ) {
if ( entry . ref . empty ( ) ) {
result . AppendError ( " empty typenames not allowed " ) ;
2013-08-23 13:46:38 -04:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2017-01-02 14:26:05 -05:00
}
options - > m_target_types < < entry . ref ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
m_interpreter . GetPythonCommandsFromIOHandler (
" " , // Prompt
* this , // IOHandlerDelegate
true , // Run IOHandler in async mode
options ) ; // Baton for the "io_handler" that will be passed back into
// our IOHandlerDelegate functions
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return result . Succeeded ( ) ;
}
// if I am here, script_format must point to something good, so I can add that
// as a script summary to all interested parties
Error error ;
for ( auto & entry : command . entries ( ) ) {
CommandObjectTypeSummaryAdd : : AddSummary (
ConstString ( entry . ref ) , script_format ,
( m_options . m_regex ? eRegexSummary : eRegularSummary ) ,
m_options . m_category , & error ) ;
if ( error . Fail ( ) ) {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
if ( m_options . m_name ) {
AddSummary ( m_options . m_name , script_format , eNamedSummary ,
m_options . m_category , & error ) ;
if ( error . Fail ( ) ) {
result . AppendError ( error . AsCString ( ) ) ;
result . AppendError ( " added to types, but not given a name " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
return result . Succeeded ( ) ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
# endif // LLDB_DISABLE_PYTHON
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
bool CommandObjectTypeSummaryAdd : : Execute_StringSummary (
Args & command , CommandReturnObject & result ) {
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc < 1 & & ! m_options . m_name ) {
result . AppendErrorWithFormat ( " %s takes one or more args. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( ! m_options . m_flags . GetShowMembersOneLiner ( ) & &
m_options . m_format_string . empty ( ) ) {
result . AppendError ( " empty summary strings not allowed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
const char * format_cstr = ( m_options . m_flags . GetShowMembersOneLiner ( )
? " "
: m_options . m_format_string . c_str ( ) ) ;
// ${var%S} is an endless recursion, prevent it
if ( strcmp ( format_cstr , " ${var%S} " ) = = 0 ) {
result . AppendError ( " recursive summary not allowed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
std : : unique_ptr < StringSummaryFormat > string_format (
new StringSummaryFormat ( m_options . m_flags , format_cstr ) ) ;
if ( ! string_format ) {
result . AppendError ( " summary creation failed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( string_format - > m_error . Fail ( ) ) {
result . AppendErrorWithFormat ( " syntax error: %s " ,
string_format - > m_error . AsCString ( " <unknown> " ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
lldb : : TypeSummaryImplSP entry ( string_format . release ( ) ) ;
// now I have a valid format, let's add it to every type
Error error ;
for ( auto & arg_entry : command . entries ( ) ) {
if ( arg_entry . ref . empty ( ) ) {
result . AppendError ( " empty typenames not allowed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
ConstString typeCS ( arg_entry . ref ) ;
AddSummary ( typeCS , entry ,
( m_options . m_regex ? eRegexSummary : eRegularSummary ) ,
m_options . m_category , & error ) ;
if ( error . Fail ( ) ) {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
if ( m_options . m_name ) {
AddSummary ( m_options . m_name , entry , eNamedSummary , m_options . m_category ,
& error ) ;
if ( error . Fail ( ) ) {
result . AppendError ( error . AsCString ( ) ) ;
result . AppendError ( " added to types, but not given a name " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return result . Succeeded ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
CommandObjectTypeSummaryAdd : : CommandObjectTypeSummaryAdd (
CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " type summary add " ,
" Add a new summary style for a type. " , nullptr ) ,
IOHandlerDelegateMultiline ( " DONE " ) , m_options ( interpreter ) {
CommandArgumentEntry type_arg ;
CommandArgumentData type_style_arg ;
type_style_arg . arg_type = eArgTypeName ;
type_style_arg . arg_repetition = eArgRepeatPlus ;
type_arg . push_back ( type_style_arg ) ;
m_arguments . push_back ( type_arg ) ;
SetHelpLong (
R " (
2015-09-06 10:32:30 -04:00
The following examples of ' type summary add ' refer to this code snippet for context :
struct JustADemo
{
int * ptr ;
float value ;
JustADemo ( int p = 1 , float v = 0.1 ) : ptr ( new int ( p ) ) , value ( v ) { }
} ;
JustADemo demo_instance ( 42 , 3.14 ) ;
typedef JustADemo NewDemo ;
NewDemo new_demo_instance ( 42 , 3.14 ) ;
( lldb ) type summary add - - summary - string " the answer is ${*var.ptr} " JustADemo
Subsequently displaying demo_instance with ' frame variable ' or ' expression ' will display " the answer is 42 "
( lldb ) type summary add - - summary - string " the answer is ${*var.ptr}, and the question is ${var.value} " JustADemo
Subsequently displaying demo_instance with ' frame variable ' or ' expression ' will display " the answer is 42 and the question is 3.14 "
2017-01-02 14:26:05 -05:00
) "
" Alternatively, you could define formatting for all pointers to integers and \
rely on that when formatting JustADemo to obtain the same result : "
R " (
2015-09-06 10:32:30 -04:00
( lldb ) type summary add - - summary - string " ${var%V} -> ${*var} " " int * "
( lldb ) type summary add - - summary - string " the answer is ${var.ptr}, and the question is ${var.value} " JustADemo
2017-01-02 14:26:05 -05:00
) "
" Type summaries are automatically applied to derived typedefs, so the examples \
2015-09-06 10:32:30 -04:00
above apply to both JustADemo and NewDemo . The cascade option can be used to \
2017-01-02 14:26:05 -05:00
suppress this behavior : "
R " (
2015-09-06 10:32:30 -04:00
( lldb ) type summary add - - summary - string " ${var.ptr}, ${var.value},{${var.byte}} " JustADemo - C no
The summary will now be used for values of JustADemo but not NewDemo .
2017-01-02 14:26:05 -05:00
) "
" By default summaries are shown for pointers and references to values of the \
2015-09-06 10:32:30 -04:00
specified type . To suppress formatting for pointers use the - p option , or apply \
2017-01-02 14:26:05 -05:00
the corresponding - r option to suppress formatting for references : "
R " (
2015-09-06 10:32:30 -04:00
( lldb ) type summary add - p - r - - summary - string " ${var.ptr}, ${var.value},{${var.byte}} " JustADemo
2017-01-02 14:26:05 -05:00
) "
" One-line summaries including all fields in a type can be inferred without supplying an \
explicit summary string by passing the - c option : "
R " (
2015-09-06 10:32:30 -04:00
( lldb ) type summary add - c JustADemo
( lldb ) frame variable demo_instance
( ptr = < address > , value = 3.14 )
2017-01-02 14:26:05 -05:00
) "
" Type summaries normally suppress the nested display of individual fields. To \
supply a summary to supplement the default structure add the - e option : "
R " (
2015-09-06 10:32:30 -04:00
( lldb ) type summary add - e - - summary - string " *ptr = ${*var.ptr} " JustADemo
2017-01-02 14:26:05 -05:00
) "
" Now when displaying JustADemo values the int* is displayed, followed by the \
standard LLDB sequence of children , one per line : "
R " (
2015-09-06 10:32:30 -04:00
* ptr = 42 {
ptr = < address >
value = 3.14
}
2017-01-02 14:26:05 -05:00
) "
" You can also add summaries written in Python. These scripts use lldb public API to \
2015-09-06 10:32:30 -04:00
gather information from your variables and produce a meaningful summary . To start a \
multi - line script use the - P option . The function declaration will be displayed along with \
a comment describing the two arguments . End your script with the word ' DONE ' on a line by \
2017-01-02 14:26:05 -05:00
itself : "
R " (
2015-09-06 10:32:30 -04:00
( lldb ) type summary add JustADemo - P
def function ( valobj , internal_dict ) :
" " " valobj: an SBValue which you want to provide a summary for
internal_dict : an LLDB support object not to be used " " "
value = valobj . GetChildMemberWithName ( ' value ' ) ;
return ' My value is ' + value . GetValue ( ) ;
DONE
Alternatively , the - o option can be used when providing a simple one - line Python script :
2017-01-02 14:26:05 -05:00
( lldb ) type summary add JustADemo - o " value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue(); " ) " );
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
bool CommandObjectTypeSummaryAdd : : DoExecute ( Args & command ,
CommandReturnObject & result ) {
WarnOnPotentialUnquotedUnsignedType ( command , result ) ;
2014-02-18 11:23:10 -05:00
2017-01-02 14:26:05 -05:00
if ( m_options . m_is_add_script ) {
2013-08-23 13:46:38 -04:00
# ifndef LLDB_DISABLE_PYTHON
2017-01-02 14:26:05 -05:00
return Execute_ScriptSummary ( command , result ) ;
2013-08-23 13:46:38 -04:00
# else
2017-01-02 14:26:05 -05:00
result . AppendError ( " python is disabled " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2016-07-23 16:50:09 -04:00
# endif // LLDB_DISABLE_PYTHON
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
return Execute_StringSummary ( command , result ) ;
2014-11-25 16:00:58 -05:00
}
2017-01-02 14:26:05 -05:00
static bool FixArrayTypeNameWithRegex ( ConstString & type_name ) {
llvm : : StringRef type_name_ref ( type_name . GetStringRef ( ) ) ;
if ( type_name_ref . endswith ( " [] " ) ) {
std : : string type_name_str ( type_name . GetCString ( ) ) ;
type_name_str . resize ( type_name_str . length ( ) - 2 ) ;
if ( type_name_str . back ( ) ! = ' ' )
type_name_str . append ( " \\ [[0-9]+ \\ ] " ) ;
2013-08-23 13:46:38 -04:00
else
2017-01-02 14:26:05 -05:00
type_name_str . append ( " \\ [[0-9]+ \\ ] " ) ;
type_name . SetCString ( type_name_str . c_str ( ) ) ;
return true ;
}
return false ;
}
bool CommandObjectTypeSummaryAdd : : AddSummary ( ConstString type_name ,
TypeSummaryImplSP entry ,
SummaryFormatType type ,
std : : string category_name ,
Error * error ) {
lldb : : TypeCategoryImplSP category ;
DataVisualization : : Categories : : GetCategory ( ConstString ( category_name . c_str ( ) ) ,
category ) ;
if ( type = = eRegularSummary ) {
if ( FixArrayTypeNameWithRegex ( type_name ) )
type = eRegexSummary ;
}
if ( type = = eRegexSummary ) {
RegularExpressionSP typeRX ( new RegularExpression ( ) ) ;
if ( ! typeRX - > Compile ( type_name . GetStringRef ( ) ) ) {
if ( error )
error - > SetErrorString (
" regex format error (maybe this is not really a regex?) " ) ;
return false ;
}
category - > GetRegexTypeSummariesContainer ( ) - > Delete ( type_name ) ;
category - > GetRegexTypeSummariesContainer ( ) - > Add ( typeRX , entry ) ;
return true ;
} else if ( type = = eNamedSummary ) {
// system named summaries do not exist (yet?)
DataVisualization : : NamedSummaryFormats : : Add ( type_name , entry ) ;
return true ;
} else {
category - > GetTypeSummariesContainer ( ) - > Add ( type_name , entry ) ;
return true ;
}
}
2013-08-23 13:46:38 -04:00
//-------------------------------------------------------------------------
// CommandObjectTypeSummaryDelete
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
2015-12-30 06:55:28 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeSummaryDelete ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterDelete (
interpreter ,
eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary ,
" type summary delete " , " Delete an existing summary for a type. " ) { }
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTypeSummaryDelete ( ) override = default ;
2016-07-23 16:50:09 -04:00
2015-12-30 06:55:28 -05:00
protected :
2017-01-02 14:26:05 -05:00
bool FormatterSpecificDeletion ( ConstString typeCS ) override {
if ( m_options . m_language ! = lldb : : eLanguageTypeUnknown )
return false ;
return DataVisualization : : NamedSummaryFormats : : Delete ( typeCS ) ;
}
2015-12-30 06:55:28 -05:00
} ;
2017-01-02 14:26:05 -05:00
class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear {
2015-12-30 06:55:28 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeSummaryClear ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterClear (
interpreter ,
eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary ,
" type summary clear " , " Delete all existing summaries. " ) { }
2015-12-30 06:55:28 -05:00
protected :
2017-01-02 14:26:05 -05:00
void FormatterSpecificDeletion ( ) override {
DataVisualization : : NamedSummaryFormats : : Clear ( ) ;
}
2015-12-30 06:55:28 -05:00
} ;
//-------------------------------------------------------------------------
// CommandObjectTypeSummaryList
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTypeSummaryList
: public CommandObjectTypeFormatterList < TypeSummaryImpl > {
2015-12-30 06:55:28 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeSummaryList ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterList ( interpreter , " type summary list " ,
" Show a list of current summaries. " ) { }
2015-12-30 06:55:28 -05:00
protected :
2017-01-02 14:26:05 -05:00
bool FormatterSpecificList ( CommandReturnObject & result ) override {
if ( DataVisualization : : NamedSummaryFormats : : GetCount ( ) > 0 ) {
result . GetOutputStream ( ) . Printf ( " Named summaries: \n " ) ;
DataVisualization : : NamedSummaryFormats : : ForEach (
[ & result ] ( ConstString name ,
const TypeSummaryImplSP & summary_sp ) - > bool {
result . GetOutputStream ( ) . Printf (
" %s: %s \n " , name . AsCString ( ) ,
summary_sp - > GetDescription ( ) . c_str ( ) ) ;
2016-07-23 16:50:09 -04:00
return true ;
2017-01-02 14:26:05 -05:00
} ) ;
return true ;
2015-12-30 06:55:28 -05:00
}
2017-01-02 14:26:05 -05:00
return false ;
}
2015-12-30 06:55:28 -05:00
} ;
//-------------------------------------------------------------------------
// CommandObjectTypeCategoryDefine
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
static OptionDefinition g_type_category_define_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " enabled " , ' e ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " If specified, this category will be created enabled. " } ,
{ LLDB_OPT_SET_ALL , false , " language " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLanguage , " Specify the language that this category is supported for. " }
// clang-format on
} ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
class CommandObjectTypeCategoryDefine : public CommandObjectParsed {
class CommandOptions : public Options {
public :
CommandOptions ( )
: Options ( ) , m_define_enabled ( false , false ) ,
m_cate_language ( eLanguageTypeUnknown , eLanguageTypeUnknown ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' e ' :
m_define_enabled . SetValueFromString ( llvm : : StringRef ( " true " ) ) ;
break ;
case ' l ' :
error = m_cate_language . SetValueFromString ( option_arg ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
}
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_define_enabled . Clear ( ) ;
m_cate_language . Clear ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_type_category_define_options ) ;
}
// Instance variables to hold the values for command options.
OptionValueBoolean m_define_enabled ;
OptionValueLanguage m_cate_language ;
} ;
CommandOptions m_options ;
Options * GetOptions ( ) override { return & m_options ; }
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeCategoryDefine ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " type category define " ,
2016-07-23 16:50:09 -04:00
" Define a new category as a source of formatters. " ,
nullptr ) ,
2017-01-02 14:26:05 -05:00
m_options ( ) {
CommandArgumentEntry type_arg ;
CommandArgumentData type_style_arg ;
type_style_arg . arg_type = eArgTypeName ;
type_style_arg . arg_repetition = eArgRepeatPlus ;
type_arg . push_back ( type_style_arg ) ;
m_arguments . push_back ( type_arg ) ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTypeCategoryDefine ( ) override = default ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc < 1 ) {
result . AppendErrorWithFormat ( " %s takes 1 or more args. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
for ( auto & entry : command . entries ( ) ) {
TypeCategoryImplSP category_sp ;
if ( DataVisualization : : Categories : : GetCategory ( ConstString ( entry . ref ) ,
category_sp ) & &
category_sp ) {
category_sp - > AddLanguage ( m_options . m_cate_language . GetCurrentValue ( ) ) ;
if ( m_options . m_define_enabled . GetCurrentValue ( ) )
DataVisualization : : Categories : : Enable ( category_sp ,
TypeCategoryMap : : Default ) ;
}
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
2015-12-30 06:55:28 -05:00
//-------------------------------------------------------------------------
// CommandObjectTypeCategoryEnable
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
static OptionDefinition g_type_category_enable_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " language " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLanguage , " Enable the category for this language. " } ,
// clang-format on
} ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
class CommandObjectTypeCategoryEnable : public CommandObjectParsed {
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' l ' :
if ( ! option_arg . empty ( ) ) {
m_language = Language : : GetLanguageTypeFromString ( option_arg ) ;
if ( m_language = = lldb : : eLanguageTypeUnknown )
error . SetErrorStringWithFormat ( " unrecognized language '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
}
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_language = lldb : : eLanguageTypeUnknown ;
}
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_type_category_enable_options ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
// Instance variables to hold the values for command options.
lldb : : LanguageType m_language ;
} ;
CommandOptions m_options ;
Options * GetOptions ( ) override { return & m_options ; }
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeCategoryEnable ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " type category enable " ,
2016-07-23 16:50:09 -04:00
" Enable a category as a source of formatters. " ,
nullptr ) ,
2017-01-02 14:26:05 -05:00
m_options ( ) {
CommandArgumentEntry type_arg ;
CommandArgumentData type_style_arg ;
type_style_arg . arg_type = eArgTypeName ;
type_style_arg . arg_repetition = eArgRepeatPlus ;
type_arg . push_back ( type_style_arg ) ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
m_arguments . push_back ( type_arg ) ;
}
~ CommandObjectTypeCategoryEnable ( ) override = default ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc < 1 & & m_options . m_language = = lldb : : eLanguageTypeUnknown ) {
result . AppendErrorWithFormat ( " %s takes arguments and/or a language " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( argc = = 1 & & strcmp ( command . GetArgumentAtIndex ( 0 ) , " * " ) = = 0 ) {
DataVisualization : : Categories : : EnableStar ( ) ;
} else if ( argc > 0 ) {
for ( int i = argc - 1 ; i > = 0 ; i - - ) {
const char * typeA = command . GetArgumentAtIndex ( i ) ;
ConstString typeCS ( typeA ) ;
if ( ! typeCS ) {
result . AppendError ( " empty category name not allowed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2015-12-30 06:55:28 -05:00
}
2017-01-02 14:26:05 -05:00
DataVisualization : : Categories : : Enable ( typeCS ) ;
lldb : : TypeCategoryImplSP cate ;
if ( DataVisualization : : Categories : : GetCategory ( typeCS , cate ) & & cate ) {
if ( cate - > GetCount ( ) = = 0 ) {
result . AppendWarning ( " empty category enabled (typo?) " ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( m_options . m_language ! = lldb : : eLanguageTypeUnknown )
DataVisualization : : Categories : : Enable ( m_options . m_language ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
2015-12-30 06:55:28 -05:00
// CommandObjectTypeCategoryDelete
2013-08-23 13:46:38 -04:00
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTypeCategoryDelete : public CommandObjectParsed {
2015-12-30 06:55:28 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeCategoryDelete ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " type category delete " ,
2016-07-23 16:50:09 -04:00
" Delete a category and all associated formatters. " ,
2017-01-02 14:26:05 -05:00
nullptr ) {
CommandArgumentEntry type_arg ;
CommandArgumentData type_style_arg ;
type_style_arg . arg_type = eArgTypeName ;
type_style_arg . arg_repetition = eArgRepeatPlus ;
type_arg . push_back ( type_style_arg ) ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
m_arguments . push_back ( type_arg ) ;
}
~ CommandObjectTypeCategoryDelete ( ) override = default ;
2016-07-23 16:50:09 -04:00
2015-12-30 06:55:28 -05:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc < 1 ) {
result . AppendErrorWithFormat ( " %s takes 1 or more arg. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2015-12-30 06:55:28 -05:00
}
2017-01-02 14:26:05 -05:00
bool success = true ;
// the order is not relevant here
for ( int i = argc - 1 ; i > = 0 ; i - - ) {
const char * typeA = command . GetArgumentAtIndex ( i ) ;
ConstString typeCS ( typeA ) ;
if ( ! typeCS ) {
result . AppendError ( " empty category name not allowed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( ! DataVisualization : : Categories : : Delete ( typeCS ) )
success = false ; // keep deleting even if we hit an error
}
if ( success ) {
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return result . Succeeded ( ) ;
} else {
result . AppendError ( " cannot delete one or more categories \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
2013-08-23 13:46:38 -04:00
} ;
2015-12-30 06:55:28 -05:00
//-------------------------------------------------------------------------
// CommandObjectTypeCategoryDisable
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
OptionDefinition g_type_category_disable_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " language " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLanguage , " Enable the category for this language. " }
// clang-format on
} ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
class CommandObjectTypeCategoryDisable : public CommandObjectParsed {
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' l ' :
if ( ! option_arg . empty ( ) ) {
m_language = Language : : GetLanguageTypeFromString ( option_arg ) ;
if ( m_language = = lldb : : eLanguageTypeUnknown )
error . SetErrorStringWithFormat ( " unrecognized language '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
}
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_language = lldb : : eLanguageTypeUnknown ;
}
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_type_category_disable_options ) ;
2013-08-23 13:46:38 -04:00
}
2015-12-30 06:55:28 -05:00
2017-01-02 14:26:05 -05:00
// Instance variables to hold the values for command options.
lldb : : LanguageType m_language ;
} ;
CommandOptions m_options ;
Options * GetOptions ( ) override { return & m_options ; }
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeCategoryDisable ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " type category disable " ,
2016-07-23 16:50:09 -04:00
" Disable a category as a source of formatters. " ,
nullptr ) ,
2017-01-02 14:26:05 -05:00
m_options ( ) {
CommandArgumentEntry type_arg ;
CommandArgumentData type_style_arg ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
type_style_arg . arg_type = eArgTypeName ;
type_style_arg . arg_repetition = eArgRepeatPlus ;
type_arg . push_back ( type_style_arg ) ;
m_arguments . push_back ( type_arg ) ;
}
~ CommandObjectTypeCategoryDisable ( ) override = default ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
const size_t argc = command . GetArgumentCount ( ) ;
2015-12-30 06:55:28 -05:00
2017-01-02 14:26:05 -05:00
if ( argc < 1 & & m_options . m_language = = lldb : : eLanguageTypeUnknown ) {
result . AppendErrorWithFormat ( " %s takes arguments and/or a language " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( argc = = 1 & & strcmp ( command . GetArgumentAtIndex ( 0 ) , " * " ) = = 0 ) {
DataVisualization : : Categories : : DisableStar ( ) ;
} else if ( argc > 0 ) {
// the order is not relevant here
for ( int i = argc - 1 ; i > = 0 ; i - - ) {
const char * typeA = command . GetArgumentAtIndex ( i ) ;
ConstString typeCS ( typeA ) ;
if ( ! typeCS ) {
result . AppendError ( " empty category name not allowed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
DataVisualization : : Categories : : Disable ( typeCS ) ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( m_options . m_language ! = lldb : : eLanguageTypeUnknown )
DataVisualization : : Categories : : Disable ( m_options . m_language ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectTypeCategoryList
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTypeCategoryList : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeCategoryList ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " type category list " ,
2016-07-23 16:50:09 -04:00
" Provide a list of all existing categories. " ,
2017-01-02 14:26:05 -05:00
nullptr ) {
CommandArgumentEntry type_arg ;
CommandArgumentData type_style_arg ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
type_style_arg . arg_type = eArgTypeName ;
type_style_arg . arg_repetition = eArgRepeatOptional ;
type_arg . push_back ( type_style_arg ) ;
m_arguments . push_back ( type_arg ) ;
}
~ CommandObjectTypeCategoryList ( ) override = default ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
const size_t argc = command . GetArgumentCount ( ) ;
std : : unique_ptr < RegularExpression > regex ;
if ( argc = = 1 ) {
regex . reset ( new RegularExpression ( ) ) ;
const char * arg = command . GetArgumentAtIndex ( 0 ) ;
if ( ! regex - > Compile ( llvm : : StringRef : : withNullAsEmpty ( arg ) ) ) {
result . AppendErrorWithFormat (
" syntax error in category regular expression '%s' " , arg ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
} else if ( argc ! = 0 ) {
result . AppendErrorWithFormat ( " %s takes 0 or one arg. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
DataVisualization : : Categories : : ForEach (
[ & regex , & result ] ( const lldb : : TypeCategoryImplSP & category_sp ) - > bool {
if ( regex ) {
bool escape = true ;
if ( regex - > GetText ( ) = = category_sp - > GetName ( ) ) {
escape = false ;
} else if ( regex - > Execute ( llvm : : StringRef : : withNullAsEmpty (
category_sp - > GetName ( ) ) ) ) {
escape = false ;
2015-12-30 06:55:28 -05:00
}
2017-01-02 14:26:05 -05:00
if ( escape )
return true ;
}
result . GetOutputStream ( ) . Printf (
" Category: %s \n " , category_sp - > GetDescription ( ) . c_str ( ) ) ;
return true ;
2015-12-30 06:55:28 -05:00
} ) ;
2017-01-02 14:26:05 -05:00
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
return result . Succeeded ( ) ;
}
2015-12-30 06:55:28 -05:00
} ;
//-------------------------------------------------------------------------
// CommandObjectTypeFilterList
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTypeFilterList
: public CommandObjectTypeFormatterList < TypeFilterImpl > {
2015-12-30 06:55:28 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeFilterList ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterList ( interpreter , " type filter list " ,
" Show a list of current filters. " ) { }
2015-12-30 06:55:28 -05:00
} ;
# ifndef LLDB_DISABLE_PYTHON
//-------------------------------------------------------------------------
// CommandObjectTypeSynthList
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTypeSynthList
: public CommandObjectTypeFormatterList < SyntheticChildren > {
2015-12-30 06:55:28 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeSynthList ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterList (
interpreter , " type synthetic list " ,
" Show a list of current synthetic providers. " ) { }
2015-12-30 06:55:28 -05:00
} ;
2016-07-23 16:50:09 -04:00
# endif // LLDB_DISABLE_PYTHON
2015-12-30 06:55:28 -05:00
//-------------------------------------------------------------------------
// CommandObjectTypeFilterDelete
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeFilterDelete ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterDelete (
interpreter ,
eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter ,
" type filter delete " , " Delete an existing filter for a type. " ) { }
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTypeFilterDelete ( ) override = default ;
2015-12-30 06:55:28 -05:00
} ;
# ifndef LLDB_DISABLE_PYTHON
//-------------------------------------------------------------------------
// CommandObjectTypeSynthDelete
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
2015-12-30 06:55:28 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeSynthDelete ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterDelete (
interpreter ,
eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth ,
" type synthetic delete " ,
" Delete an existing synthetic provider for a type. " ) { }
~ CommandObjectTypeSynthDelete ( ) override = default ;
2013-08-23 13:46:38 -04:00
} ;
2016-07-23 16:50:09 -04:00
# endif // LLDB_DISABLE_PYTHON
2015-12-30 06:55:28 -05:00
//-------------------------------------------------------------------------
// CommandObjectTypeFilterClear
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
2015-12-30 06:55:28 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeFilterClear ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterClear (
interpreter ,
eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter ,
" type filter clear " , " Delete all existing filter. " ) { }
2013-08-23 13:46:38 -04:00
} ;
2015-12-30 06:55:28 -05:00
# ifndef LLDB_DISABLE_PYTHON
//-------------------------------------------------------------------------
// CommandObjectTypeSynthClear
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear {
2015-12-30 06:55:28 -05:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeSynthClear ( CommandInterpreter & interpreter )
: CommandObjectTypeFormatterClear (
interpreter ,
eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth ,
" type synthetic clear " ,
" Delete all existing synthetic providers. " ) { }
2015-12-30 06:55:28 -05:00
} ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
bool CommandObjectTypeSynthAdd : : Execute_HandwritePython (
Args & command , CommandReturnObject & result ) {
SynthAddOptions * options = new SynthAddOptions (
m_options . m_skip_pointers , m_options . m_skip_references ,
m_options . m_cascade , m_options . m_regex , m_options . m_category ) ;
for ( auto & entry : command . entries ( ) ) {
if ( entry . ref . empty ( ) ) {
result . AppendError ( " empty typenames not allowed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
options - > m_target_types < < entry . ref ;
}
m_interpreter . GetPythonCommandsFromIOHandler (
" " , // Prompt
* this , // IOHandlerDelegate
true , // Run IOHandler in async mode
options ) ; // Baton for the "io_handler" that will be passed back into our
// IOHandlerDelegate functions
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return result . Succeeded ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
bool CommandObjectTypeSynthAdd : : Execute_PythonClass (
Args & command , CommandReturnObject & result ) {
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc < 1 ) {
result . AppendErrorWithFormat ( " %s takes one or more args. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( m_options . m_class_name . empty ( ) & & ! m_options . m_input_python ) {
result . AppendErrorWithFormat ( " %s needs either a Python class name or -P to "
" directly input Python code. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
SyntheticChildrenSP entry ;
ScriptedSyntheticChildren * impl = new ScriptedSyntheticChildren (
SyntheticChildren : : Flags ( )
. SetCascades ( m_options . m_cascade )
. SetSkipPointers ( m_options . m_skip_pointers )
. SetSkipReferences ( m_options . m_skip_references ) ,
m_options . m_class_name . c_str ( ) ) ;
entry . reset ( impl ) ;
ScriptInterpreter * interpreter = m_interpreter . GetScriptInterpreter ( ) ;
if ( interpreter & &
! interpreter - > CheckObjectExists ( impl - > GetPythonClassName ( ) ) )
result . AppendWarning ( " The provided class does not exist - please define it "
" before attempting to use this synthetic provider " ) ;
// now I have a valid provider, let's add it to every type
lldb : : TypeCategoryImplSP category ;
DataVisualization : : Categories : : GetCategory (
ConstString ( m_options . m_category . c_str ( ) ) , category ) ;
Error error ;
for ( auto & arg_entry : command . entries ( ) ) {
if ( arg_entry . ref . empty ( ) ) {
result . AppendError ( " empty typenames not allowed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
ConstString typeCS ( arg_entry . ref ) ;
if ( ! AddSynth ( typeCS , entry ,
m_options . m_regex ? eRegexSynth : eRegularSynth ,
m_options . m_category , & error ) ) {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return result . Succeeded ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
CommandObjectTypeSynthAdd : : CommandObjectTypeSynthAdd (
CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " type synthetic add " ,
" Add a new synthetic provider for a type. " , nullptr ) ,
IOHandlerDelegateMultiline ( " DONE " ) , m_options ( ) {
CommandArgumentEntry type_arg ;
CommandArgumentData type_style_arg ;
type_style_arg . arg_type = eArgTypeName ;
type_style_arg . arg_repetition = eArgRepeatPlus ;
type_arg . push_back ( type_style_arg ) ;
m_arguments . push_back ( type_arg ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
bool CommandObjectTypeSynthAdd : : AddSynth ( ConstString type_name ,
SyntheticChildrenSP entry ,
SynthFormatType type ,
std : : string category_name ,
Error * error ) {
lldb : : TypeCategoryImplSP category ;
DataVisualization : : Categories : : GetCategory ( ConstString ( category_name . c_str ( ) ) ,
category ) ;
if ( type = = eRegularSynth ) {
if ( FixArrayTypeNameWithRegex ( type_name ) )
type = eRegexSynth ;
}
if ( category - > AnyMatches ( type_name , eFormatCategoryItemFilter |
eFormatCategoryItemRegexFilter ,
false ) ) {
if ( error )
error - > SetErrorStringWithFormat ( " cannot add synthetic for type %s when "
" filter is defined in same category! " ,
type_name . AsCString ( ) ) ;
return false ;
}
if ( type = = eRegexSynth ) {
RegularExpressionSP typeRX ( new RegularExpression ( ) ) ;
if ( ! typeRX - > Compile ( type_name . GetStringRef ( ) ) ) {
if ( error )
error - > SetErrorString (
" regex format error (maybe this is not really a regex?) " ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
category - > GetRegexTypeSyntheticsContainer ( ) - > Delete ( type_name ) ;
category - > GetRegexTypeSyntheticsContainer ( ) - > Add ( typeRX , entry ) ;
return true ;
} else {
category - > GetTypeSyntheticsContainer ( ) - > Add ( type_name , entry ) ;
return true ;
}
}
2013-08-23 13:46:38 -04:00
2016-07-23 16:50:09 -04:00
# endif // LLDB_DISABLE_PYTHON
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
static OptionDefinition g_type_filter_add_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " cascade " , ' C ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " If true, cascade through typedef chains. " } ,
{ LLDB_OPT_SET_ALL , false , " skip-pointers " , ' p ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Don't use this format for pointers-to-type objects. " } ,
{ LLDB_OPT_SET_ALL , false , " skip-references " , ' r ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Don't use this format for references-to-type objects. " } ,
{ LLDB_OPT_SET_ALL , false , " category " , ' w ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeName , " Add this to the given category instead of the default one. " } ,
{ LLDB_OPT_SET_ALL , false , " child " , ' c ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeExpressionPath , " Include this expression path in the synthetic view. " } ,
{ LLDB_OPT_SET_ALL , false , " regex " , ' x ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Type names are actually regular expressions. " }
// clang-format on
} ;
class CommandObjectTypeFilterAdd : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
private :
2017-01-02 14:26:05 -05:00
class CommandOptions : public Options {
typedef std : : vector < std : : string > option_vector ;
public :
CommandOptions ( ) : Options ( ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
bool success ;
switch ( short_option ) {
case ' C ' :
m_cascade = Args : : StringToBoolean ( option_arg , true , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " invalid value for cascade: %s " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' c ' :
m_expr_paths . push_back ( option_arg ) ;
has_child_list = true ;
break ;
case ' p ' :
m_skip_pointers = true ;
break ;
case ' r ' :
m_skip_references = true ;
break ;
case ' w ' :
m_category = std : : string ( option_arg ) ;
break ;
case ' x ' :
m_regex = true ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
}
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_cascade = true ;
m_skip_pointers = false ;
m_skip_references = false ;
m_category = " default " ;
m_expr_paths . clear ( ) ;
has_child_list = false ;
m_regex = false ;
}
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_type_filter_add_options ) ;
}
// Instance variables to hold the values for command options.
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
bool m_cascade ;
bool m_skip_references ;
bool m_skip_pointers ;
bool m_input_python ;
option_vector m_expr_paths ;
std : : string m_category ;
bool has_child_list ;
bool m_regex ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
typedef option_vector : : iterator ExpressionPathsIterator ;
} ;
CommandOptions m_options ;
Options * GetOptions ( ) override { return & m_options ; }
enum FilterFormatType { eRegularFilter , eRegexFilter } ;
bool AddFilter ( ConstString type_name , TypeFilterImplSP entry ,
FilterFormatType type , std : : string category_name ,
Error * error ) {
lldb : : TypeCategoryImplSP category ;
DataVisualization : : Categories : : GetCategory (
ConstString ( category_name . c_str ( ) ) , category ) ;
if ( type = = eRegularFilter ) {
if ( FixArrayTypeNameWithRegex ( type_name ) )
type = eRegexFilter ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( category - > AnyMatches ( type_name , eFormatCategoryItemSynth |
eFormatCategoryItemRegexSynth ,
false ) ) {
if ( error )
error - > SetErrorStringWithFormat ( " cannot add filter for type %s when "
" synthetic is defined in same "
" category! " ,
type_name . AsCString ( ) ) ;
return false ;
}
if ( type = = eRegexFilter ) {
RegularExpressionSP typeRX ( new RegularExpression ( ) ) ;
if ( ! typeRX - > Compile ( type_name . GetStringRef ( ) ) ) {
if ( error )
error - > SetErrorString (
" regex format error (maybe this is not really a regex?) " ) ;
return false ;
}
category - > GetRegexTypeFiltersContainer ( ) - > Delete ( type_name ) ;
category - > GetRegexTypeFiltersContainer ( ) - > Add ( typeRX , entry ) ;
return true ;
} else {
category - > GetTypeFiltersContainer ( ) - > Add ( type_name , entry ) ;
return true ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeFilterAdd ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " type filter add " ,
" Add a new filter for a type. " , nullptr ) ,
m_options ( ) {
CommandArgumentEntry type_arg ;
CommandArgumentData type_style_arg ;
type_style_arg . arg_type = eArgTypeName ;
type_style_arg . arg_repetition = eArgRepeatPlus ;
type_arg . push_back ( type_style_arg ) ;
m_arguments . push_back ( type_arg ) ;
SetHelpLong (
R " (
2015-09-06 10:32:30 -04:00
The following examples of ' type filter add ' refer to this code snippet for context :
class Foo {
int a ;
int b ;
int c ;
int d ;
int e ;
int f ;
int g ;
int h ;
int i ;
}
Foo my_foo ;
Adding a simple filter :
( lldb ) type filter add - - child a - - child g Foo
( lldb ) frame variable my_foo
2017-01-02 14:26:05 -05:00
) "
" Produces output where only a and g are displayed. Other children of my_foo \
( b , c , d , e , f , h and i ) are available by asking for them explicitly : "
R " (
2015-09-06 10:32:30 -04:00
( lldb ) frame variable my_foo . b my_foo . c my_foo . i
2017-01-02 14:26:05 -05:00
) "
" The formatting option --raw on frame variable bypasses the filter, showing \
all children of my_foo as if no filter was defined : "
R " (
2015-09-06 10:32:30 -04:00
2017-01-02 14:26:05 -05:00
( lldb ) frame variable my_foo - - raw ) " );
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectTypeFilterAdd ( ) override = default ;
2016-07-23 16:50:09 -04:00
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
const size_t argc = command . GetArgumentCount ( ) ;
if ( argc < 1 ) {
result . AppendErrorWithFormat ( " %s takes one or more args. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( m_options . m_expr_paths . empty ( ) ) {
result . AppendErrorWithFormat ( " %s needs one or more children. \n " ,
m_cmd_name . c_str ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
TypeFilterImplSP entry ( new TypeFilterImpl (
SyntheticChildren : : Flags ( )
. SetCascades ( m_options . m_cascade )
. SetSkipPointers ( m_options . m_skip_pointers )
. SetSkipReferences ( m_options . m_skip_references ) ) ) ;
// go through the expression paths
CommandOptions : : ExpressionPathsIterator begin ,
end = m_options . m_expr_paths . end ( ) ;
for ( begin = m_options . m_expr_paths . begin ( ) ; begin ! = end ; begin + + )
entry - > AddExpressionPath ( * begin ) ;
// now I have a valid provider, let's add it to every type
lldb : : TypeCategoryImplSP category ;
DataVisualization : : Categories : : GetCategory (
ConstString ( m_options . m_category . c_str ( ) ) , category ) ;
Error error ;
WarnOnPotentialUnquotedUnsignedType ( command , result ) ;
for ( auto & arg_entry : command . entries ( ) ) {
if ( arg_entry . ref . empty ( ) ) {
result . AppendError ( " empty typenames not allowed " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
ConstString typeCS ( arg_entry . ref ) ;
if ( ! AddFilter ( typeCS , entry ,
m_options . m_regex ? eRegexFilter : eRegularFilter ,
m_options . m_category , & error ) ) {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
2015-12-30 06:55:28 -05:00
//----------------------------------------------------------------------
// "type lookup"
//----------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
static OptionDefinition g_type_lookup_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " show-help " , ' h ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Display available help for types " } ,
{ LLDB_OPT_SET_ALL , false , " language " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLanguage , " Which language's types should the search scope be " }
// clang-format on
} ;
class CommandObjectTypeLookup : public CommandObjectRaw {
2015-12-30 06:55:28 -05:00
protected :
2017-01-02 14:26:05 -05:00
// this function is allowed to do a more aggressive job at guessing languages
// than the expression parser
// is comfortable with - so leave the original call alone and add one that is
// specific to type lookup
lldb : : LanguageType GuessLanguage ( StackFrame * frame ) {
lldb : : LanguageType lang_type = lldb : : eLanguageTypeUnknown ;
if ( ! frame )
return lang_type ;
lang_type = frame - > GuessLanguage ( ) ;
if ( lang_type ! = lldb : : eLanguageTypeUnknown )
return lang_type ;
Symbol * s = frame - > GetSymbolContext ( eSymbolContextSymbol ) . symbol ;
if ( s )
lang_type = s - > GetMangled ( ) . GuessLanguage ( ) ;
return lang_type ;
}
class CommandOptions : public OptionGroup {
public :
CommandOptions ( )
: OptionGroup ( ) , m_show_help ( false ) , m_language ( eLanguageTypeUnknown ) { }
~ CommandOptions ( ) override = default ;
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_type_lookup_options ) ;
2015-12-30 06:55:28 -05:00
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
Error SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_value ,
ExecutionContext * execution_context ) override {
Error error ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
const int short_option = g_type_lookup_options [ option_idx ] . short_option ;
switch ( short_option ) {
case ' h ' :
m_show_help = true ;
break ;
case ' l ' :
m_language = Language : : GetLanguageTypeFromString ( option_value ) ;
break ;
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " ,
short_option ) ;
break ;
}
return error ;
2015-12-30 06:55:28 -05:00
}
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_show_help = false ;
m_language = eLanguageTypeUnknown ;
2016-07-23 16:50:09 -04:00
}
2017-01-02 14:26:05 -05:00
// Options table: Required for subclasses of Options.
bool m_show_help ;
lldb : : LanguageType m_language ;
} ;
OptionGroupOptions m_option_group ;
CommandOptions m_command_options ;
public :
CommandObjectTypeLookup ( CommandInterpreter & interpreter )
: CommandObjectRaw ( interpreter , " type lookup " ,
" Lookup types and declarations in the current target, "
" following language-specific naming conventions. " ,
" type lookup <type-specifier> " ,
eCommandRequiresTarget ) ,
m_option_group ( ) , m_command_options ( ) {
m_option_group . Append ( & m_command_options ) ;
m_option_group . Finalize ( ) ;
}
~ CommandObjectTypeLookup ( ) override = default ;
Options * GetOptions ( ) override { return & m_option_group ; }
llvm : : StringRef GetHelpLong ( ) override {
if ( ! m_cmd_help_long . empty ( ) )
return m_cmd_help_long ;
StreamString stream ;
// FIXME: hardcoding languages is not good
lldb : : LanguageType languages [ ] = { eLanguageTypeObjC ,
eLanguageTypeC_plus_plus } ;
for ( const auto lang_type : languages ) {
if ( auto language = Language : : FindPlugin ( lang_type ) ) {
if ( const char * help = language - > GetLanguageSpecificTypeLookupHelp ( ) ) {
stream . Printf ( " %s \n " , help ) ;
}
}
}
m_cmd_help_long = stream . GetString ( ) ;
return m_cmd_help_long ;
}
bool DoExecute ( const char * raw_command_line ,
CommandReturnObject & result ) override {
if ( ! raw_command_line | | ! raw_command_line [ 0 ] ) {
result . SetError (
" type lookup cannot be invoked without a type name as argument " ) ;
return false ;
}
auto exe_ctx = GetCommandInterpreter ( ) . GetExecutionContext ( ) ;
m_option_group . NotifyOptionParsingStarting ( & exe_ctx ) ;
const char * name_of_type = nullptr ;
if ( raw_command_line [ 0 ] = = ' - ' ) {
// We have some options and these options MUST end with --.
const char * end_options = nullptr ;
const char * s = raw_command_line ;
while ( s & & s [ 0 ] ) {
end_options = : : strstr ( s , " -- " ) ;
if ( end_options ) {
end_options + = 2 ; // Get past the "--"
if ( : : isspace ( end_options [ 0 ] ) ) {
name_of_type = end_options ;
while ( : : isspace ( * name_of_type ) )
+ + name_of_type ;
break ;
}
}
s = end_options ;
}
if ( end_options ) {
Args args (
llvm : : StringRef ( raw_command_line , end_options - raw_command_line ) ) ;
if ( ! ParseOptions ( args , result ) )
return false ;
Error error ( m_option_group . NotifyOptionParsingFinished ( & exe_ctx ) ) ;
if ( error . Fail ( ) ) {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
}
if ( nullptr = = name_of_type )
name_of_type = raw_command_line ;
// TargetSP
// target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());
// const bool fill_all_in = true;
// ExecutionContext exe_ctx(target_sp.get(), fill_all_in);
ExecutionContextScope * best_scope = exe_ctx . GetBestExecutionContextScope ( ) ;
bool any_found = false ;
std : : vector < Language * > languages ;
bool is_global_search = false ;
LanguageType guessed_language = lldb : : eLanguageTypeUnknown ;
if ( ( is_global_search =
( m_command_options . m_language = = eLanguageTypeUnknown ) ) ) {
// FIXME: hardcoding languages is not good
languages . push_back ( Language : : FindPlugin ( eLanguageTypeObjC ) ) ;
languages . push_back ( Language : : FindPlugin ( eLanguageTypeC_plus_plus ) ) ;
} else {
languages . push_back ( Language : : FindPlugin ( m_command_options . m_language ) ) ;
}
// This is not the most efficient way to do this, but we support very few
// languages
// so the cost of the sort is going to be dwarfed by the actual lookup
// anyway
if ( StackFrame * frame = m_exe_ctx . GetFramePtr ( ) ) {
guessed_language = GuessLanguage ( frame ) ;
if ( guessed_language ! = eLanguageTypeUnknown ) {
std : : sort (
languages . begin ( ) , languages . end ( ) ,
[ guessed_language ] ( Language * lang1 , Language * lang2 ) - > bool {
if ( ! lang1 | | ! lang2 )
return false ;
LanguageType lt1 = lang1 - > GetLanguageType ( ) ;
LanguageType lt2 = lang2 - > GetLanguageType ( ) ;
if ( lt1 = = guessed_language )
return true ; // make the selected frame's language come first
if ( lt2 = = guessed_language )
return false ; // make the selected frame's language come first
return ( lt1 < lt2 ) ; // normal comparison otherwise
} ) ;
}
2015-12-30 06:55:28 -05:00
}
2017-01-02 14:26:05 -05:00
bool is_first_language = true ;
for ( Language * language : languages ) {
if ( ! language )
continue ;
if ( auto scavenger = language - > GetTypeScavenger ( ) ) {
Language : : TypeScavenger : : ResultSet search_results ;
if ( scavenger - > Find ( best_scope , name_of_type , search_results ) > 0 ) {
for ( const auto & search_result : search_results ) {
if ( search_result & & search_result - > IsValid ( ) ) {
any_found = true ;
search_result - > DumpToStream ( result . GetOutputStream ( ) ,
this - > m_command_options . m_show_help ) ;
}
}
}
}
// this is "type lookup SomeName" and we did find a match, so get out
if ( any_found & & is_global_search )
break ;
else if ( is_first_language & & is_global_search & &
guessed_language ! = lldb : : eLanguageTypeUnknown ) {
is_first_language = false ;
result . GetOutputStream ( ) . Printf (
" no type was found in the current language %s matching '%s'; "
" performing a global search across all languages \n " ,
Language : : GetNameForLanguageType ( guessed_language ) , name_of_type ) ;
}
}
if ( ! any_found )
result . AppendMessageWithFormat ( " no type was found matching '%s' \n " ,
name_of_type ) ;
result . SetStatus ( any_found ? lldb : : eReturnStatusSuccessFinishResult
: lldb : : eReturnStatusSuccessFinishNoResult ) ;
return true ;
}
2015-12-30 06:55:28 -05:00
} ;
2015-02-06 16:38:51 -05:00
template < typename FormatterType >
2017-01-02 14:26:05 -05:00
class CommandObjectFormatterInfo : public CommandObjectRaw {
2015-02-06 16:38:51 -05:00
public :
2017-01-02 14:26:05 -05:00
typedef std : : function < typename FormatterType : : SharedPointer ( ValueObject & ) >
DiscoveryFunction ;
CommandObjectFormatterInfo ( CommandInterpreter & interpreter ,
const char * formatter_name ,
DiscoveryFunction discovery_func )
: CommandObjectRaw ( interpreter , " " , " " , " " ,
eCommandRequiresFrame ) ,
m_formatter_name ( formatter_name ? formatter_name : " " ) ,
m_discovery_function ( discovery_func ) {
StreamString name ;
name . Printf ( " type %s info " , formatter_name ) ;
SetCommandName ( name . GetString ( ) ) ;
StreamString help ;
help . Printf ( " This command evaluates the provided expression and shows "
" which %s is applied to the resulting value (if any). " ,
formatter_name ) ;
SetHelp ( help . GetString ( ) ) ;
StreamString syntax ;
syntax . Printf ( " type %s info <expr> " , formatter_name ) ;
SetSyntax ( syntax . GetString ( ) ) ;
}
~ CommandObjectFormatterInfo ( ) override = default ;
2016-07-23 16:50:09 -04:00
2015-02-06 16:38:51 -05:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( const char * command , CommandReturnObject & result ) override {
TargetSP target_sp = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) ;
Thread * thread = GetDefaultThread ( ) ;
if ( ! thread ) {
result . AppendError ( " no default thread " ) ;
result . SetStatus ( lldb : : eReturnStatusFailed ) ;
return false ;
}
StackFrameSP frame_sp = thread - > GetSelectedFrame ( ) ;
ValueObjectSP result_valobj_sp ;
EvaluateExpressionOptions options ;
lldb : : ExpressionResults expr_result = target_sp - > EvaluateExpression (
command , frame_sp . get ( ) , result_valobj_sp , options ) ;
if ( expr_result = = eExpressionCompleted & & result_valobj_sp ) {
result_valobj_sp =
result_valobj_sp - > GetQualifiedRepresentationIfAvailable (
target_sp - > GetPreferDynamicValue ( ) ,
target_sp - > GetEnableSyntheticValue ( ) ) ;
typename FormatterType : : SharedPointer formatter_sp =
m_discovery_function ( * result_valobj_sp ) ;
if ( formatter_sp ) {
std : : string description ( formatter_sp - > GetDescription ( ) ) ;
result . AppendMessageWithFormat (
" %s applied to (%s) %s is: %s \n " , m_formatter_name . c_str ( ) ,
result_valobj_sp - > GetDisplayTypeName ( ) . AsCString ( " <unknown> " ) ,
command , description . c_str ( ) ) ;
result . SetStatus ( lldb : : eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendMessageWithFormat (
" no %s applies to (%s) %s \n " , m_formatter_name . c_str ( ) ,
result_valobj_sp - > GetDisplayTypeName ( ) . AsCString ( " <unknown> " ) ,
command ) ;
result . SetStatus ( lldb : : eReturnStatusSuccessFinishNoResult ) ;
}
return true ;
} else {
result . AppendError ( " failed to evaluate expression " ) ;
result . SetStatus ( lldb : : eReturnStatusFailed ) ;
return false ;
}
}
2015-02-06 16:38:51 -05:00
private :
2017-01-02 14:26:05 -05:00
std : : string m_formatter_name ;
DiscoveryFunction m_discovery_function ;
2015-02-06 16:38:51 -05:00
} ;
2017-01-02 14:26:05 -05:00
class CommandObjectTypeFormat : public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeFormat ( CommandInterpreter & interpreter )
: CommandObjectMultiword (
interpreter , " type format " ,
" Commands for customizing value display formats. " ,
" type format [<sub-command-options>] " ) {
LoadSubCommand (
" add " , CommandObjectSP ( new CommandObjectTypeFormatAdd ( interpreter ) ) ) ;
LoadSubCommand ( " clear " , CommandObjectSP (
new CommandObjectTypeFormatClear ( interpreter ) ) ) ;
LoadSubCommand ( " delete " , CommandObjectSP ( new CommandObjectTypeFormatDelete (
interpreter ) ) ) ;
LoadSubCommand (
" list " , CommandObjectSP ( new CommandObjectTypeFormatList ( interpreter ) ) ) ;
LoadSubCommand (
" info " , CommandObjectSP ( new CommandObjectFormatterInfo < TypeFormatImpl > (
interpreter , " format " ,
[ ] ( ValueObject & valobj ) - > TypeFormatImpl : : SharedPointer {
return valobj . GetValueFormat ( ) ;
} ) ) ) ;
}
~ CommandObjectTypeFormat ( ) override = default ;
2013-08-23 13:46:38 -04:00
} ;
# ifndef LLDB_DISABLE_PYTHON
2017-01-02 14:26:05 -05:00
class CommandObjectTypeSynth : public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeSynth ( CommandInterpreter & interpreter )
: CommandObjectMultiword (
interpreter , " type synthetic " ,
" Commands for operating on synthetic type representations. " ,
" type synthetic [<sub-command-options>] " ) {
LoadSubCommand ( " add " ,
CommandObjectSP ( new CommandObjectTypeSynthAdd ( interpreter ) ) ) ;
LoadSubCommand (
" clear " , CommandObjectSP ( new CommandObjectTypeSynthClear ( interpreter ) ) ) ;
LoadSubCommand ( " delete " , CommandObjectSP ( new CommandObjectTypeSynthDelete (
interpreter ) ) ) ;
LoadSubCommand (
" list " , CommandObjectSP ( new CommandObjectTypeSynthList ( interpreter ) ) ) ;
LoadSubCommand (
" info " ,
CommandObjectSP ( new CommandObjectFormatterInfo < SyntheticChildren > (
interpreter , " synthetic " ,
[ ] ( ValueObject & valobj ) - > SyntheticChildren : : SharedPointer {
return valobj . GetSyntheticChildren ( ) ;
} ) ) ) ;
}
~ CommandObjectTypeSynth ( ) override = default ;
2013-08-23 13:46:38 -04:00
} ;
2016-07-23 16:50:09 -04:00
# endif // LLDB_DISABLE_PYTHON
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
class CommandObjectTypeFilter : public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeFilter ( CommandInterpreter & interpreter )
: CommandObjectMultiword ( interpreter , " type filter " ,
" Commands for operating on type filters. " ,
" type synthetic [<sub-command-options>] " ) {
LoadSubCommand (
" add " , CommandObjectSP ( new CommandObjectTypeFilterAdd ( interpreter ) ) ) ;
LoadSubCommand ( " clear " , CommandObjectSP (
new CommandObjectTypeFilterClear ( interpreter ) ) ) ;
LoadSubCommand ( " delete " , CommandObjectSP ( new CommandObjectTypeFilterDelete (
interpreter ) ) ) ;
LoadSubCommand (
" list " , CommandObjectSP ( new CommandObjectTypeFilterList ( interpreter ) ) ) ;
}
~ CommandObjectTypeFilter ( ) override = default ;
2013-08-23 13:46:38 -04:00
} ;
2017-01-02 14:26:05 -05:00
class CommandObjectTypeCategory : public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeCategory ( CommandInterpreter & interpreter )
: CommandObjectMultiword ( interpreter , " type category " ,
" Commands for operating on type categories. " ,
" type category [<sub-command-options>] " ) {
LoadSubCommand (
" define " ,
CommandObjectSP ( new CommandObjectTypeCategoryDefine ( interpreter ) ) ) ;
LoadSubCommand (
" enable " ,
CommandObjectSP ( new CommandObjectTypeCategoryEnable ( interpreter ) ) ) ;
LoadSubCommand (
" disable " ,
CommandObjectSP ( new CommandObjectTypeCategoryDisable ( interpreter ) ) ) ;
LoadSubCommand (
" delete " ,
CommandObjectSP ( new CommandObjectTypeCategoryDelete ( interpreter ) ) ) ;
LoadSubCommand ( " list " , CommandObjectSP (
new CommandObjectTypeCategoryList ( interpreter ) ) ) ;
}
~ CommandObjectTypeCategory ( ) override = default ;
2013-08-23 13:46:38 -04:00
} ;
2017-01-02 14:26:05 -05:00
class CommandObjectTypeSummary : public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectTypeSummary ( CommandInterpreter & interpreter )
: CommandObjectMultiword (
interpreter , " type summary " ,
" Commands for editing variable summary display options. " ,
" type summary [<sub-command-options>] " ) {
LoadSubCommand (
" add " , CommandObjectSP ( new CommandObjectTypeSummaryAdd ( interpreter ) ) ) ;
LoadSubCommand ( " clear " , CommandObjectSP ( new CommandObjectTypeSummaryClear (
interpreter ) ) ) ;
LoadSubCommand ( " delete " , CommandObjectSP ( new CommandObjectTypeSummaryDelete (
interpreter ) ) ) ;
LoadSubCommand (
" list " , CommandObjectSP ( new CommandObjectTypeSummaryList ( interpreter ) ) ) ;
LoadSubCommand (
" info " , CommandObjectSP ( new CommandObjectFormatterInfo < TypeSummaryImpl > (
interpreter , " summary " ,
[ ] ( ValueObject & valobj ) - > TypeSummaryImpl : : SharedPointer {
return valobj . GetSummaryFormat ( ) ;
} ) ) ) ;
}
~ CommandObjectTypeSummary ( ) override = default ;
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectType
//-------------------------------------------------------------------------
2016-07-23 16:50:09 -04:00
CommandObjectType : : CommandObjectType ( CommandInterpreter & interpreter )
2017-01-02 14:26:05 -05:00
: CommandObjectMultiword ( interpreter , " type " ,
" Commands for operating on the type system. " ,
" type [<sub-command-options>] " ) {
LoadSubCommand ( " category " ,
CommandObjectSP ( new CommandObjectTypeCategory ( interpreter ) ) ) ;
LoadSubCommand ( " filter " ,
CommandObjectSP ( new CommandObjectTypeFilter ( interpreter ) ) ) ;
LoadSubCommand ( " format " ,
CommandObjectSP ( new CommandObjectTypeFormat ( interpreter ) ) ) ;
LoadSubCommand ( " summary " ,
CommandObjectSP ( new CommandObjectTypeSummary ( interpreter ) ) ) ;
2013-08-23 13:46:38 -04:00
# ifndef LLDB_DISABLE_PYTHON
2017-01-02 14:26:05 -05:00
LoadSubCommand ( " synthetic " ,
CommandObjectSP ( new CommandObjectTypeSynth ( interpreter ) ) ) ;
2016-07-23 16:50:09 -04:00
# endif // LLDB_DISABLE_PYTHON
2017-01-02 14:26:05 -05:00
LoadSubCommand ( " lookup " ,
CommandObjectSP ( new CommandObjectTypeLookup ( interpreter ) ) ) ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
CommandObjectType : : ~ CommandObjectType ( ) = default ;