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." },
64*279b2e88SJim Ingham     { 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." },
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."},
663fe71581SMarianne Mailhot-Sarrasin     { 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."},
673fe71581SMarianne Mailhot-Sarrasin     { 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)."}
681deb7962SGreg Clayton };
691deb7962SGreg Clayton 
701deb7962SGreg Clayton uint32_t
711deb7962SGreg Clayton CommandObjectExpression::CommandOptions::GetNumDefinitions ()
721deb7962SGreg Clayton {
7328606954SSaleem Abdulrasool     return llvm::array_lengthof(g_option_table);
741deb7962SGreg Clayton }
751deb7962SGreg Clayton 
7630fdc8d8SChris Lattner Error
771deb7962SGreg Clayton CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &interpreter,
781deb7962SGreg Clayton                                                          uint32_t option_idx,
791deb7962SGreg Clayton                                                          const char *option_arg)
8030fdc8d8SChris Lattner {
8130fdc8d8SChris Lattner     Error error;
8230fdc8d8SChris Lattner 
833bcdfc0eSGreg Clayton     const int short_option = g_option_table[option_idx].short_option;
8430fdc8d8SChris Lattner 
8530fdc8d8SChris Lattner     switch (short_option)
8630fdc8d8SChris Lattner     {
8715663c53SDawn Perchik     case 'l':
880e0984eeSJim Ingham         language = Language::GetLanguageTypeFromString (option_arg);
8915663c53SDawn Perchik         if (language == eLanguageTypeUnknown)
9015663c53SDawn Perchik             error.SetErrorStringWithFormat ("unknown language type: '%s' for expression", option_arg);
9115663c53SDawn Perchik         break;
9230fdc8d8SChris Lattner 
9335e1bda6SJim Ingham     case 'a':
9435e1bda6SJim Ingham         {
9535e1bda6SJim Ingham             bool success;
9635e1bda6SJim Ingham             bool result;
9735e1bda6SJim Ingham             result = Args::StringToBoolean(option_arg, true, &success);
9835e1bda6SJim Ingham             if (!success)
9935e1bda6SJim Ingham                 error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg);
10035e1bda6SJim Ingham             else
10135e1bda6SJim Ingham                 try_all_threads = result;
10235e1bda6SJim Ingham         }
1036c68fb45SJim Ingham         break;
1046c68fb45SJim Ingham 
105184e9811SJim Ingham     case 'i':
106184e9811SJim Ingham         {
107184e9811SJim Ingham             bool success;
108184e9811SJim Ingham             bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
109184e9811SJim Ingham             if (success)
110184e9811SJim Ingham                 ignore_breakpoints = tmp_value;
111184e9811SJim Ingham             else
112184e9811SJim Ingham                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
113184e9811SJim Ingham             break;
114184e9811SJim Ingham         }
1153fe71581SMarianne Mailhot-Sarrasin 
1163fe71581SMarianne Mailhot-Sarrasin     case 'j':
1173fe71581SMarianne Mailhot-Sarrasin         {
1183fe71581SMarianne Mailhot-Sarrasin             bool success;
1193fe71581SMarianne Mailhot-Sarrasin             bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
1203fe71581SMarianne Mailhot-Sarrasin             if (success)
1213fe71581SMarianne Mailhot-Sarrasin                 allow_jit = tmp_value;
1223fe71581SMarianne Mailhot-Sarrasin             else
1233fe71581SMarianne Mailhot-Sarrasin                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
1243fe71581SMarianne Mailhot-Sarrasin             break;
1253fe71581SMarianne Mailhot-Sarrasin         }
1263fe71581SMarianne Mailhot-Sarrasin 
12735e1bda6SJim Ingham     case 't':
12835e1bda6SJim Ingham         {
12935e1bda6SJim Ingham             bool success;
13035e1bda6SJim Ingham             uint32_t result;
1315275aaa0SVince Harron             result = StringConvert::ToUInt32(option_arg, 0, 0, &success);
13235e1bda6SJim Ingham             if (success)
13335e1bda6SJim Ingham                 timeout = result;
13435e1bda6SJim Ingham             else
13535e1bda6SJim Ingham                 error.SetErrorStringWithFormat ("invalid timeout setting \"%s\"", option_arg);
13635e1bda6SJim Ingham         }
13735e1bda6SJim Ingham         break;
13835e1bda6SJim Ingham 
139399f1cafSJim Ingham     case 'u':
1403bfdaa2aSSean Callanan         {
141399f1cafSJim Ingham             bool success;
142184e9811SJim Ingham             bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
143184e9811SJim Ingham             if (success)
144184e9811SJim Ingham                 unwind_on_error = tmp_value;
145184e9811SJim Ingham             else
14686edbf41SGreg Clayton                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
147399f1cafSJim Ingham             break;
1483bfdaa2aSSean Callanan         }
1494d93b8cdSEnrico Granata 
1504d93b8cdSEnrico Granata     case 'v':
1514d93b8cdSEnrico Granata         if (!option_arg)
1524d93b8cdSEnrico Granata         {
1534d93b8cdSEnrico Granata             m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull;
1544d93b8cdSEnrico Granata             break;
1554d93b8cdSEnrico Granata         }
1564d93b8cdSEnrico Granata         m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
1574d93b8cdSEnrico Granata         if (!error.Success())
1584d93b8cdSEnrico Granata             error.SetErrorStringWithFormat ("unrecognized value for description-verbosity '%s'", option_arg);
1594d93b8cdSEnrico Granata         break;
1604d93b8cdSEnrico Granata 
16162afb9f6SGreg Clayton     case 'g':
16262afb9f6SGreg Clayton         debug = true;
16362afb9f6SGreg Clayton         unwind_on_error = false;
16462afb9f6SGreg Clayton         ignore_breakpoints = false;
16562afb9f6SGreg Clayton         break;
16662afb9f6SGreg Clayton 
167863fab69SSean Callanan     case 'p':
168863fab69SSean Callanan         top_level = true;
169863fab69SSean Callanan         break;
170863fab69SSean Callanan 
171a1e541bfSJim Ingham     case 'X':
172a1e541bfSJim Ingham         {
173a1e541bfSJim Ingham             bool success;
174a1e541bfSJim Ingham             bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
175a1e541bfSJim Ingham             if (success)
176a1e541bfSJim Ingham                 auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo;
177a1e541bfSJim Ingham             else
178a1e541bfSJim Ingham                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
179a1e541bfSJim Ingham             break;
180a1e541bfSJim Ingham         }
181a1e541bfSJim Ingham 
18230fdc8d8SChris Lattner     default:
18386edbf41SGreg Clayton         error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
18430fdc8d8SChris Lattner         break;
18530fdc8d8SChris Lattner     }
18630fdc8d8SChris Lattner 
18730fdc8d8SChris Lattner     return error;
18830fdc8d8SChris Lattner }
18930fdc8d8SChris Lattner 
19030fdc8d8SChris Lattner void
1911deb7962SGreg Clayton CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter)
19230fdc8d8SChris Lattner {
193184e9811SJim Ingham     Process *process = interpreter.GetExecutionContext().GetProcessPtr();
194c8ecc2a9SEugene Zelenko     if (process != nullptr)
195184e9811SJim Ingham     {
196184e9811SJim Ingham         ignore_breakpoints = process->GetIgnoreBreakpointsInExpressions();
197184e9811SJim Ingham         unwind_on_error    = process->GetUnwindOnErrorInExpressions();
198184e9811SJim Ingham     }
199184e9811SJim Ingham     else
200184e9811SJim Ingham     {
201fc03f8fcSGreg Clayton         ignore_breakpoints = true;
202399f1cafSJim Ingham         unwind_on_error = true;
203184e9811SJim Ingham     }
204184e9811SJim Ingham 
20530fdc8d8SChris Lattner     show_summary = true;
20635e1bda6SJim Ingham     try_all_threads = true;
20735e1bda6SJim Ingham     timeout = 0;
20862afb9f6SGreg Clayton     debug = false;
20915663c53SDawn Perchik     language = eLanguageTypeUnknown;
2104d93b8cdSEnrico Granata     m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
211a1e541bfSJim Ingham     auto_apply_fixits = eLazyBoolCalculate;
212863fab69SSean Callanan     top_level = false;
2133fe71581SMarianne Mailhot-Sarrasin     allow_jit = true;
21430fdc8d8SChris Lattner }
21530fdc8d8SChris Lattner 
216e0d378b3SGreg Clayton const OptionDefinition*
21730fdc8d8SChris Lattner CommandObjectExpression::CommandOptions::GetDefinitions ()
21830fdc8d8SChris Lattner {
21930fdc8d8SChris Lattner     return g_option_table;
22030fdc8d8SChris Lattner }
22130fdc8d8SChris Lattner 
222a7015092SGreg Clayton CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) :
2235a988416SJim Ingham     CommandObjectRaw(interpreter,
22430fdc8d8SChris Lattner                      "expression",
22515663c53SDawn Perchik                      "Evaluate an expression in the current program context, using user defined variables and variables currently in scope.",
226c8ecc2a9SEugene Zelenko                      nullptr,
227e87764f2SEnrico Granata                      eCommandProcessMustBePaused | eCommandTryTargetAPILock),
22844d93782SGreg Clayton     IOHandlerDelegate (IOHandlerDelegate::Completion::Expression),
2291deb7962SGreg Clayton     m_option_group (interpreter),
2301deb7962SGreg Clayton     m_format_options (eFormatDefault),
231f2bd5c3eSSean Callanan     m_repl_option (LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false, true),
2321deb7962SGreg Clayton     m_command_options (),
23330fdc8d8SChris Lattner     m_expr_line_count (0),
23430fdc8d8SChris Lattner     m_expr_lines ()
23530fdc8d8SChris Lattner {
23630fdc8d8SChris Lattner     SetHelpLong(
237ea671fbdSKate Stone R"(
238ea671fbdSKate Stone Timeouts:
239ea671fbdSKate Stone 
240ea671fbdSKate Stone )" "    If the expression can be evaluated statically (without running code) then it will be.  \
241ea671fbdSKate Stone Otherwise, by default the expression will run on the current thread with a short timeout: \
242ea671fbdSKate Stone currently .25 seconds.  If it doesn't return in that time, the evaluation will be interrupted \
243ea671fbdSKate Stone and resumed with all threads running.  You can use the -a option to disable retrying on all \
244ea671fbdSKate Stone threads.  You can use the -t option to set a shorter timeout." R"(
245ea671fbdSKate Stone 
246ea671fbdSKate Stone User defined variables:
247ea671fbdSKate Stone 
248ea671fbdSKate Stone )" "    You can define your own variables for convenience or to be used in subsequent expressions.  \
249ea671fbdSKate Stone You define them the same way you would define variables in C.  If the first character of \
250ea671fbdSKate Stone your user defined variable is a $, then the variable's value will be available in future \
251ea671fbdSKate Stone expressions, otherwise it will just be available in the current expression." R"(
252ea671fbdSKate Stone 
253ea671fbdSKate Stone Continuing evaluation after a breakpoint:
254ea671fbdSKate Stone 
255ea671fbdSKate Stone )" "    If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \
256ea671fbdSKate Stone you are done with your investigation, you can either remove the expression execution frames \
257ea671fbdSKate Stone from the stack with \"thread return -x\" or if you are still interested in the expression result \
258ea671fbdSKate Stone you can issue the \"continue\" command and the expression evaluation will complete and the \
259ea671fbdSKate Stone expression result will be available using the \"thread.completed-expression\" key in the thread \
260ea671fbdSKate Stone format." R"(
261ea671fbdSKate Stone 
262ea671fbdSKate Stone Examples:
263ea671fbdSKate Stone 
264ea671fbdSKate Stone     expr my_struct->a = my_array[3]
265ea671fbdSKate Stone     expr -f bin -- (index * 8) + 5
266ea671fbdSKate Stone     expr unsigned int $foo = 5
267ea671fbdSKate Stone     expr char c[] = \"foo\"; c[0])"
268ea671fbdSKate Stone     );
269405fe67fSCaroline Tice 
270405fe67fSCaroline Tice     CommandArgumentEntry arg;
271405fe67fSCaroline Tice     CommandArgumentData expression_arg;
272405fe67fSCaroline Tice 
273405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
274405fe67fSCaroline Tice     expression_arg.arg_type = eArgTypeExpression;
275405fe67fSCaroline Tice     expression_arg.arg_repetition = eArgRepeatPlain;
276405fe67fSCaroline Tice 
277405fe67fSCaroline Tice     // There is only one variant this argument could be; put it into the argument entry.
278405fe67fSCaroline Tice     arg.push_back (expression_arg);
279405fe67fSCaroline Tice 
280405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
281405fe67fSCaroline Tice     m_arguments.push_back (arg);
2821deb7962SGreg Clayton 
2835009f9d5SGreg Clayton     // Add the "--format" and "--gdb-format"
2845009f9d5SGreg Clayton     m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1);
2851deb7962SGreg Clayton     m_option_group.Append (&m_command_options);
286b576bba2SEnrico Granata     m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
287f2bd5c3eSSean Callanan     m_option_group.Append (&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
2881deb7962SGreg Clayton     m_option_group.Finalize();
28930fdc8d8SChris Lattner }
29030fdc8d8SChris Lattner 
291c8ecc2a9SEugene Zelenko CommandObjectExpression::~CommandObjectExpression() = default;
29230fdc8d8SChris Lattner 
29330fdc8d8SChris Lattner Options *
29430fdc8d8SChris Lattner CommandObjectExpression::GetOptions ()
29530fdc8d8SChris Lattner {
2961deb7962SGreg Clayton     return &m_option_group;
29730fdc8d8SChris Lattner }
29830fdc8d8SChris Lattner 
299520a422bSEnrico Granata static lldb_private::Error
300520a422bSEnrico Granata CanBeUsedForElementCountPrinting (ValueObject& valobj)
301520a422bSEnrico Granata {
302520a422bSEnrico Granata     CompilerType type(valobj.GetCompilerType());
303520a422bSEnrico Granata     CompilerType pointee;
304520a422bSEnrico Granata     if (!type.IsPointerType(&pointee))
305520a422bSEnrico Granata         return Error("as it does not refer to a pointer");
306520a422bSEnrico Granata     if (pointee.IsVoidType())
307520a422bSEnrico Granata         return Error("as it refers to a pointer to void");
308520a422bSEnrico Granata     return Error();
309520a422bSEnrico Granata }
310520a422bSEnrico Granata 
31130fdc8d8SChris Lattner bool
312c8ecc2a9SEugene Zelenko CommandObjectExpression::EvaluateExpression(const char *expr,
3136e8dc334SCaroline Tice                                             Stream *output_stream,
3146e8dc334SCaroline Tice                                             Stream *error_stream,
315c8ecc2a9SEugene Zelenko                                             CommandReturnObject *result)
31630fdc8d8SChris Lattner {
317ba7b8e2cSGreg Clayton     // Don't use m_exe_ctx as this might be called asynchronously
318ba7b8e2cSGreg Clayton     // after the command object DoExecute has finished when doing
319ba7b8e2cSGreg Clayton     // multi-line expression that use an input reader...
320ba7b8e2cSGreg Clayton     ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
321ba7b8e2cSGreg Clayton 
322ba7b8e2cSGreg Clayton     Target *target = exe_ctx.GetTargetPtr();
323c0a6e061SSean Callanan 
324c0a6e061SSean Callanan     if (!target)
325893c932aSJim Ingham         target = GetDummyTarget();
326c0a6e061SSean Callanan 
327c14ee32dSGreg Clayton     if (target)
3286961e878SSean Callanan     {
3298b2fe6dcSGreg Clayton         lldb::ValueObjectSP result_valobj_sp;
33092adcac9SSean Callanan         bool keep_in_memory = true;
331009d110dSDawn Perchik         StackFrame *frame = exe_ctx.GetFramePtr();
33292adcac9SSean Callanan 
33335e1bda6SJim Ingham         EvaluateExpressionOptions options;
3346fbc48bcSJim Ingham         options.SetCoerceToId(m_varobj_options.use_objc);
3356fbc48bcSJim Ingham         options.SetUnwindOnError(m_command_options.unwind_on_error);
3366fbc48bcSJim Ingham         options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);
3376fbc48bcSJim Ingham         options.SetKeepInMemory(keep_in_memory);
3386fbc48bcSJim Ingham         options.SetUseDynamic(m_varobj_options.use_dynamic);
3396fbc48bcSJim Ingham         options.SetTryAllThreads(m_command_options.try_all_threads);
3406fbc48bcSJim Ingham         options.SetDebug(m_command_options.debug);
34115663c53SDawn Perchik         options.SetLanguage(m_command_options.language);
3423fe71581SMarianne Mailhot-Sarrasin         options.SetExecutionPolicy(m_command_options.allow_jit ?
3433fe71581SMarianne Mailhot-Sarrasin             EvaluateExpressionOptions::default_execution_policy :
3443fe71581SMarianne Mailhot-Sarrasin             lldb_private::eExecutionPolicyNever);
34515663c53SDawn Perchik 
346a1e541bfSJim Ingham         bool auto_apply_fixits;
347a1e541bfSJim Ingham         if (m_command_options.auto_apply_fixits == eLazyBoolCalculate)
348a1e541bfSJim Ingham             auto_apply_fixits = target->GetEnableAutoApplyFixIts();
349a1e541bfSJim Ingham         else
350a1e541bfSJim Ingham             auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes ? true : false;
351a1e541bfSJim Ingham 
352a1e541bfSJim Ingham         options.SetAutoApplyFixIts(auto_apply_fixits);
353a1e541bfSJim Ingham 
354863fab69SSean Callanan         if (m_command_options.top_level)
355863fab69SSean Callanan             options.SetExecutionPolicy(eExecutionPolicyTopLevel);
356863fab69SSean Callanan 
35723f8c95aSGreg Clayton         // If there is any chance we are going to stop and want to see
35823f8c95aSGreg Clayton         // what went wrong with our expression, we should generate debug info
35923f8c95aSGreg Clayton         if (!m_command_options.ignore_breakpoints ||
36023f8c95aSGreg Clayton             !m_command_options.unwind_on_error)
36123f8c95aSGreg Clayton             options.SetGenerateDebugInfo(true);
36223f8c95aSGreg Clayton 
36362afb9f6SGreg Clayton         if (m_command_options.timeout > 0)
36462afb9f6SGreg Clayton             options.SetTimeoutUsec(m_command_options.timeout);
3656f78f386SJim Ingham         else
3666f78f386SJim Ingham             options.SetTimeoutUsec(0);
367d4439aa9SEnrico Granata 
368e5ee6f04SJim Ingham         ExpressionResults success = target->EvaluateExpression(expr, frame, result_valobj_sp, options, &m_fixed_expression);
369e5ee6f04SJim Ingham 
370e5ee6f04SJim Ingham         // We only tell you about the FixIt if we applied it.  The compiler errors will suggest the FixIt if it parsed.
371e5ee6f04SJim Ingham         if (error_stream && !m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts())
372e5ee6f04SJim Ingham         {
373e5ee6f04SJim Ingham             if (success == eExpressionCompleted)
374*279b2e88SJim Ingham                 error_stream->Printf ("  Fix-it applied, fixed expression was: \n    %s\n", m_fixed_expression.c_str());
375e5ee6f04SJim Ingham         }
3768b2fe6dcSGreg Clayton 
3778b2fe6dcSGreg Clayton         if (result_valobj_sp)
3788b2fe6dcSGreg Clayton         {
379bf154daeSSean Callanan             Format format = m_format_options.GetFormat();
380bf154daeSSean Callanan 
381b71f3844SGreg Clayton             if (result_valobj_sp->GetError().Success())
38230fdc8d8SChris Lattner             {
383bf154daeSSean Callanan                 if (format != eFormatVoid)
384bf154daeSSean Callanan                 {
3851deb7962SGreg Clayton                     if (format != eFormatDefault)
3861deb7962SGreg Clayton                         result_valobj_sp->SetFormat (format);
38732c4085bSGreg Clayton 
388520a422bSEnrico Granata                     if (m_varobj_options.elem_count > 0)
389520a422bSEnrico Granata                     {
390520a422bSEnrico Granata                         Error error(CanBeUsedForElementCountPrinting(*result_valobj_sp));
391520a422bSEnrico Granata                         if (error.Fail())
392520a422bSEnrico Granata                         {
393520a422bSEnrico Granata                             result->AppendErrorWithFormat("expression cannot be used with --element-count %s\n", error.AsCString(""));
394520a422bSEnrico Granata                             result->SetStatus(eReturnStatusFailed);
395520a422bSEnrico Granata                             return false;
396520a422bSEnrico Granata                         }
397520a422bSEnrico Granata                     }
398520a422bSEnrico Granata 
3994d93b8cdSEnrico Granata                     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format));
40073e8c4d0SEnrico Granata                     options.SetVariableFormatDisplayLanguage(result_valobj_sp->GetPreferredDisplayLanguage());
401770eb05aSEnrico Granata 
4024d93b8cdSEnrico Granata                     result_valobj_sp->Dump(*output_stream,options);
4034d93b8cdSEnrico Granata 
404fcd43b71SJohnny Chen                     if (result)
405fcd43b71SJohnny Chen                         result->SetStatus (eReturnStatusSuccessFinishResult);
40630fdc8d8SChris Lattner                 }
407bf154daeSSean Callanan             }
40830fdc8d8SChris Lattner             else
40930fdc8d8SChris Lattner             {
410151c032cSJim Ingham                 if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult)
411bccce813SSean Callanan                 {
412bcf897faSSean Callanan                     if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid())
413bf154daeSSean Callanan                     {
414bcf897faSSean Callanan                         error_stream->PutCString("(void)\n");
415bcf897faSSean Callanan                     }
416bccce813SSean Callanan 
417bccce813SSean Callanan                     if (result)
418bccce813SSean Callanan                         result->SetStatus (eReturnStatusSuccessFinishResult);
419bccce813SSean Callanan                 }
420bccce813SSean Callanan                 else
421bccce813SSean Callanan                 {
4225fd05903SGreg Clayton                     const char *error_cstr = result_valobj_sp->GetError().AsCString();
4235fd05903SGreg Clayton                     if (error_cstr && error_cstr[0])
4245fd05903SGreg Clayton                     {
425c7bece56SGreg Clayton                         const size_t error_cstr_len = strlen (error_cstr);
4265fd05903SGreg Clayton                         const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';
4275fd05903SGreg Clayton                         if (strstr(error_cstr, "error:") != error_cstr)
4285fd05903SGreg Clayton                             error_stream->PutCString ("error: ");
4295fd05903SGreg Clayton                         error_stream->Write(error_cstr, error_cstr_len);
4305fd05903SGreg Clayton                         if (!ends_with_newline)
4315fd05903SGreg Clayton                             error_stream->EOL();
4325fd05903SGreg Clayton                     }
4335fd05903SGreg Clayton                     else
4345fd05903SGreg Clayton                     {
4355fd05903SGreg Clayton                         error_stream->PutCString ("error: unknown error\n");
4365fd05903SGreg Clayton                     }
4375fd05903SGreg Clayton 
438fcd43b71SJohnny Chen                     if (result)
439b71f3844SGreg Clayton                         result->SetStatus (eReturnStatusFailed);
44030fdc8d8SChris Lattner                 }
4418b2fe6dcSGreg Clayton             }
4428b2fe6dcSGreg Clayton         }
443bccce813SSean Callanan     }
4448b2fe6dcSGreg Clayton     else
4458b2fe6dcSGreg Clayton     {
4466e8dc334SCaroline Tice         error_stream->Printf ("error: invalid execution context for expression\n");
4478b2fe6dcSGreg Clayton         return false;
4488b2fe6dcSGreg Clayton     }
44930fdc8d8SChris Lattner 
45016ad5faeSSean Callanan     return true;
45130fdc8d8SChris Lattner }
45230fdc8d8SChris Lattner 
45344d93782SGreg Clayton void
45444d93782SGreg Clayton CommandObjectExpression::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
45544d93782SGreg Clayton {
45644d93782SGreg Clayton     io_handler.SetIsDone(true);
45744d93782SGreg Clayton //    StreamSP output_stream = io_handler.GetDebugger().GetAsyncOutputStream();
45844d93782SGreg Clayton //    StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream();
45944d93782SGreg Clayton     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
46044d93782SGreg Clayton     StreamFileSP error_sp(io_handler.GetErrorStreamFile());
46144d93782SGreg Clayton 
46244d93782SGreg Clayton     EvaluateExpression (line.c_str(),
46344d93782SGreg Clayton                         output_sp.get(),
46444d93782SGreg Clayton                         error_sp.get());
46544d93782SGreg Clayton     if (output_sp)
46644d93782SGreg Clayton         output_sp->Flush();
46744d93782SGreg Clayton     if (error_sp)
46844d93782SGreg Clayton         error_sp->Flush();
46944d93782SGreg Clayton }
47044d93782SGreg Clayton 
471f52c40c5SSean Callanan bool
472f52c40c5SSean Callanan CommandObjectExpression::IOHandlerIsInputComplete (IOHandler &io_handler,
473f52c40c5SSean Callanan                                                    StringList &lines)
47444d93782SGreg Clayton {
475f52c40c5SSean Callanan     // An empty lines is used to indicate the end of input
476f52c40c5SSean Callanan     const size_t num_lines = lines.GetSize();
477f52c40c5SSean Callanan     if (num_lines > 0 && lines[num_lines - 1].empty())
47844d93782SGreg Clayton     {
479f52c40c5SSean Callanan         // Remove the last empty line from "lines" so it doesn't appear
480f52c40c5SSean Callanan         // in our resulting input and return true to indicate we are done
481f52c40c5SSean Callanan         // getting lines
48244d93782SGreg Clayton         lines.PopBack();
483f52c40c5SSean Callanan         return true;
48444d93782SGreg Clayton     }
485f52c40c5SSean Callanan     return false;
48644d93782SGreg Clayton }
48744d93782SGreg Clayton 
488cf28a8b7SGreg Clayton void
489cf28a8b7SGreg Clayton CommandObjectExpression::GetMultilineExpression ()
49030fdc8d8SChris Lattner {
49130fdc8d8SChris Lattner     m_expr_lines.clear();
49230fdc8d8SChris Lattner     m_expr_line_count = 0;
49330fdc8d8SChris Lattner 
49444d93782SGreg Clayton     Debugger &debugger = GetCommandInterpreter().GetDebugger();
495e30f11d9SKate Stone     bool color_prompt = debugger.GetUseColor();
49644d93782SGreg Clayton     const bool multiple_lines = true; // Get multiple lines
49744d93782SGreg Clayton     IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger,
498e30f11d9SKate Stone                                                     IOHandler::Type::Expression,
49944d93782SGreg Clayton                                                     "lldb-expr",      // Name of input reader for history
500c8ecc2a9SEugene Zelenko                                                     nullptr,          // No prompt
501c8ecc2a9SEugene Zelenko                                                     nullptr,          // Continuation prompt
50244d93782SGreg Clayton                                                     multiple_lines,
503e30f11d9SKate Stone                                                     color_prompt,
504f6913cd7SGreg Clayton                                                     1,                // Show line numbers starting at 1
50544d93782SGreg Clayton                                                     *this));
506b6892508SGreg Clayton 
507b6892508SGreg Clayton     StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile());
508b6892508SGreg Clayton     if (output_sp)
509b6892508SGreg Clayton     {
510b6892508SGreg Clayton         output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
511b6892508SGreg Clayton         output_sp->Flush();
512b6892508SGreg Clayton     }
51344d93782SGreg Clayton     debugger.PushIOHandler(io_handler_sp);
514cf28a8b7SGreg Clayton }
515cf28a8b7SGreg Clayton 
516cf28a8b7SGreg Clayton bool
517c8ecc2a9SEugene Zelenko CommandObjectExpression::DoExecute(const char *command,
518c8ecc2a9SEugene Zelenko                                    CommandReturnObject &result)
519cf28a8b7SGreg Clayton {
520e5ee6f04SJim Ingham     m_fixed_expression.clear();
521cf28a8b7SGreg Clayton     m_option_group.NotifyOptionParsingStarting();
522cf28a8b7SGreg Clayton 
523c8ecc2a9SEugene Zelenko     const char * expr = nullptr;
524cf28a8b7SGreg Clayton 
525cf28a8b7SGreg Clayton     if (command[0] == '\0')
526cf28a8b7SGreg Clayton     {
527cf28a8b7SGreg Clayton         GetMultilineExpression ();
52830fdc8d8SChris Lattner         return result.Succeeded();
52930fdc8d8SChris Lattner     }
53030fdc8d8SChris Lattner 
53130fdc8d8SChris Lattner     if (command[0] == '-')
53230fdc8d8SChris Lattner     {
53330fdc8d8SChris Lattner         // We have some options and these options MUST end with --.
534c8ecc2a9SEugene Zelenko         const char *end_options = nullptr;
53530fdc8d8SChris Lattner         const char *s = command;
53630fdc8d8SChris Lattner         while (s && s[0])
53730fdc8d8SChris Lattner         {
53830fdc8d8SChris Lattner             end_options = ::strstr (s, "--");
53930fdc8d8SChris Lattner             if (end_options)
54030fdc8d8SChris Lattner             {
54130fdc8d8SChris Lattner                 end_options += 2; // Get past the "--"
54230fdc8d8SChris Lattner                 if (::isspace (end_options[0]))
54330fdc8d8SChris Lattner                 {
54430fdc8d8SChris Lattner                     expr = end_options;
54530fdc8d8SChris Lattner                     while (::isspace (*expr))
54630fdc8d8SChris Lattner                         ++expr;
54730fdc8d8SChris Lattner                     break;
54830fdc8d8SChris Lattner                 }
54930fdc8d8SChris Lattner             }
55030fdc8d8SChris Lattner             s = end_options;
55130fdc8d8SChris Lattner         }
55230fdc8d8SChris Lattner 
55330fdc8d8SChris Lattner         if (end_options)
55430fdc8d8SChris Lattner         {
55500b7f95bSPavel Labath             Args args (llvm::StringRef(command, end_options - command));
556a7015092SGreg Clayton             if (!ParseOptions (args, result))
55730fdc8d8SChris Lattner                 return false;
558f6b8b581SGreg Clayton 
5591deb7962SGreg Clayton             Error error (m_option_group.NotifyOptionParsingFinished());
560f6b8b581SGreg Clayton             if (error.Fail())
561f6b8b581SGreg Clayton             {
562f6b8b581SGreg Clayton                 result.AppendError (error.AsCString());
563f6b8b581SGreg Clayton                 result.SetStatus (eReturnStatusFailed);
564f6b8b581SGreg Clayton                 return false;
565f6b8b581SGreg Clayton             }
566cf28a8b7SGreg Clayton 
567f2bd5c3eSSean Callanan             if (m_repl_option.GetOptionValue().GetCurrentValue())
568f2bd5c3eSSean Callanan             {
569f2bd5c3eSSean Callanan                 Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
570f2bd5c3eSSean Callanan                 if (target)
571f2bd5c3eSSean Callanan                 {
572f2bd5c3eSSean Callanan                     // Drop into REPL
573f2bd5c3eSSean Callanan                     m_expr_lines.clear();
574f2bd5c3eSSean Callanan                     m_expr_line_count = 0;
575f2bd5c3eSSean Callanan 
576f2bd5c3eSSean Callanan                     Debugger &debugger = target->GetDebugger();
577f2bd5c3eSSean Callanan 
578f2bd5c3eSSean Callanan                     // Check if the LLDB command interpreter is sitting on top of a REPL that
579f2bd5c3eSSean Callanan                     // launched it...
580f2bd5c3eSSean Callanan                     if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter, IOHandler::Type::REPL))
581f2bd5c3eSSean Callanan                     {
582f2bd5c3eSSean Callanan                         // the LLDB command interpreter is sitting on top of a REPL that launched it,
583f2bd5c3eSSean Callanan                         // so just say the command interpreter is done and fall back to the existing REPL
584f2bd5c3eSSean Callanan                         m_interpreter.GetIOHandler(false)->SetIsDone(true);
585f2bd5c3eSSean Callanan                     }
586f2bd5c3eSSean Callanan                     else
587f2bd5c3eSSean Callanan                     {
588f2bd5c3eSSean Callanan                         // We are launching the REPL on top of the current LLDB command interpreter,
589f2bd5c3eSSean Callanan                         // so just push one
590f2bd5c3eSSean Callanan                         bool initialize = false;
591f2bd5c3eSSean Callanan                         Error repl_error;
592f2bd5c3eSSean Callanan                         REPLSP repl_sp (target->GetREPL(repl_error, m_command_options.language, nullptr, false));
593f2bd5c3eSSean Callanan 
594f2bd5c3eSSean Callanan                         if (!repl_sp)
595f2bd5c3eSSean Callanan                         {
596f2bd5c3eSSean Callanan                             initialize = true;
597f2bd5c3eSSean Callanan                             repl_sp = target->GetREPL(repl_error, m_command_options.language, nullptr, true);
598f2bd5c3eSSean Callanan                             if (!repl_error.Success())
599f2bd5c3eSSean Callanan                             {
600f2bd5c3eSSean Callanan                                 result.SetError(repl_error);
601f2bd5c3eSSean Callanan                                 return result.Succeeded();
602f2bd5c3eSSean Callanan                             }
603f2bd5c3eSSean Callanan                         }
604f2bd5c3eSSean Callanan 
605f2bd5c3eSSean Callanan                         if (repl_sp)
606f2bd5c3eSSean Callanan                         {
607f2bd5c3eSSean Callanan                             if (initialize)
608f2bd5c3eSSean Callanan                             {
609f2bd5c3eSSean Callanan                                 repl_sp->SetCommandOptions(m_command_options);
610f2bd5c3eSSean Callanan                                 repl_sp->SetFormatOptions(m_format_options);
611f2bd5c3eSSean Callanan                                 repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
612f2bd5c3eSSean Callanan                             }
613f2bd5c3eSSean Callanan 
614f2bd5c3eSSean Callanan                             IOHandlerSP io_handler_sp (repl_sp->GetIOHandler());
615f2bd5c3eSSean Callanan 
616f2bd5c3eSSean Callanan                             io_handler_sp->SetIsDone(false);
617f2bd5c3eSSean Callanan 
618f2bd5c3eSSean Callanan                             debugger.PushIOHandler(io_handler_sp);
619f2bd5c3eSSean Callanan                         }
620f2bd5c3eSSean Callanan                         else
621f2bd5c3eSSean Callanan                         {
622f2bd5c3eSSean Callanan                             repl_error.SetErrorStringWithFormat("Couldn't create a REPL for %s", Language::GetNameForLanguageType(m_command_options.language));
623f2bd5c3eSSean Callanan                             result.SetError(repl_error);
624f2bd5c3eSSean Callanan                             return result.Succeeded();
625f2bd5c3eSSean Callanan                         }
626f2bd5c3eSSean Callanan                     }
627f2bd5c3eSSean Callanan                 }
628f2bd5c3eSSean Callanan             }
629cf28a8b7SGreg Clayton             // No expression following options
630c8ecc2a9SEugene Zelenko             else if (expr == nullptr || expr[0] == '\0')
631cf28a8b7SGreg Clayton             {
632cf28a8b7SGreg Clayton                 GetMultilineExpression ();
633cf28a8b7SGreg Clayton                 return result.Succeeded();
634cf28a8b7SGreg Clayton             }
63530fdc8d8SChris Lattner         }
63630fdc8d8SChris Lattner     }
63730fdc8d8SChris Lattner 
638c8ecc2a9SEugene Zelenko     if (expr == nullptr)
63930fdc8d8SChris Lattner         expr = command;
64030fdc8d8SChris Lattner 
6416e8dc334SCaroline Tice     if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result))
642e5ee6f04SJim Ingham     {
643e5ee6f04SJim Ingham         Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
644e5ee6f04SJim Ingham         if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts())
645e5ee6f04SJim Ingham         {
646e5ee6f04SJim Ingham             CommandHistory &history = m_interpreter.GetCommandHistory();
647e5ee6f04SJim Ingham             // FIXME: Can we figure out what the user actually typed (e.g. some alias for expr???)
648e5ee6f04SJim Ingham             // If we can it would be nice to show that.
649e5ee6f04SJim Ingham             std::string fixed_command("expression ");
650e5ee6f04SJim Ingham             if (expr == command)
651e5ee6f04SJim Ingham                 fixed_command.append(m_fixed_expression);
652e5ee6f04SJim Ingham             else
653e5ee6f04SJim Ingham             {
654e5ee6f04SJim Ingham                 // Add in any options that might have been in the original command:
655e5ee6f04SJim Ingham                 fixed_command.append(command, expr - command);
656e5ee6f04SJim Ingham                 fixed_command.append(m_fixed_expression);
657e5ee6f04SJim Ingham             }
658e5ee6f04SJim Ingham             history.AppendString(fixed_command);
659e5ee6f04SJim Ingham         }
660fcd43b71SJohnny Chen         return true;
661e5ee6f04SJim Ingham     }
662fcd43b71SJohnny Chen 
663fcd43b71SJohnny Chen     result.SetStatus (eReturnStatusFailed);
664fcd43b71SJohnny Chen     return false;
66530fdc8d8SChris Lattner }
666