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 
285520a422bSEnrico Granata static lldb_private::Error
286520a422bSEnrico Granata CanBeUsedForElementCountPrinting (ValueObject& valobj)
287520a422bSEnrico Granata {
288520a422bSEnrico Granata     CompilerType type(valobj.GetCompilerType());
289520a422bSEnrico Granata     CompilerType pointee;
290520a422bSEnrico Granata     if (!type.IsPointerType(&pointee))
291520a422bSEnrico Granata         return Error("as it does not refer to a pointer");
292520a422bSEnrico Granata     if (pointee.IsVoidType())
293520a422bSEnrico Granata         return Error("as it refers to a pointer to void");
294520a422bSEnrico Granata     return Error();
295520a422bSEnrico Granata }
296520a422bSEnrico Granata 
29730fdc8d8SChris Lattner bool
298c8ecc2a9SEugene Zelenko CommandObjectExpression::EvaluateExpression(const char *expr,
2996e8dc334SCaroline Tice                                             Stream *output_stream,
3006e8dc334SCaroline Tice                                             Stream *error_stream,
301c8ecc2a9SEugene Zelenko                                             CommandReturnObject *result)
30230fdc8d8SChris Lattner {
303ba7b8e2cSGreg Clayton     // Don't use m_exe_ctx as this might be called asynchronously
304ba7b8e2cSGreg Clayton     // after the command object DoExecute has finished when doing
305ba7b8e2cSGreg Clayton     // multi-line expression that use an input reader...
306ba7b8e2cSGreg Clayton     ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
307ba7b8e2cSGreg Clayton 
308ba7b8e2cSGreg Clayton     Target *target = exe_ctx.GetTargetPtr();
309c0a6e061SSean Callanan 
310c0a6e061SSean Callanan     if (!target)
311893c932aSJim Ingham         target = GetDummyTarget();
312c0a6e061SSean Callanan 
313c14ee32dSGreg Clayton     if (target)
3146961e878SSean Callanan     {
3158b2fe6dcSGreg Clayton         lldb::ValueObjectSP result_valobj_sp;
31692adcac9SSean Callanan         bool keep_in_memory = true;
317009d110dSDawn Perchik         StackFrame *frame = exe_ctx.GetFramePtr();
31892adcac9SSean Callanan 
31935e1bda6SJim Ingham         EvaluateExpressionOptions options;
3206fbc48bcSJim Ingham         options.SetCoerceToId(m_varobj_options.use_objc);
3216fbc48bcSJim Ingham         options.SetUnwindOnError(m_command_options.unwind_on_error);
3226fbc48bcSJim Ingham         options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);
3236fbc48bcSJim Ingham         options.SetKeepInMemory(keep_in_memory);
3246fbc48bcSJim Ingham         options.SetUseDynamic(m_varobj_options.use_dynamic);
3256fbc48bcSJim Ingham         options.SetTryAllThreads(m_command_options.try_all_threads);
3266fbc48bcSJim Ingham         options.SetDebug(m_command_options.debug);
32715663c53SDawn Perchik         options.SetLanguage(m_command_options.language);
32815663c53SDawn Perchik 
329a1e541bfSJim Ingham         bool auto_apply_fixits;
330a1e541bfSJim Ingham         if (m_command_options.auto_apply_fixits == eLazyBoolCalculate)
331a1e541bfSJim Ingham             auto_apply_fixits = target->GetEnableAutoApplyFixIts();
332a1e541bfSJim Ingham         else
333a1e541bfSJim Ingham             auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes ? true : false;
334a1e541bfSJim Ingham 
335a1e541bfSJim Ingham         options.SetAutoApplyFixIts(auto_apply_fixits);
336a1e541bfSJim Ingham 
337863fab69SSean Callanan         if (m_command_options.top_level)
338863fab69SSean Callanan             options.SetExecutionPolicy(eExecutionPolicyTopLevel);
339863fab69SSean Callanan 
34023f8c95aSGreg Clayton         // If there is any chance we are going to stop and want to see
34123f8c95aSGreg Clayton         // what went wrong with our expression, we should generate debug info
34223f8c95aSGreg Clayton         if (!m_command_options.ignore_breakpoints ||
34323f8c95aSGreg Clayton             !m_command_options.unwind_on_error)
34423f8c95aSGreg Clayton             options.SetGenerateDebugInfo(true);
34523f8c95aSGreg Clayton 
34662afb9f6SGreg Clayton         if (m_command_options.timeout > 0)
34762afb9f6SGreg Clayton             options.SetTimeoutUsec(m_command_options.timeout);
3486f78f386SJim Ingham         else
3496f78f386SJim Ingham             options.SetTimeoutUsec(0);
350d4439aa9SEnrico Granata 
351e5ee6f04SJim Ingham         ExpressionResults success = target->EvaluateExpression(expr, frame, result_valobj_sp, options, &m_fixed_expression);
352e5ee6f04SJim Ingham 
353e5ee6f04SJim Ingham         // We only tell you about the FixIt if we applied it.  The compiler errors will suggest the FixIt if it parsed.
354e5ee6f04SJim Ingham         if (error_stream && !m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts())
355e5ee6f04SJim Ingham         {
356e5ee6f04SJim Ingham             if (success == eExpressionCompleted)
357e5ee6f04SJim Ingham                 error_stream->Printf ("  Fixit applied, fixed expression was: \n    %s\n", m_fixed_expression.c_str());
358e5ee6f04SJim Ingham         }
3598b2fe6dcSGreg Clayton 
3608b2fe6dcSGreg Clayton         if (result_valobj_sp)
3618b2fe6dcSGreg Clayton         {
362bf154daeSSean Callanan             Format format = m_format_options.GetFormat();
363bf154daeSSean Callanan 
364b71f3844SGreg Clayton             if (result_valobj_sp->GetError().Success())
36530fdc8d8SChris Lattner             {
366bf154daeSSean Callanan                 if (format != eFormatVoid)
367bf154daeSSean Callanan                 {
3681deb7962SGreg Clayton                     if (format != eFormatDefault)
3691deb7962SGreg Clayton                         result_valobj_sp->SetFormat (format);
37032c4085bSGreg Clayton 
371520a422bSEnrico Granata                     if (m_varobj_options.elem_count > 0)
372520a422bSEnrico Granata                     {
373520a422bSEnrico Granata                         Error error(CanBeUsedForElementCountPrinting(*result_valobj_sp));
374520a422bSEnrico Granata                         if (error.Fail())
375520a422bSEnrico Granata                         {
376520a422bSEnrico Granata                             result->AppendErrorWithFormat("expression cannot be used with --element-count %s\n", error.AsCString(""));
377520a422bSEnrico Granata                             result->SetStatus(eReturnStatusFailed);
378520a422bSEnrico Granata                             return false;
379520a422bSEnrico Granata                         }
380520a422bSEnrico Granata                     }
381520a422bSEnrico Granata 
3824d93b8cdSEnrico Granata                     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format));
38373e8c4d0SEnrico Granata                     options.SetVariableFormatDisplayLanguage(result_valobj_sp->GetPreferredDisplayLanguage());
384770eb05aSEnrico Granata 
3854d93b8cdSEnrico Granata                     result_valobj_sp->Dump(*output_stream,options);
3864d93b8cdSEnrico Granata 
387fcd43b71SJohnny Chen                     if (result)
388fcd43b71SJohnny Chen                         result->SetStatus (eReturnStatusSuccessFinishResult);
38930fdc8d8SChris Lattner                 }
390bf154daeSSean Callanan             }
39130fdc8d8SChris Lattner             else
39230fdc8d8SChris Lattner             {
393151c032cSJim Ingham                 if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult)
394bccce813SSean Callanan                 {
395bcf897faSSean Callanan                     if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid())
396bf154daeSSean Callanan                     {
397bcf897faSSean Callanan                         error_stream->PutCString("(void)\n");
398bcf897faSSean Callanan                     }
399bccce813SSean Callanan 
400bccce813SSean Callanan                     if (result)
401bccce813SSean Callanan                         result->SetStatus (eReturnStatusSuccessFinishResult);
402bccce813SSean Callanan                 }
403bccce813SSean Callanan                 else
404bccce813SSean Callanan                 {
4055fd05903SGreg Clayton                     const char *error_cstr = result_valobj_sp->GetError().AsCString();
4065fd05903SGreg Clayton                     if (error_cstr && error_cstr[0])
4075fd05903SGreg Clayton                     {
408c7bece56SGreg Clayton                         const size_t error_cstr_len = strlen (error_cstr);
4095fd05903SGreg Clayton                         const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';
4105fd05903SGreg Clayton                         if (strstr(error_cstr, "error:") != error_cstr)
4115fd05903SGreg Clayton                             error_stream->PutCString ("error: ");
4125fd05903SGreg Clayton                         error_stream->Write(error_cstr, error_cstr_len);
4135fd05903SGreg Clayton                         if (!ends_with_newline)
4145fd05903SGreg Clayton                             error_stream->EOL();
4155fd05903SGreg Clayton                     }
4165fd05903SGreg Clayton                     else
4175fd05903SGreg Clayton                     {
4185fd05903SGreg Clayton                         error_stream->PutCString ("error: unknown error\n");
4195fd05903SGreg Clayton                     }
4205fd05903SGreg Clayton 
421fcd43b71SJohnny Chen                     if (result)
422b71f3844SGreg Clayton                         result->SetStatus (eReturnStatusFailed);
42330fdc8d8SChris Lattner                 }
4248b2fe6dcSGreg Clayton             }
4258b2fe6dcSGreg Clayton         }
426bccce813SSean Callanan     }
4278b2fe6dcSGreg Clayton     else
4288b2fe6dcSGreg Clayton     {
4296e8dc334SCaroline Tice         error_stream->Printf ("error: invalid execution context for expression\n");
4308b2fe6dcSGreg Clayton         return false;
4318b2fe6dcSGreg Clayton     }
43230fdc8d8SChris Lattner 
43316ad5faeSSean Callanan     return true;
43430fdc8d8SChris Lattner }
43530fdc8d8SChris Lattner 
43644d93782SGreg Clayton void
43744d93782SGreg Clayton CommandObjectExpression::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
43844d93782SGreg Clayton {
43944d93782SGreg Clayton     io_handler.SetIsDone(true);
44044d93782SGreg Clayton //    StreamSP output_stream = io_handler.GetDebugger().GetAsyncOutputStream();
44144d93782SGreg Clayton //    StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream();
44244d93782SGreg Clayton     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
44344d93782SGreg Clayton     StreamFileSP error_sp(io_handler.GetErrorStreamFile());
44444d93782SGreg Clayton 
44544d93782SGreg Clayton     EvaluateExpression (line.c_str(),
44644d93782SGreg Clayton                         output_sp.get(),
44744d93782SGreg Clayton                         error_sp.get());
44844d93782SGreg Clayton     if (output_sp)
44944d93782SGreg Clayton         output_sp->Flush();
45044d93782SGreg Clayton     if (error_sp)
45144d93782SGreg Clayton         error_sp->Flush();
45244d93782SGreg Clayton }
45344d93782SGreg Clayton 
454*f52c40c5SSean Callanan bool
455*f52c40c5SSean Callanan CommandObjectExpression::IOHandlerIsInputComplete (IOHandler &io_handler,
456*f52c40c5SSean Callanan                                                    StringList &lines)
45744d93782SGreg Clayton {
458*f52c40c5SSean Callanan     // An empty lines is used to indicate the end of input
459*f52c40c5SSean Callanan     const size_t num_lines = lines.GetSize();
460*f52c40c5SSean Callanan     if (num_lines > 0 && lines[num_lines - 1].empty())
46144d93782SGreg Clayton     {
462*f52c40c5SSean Callanan         // Remove the last empty line from "lines" so it doesn't appear
463*f52c40c5SSean Callanan         // in our resulting input and return true to indicate we are done
464*f52c40c5SSean Callanan         // getting lines
46544d93782SGreg Clayton         lines.PopBack();
466*f52c40c5SSean Callanan         return true;
46744d93782SGreg Clayton     }
468*f52c40c5SSean Callanan     return false;
46944d93782SGreg Clayton }
47044d93782SGreg Clayton 
471cf28a8b7SGreg Clayton void
472cf28a8b7SGreg Clayton CommandObjectExpression::GetMultilineExpression ()
47330fdc8d8SChris Lattner {
47430fdc8d8SChris Lattner     m_expr_lines.clear();
47530fdc8d8SChris Lattner     m_expr_line_count = 0;
47630fdc8d8SChris Lattner 
47744d93782SGreg Clayton     Debugger &debugger = GetCommandInterpreter().GetDebugger();
478e30f11d9SKate Stone     bool color_prompt = debugger.GetUseColor();
47944d93782SGreg Clayton     const bool multiple_lines = true; // Get multiple lines
48044d93782SGreg Clayton     IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger,
481e30f11d9SKate Stone                                                     IOHandler::Type::Expression,
48244d93782SGreg Clayton                                                     "lldb-expr",      // Name of input reader for history
483c8ecc2a9SEugene Zelenko                                                     nullptr,          // No prompt
484c8ecc2a9SEugene Zelenko                                                     nullptr,          // Continuation prompt
48544d93782SGreg Clayton                                                     multiple_lines,
486e30f11d9SKate Stone                                                     color_prompt,
487f6913cd7SGreg Clayton                                                     1,                // Show line numbers starting at 1
48844d93782SGreg Clayton                                                     *this));
489b6892508SGreg Clayton 
490b6892508SGreg Clayton     StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile());
491b6892508SGreg Clayton     if (output_sp)
492b6892508SGreg Clayton     {
493b6892508SGreg Clayton         output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
494b6892508SGreg Clayton         output_sp->Flush();
495b6892508SGreg Clayton     }
49644d93782SGreg Clayton     debugger.PushIOHandler(io_handler_sp);
497cf28a8b7SGreg Clayton }
498cf28a8b7SGreg Clayton 
499cf28a8b7SGreg Clayton bool
500c8ecc2a9SEugene Zelenko CommandObjectExpression::DoExecute(const char *command,
501c8ecc2a9SEugene Zelenko                                    CommandReturnObject &result)
502cf28a8b7SGreg Clayton {
503e5ee6f04SJim Ingham     m_fixed_expression.clear();
504cf28a8b7SGreg Clayton     m_option_group.NotifyOptionParsingStarting();
505cf28a8b7SGreg Clayton 
506c8ecc2a9SEugene Zelenko     const char * expr = nullptr;
507cf28a8b7SGreg Clayton 
508cf28a8b7SGreg Clayton     if (command[0] == '\0')
509cf28a8b7SGreg Clayton     {
510cf28a8b7SGreg Clayton         GetMultilineExpression ();
51130fdc8d8SChris Lattner         return result.Succeeded();
51230fdc8d8SChris Lattner     }
51330fdc8d8SChris Lattner 
51430fdc8d8SChris Lattner     if (command[0] == '-')
51530fdc8d8SChris Lattner     {
51630fdc8d8SChris Lattner         // We have some options and these options MUST end with --.
517c8ecc2a9SEugene Zelenko         const char *end_options = nullptr;
51830fdc8d8SChris Lattner         const char *s = command;
51930fdc8d8SChris Lattner         while (s && s[0])
52030fdc8d8SChris Lattner         {
52130fdc8d8SChris Lattner             end_options = ::strstr (s, "--");
52230fdc8d8SChris Lattner             if (end_options)
52330fdc8d8SChris Lattner             {
52430fdc8d8SChris Lattner                 end_options += 2; // Get past the "--"
52530fdc8d8SChris Lattner                 if (::isspace (end_options[0]))
52630fdc8d8SChris Lattner                 {
52730fdc8d8SChris Lattner                     expr = end_options;
52830fdc8d8SChris Lattner                     while (::isspace (*expr))
52930fdc8d8SChris Lattner                         ++expr;
53030fdc8d8SChris Lattner                     break;
53130fdc8d8SChris Lattner                 }
53230fdc8d8SChris Lattner             }
53330fdc8d8SChris Lattner             s = end_options;
53430fdc8d8SChris Lattner         }
53530fdc8d8SChris Lattner 
53630fdc8d8SChris Lattner         if (end_options)
53730fdc8d8SChris Lattner         {
53800b7f95bSPavel Labath             Args args (llvm::StringRef(command, end_options - command));
539a7015092SGreg Clayton             if (!ParseOptions (args, result))
54030fdc8d8SChris Lattner                 return false;
541f6b8b581SGreg Clayton 
5421deb7962SGreg Clayton             Error error (m_option_group.NotifyOptionParsingFinished());
543f6b8b581SGreg Clayton             if (error.Fail())
544f6b8b581SGreg Clayton             {
545f6b8b581SGreg Clayton                 result.AppendError (error.AsCString());
546f6b8b581SGreg Clayton                 result.SetStatus (eReturnStatusFailed);
547f6b8b581SGreg Clayton                 return false;
548f6b8b581SGreg Clayton             }
549cf28a8b7SGreg Clayton 
550f2bd5c3eSSean Callanan             if (m_repl_option.GetOptionValue().GetCurrentValue())
551f2bd5c3eSSean Callanan             {
552f2bd5c3eSSean Callanan                 Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
553f2bd5c3eSSean Callanan                 if (target)
554f2bd5c3eSSean Callanan                 {
555f2bd5c3eSSean Callanan                     // Drop into REPL
556f2bd5c3eSSean Callanan                     m_expr_lines.clear();
557f2bd5c3eSSean Callanan                     m_expr_line_count = 0;
558f2bd5c3eSSean Callanan 
559f2bd5c3eSSean Callanan                     Debugger &debugger = target->GetDebugger();
560f2bd5c3eSSean Callanan 
561f2bd5c3eSSean Callanan                     // Check if the LLDB command interpreter is sitting on top of a REPL that
562f2bd5c3eSSean Callanan                     // launched it...
563f2bd5c3eSSean Callanan                     if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter, IOHandler::Type::REPL))
564f2bd5c3eSSean Callanan                     {
565f2bd5c3eSSean Callanan                         // the LLDB command interpreter is sitting on top of a REPL that launched it,
566f2bd5c3eSSean Callanan                         // so just say the command interpreter is done and fall back to the existing REPL
567f2bd5c3eSSean Callanan                         m_interpreter.GetIOHandler(false)->SetIsDone(true);
568f2bd5c3eSSean Callanan                     }
569f2bd5c3eSSean Callanan                     else
570f2bd5c3eSSean Callanan                     {
571f2bd5c3eSSean Callanan                         // We are launching the REPL on top of the current LLDB command interpreter,
572f2bd5c3eSSean Callanan                         // so just push one
573f2bd5c3eSSean Callanan                         bool initialize = false;
574f2bd5c3eSSean Callanan                         Error repl_error;
575f2bd5c3eSSean Callanan                         REPLSP repl_sp (target->GetREPL(repl_error, m_command_options.language, nullptr, false));
576f2bd5c3eSSean Callanan 
577f2bd5c3eSSean Callanan                         if (!repl_sp)
578f2bd5c3eSSean Callanan                         {
579f2bd5c3eSSean Callanan                             initialize = true;
580f2bd5c3eSSean Callanan                             repl_sp = target->GetREPL(repl_error, m_command_options.language, nullptr, true);
581f2bd5c3eSSean Callanan                             if (!repl_error.Success())
582f2bd5c3eSSean Callanan                             {
583f2bd5c3eSSean Callanan                                 result.SetError(repl_error);
584f2bd5c3eSSean Callanan                                 return result.Succeeded();
585f2bd5c3eSSean Callanan                             }
586f2bd5c3eSSean Callanan                         }
587f2bd5c3eSSean Callanan 
588f2bd5c3eSSean Callanan                         if (repl_sp)
589f2bd5c3eSSean Callanan                         {
590f2bd5c3eSSean Callanan                             if (initialize)
591f2bd5c3eSSean Callanan                             {
592f2bd5c3eSSean Callanan                                 repl_sp->SetCommandOptions(m_command_options);
593f2bd5c3eSSean Callanan                                 repl_sp->SetFormatOptions(m_format_options);
594f2bd5c3eSSean Callanan                                 repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
595f2bd5c3eSSean Callanan                             }
596f2bd5c3eSSean Callanan 
597f2bd5c3eSSean Callanan                             IOHandlerSP io_handler_sp (repl_sp->GetIOHandler());
598f2bd5c3eSSean Callanan 
599f2bd5c3eSSean Callanan                             io_handler_sp->SetIsDone(false);
600f2bd5c3eSSean Callanan 
601f2bd5c3eSSean Callanan                             debugger.PushIOHandler(io_handler_sp);
602f2bd5c3eSSean Callanan                         }
603f2bd5c3eSSean Callanan                         else
604f2bd5c3eSSean Callanan                         {
605f2bd5c3eSSean Callanan                             repl_error.SetErrorStringWithFormat("Couldn't create a REPL for %s", Language::GetNameForLanguageType(m_command_options.language));
606f2bd5c3eSSean Callanan                             result.SetError(repl_error);
607f2bd5c3eSSean Callanan                             return result.Succeeded();
608f2bd5c3eSSean Callanan                         }
609f2bd5c3eSSean Callanan                     }
610f2bd5c3eSSean Callanan                 }
611f2bd5c3eSSean Callanan             }
612cf28a8b7SGreg Clayton             // No expression following options
613c8ecc2a9SEugene Zelenko             else if (expr == nullptr || expr[0] == '\0')
614cf28a8b7SGreg Clayton             {
615cf28a8b7SGreg Clayton                 GetMultilineExpression ();
616cf28a8b7SGreg Clayton                 return result.Succeeded();
617cf28a8b7SGreg Clayton             }
61830fdc8d8SChris Lattner         }
61930fdc8d8SChris Lattner     }
62030fdc8d8SChris Lattner 
621c8ecc2a9SEugene Zelenko     if (expr == nullptr)
62230fdc8d8SChris Lattner         expr = command;
62330fdc8d8SChris Lattner 
6246e8dc334SCaroline Tice     if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result))
625e5ee6f04SJim Ingham     {
626e5ee6f04SJim Ingham         Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
627e5ee6f04SJim Ingham         if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts())
628e5ee6f04SJim Ingham         {
629e5ee6f04SJim Ingham             CommandHistory &history = m_interpreter.GetCommandHistory();
630e5ee6f04SJim Ingham             // FIXME: Can we figure out what the user actually typed (e.g. some alias for expr???)
631e5ee6f04SJim Ingham             // If we can it would be nice to show that.
632e5ee6f04SJim Ingham             std::string fixed_command("expression ");
633e5ee6f04SJim Ingham             if (expr == command)
634e5ee6f04SJim Ingham                 fixed_command.append(m_fixed_expression);
635e5ee6f04SJim Ingham             else
636e5ee6f04SJim Ingham             {
637e5ee6f04SJim Ingham                 // Add in any options that might have been in the original command:
638e5ee6f04SJim Ingham                 fixed_command.append(command, expr - command);
639e5ee6f04SJim Ingham                 fixed_command.append(m_fixed_expression);
640e5ee6f04SJim Ingham             }
641e5ee6f04SJim Ingham             history.AppendString(fixed_command);
642e5ee6f04SJim Ingham         }
643fcd43b71SJohnny Chen         return true;
644e5ee6f04SJim Ingham     }
645fcd43b71SJohnny Chen 
646fcd43b71SJohnny Chen     result.SetStatus (eReturnStatusFailed);
647fcd43b71SJohnny Chen     return false;
64830fdc8d8SChris Lattner }
649