130fdc8d8SChris Lattner //===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner // C Includes 1130fdc8d8SChris Lattner // C++ Includes 1230fdc8d8SChris Lattner // Other libraries and framework includes 13c8ecc2a9SEugene Zelenko #include "llvm/ADT/STLExtras.h" 14c8ecc2a9SEugene Zelenko #include "llvm/ADT/StringRef.h" 15c8ecc2a9SEugene Zelenko 1630fdc8d8SChris Lattner // Project includes 17c8ecc2a9SEugene Zelenko #include "CommandObjectExpression.h" 1830fdc8d8SChris Lattner #include "lldb/Core/Value.h" 196c68fb45SJim Ingham #include "lldb/Core/ValueObjectVariable.h" 204d93b8cdSEnrico Granata #include "lldb/DataFormatters/ValueObjectPrinter.h" 2130e33974SSean Callanan #include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" 22151c032cSJim Ingham #include "lldb/Expression/UserExpression.h" 2330fdc8d8SChris Lattner #include "lldb/Expression/DWARFExpression.h" 24f2bd5c3eSSean Callanan #include "lldb/Expression/REPL.h" 2530fdc8d8SChris Lattner #include "lldb/Host/Host.h" 265275aaa0SVince Harron #include "lldb/Host/StringConvert.h" 27ebf7707eSSean Callanan #include "lldb/Core/Debugger.h" 286611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 2930fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 300e0984eeSJim Ingham #include "lldb/Target/Language.h" 3130fdc8d8SChris Lattner #include "lldb/Symbol/ObjectFile.h" 3230fdc8d8SChris Lattner #include "lldb/Symbol/Variable.h" 3330fdc8d8SChris Lattner #include "lldb/Target/Process.h" 34b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 3530fdc8d8SChris Lattner #include "lldb/Target/Target.h" 367260f620SGreg Clayton #include "lldb/Target/Thread.h" 3730fdc8d8SChris Lattner 3830fdc8d8SChris Lattner using namespace lldb; 3930fdc8d8SChris Lattner using namespace lldb_private; 4030fdc8d8SChris Lattner 411deb7962SGreg Clayton CommandObjectExpression::CommandOptions::CommandOptions () : 421deb7962SGreg Clayton OptionGroup() 4330fdc8d8SChris Lattner { 4430fdc8d8SChris Lattner } 4530fdc8d8SChris Lattner 46c8ecc2a9SEugene Zelenko CommandObjectExpression::CommandOptions::~CommandOptions() = default; 4730fdc8d8SChris Lattner 484d93b8cdSEnrico Granata static OptionEnumValueElement g_description_verbosity_type[] = 494d93b8cdSEnrico Granata { 504d93b8cdSEnrico Granata { eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", "Only show the description string"}, 514d93b8cdSEnrico Granata { eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", "Show the full output, including persistent variable's name and type"}, 52c8ecc2a9SEugene Zelenko { 0, nullptr, nullptr } 534d93b8cdSEnrico Granata }; 544d93b8cdSEnrico Granata 551deb7962SGreg Clayton OptionDefinition 561deb7962SGreg Clayton CommandObjectExpression::CommandOptions::g_option_table[] = 571deb7962SGreg Clayton { 58c8ecc2a9SEugene Zelenko { 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."}, 59c8ecc2a9SEugene Zelenko { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, 60c8ecc2a9SEugene Zelenko { 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."}, 61c8ecc2a9SEugene Zelenko { 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)."}, 62c8ecc2a9SEugene Zelenko { 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)."}, 63c8ecc2a9SEugene Zelenko { 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." }, 64a1e541bfSJim Ingham { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "If true, simple FixIt hints will be automatically applied to the expression." }, 65c8ecc2a9SEugene Zelenko { 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."}, 66863fab69SSean Callanan { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Interpret the expression as top-level definitions rather than code to be immediately executed."} 671deb7962SGreg Clayton }; 681deb7962SGreg Clayton 691deb7962SGreg Clayton uint32_t 701deb7962SGreg Clayton CommandObjectExpression::CommandOptions::GetNumDefinitions () 711deb7962SGreg Clayton { 7228606954SSaleem Abdulrasool return llvm::array_lengthof(g_option_table); 731deb7962SGreg Clayton } 741deb7962SGreg Clayton 7530fdc8d8SChris Lattner Error 761deb7962SGreg Clayton CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &interpreter, 771deb7962SGreg Clayton uint32_t option_idx, 781deb7962SGreg Clayton const char *option_arg) 7930fdc8d8SChris Lattner { 8030fdc8d8SChris Lattner Error error; 8130fdc8d8SChris Lattner 823bcdfc0eSGreg Clayton const int short_option = g_option_table[option_idx].short_option; 8330fdc8d8SChris Lattner 8430fdc8d8SChris Lattner switch (short_option) 8530fdc8d8SChris Lattner { 8615663c53SDawn Perchik case 'l': 870e0984eeSJim Ingham language = Language::GetLanguageTypeFromString (option_arg); 8815663c53SDawn Perchik if (language == eLanguageTypeUnknown) 8915663c53SDawn Perchik error.SetErrorStringWithFormat ("unknown language type: '%s' for expression", option_arg); 9015663c53SDawn Perchik break; 9130fdc8d8SChris Lattner 9235e1bda6SJim Ingham case 'a': 9335e1bda6SJim Ingham { 9435e1bda6SJim Ingham bool success; 9535e1bda6SJim Ingham bool result; 9635e1bda6SJim Ingham result = Args::StringToBoolean(option_arg, true, &success); 9735e1bda6SJim Ingham if (!success) 9835e1bda6SJim Ingham error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg); 9935e1bda6SJim Ingham else 10035e1bda6SJim Ingham try_all_threads = result; 10135e1bda6SJim Ingham } 1026c68fb45SJim Ingham break; 1036c68fb45SJim Ingham 104184e9811SJim Ingham case 'i': 105184e9811SJim Ingham { 106184e9811SJim Ingham bool success; 107184e9811SJim Ingham bool tmp_value = Args::StringToBoolean(option_arg, true, &success); 108184e9811SJim Ingham if (success) 109184e9811SJim Ingham ignore_breakpoints = tmp_value; 110184e9811SJim Ingham else 111184e9811SJim Ingham error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); 112184e9811SJim Ingham break; 113184e9811SJim Ingham } 11435e1bda6SJim Ingham case 't': 11535e1bda6SJim Ingham { 11635e1bda6SJim Ingham bool success; 11735e1bda6SJim Ingham uint32_t result; 1185275aaa0SVince Harron result = StringConvert::ToUInt32(option_arg, 0, 0, &success); 11935e1bda6SJim Ingham if (success) 12035e1bda6SJim Ingham timeout = result; 12135e1bda6SJim Ingham else 12235e1bda6SJim Ingham error.SetErrorStringWithFormat ("invalid timeout setting \"%s\"", option_arg); 12335e1bda6SJim Ingham } 12435e1bda6SJim Ingham break; 12535e1bda6SJim Ingham 126399f1cafSJim Ingham case 'u': 1273bfdaa2aSSean Callanan { 128399f1cafSJim Ingham bool success; 129184e9811SJim Ingham bool tmp_value = Args::StringToBoolean(option_arg, true, &success); 130184e9811SJim Ingham if (success) 131184e9811SJim Ingham unwind_on_error = tmp_value; 132184e9811SJim Ingham else 13386edbf41SGreg Clayton error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); 134399f1cafSJim Ingham break; 1353bfdaa2aSSean Callanan } 1364d93b8cdSEnrico Granata 1374d93b8cdSEnrico Granata case 'v': 1384d93b8cdSEnrico Granata if (!option_arg) 1394d93b8cdSEnrico Granata { 1404d93b8cdSEnrico Granata m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull; 1414d93b8cdSEnrico Granata break; 1424d93b8cdSEnrico Granata } 1434d93b8cdSEnrico Granata m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); 1444d93b8cdSEnrico Granata if (!error.Success()) 1454d93b8cdSEnrico Granata error.SetErrorStringWithFormat ("unrecognized value for description-verbosity '%s'", option_arg); 1464d93b8cdSEnrico Granata break; 1474d93b8cdSEnrico Granata 14862afb9f6SGreg Clayton case 'g': 14962afb9f6SGreg Clayton debug = true; 15062afb9f6SGreg Clayton unwind_on_error = false; 15162afb9f6SGreg Clayton ignore_breakpoints = false; 15262afb9f6SGreg Clayton break; 15362afb9f6SGreg Clayton 154863fab69SSean Callanan case 'p': 155863fab69SSean Callanan top_level = true; 156863fab69SSean Callanan break; 157863fab69SSean Callanan 158a1e541bfSJim Ingham case 'X': 159a1e541bfSJim Ingham { 160a1e541bfSJim Ingham bool success; 161a1e541bfSJim Ingham bool tmp_value = Args::StringToBoolean(option_arg, true, &success); 162a1e541bfSJim Ingham if (success) 163a1e541bfSJim Ingham auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo; 164a1e541bfSJim Ingham else 165a1e541bfSJim Ingham error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); 166a1e541bfSJim Ingham break; 167a1e541bfSJim Ingham } 168a1e541bfSJim Ingham 16930fdc8d8SChris Lattner default: 17086edbf41SGreg Clayton error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 17130fdc8d8SChris Lattner break; 17230fdc8d8SChris Lattner } 17330fdc8d8SChris Lattner 17430fdc8d8SChris Lattner return error; 17530fdc8d8SChris Lattner } 17630fdc8d8SChris Lattner 17730fdc8d8SChris Lattner void 1781deb7962SGreg Clayton CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter) 17930fdc8d8SChris Lattner { 180184e9811SJim Ingham Process *process = interpreter.GetExecutionContext().GetProcessPtr(); 181c8ecc2a9SEugene Zelenko if (process != nullptr) 182184e9811SJim Ingham { 183184e9811SJim Ingham ignore_breakpoints = process->GetIgnoreBreakpointsInExpressions(); 184184e9811SJim Ingham unwind_on_error = process->GetUnwindOnErrorInExpressions(); 185184e9811SJim Ingham } 186184e9811SJim Ingham else 187184e9811SJim Ingham { 188fc03f8fcSGreg Clayton ignore_breakpoints = true; 189399f1cafSJim Ingham unwind_on_error = true; 190184e9811SJim Ingham } 191184e9811SJim Ingham 19230fdc8d8SChris Lattner show_summary = true; 19335e1bda6SJim Ingham try_all_threads = true; 19435e1bda6SJim Ingham timeout = 0; 19562afb9f6SGreg Clayton debug = false; 19615663c53SDawn Perchik language = eLanguageTypeUnknown; 1974d93b8cdSEnrico Granata m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; 198a1e541bfSJim Ingham auto_apply_fixits = eLazyBoolCalculate; 199863fab69SSean Callanan top_level = false; 20030fdc8d8SChris Lattner } 20130fdc8d8SChris Lattner 202e0d378b3SGreg Clayton const OptionDefinition* 20330fdc8d8SChris Lattner CommandObjectExpression::CommandOptions::GetDefinitions () 20430fdc8d8SChris Lattner { 20530fdc8d8SChris Lattner return g_option_table; 20630fdc8d8SChris Lattner } 20730fdc8d8SChris Lattner 208a7015092SGreg Clayton CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) : 2095a988416SJim Ingham CommandObjectRaw(interpreter, 21030fdc8d8SChris Lattner "expression", 21115663c53SDawn Perchik "Evaluate an expression in the current program context, using user defined variables and variables currently in scope.", 212c8ecc2a9SEugene Zelenko nullptr, 213e87764f2SEnrico Granata eCommandProcessMustBePaused | eCommandTryTargetAPILock), 21444d93782SGreg Clayton IOHandlerDelegate (IOHandlerDelegate::Completion::Expression), 2151deb7962SGreg Clayton m_option_group (interpreter), 2161deb7962SGreg Clayton m_format_options (eFormatDefault), 217f2bd5c3eSSean Callanan m_repl_option (LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false, true), 2181deb7962SGreg Clayton m_command_options (), 21930fdc8d8SChris Lattner m_expr_line_count (0), 22030fdc8d8SChris Lattner m_expr_lines () 22130fdc8d8SChris Lattner { 22230fdc8d8SChris Lattner SetHelpLong( 223ea671fbdSKate Stone R"( 224ea671fbdSKate Stone Timeouts: 225ea671fbdSKate Stone 226ea671fbdSKate Stone )" " If the expression can be evaluated statically (without running code) then it will be. \ 227ea671fbdSKate Stone Otherwise, by default the expression will run on the current thread with a short timeout: \ 228ea671fbdSKate Stone currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted \ 229ea671fbdSKate Stone and resumed with all threads running. You can use the -a option to disable retrying on all \ 230ea671fbdSKate Stone threads. You can use the -t option to set a shorter timeout." R"( 231ea671fbdSKate Stone 232ea671fbdSKate Stone User defined variables: 233ea671fbdSKate Stone 234ea671fbdSKate Stone )" " You can define your own variables for convenience or to be used in subsequent expressions. \ 235ea671fbdSKate Stone You define them the same way you would define variables in C. If the first character of \ 236ea671fbdSKate Stone your user defined variable is a $, then the variable's value will be available in future \ 237ea671fbdSKate Stone expressions, otherwise it will just be available in the current expression." R"( 238ea671fbdSKate Stone 239ea671fbdSKate Stone Continuing evaluation after a breakpoint: 240ea671fbdSKate Stone 241ea671fbdSKate Stone )" " If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \ 242ea671fbdSKate Stone you are done with your investigation, you can either remove the expression execution frames \ 243ea671fbdSKate Stone from the stack with \"thread return -x\" or if you are still interested in the expression result \ 244ea671fbdSKate Stone you can issue the \"continue\" command and the expression evaluation will complete and the \ 245ea671fbdSKate Stone expression result will be available using the \"thread.completed-expression\" key in the thread \ 246ea671fbdSKate Stone format." R"( 247ea671fbdSKate Stone 248ea671fbdSKate Stone Examples: 249ea671fbdSKate Stone 250ea671fbdSKate Stone expr my_struct->a = my_array[3] 251ea671fbdSKate Stone expr -f bin -- (index * 8) + 5 252ea671fbdSKate Stone expr unsigned int $foo = 5 253ea671fbdSKate Stone expr char c[] = \"foo\"; c[0])" 254ea671fbdSKate Stone ); 255405fe67fSCaroline Tice 256405fe67fSCaroline Tice CommandArgumentEntry arg; 257405fe67fSCaroline Tice CommandArgumentData expression_arg; 258405fe67fSCaroline Tice 259405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 260405fe67fSCaroline Tice expression_arg.arg_type = eArgTypeExpression; 261405fe67fSCaroline Tice expression_arg.arg_repetition = eArgRepeatPlain; 262405fe67fSCaroline Tice 263405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 264405fe67fSCaroline Tice arg.push_back (expression_arg); 265405fe67fSCaroline Tice 266405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 267405fe67fSCaroline Tice m_arguments.push_back (arg); 2681deb7962SGreg Clayton 2695009f9d5SGreg Clayton // Add the "--format" and "--gdb-format" 2705009f9d5SGreg Clayton m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); 2711deb7962SGreg Clayton m_option_group.Append (&m_command_options); 272b576bba2SEnrico Granata m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2); 273f2bd5c3eSSean Callanan m_option_group.Append (&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); 2741deb7962SGreg Clayton m_option_group.Finalize(); 27530fdc8d8SChris Lattner } 27630fdc8d8SChris Lattner 277c8ecc2a9SEugene Zelenko CommandObjectExpression::~CommandObjectExpression() = default; 27830fdc8d8SChris Lattner 27930fdc8d8SChris Lattner Options * 28030fdc8d8SChris Lattner CommandObjectExpression::GetOptions () 28130fdc8d8SChris Lattner { 2821deb7962SGreg Clayton return &m_option_group; 28330fdc8d8SChris Lattner } 28430fdc8d8SChris Lattner 28530fdc8d8SChris Lattner bool 286c8ecc2a9SEugene Zelenko CommandObjectExpression::EvaluateExpression(const char *expr, 2876e8dc334SCaroline Tice Stream *output_stream, 2886e8dc334SCaroline Tice Stream *error_stream, 289c8ecc2a9SEugene Zelenko CommandReturnObject *result) 29030fdc8d8SChris Lattner { 291ba7b8e2cSGreg Clayton // Don't use m_exe_ctx as this might be called asynchronously 292ba7b8e2cSGreg Clayton // after the command object DoExecute has finished when doing 293ba7b8e2cSGreg Clayton // multi-line expression that use an input reader... 294ba7b8e2cSGreg Clayton ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 295ba7b8e2cSGreg Clayton 296ba7b8e2cSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 297c0a6e061SSean Callanan 298c0a6e061SSean Callanan if (!target) 299893c932aSJim Ingham target = GetDummyTarget(); 300c0a6e061SSean Callanan 301c14ee32dSGreg Clayton if (target) 3026961e878SSean Callanan { 3038b2fe6dcSGreg Clayton lldb::ValueObjectSP result_valobj_sp; 30492adcac9SSean Callanan bool keep_in_memory = true; 305009d110dSDawn Perchik StackFrame *frame = exe_ctx.GetFramePtr(); 30692adcac9SSean Callanan 30735e1bda6SJim Ingham EvaluateExpressionOptions options; 3086fbc48bcSJim Ingham options.SetCoerceToId(m_varobj_options.use_objc); 3096fbc48bcSJim Ingham options.SetUnwindOnError(m_command_options.unwind_on_error); 3106fbc48bcSJim Ingham options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints); 3116fbc48bcSJim Ingham options.SetKeepInMemory(keep_in_memory); 3126fbc48bcSJim Ingham options.SetUseDynamic(m_varobj_options.use_dynamic); 3136fbc48bcSJim Ingham options.SetTryAllThreads(m_command_options.try_all_threads); 3146fbc48bcSJim Ingham options.SetDebug(m_command_options.debug); 31515663c53SDawn Perchik options.SetLanguage(m_command_options.language); 31615663c53SDawn Perchik 317a1e541bfSJim Ingham bool auto_apply_fixits; 318a1e541bfSJim Ingham if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) 319a1e541bfSJim Ingham auto_apply_fixits = target->GetEnableAutoApplyFixIts(); 320a1e541bfSJim Ingham else 321a1e541bfSJim Ingham auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes ? true : false; 322a1e541bfSJim Ingham 323a1e541bfSJim Ingham options.SetAutoApplyFixIts(auto_apply_fixits); 324a1e541bfSJim Ingham 325863fab69SSean Callanan if (m_command_options.top_level) 326863fab69SSean Callanan options.SetExecutionPolicy(eExecutionPolicyTopLevel); 327863fab69SSean Callanan 32823f8c95aSGreg Clayton // If there is any chance we are going to stop and want to see 32923f8c95aSGreg Clayton // what went wrong with our expression, we should generate debug info 33023f8c95aSGreg Clayton if (!m_command_options.ignore_breakpoints || 33123f8c95aSGreg Clayton !m_command_options.unwind_on_error) 33223f8c95aSGreg Clayton options.SetGenerateDebugInfo(true); 33323f8c95aSGreg Clayton 33462afb9f6SGreg Clayton if (m_command_options.timeout > 0) 33562afb9f6SGreg Clayton options.SetTimeoutUsec(m_command_options.timeout); 3366f78f386SJim Ingham else 3376f78f386SJim Ingham options.SetTimeoutUsec(0); 338d4439aa9SEnrico Granata 339*e5ee6f04SJim Ingham ExpressionResults success = target->EvaluateExpression(expr, frame, result_valobj_sp, options, &m_fixed_expression); 340*e5ee6f04SJim Ingham 341*e5ee6f04SJim Ingham // We only tell you about the FixIt if we applied it. The compiler errors will suggest the FixIt if it parsed. 342*e5ee6f04SJim Ingham if (error_stream && !m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts()) 343*e5ee6f04SJim Ingham { 344*e5ee6f04SJim Ingham if (success == eExpressionCompleted) 345*e5ee6f04SJim Ingham error_stream->Printf (" Fixit applied, fixed expression was: \n %s\n", m_fixed_expression.c_str()); 346*e5ee6f04SJim Ingham } 3478b2fe6dcSGreg Clayton 3488b2fe6dcSGreg Clayton if (result_valobj_sp) 3498b2fe6dcSGreg Clayton { 350bf154daeSSean Callanan Format format = m_format_options.GetFormat(); 351bf154daeSSean Callanan 352b71f3844SGreg Clayton if (result_valobj_sp->GetError().Success()) 35330fdc8d8SChris Lattner { 354bf154daeSSean Callanan if (format != eFormatVoid) 355bf154daeSSean Callanan { 3561deb7962SGreg Clayton if (format != eFormatDefault) 3571deb7962SGreg Clayton result_valobj_sp->SetFormat (format); 35832c4085bSGreg Clayton 3594d93b8cdSEnrico Granata DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format)); 36073e8c4d0SEnrico Granata options.SetVariableFormatDisplayLanguage(result_valobj_sp->GetPreferredDisplayLanguage()); 361770eb05aSEnrico Granata 3624d93b8cdSEnrico Granata result_valobj_sp->Dump(*output_stream,options); 3634d93b8cdSEnrico Granata 364fcd43b71SJohnny Chen if (result) 365fcd43b71SJohnny Chen result->SetStatus (eReturnStatusSuccessFinishResult); 36630fdc8d8SChris Lattner } 367bf154daeSSean Callanan } 36830fdc8d8SChris Lattner else 36930fdc8d8SChris Lattner { 370151c032cSJim Ingham if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult) 371bccce813SSean Callanan { 372bcf897faSSean Callanan if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid()) 373bf154daeSSean Callanan { 374bcf897faSSean Callanan error_stream->PutCString("(void)\n"); 375bcf897faSSean Callanan } 376bccce813SSean Callanan 377bccce813SSean Callanan if (result) 378bccce813SSean Callanan result->SetStatus (eReturnStatusSuccessFinishResult); 379bccce813SSean Callanan } 380bccce813SSean Callanan else 381bccce813SSean Callanan { 3825fd05903SGreg Clayton const char *error_cstr = result_valobj_sp->GetError().AsCString(); 3835fd05903SGreg Clayton if (error_cstr && error_cstr[0]) 3845fd05903SGreg Clayton { 385c7bece56SGreg Clayton const size_t error_cstr_len = strlen (error_cstr); 3865fd05903SGreg Clayton const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n'; 3875fd05903SGreg Clayton if (strstr(error_cstr, "error:") != error_cstr) 3885fd05903SGreg Clayton error_stream->PutCString ("error: "); 3895fd05903SGreg Clayton error_stream->Write(error_cstr, error_cstr_len); 3905fd05903SGreg Clayton if (!ends_with_newline) 3915fd05903SGreg Clayton error_stream->EOL(); 3925fd05903SGreg Clayton } 3935fd05903SGreg Clayton else 3945fd05903SGreg Clayton { 3955fd05903SGreg Clayton error_stream->PutCString ("error: unknown error\n"); 3965fd05903SGreg Clayton } 3975fd05903SGreg Clayton 398fcd43b71SJohnny Chen if (result) 399b71f3844SGreg Clayton result->SetStatus (eReturnStatusFailed); 40030fdc8d8SChris Lattner } 4018b2fe6dcSGreg Clayton } 4028b2fe6dcSGreg Clayton } 403bccce813SSean Callanan } 4048b2fe6dcSGreg Clayton else 4058b2fe6dcSGreg Clayton { 4066e8dc334SCaroline Tice error_stream->Printf ("error: invalid execution context for expression\n"); 4078b2fe6dcSGreg Clayton return false; 4088b2fe6dcSGreg Clayton } 40930fdc8d8SChris Lattner 41016ad5faeSSean Callanan return true; 41130fdc8d8SChris Lattner } 41230fdc8d8SChris Lattner 41344d93782SGreg Clayton void 41444d93782SGreg Clayton CommandObjectExpression::IOHandlerInputComplete (IOHandler &io_handler, std::string &line) 41544d93782SGreg Clayton { 41644d93782SGreg Clayton io_handler.SetIsDone(true); 41744d93782SGreg Clayton // StreamSP output_stream = io_handler.GetDebugger().GetAsyncOutputStream(); 41844d93782SGreg Clayton // StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream(); 41944d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 42044d93782SGreg Clayton StreamFileSP error_sp(io_handler.GetErrorStreamFile()); 42144d93782SGreg Clayton 42244d93782SGreg Clayton EvaluateExpression (line.c_str(), 42344d93782SGreg Clayton output_sp.get(), 42444d93782SGreg Clayton error_sp.get()); 42544d93782SGreg Clayton if (output_sp) 42644d93782SGreg Clayton output_sp->Flush(); 42744d93782SGreg Clayton if (error_sp) 42844d93782SGreg Clayton error_sp->Flush(); 42944d93782SGreg Clayton } 43044d93782SGreg Clayton 43144d93782SGreg Clayton LineStatus 43244d93782SGreg Clayton CommandObjectExpression::IOHandlerLinesUpdated (IOHandler &io_handler, 43344d93782SGreg Clayton StringList &lines, 43444d93782SGreg Clayton uint32_t line_idx, 43544d93782SGreg Clayton Error &error) 43644d93782SGreg Clayton { 43744d93782SGreg Clayton if (line_idx == UINT32_MAX) 43844d93782SGreg Clayton { 43944d93782SGreg Clayton // Remove the last line from "lines" so it doesn't appear 44044d93782SGreg Clayton // in our final expression 44144d93782SGreg Clayton lines.PopBack(); 44244d93782SGreg Clayton error.Clear(); 44344d93782SGreg Clayton return LineStatus::Done; 44444d93782SGreg Clayton } 44544d93782SGreg Clayton else if (line_idx + 1 == lines.GetSize()) 44644d93782SGreg Clayton { 44744d93782SGreg Clayton // The last line was edited, if this line is empty, then we are done 44844d93782SGreg Clayton // getting our multiple lines. 44944d93782SGreg Clayton if (lines[line_idx].empty()) 45044d93782SGreg Clayton return LineStatus::Done; 45144d93782SGreg Clayton } 45244d93782SGreg Clayton return LineStatus::Success; 45344d93782SGreg Clayton } 45444d93782SGreg Clayton 455cf28a8b7SGreg Clayton void 456cf28a8b7SGreg Clayton CommandObjectExpression::GetMultilineExpression () 45730fdc8d8SChris Lattner { 45830fdc8d8SChris Lattner m_expr_lines.clear(); 45930fdc8d8SChris Lattner m_expr_line_count = 0; 46030fdc8d8SChris Lattner 46144d93782SGreg Clayton Debugger &debugger = GetCommandInterpreter().GetDebugger(); 462e30f11d9SKate Stone bool color_prompt = debugger.GetUseColor(); 46344d93782SGreg Clayton const bool multiple_lines = true; // Get multiple lines 46444d93782SGreg Clayton IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger, 465e30f11d9SKate Stone IOHandler::Type::Expression, 46644d93782SGreg Clayton "lldb-expr", // Name of input reader for history 467c8ecc2a9SEugene Zelenko nullptr, // No prompt 468c8ecc2a9SEugene Zelenko nullptr, // Continuation prompt 46944d93782SGreg Clayton multiple_lines, 470e30f11d9SKate Stone color_prompt, 471f6913cd7SGreg Clayton 1, // Show line numbers starting at 1 47244d93782SGreg Clayton *this)); 473b6892508SGreg Clayton 474b6892508SGreg Clayton StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile()); 475b6892508SGreg Clayton if (output_sp) 476b6892508SGreg Clayton { 477b6892508SGreg Clayton output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n"); 478b6892508SGreg Clayton output_sp->Flush(); 479b6892508SGreg Clayton } 48044d93782SGreg Clayton debugger.PushIOHandler(io_handler_sp); 481cf28a8b7SGreg Clayton } 482cf28a8b7SGreg Clayton 483cf28a8b7SGreg Clayton bool 484c8ecc2a9SEugene Zelenko CommandObjectExpression::DoExecute(const char *command, 485c8ecc2a9SEugene Zelenko CommandReturnObject &result) 486cf28a8b7SGreg Clayton { 487*e5ee6f04SJim Ingham m_fixed_expression.clear(); 488cf28a8b7SGreg Clayton m_option_group.NotifyOptionParsingStarting(); 489cf28a8b7SGreg Clayton 490c8ecc2a9SEugene Zelenko const char * expr = nullptr; 491cf28a8b7SGreg Clayton 492cf28a8b7SGreg Clayton if (command[0] == '\0') 493cf28a8b7SGreg Clayton { 494cf28a8b7SGreg Clayton GetMultilineExpression (); 49530fdc8d8SChris Lattner return result.Succeeded(); 49630fdc8d8SChris Lattner } 49730fdc8d8SChris Lattner 49830fdc8d8SChris Lattner if (command[0] == '-') 49930fdc8d8SChris Lattner { 50030fdc8d8SChris Lattner // We have some options and these options MUST end with --. 501c8ecc2a9SEugene Zelenko const char *end_options = nullptr; 50230fdc8d8SChris Lattner const char *s = command; 50330fdc8d8SChris Lattner while (s && s[0]) 50430fdc8d8SChris Lattner { 50530fdc8d8SChris Lattner end_options = ::strstr (s, "--"); 50630fdc8d8SChris Lattner if (end_options) 50730fdc8d8SChris Lattner { 50830fdc8d8SChris Lattner end_options += 2; // Get past the "--" 50930fdc8d8SChris Lattner if (::isspace (end_options[0])) 51030fdc8d8SChris Lattner { 51130fdc8d8SChris Lattner expr = end_options; 51230fdc8d8SChris Lattner while (::isspace (*expr)) 51330fdc8d8SChris Lattner ++expr; 51430fdc8d8SChris Lattner break; 51530fdc8d8SChris Lattner } 51630fdc8d8SChris Lattner } 51730fdc8d8SChris Lattner s = end_options; 51830fdc8d8SChris Lattner } 51930fdc8d8SChris Lattner 52030fdc8d8SChris Lattner if (end_options) 52130fdc8d8SChris Lattner { 52200b7f95bSPavel Labath Args args (llvm::StringRef(command, end_options - command)); 523a7015092SGreg Clayton if (!ParseOptions (args, result)) 52430fdc8d8SChris Lattner return false; 525f6b8b581SGreg Clayton 5261deb7962SGreg Clayton Error error (m_option_group.NotifyOptionParsingFinished()); 527f6b8b581SGreg Clayton if (error.Fail()) 528f6b8b581SGreg Clayton { 529f6b8b581SGreg Clayton result.AppendError (error.AsCString()); 530f6b8b581SGreg Clayton result.SetStatus (eReturnStatusFailed); 531f6b8b581SGreg Clayton return false; 532f6b8b581SGreg Clayton } 533cf28a8b7SGreg Clayton 534f2bd5c3eSSean Callanan if (m_repl_option.GetOptionValue().GetCurrentValue()) 535f2bd5c3eSSean Callanan { 536f2bd5c3eSSean Callanan Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); 537f2bd5c3eSSean Callanan if (target) 538f2bd5c3eSSean Callanan { 539f2bd5c3eSSean Callanan // Drop into REPL 540f2bd5c3eSSean Callanan m_expr_lines.clear(); 541f2bd5c3eSSean Callanan m_expr_line_count = 0; 542f2bd5c3eSSean Callanan 543f2bd5c3eSSean Callanan Debugger &debugger = target->GetDebugger(); 544f2bd5c3eSSean Callanan 545f2bd5c3eSSean Callanan // Check if the LLDB command interpreter is sitting on top of a REPL that 546f2bd5c3eSSean Callanan // launched it... 547f2bd5c3eSSean Callanan if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter, IOHandler::Type::REPL)) 548f2bd5c3eSSean Callanan { 549f2bd5c3eSSean Callanan // the LLDB command interpreter is sitting on top of a REPL that launched it, 550f2bd5c3eSSean Callanan // so just say the command interpreter is done and fall back to the existing REPL 551f2bd5c3eSSean Callanan m_interpreter.GetIOHandler(false)->SetIsDone(true); 552f2bd5c3eSSean Callanan } 553f2bd5c3eSSean Callanan else 554f2bd5c3eSSean Callanan { 555f2bd5c3eSSean Callanan // We are launching the REPL on top of the current LLDB command interpreter, 556f2bd5c3eSSean Callanan // so just push one 557f2bd5c3eSSean Callanan bool initialize = false; 558f2bd5c3eSSean Callanan Error repl_error; 559f2bd5c3eSSean Callanan REPLSP repl_sp (target->GetREPL(repl_error, m_command_options.language, nullptr, false)); 560f2bd5c3eSSean Callanan 561f2bd5c3eSSean Callanan if (!repl_sp) 562f2bd5c3eSSean Callanan { 563f2bd5c3eSSean Callanan initialize = true; 564f2bd5c3eSSean Callanan repl_sp = target->GetREPL(repl_error, m_command_options.language, nullptr, true); 565f2bd5c3eSSean Callanan if (!repl_error.Success()) 566f2bd5c3eSSean Callanan { 567f2bd5c3eSSean Callanan result.SetError(repl_error); 568f2bd5c3eSSean Callanan return result.Succeeded(); 569f2bd5c3eSSean Callanan } 570f2bd5c3eSSean Callanan } 571f2bd5c3eSSean Callanan 572f2bd5c3eSSean Callanan if (repl_sp) 573f2bd5c3eSSean Callanan { 574f2bd5c3eSSean Callanan if (initialize) 575f2bd5c3eSSean Callanan { 576f2bd5c3eSSean Callanan repl_sp->SetCommandOptions(m_command_options); 577f2bd5c3eSSean Callanan repl_sp->SetFormatOptions(m_format_options); 578f2bd5c3eSSean Callanan repl_sp->SetValueObjectDisplayOptions(m_varobj_options); 579f2bd5c3eSSean Callanan } 580f2bd5c3eSSean Callanan 581f2bd5c3eSSean Callanan IOHandlerSP io_handler_sp (repl_sp->GetIOHandler()); 582f2bd5c3eSSean Callanan 583f2bd5c3eSSean Callanan io_handler_sp->SetIsDone(false); 584f2bd5c3eSSean Callanan 585f2bd5c3eSSean Callanan debugger.PushIOHandler(io_handler_sp); 586f2bd5c3eSSean Callanan } 587f2bd5c3eSSean Callanan else 588f2bd5c3eSSean Callanan { 589f2bd5c3eSSean Callanan repl_error.SetErrorStringWithFormat("Couldn't create a REPL for %s", Language::GetNameForLanguageType(m_command_options.language)); 590f2bd5c3eSSean Callanan result.SetError(repl_error); 591f2bd5c3eSSean Callanan return result.Succeeded(); 592f2bd5c3eSSean Callanan } 593f2bd5c3eSSean Callanan } 594f2bd5c3eSSean Callanan } 595f2bd5c3eSSean Callanan } 596cf28a8b7SGreg Clayton // No expression following options 597c8ecc2a9SEugene Zelenko else if (expr == nullptr || expr[0] == '\0') 598cf28a8b7SGreg Clayton { 599cf28a8b7SGreg Clayton GetMultilineExpression (); 600cf28a8b7SGreg Clayton return result.Succeeded(); 601cf28a8b7SGreg Clayton } 60230fdc8d8SChris Lattner } 60330fdc8d8SChris Lattner } 60430fdc8d8SChris Lattner 605c8ecc2a9SEugene Zelenko if (expr == nullptr) 60630fdc8d8SChris Lattner expr = command; 60730fdc8d8SChris Lattner 6086e8dc334SCaroline Tice if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result)) 609*e5ee6f04SJim Ingham { 610*e5ee6f04SJim Ingham Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); 611*e5ee6f04SJim Ingham if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts()) 612*e5ee6f04SJim Ingham { 613*e5ee6f04SJim Ingham CommandHistory &history = m_interpreter.GetCommandHistory(); 614*e5ee6f04SJim Ingham // FIXME: Can we figure out what the user actually typed (e.g. some alias for expr???) 615*e5ee6f04SJim Ingham // If we can it would be nice to show that. 616*e5ee6f04SJim Ingham std::string fixed_command("expression "); 617*e5ee6f04SJim Ingham if (expr == command) 618*e5ee6f04SJim Ingham fixed_command.append(m_fixed_expression); 619*e5ee6f04SJim Ingham else 620*e5ee6f04SJim Ingham { 621*e5ee6f04SJim Ingham // Add in any options that might have been in the original command: 622*e5ee6f04SJim Ingham fixed_command.append(command, expr - command); 623*e5ee6f04SJim Ingham fixed_command.append(m_fixed_expression); 624*e5ee6f04SJim Ingham } 625*e5ee6f04SJim Ingham history.AppendString(fixed_command); 626*e5ee6f04SJim Ingham } 627fcd43b71SJohnny Chen return true; 628*e5ee6f04SJim Ingham } 629fcd43b71SJohnny Chen 630fcd43b71SJohnny Chen result.SetStatus (eReturnStatusFailed); 631fcd43b71SJohnny Chen return false; 63230fdc8d8SChris Lattner } 633