2013-08-23 13:46:38 -04:00
//===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
// C++ Includes
// Other libraries and framework includes
2016-07-23 16:50:09 -04:00
# include "llvm/ADT/STLExtras.h"
# include "llvm/ADT/StringRef.h"
2013-08-23 13:46:38 -04:00
// Project includes
2016-07-23 16:50:09 -04:00
# include "CommandObjectExpression.h"
2017-01-02 14:26:05 -05:00
# include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
# include "lldb/Core/Debugger.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Core/Value.h"
# include "lldb/Core/ValueObjectVariable.h"
2013-11-06 11:48:53 -05:00
# include "lldb/DataFormatters/ValueObjectPrinter.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Expression/DWARFExpression.h"
2015-12-30 06:55:28 -05:00
# include "lldb/Expression/REPL.h"
2017-01-02 14:26:05 -05:00
# include "lldb/Expression/UserExpression.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Host/Host.h"
2015-02-08 20:44:09 -05:00
# include "lldb/Host/StringConvert.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Symbol/ObjectFile.h"
# include "lldb/Symbol/Variable.h"
2017-01-02 14:26:05 -05:00
# include "lldb/Target/Language.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Target/Process.h"
# include "lldb/Target/StackFrame.h"
# include "lldb/Target/Target.h"
# include "lldb/Target/Thread.h"
using namespace lldb ;
using namespace lldb_private ;
2017-01-02 14:26:05 -05:00
CommandObjectExpression : : CommandOptions : : CommandOptions ( ) : OptionGroup ( ) { }
2013-08-23 13:46:38 -04:00
2016-07-23 16:50:09 -04:00
CommandObjectExpression : : CommandOptions : : ~ CommandOptions ( ) = default ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
static OptionEnumValueElement g_description_verbosity_type [ ] = {
{ eLanguageRuntimeDescriptionDisplayVerbosityCompact , " compact " ,
" Only show the description string " } ,
{ eLanguageRuntimeDescriptionDisplayVerbosityFull , " full " ,
" Show the full output, including persistent variable's name and type " } ,
{ 0 , nullptr , nullptr } } ;
static OptionDefinition g_expression_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2 , false , " all-threads " , ' a ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Should we run all threads if the execution doesn't complete on one thread. " } ,
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2 , false , " ignore-breakpoints " , ' i ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Ignore breakpoint hits while running expressions " } ,
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2 , false , " timeout " , ' t ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeUnsignedInteger , " Timeout value (in microseconds) for running the expression. " } ,
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2 , false , " unwind-on-error " , ' u ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Clean up program state if the expression causes a crash, or raises a signal. "
" Note, unlike gdb hitting a breakpoint is controlled by another option (-i). " } ,
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2 , false , " debug " , ' g ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " When specified, debug the JIT code by setting a breakpoint on the first instruction "
" and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0). " } ,
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2 , false , " language " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLanguage , " Specifies the Language to use when parsing the expression. If not set the target.language "
" setting is used. " } ,
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2 , false , " apply-fixits " , ' X ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLanguage , " If true, simple fix-it hints will be automatically applied to the expression. " } ,
{ LLDB_OPT_SET_1 , false , " description-verbosity " , ' v ' , OptionParser : : eOptionalArgument , nullptr , g_description_verbosity_type , 0 , eArgTypeDescriptionVerbosity , " How verbose should the output of this expression be, if the object description is asked for. " } ,
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2 , false , " top-level " , ' p ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Interpret the expression as a complete translation unit, without injecting it into the local "
" context. Allows declaration of persistent, top-level entities without a $ prefix. " } ,
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2 , false , " allow-jit " , ' j ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Controls whether the expression can fall back to being JITted if it's not supported by "
" the interpreter (defaults to true). " }
// clang-format on
2013-08-23 13:46:38 -04:00
} ;
2017-01-02 14:26:05 -05:00
Error CommandObjectExpression : : CommandOptions : : SetOptionValue (
uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) {
Error error ;
const int short_option = GetDefinitions ( ) [ option_idx ] . short_option ;
switch ( short_option ) {
case ' l ' :
language = Language : : GetLanguageTypeFromString ( option_arg ) ;
if ( language = = eLanguageTypeUnknown )
error . SetErrorStringWithFormat (
" unknown language type: '%s' for expression " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' a ' : {
bool success ;
bool result ;
result = Args : : StringToBoolean ( option_arg , true , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat (
" invalid all-threads value setting: \" %s \" " ,
option_arg . str ( ) . c_str ( ) ) ;
else
try_all_threads = result ;
} break ;
case ' i ' : {
bool success ;
bool tmp_value = Args : : StringToBoolean ( option_arg , true , & success ) ;
if ( success )
ignore_breakpoints = tmp_value ;
else
error . SetErrorStringWithFormat (
" could not convert \" %s \" to a boolean value. " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
}
case ' j ' : {
bool success ;
bool tmp_value = Args : : StringToBoolean ( option_arg , true , & success ) ;
if ( success )
allow_jit = tmp_value ;
else
error . SetErrorStringWithFormat (
" could not convert \" %s \" to a boolean value. " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
}
case ' t ' :
if ( option_arg . getAsInteger ( 0 , timeout ) ) {
timeout = 0 ;
error . SetErrorStringWithFormat ( " invalid timeout setting \" %s \" " ,
option_arg . str ( ) . c_str ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
break ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
case ' u ' : {
bool success ;
bool tmp_value = Args : : StringToBoolean ( option_arg , true , & success ) ;
if ( success )
unwind_on_error = tmp_value ;
2013-08-23 13:46:38 -04:00
else
2017-01-02 14:26:05 -05:00
error . SetErrorStringWithFormat (
" could not convert \" %s \" to a boolean value. " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
}
case ' v ' :
if ( option_arg . empty ( ) ) {
m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull ;
break ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
m_verbosity =
( LanguageRuntimeDescriptionDisplayVerbosity ) Args : : StringToOptionEnum (
option_arg , GetDefinitions ( ) [ option_idx ] . enum_values , 0 , error ) ;
if ( ! error . Success ( ) )
error . SetErrorStringWithFormat (
" unrecognized value for description-verbosity '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
case ' g ' :
debug = true ;
unwind_on_error = false ;
ignore_breakpoints = false ;
break ;
case ' p ' :
top_level = true ;
break ;
case ' X ' : {
bool success ;
bool tmp_value = Args : : StringToBoolean ( option_arg , true , & success ) ;
if ( success )
auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo ;
else
error . SetErrorStringWithFormat (
" could not convert \" %s \" to a boolean value. " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
}
default :
error . SetErrorStringWithFormat ( " invalid short option character '%c' " ,
short_option ) ;
break ;
}
return error ;
}
void CommandObjectExpression : : CommandOptions : : OptionParsingStarting (
ExecutionContext * execution_context ) {
auto process_sp =
execution_context ? execution_context - > GetProcessSP ( ) : ProcessSP ( ) ;
if ( process_sp ) {
ignore_breakpoints = process_sp - > GetIgnoreBreakpointsInExpressions ( ) ;
unwind_on_error = process_sp - > GetUnwindOnErrorInExpressions ( ) ;
} else {
ignore_breakpoints = true ;
unwind_on_error = true ;
}
show_summary = true ;
try_all_threads = true ;
timeout = 0 ;
debug = false ;
language = eLanguageTypeUnknown ;
m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact ;
auto_apply_fixits = eLazyBoolCalculate ;
top_level = false ;
allow_jit = true ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition >
CommandObjectExpression : : CommandOptions : : GetDefinitions ( ) {
return llvm : : makeArrayRef ( g_expression_options ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
CommandObjectExpression : : CommandObjectExpression (
CommandInterpreter & interpreter )
2016-07-23 16:50:09 -04:00
: CommandObjectRaw (
2017-01-02 14:26:05 -05:00
interpreter , " expression " , " Evaluate an expression on the current "
" thread. Displays any returned value "
" with LLDB's default formatting. " ,
" " , eCommandProcessMustBePaused | eCommandTryTargetAPILock ) ,
2016-07-23 16:50:09 -04:00
IOHandlerDelegate ( IOHandlerDelegate : : Completion : : Expression ) ,
2017-01-02 14:26:05 -05:00
m_option_group ( ) , m_format_options ( eFormatDefault ) ,
m_repl_option ( LLDB_OPT_SET_1 , false , " repl " , ' r ' , " Drop into REPL " , false ,
true ) ,
m_command_options ( ) , m_expr_line_count ( 0 ) , m_expr_lines ( ) {
SetHelpLong (
R " (
2015-09-06 10:32:30 -04:00
Timeouts :
2017-01-02 14:26:05 -05:00
) "
" If the expression can be evaluated statically (without running code) then it will be. \
2015-09-06 10:32:30 -04:00
Otherwise , by default the expression will run on the current thread with a short timeout : \
currently .25 seconds . If it doesn ' t return in that time , the evaluation will be interrupted \
and resumed with all threads running . You can use the - a option to disable retrying on all \
2017-01-02 14:26:05 -05:00
threads . You can use the - t option to set a shorter timeout . "
R " (
2015-09-06 10:32:30 -04:00
User defined variables :
2017-01-02 14:26:05 -05:00
) "
" You can define your own variables for convenience or to be used in subsequent expressions. \
2015-09-06 10:32:30 -04:00
You define them the same way you would define variables in C . If the first character of \
your user defined variable is a $ , then the variable ' s value will be available in future \
2017-01-02 14:26:05 -05:00
expressions , otherwise it will just be available in the current expression . "
R " (
2015-09-06 10:32:30 -04:00
Continuing evaluation after a breakpoint :
2017-01-02 14:26:05 -05:00
) "
" If the \" -i false \" option is used, and execution is interrupted by a breakpoint hit, once \
2015-09-06 10:32:30 -04:00
you are done with your investigation , you can either remove the expression execution frames \
from the stack with \ " thread return -x \" or if you are still interested in the expression result \
you can issue the \ " continue \" command and the expression evaluation will complete and the \
expression result will be available using the \ " thread.completed-expression \" key in the thread \
2017-01-02 14:26:05 -05:00
format . "
R " (
2015-09-06 10:32:30 -04:00
Examples :
expr my_struct - > a = my_array [ 3 ]
expr - f bin - - ( index * 8 ) + 5
expr unsigned int $ foo = 5
2017-01-02 14:26:05 -05:00
expr char c [ ] = \ " foo \" ; c[0]) " ) ;
CommandArgumentEntry arg ;
CommandArgumentData expression_arg ;
// Define the first (and only) variant of this arg.
expression_arg . arg_type = eArgTypeExpression ;
expression_arg . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the argument
// entry.
arg . push_back ( expression_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
// Add the "--format" and "--gdb-format"
m_option_group . Append ( & m_format_options ,
OptionGroupFormat : : OPTION_GROUP_FORMAT |
OptionGroupFormat : : OPTION_GROUP_GDB_FMT ,
LLDB_OPT_SET_1 ) ;
m_option_group . Append ( & m_command_options ) ;
m_option_group . Append ( & m_varobj_options , LLDB_OPT_SET_ALL ,
LLDB_OPT_SET_1 | LLDB_OPT_SET_2 ) ;
m_option_group . Append ( & m_repl_option , LLDB_OPT_SET_ALL , LLDB_OPT_SET_3 ) ;
m_option_group . Finalize ( ) ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
CommandObjectExpression : : ~ CommandObjectExpression ( ) = default ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
Options * CommandObjectExpression : : GetOptions ( ) { return & m_option_group ; }
2013-08-23 13:46:38 -04:00
2016-07-23 16:50:09 -04:00
static lldb_private : : Error
2017-01-02 14:26:05 -05:00
CanBeUsedForElementCountPrinting ( ValueObject & valobj ) {
CompilerType type ( valobj . GetCompilerType ( ) ) ;
CompilerType pointee ;
if ( ! type . IsPointerType ( & pointee ) )
return Error ( " as it does not refer to a pointer " ) ;
if ( pointee . IsVoidType ( ) )
return Error ( " as it refers to a pointer to void " ) ;
return Error ( ) ;
2016-07-23 16:50:09 -04:00
}
2017-01-02 14:26:05 -05:00
bool CommandObjectExpression : : EvaluateExpression ( const char * expr ,
Stream * output_stream ,
Stream * error_stream ,
CommandReturnObject * result ) {
// Don't use m_exe_ctx as this might be called asynchronously
// after the command object DoExecute has finished when doing
// multi-line expression that use an input reader...
ExecutionContext exe_ctx ( m_interpreter . GetExecutionContext ( ) ) ;
Target * target = exe_ctx . GetTargetPtr ( ) ;
if ( ! target )
target = GetDummyTarget ( ) ;
if ( target ) {
lldb : : ValueObjectSP result_valobj_sp ;
bool keep_in_memory = true ;
StackFrame * frame = exe_ctx . GetFramePtr ( ) ;
EvaluateExpressionOptions options ;
options . SetCoerceToId ( m_varobj_options . use_objc ) ;
options . SetUnwindOnError ( m_command_options . unwind_on_error ) ;
options . SetIgnoreBreakpoints ( m_command_options . ignore_breakpoints ) ;
options . SetKeepInMemory ( keep_in_memory ) ;
options . SetUseDynamic ( m_varobj_options . use_dynamic ) ;
options . SetTryAllThreads ( m_command_options . try_all_threads ) ;
options . SetDebug ( m_command_options . debug ) ;
options . SetLanguage ( m_command_options . language ) ;
options . SetExecutionPolicy (
m_command_options . allow_jit
? EvaluateExpressionOptions : : default_execution_policy
: lldb_private : : eExecutionPolicyNever ) ;
bool auto_apply_fixits ;
if ( m_command_options . auto_apply_fixits = = eLazyBoolCalculate )
auto_apply_fixits = target - > GetEnableAutoApplyFixIts ( ) ;
else
auto_apply_fixits =
m_command_options . auto_apply_fixits = = eLazyBoolYes ? true : false ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
options . SetAutoApplyFixIts ( auto_apply_fixits ) ;
if ( m_command_options . top_level )
options . SetExecutionPolicy ( eExecutionPolicyTopLevel ) ;
// If there is any chance we are going to stop and want to see
// what went wrong with our expression, we should generate debug info
if ( ! m_command_options . ignore_breakpoints | |
! m_command_options . unwind_on_error )
options . SetGenerateDebugInfo ( true ) ;
if ( m_command_options . timeout > 0 )
options . SetTimeout ( std : : chrono : : microseconds ( m_command_options . timeout ) ) ;
2013-08-23 13:46:38 -04:00
else
2017-01-02 14:26:05 -05:00
options . SetTimeout ( llvm : : None ) ;
ExpressionResults success = target - > EvaluateExpression (
expr , frame , result_valobj_sp , options , & m_fixed_expression ) ;
// We only tell you about the FixIt if we applied it. The compiler errors
// will suggest the FixIt if it parsed.
if ( error_stream & & ! m_fixed_expression . empty ( ) & &
target - > GetEnableNotifyAboutFixIts ( ) ) {
if ( success = = eExpressionCompleted )
error_stream - > Printf (
" Fix-it applied, fixed expression was: \n %s \n " ,
m_fixed_expression . c_str ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( result_valobj_sp ) {
Format format = m_format_options . GetFormat ( ) ;
if ( result_valobj_sp - > GetError ( ) . Success ( ) ) {
if ( format ! = eFormatVoid ) {
if ( format ! = eFormatDefault )
result_valobj_sp - > SetFormat ( format ) ;
if ( m_varobj_options . elem_count > 0 ) {
Error error ( CanBeUsedForElementCountPrinting ( * result_valobj_sp ) ) ;
if ( error . Fail ( ) ) {
result - > AppendErrorWithFormat (
" expression cannot be used with --element-count %s \n " ,
error . AsCString ( " " ) ) ;
result - > SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
DumpValueObjectOptions options ( m_varobj_options . GetAsDumpOptions (
m_command_options . m_verbosity , format ) ) ;
options . SetVariableFormatDisplayLanguage (
result_valobj_sp - > GetPreferredDisplayLanguage ( ) ) ;
result_valobj_sp - > Dump ( * output_stream , options ) ;
2014-02-18 11:23:10 -05:00
2017-01-02 14:26:05 -05:00
if ( result )
result - > SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
} else {
if ( result_valobj_sp - > GetError ( ) . GetError ( ) = =
UserExpression : : kNoResult ) {
if ( format ! = eFormatVoid & &
m_interpreter . GetDebugger ( ) . GetNotifyVoid ( ) ) {
error_stream - > PutCString ( " (void) \n " ) ;
}
if ( result )
result - > SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
const char * error_cstr = result_valobj_sp - > GetError ( ) . AsCString ( ) ;
if ( error_cstr & & error_cstr [ 0 ] ) {
const size_t error_cstr_len = strlen ( error_cstr ) ;
const bool ends_with_newline =
error_cstr [ error_cstr_len - 1 ] = = ' \n ' ;
if ( strstr ( error_cstr , " error: " ) ! = error_cstr )
error_stream - > PutCString ( " error: " ) ;
error_stream - > Write ( error_cstr , error_cstr_len ) ;
if ( ! ends_with_newline )
error_stream - > EOL ( ) ;
} else {
error_stream - > PutCString ( " error: unknown error \n " ) ;
}
if ( result )
result - > SetStatus ( eReturnStatusFailed ) ;
}
}
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
} else {
error_stream - > Printf ( " error: invalid execution context for expression \n " ) ;
2016-07-23 16:50:09 -04:00
return false ;
2017-01-02 14:26:05 -05:00
}
return true ;
2014-02-18 11:23:10 -05:00
}
2017-01-02 14:26:05 -05:00
void CommandObjectExpression : : IOHandlerInputComplete ( IOHandler & io_handler ,
std : : string & line ) {
io_handler . SetIsDone ( true ) ;
// StreamSP output_stream =
// io_handler.GetDebugger().GetAsyncOutputStream();
// StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream();
StreamFileSP output_sp ( io_handler . GetOutputStreamFile ( ) ) ;
StreamFileSP error_sp ( io_handler . GetErrorStreamFile ( ) ) ;
EvaluateExpression ( line . c_str ( ) , output_sp . get ( ) , error_sp . get ( ) ) ;
if ( output_sp )
output_sp - > Flush ( ) ;
if ( error_sp )
error_sp - > Flush ( ) ;
2014-11-25 16:00:58 -05:00
}
2017-01-02 14:26:05 -05:00
bool CommandObjectExpression : : IOHandlerIsInputComplete ( IOHandler & io_handler ,
StringList & lines ) {
// An empty lines is used to indicate the end of input
const size_t num_lines = lines . GetSize ( ) ;
if ( num_lines > 0 & & lines [ num_lines - 1 ] . empty ( ) ) {
// Remove the last empty line from "lines" so it doesn't appear
// in our resulting input and return true to indicate we are done
// getting lines
lines . PopBack ( ) ;
return true ;
}
return false ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
void CommandObjectExpression : : GetMultilineExpression ( ) {
m_expr_lines . clear ( ) ;
m_expr_line_count = 0 ;
Debugger & debugger = GetCommandInterpreter ( ) . GetDebugger ( ) ;
bool color_prompt = debugger . GetUseColor ( ) ;
const bool multiple_lines = true ; // Get multiple lines
IOHandlerSP io_handler_sp (
new IOHandlerEditline ( debugger , IOHandler : : Type : : Expression ,
" lldb-expr " , // Name of input reader for history
llvm : : StringRef ( ) , // No prompt
llvm : : StringRef ( ) , // Continuation prompt
multiple_lines , color_prompt ,
1 , // Show line numbers starting at 1
* this ) ) ;
StreamFileSP output_sp ( io_handler_sp - > GetOutputStreamFile ( ) ) ;
if ( output_sp ) {
output_sp - > PutCString (
" Enter expressions, then terminate with an empty line to evaluate: \n " ) ;
output_sp - > Flush ( ) ;
}
debugger . PushIOHandler ( io_handler_sp ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
bool CommandObjectExpression : : DoExecute ( const char * command ,
CommandReturnObject & result ) {
m_fixed_expression . clear ( ) ;
auto exe_ctx = GetCommandInterpreter ( ) . GetExecutionContext ( ) ;
m_option_group . NotifyOptionParsingStarting ( & exe_ctx ) ;
const char * expr = nullptr ;
if ( command [ 0 ] = = ' \0 ' ) {
GetMultilineExpression ( ) ;
return result . Succeeded ( ) ;
}
if ( command [ 0 ] = = ' - ' ) {
// We have some options and these options MUST end with --.
const char * end_options = nullptr ;
const char * s = command ;
while ( s & & s [ 0 ] ) {
end_options = : : strstr ( s , " -- " ) ;
if ( end_options ) {
end_options + = 2 ; // Get past the "--"
if ( : : isspace ( end_options [ 0 ] ) ) {
expr = end_options ;
while ( : : isspace ( * expr ) )
+ + expr ;
break ;
}
}
s = end_options ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( end_options ) {
Args args ( llvm : : StringRef ( command , end_options - command ) ) ;
if ( ! ParseOptions ( args , result ) )
return false ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
Error error ( m_option_group . NotifyOptionParsingFinished ( & exe_ctx ) ) ;
if ( error . Fail ( ) ) {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( m_repl_option . GetOptionValue ( ) . GetCurrentValue ( ) ) {
Target * target = m_interpreter . GetExecutionContext ( ) . GetTargetPtr ( ) ;
if ( target ) {
// Drop into REPL
m_expr_lines . clear ( ) ;
m_expr_line_count = 0 ;
Debugger & debugger = target - > GetDebugger ( ) ;
// Check if the LLDB command interpreter is sitting on top of a REPL
// that
// launched it...
if ( debugger . CheckTopIOHandlerTypes (
IOHandler : : Type : : CommandInterpreter , IOHandler : : Type : : REPL ) ) {
// the LLDB command interpreter is sitting on top of a REPL that
// launched it,
// so just say the command interpreter is done and fall back to the
// existing REPL
m_interpreter . GetIOHandler ( false ) - > SetIsDone ( true ) ;
} else {
// We are launching the REPL on top of the current LLDB command
// interpreter,
// so just push one
bool initialize = false ;
Error repl_error ;
REPLSP repl_sp ( target - > GetREPL (
repl_error , m_command_options . language , nullptr , false ) ) ;
if ( ! repl_sp ) {
initialize = true ;
repl_sp = target - > GetREPL ( repl_error , m_command_options . language ,
nullptr , true ) ;
if ( ! repl_error . Success ( ) ) {
result . SetError ( repl_error ) ;
2014-11-25 16:00:58 -05:00
return result . Succeeded ( ) ;
2017-01-02 14:26:05 -05:00
}
2014-11-25 16:00:58 -05:00
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( repl_sp ) {
if ( initialize ) {
repl_sp - > SetCommandOptions ( m_command_options ) ;
repl_sp - > SetFormatOptions ( m_format_options ) ;
repl_sp - > SetValueObjectDisplayOptions ( m_varobj_options ) ;
}
IOHandlerSP io_handler_sp ( repl_sp - > GetIOHandler ( ) ) ;
io_handler_sp - > SetIsDone ( false ) ;
debugger . PushIOHandler ( io_handler_sp ) ;
} else {
repl_error . SetErrorStringWithFormat (
" Couldn't create a REPL for %s " ,
Language : : GetNameForLanguageType ( m_command_options . language ) ) ;
result . SetError ( repl_error ) ;
return result . Succeeded ( ) ;
2016-07-23 16:50:09 -04:00
}
2017-01-02 14:26:05 -05:00
}
2016-07-23 16:50:09 -04:00
}
2017-01-02 14:26:05 -05:00
}
// No expression following options
else if ( expr = = nullptr | | expr [ 0 ] = = ' \0 ' ) {
GetMultilineExpression ( ) ;
return result . Succeeded ( ) ;
}
2016-07-23 16:50:09 -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 ( expr = = nullptr )
expr = command ;
if ( EvaluateExpression ( expr , & ( result . GetOutputStream ( ) ) ,
& ( result . GetErrorStream ( ) ) , & result ) ) {
Target * target = m_interpreter . GetExecutionContext ( ) . GetTargetPtr ( ) ;
if ( ! target )
target = GetDummyTarget ( ) ;
if ( ! m_fixed_expression . empty ( ) & & target - > GetEnableNotifyAboutFixIts ( ) ) {
CommandHistory & history = m_interpreter . GetCommandHistory ( ) ;
// FIXME: Can we figure out what the user actually typed (e.g. some alias
// for expr???)
// If we can it would be nice to show that.
std : : string fixed_command ( " expression " ) ;
if ( expr = = command )
fixed_command . append ( m_fixed_expression ) ;
else {
// Add in any options that might have been in the original command:
fixed_command . append ( command , expr - command ) ;
fixed_command . append ( m_fixed_expression ) ;
}
history . AppendString ( fixed_command ) ;
}
return true ;
}
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}