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*a1e541bfSJim 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."},
661deb7962SGreg Clayton };
671deb7962SGreg Clayton 
681deb7962SGreg Clayton uint32_t
691deb7962SGreg Clayton CommandObjectExpression::CommandOptions::GetNumDefinitions ()
701deb7962SGreg Clayton {
7128606954SSaleem Abdulrasool     return llvm::array_lengthof(g_option_table);
721deb7962SGreg Clayton }
731deb7962SGreg Clayton 
7430fdc8d8SChris Lattner Error
751deb7962SGreg Clayton CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &interpreter,
761deb7962SGreg Clayton                                                          uint32_t option_idx,
771deb7962SGreg Clayton                                                          const char *option_arg)
7830fdc8d8SChris Lattner {
7930fdc8d8SChris Lattner     Error error;
8030fdc8d8SChris Lattner 
813bcdfc0eSGreg Clayton     const int short_option = g_option_table[option_idx].short_option;
8230fdc8d8SChris Lattner 
8330fdc8d8SChris Lattner     switch (short_option)
8430fdc8d8SChris Lattner     {
8515663c53SDawn Perchik     case 'l':
860e0984eeSJim Ingham         language = Language::GetLanguageTypeFromString (option_arg);
8715663c53SDawn Perchik         if (language == eLanguageTypeUnknown)
8815663c53SDawn Perchik             error.SetErrorStringWithFormat ("unknown language type: '%s' for expression", option_arg);
8915663c53SDawn Perchik         break;
9030fdc8d8SChris Lattner 
9135e1bda6SJim Ingham     case 'a':
9235e1bda6SJim Ingham         {
9335e1bda6SJim Ingham             bool success;
9435e1bda6SJim Ingham             bool result;
9535e1bda6SJim Ingham             result = Args::StringToBoolean(option_arg, true, &success);
9635e1bda6SJim Ingham             if (!success)
9735e1bda6SJim Ingham                 error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg);
9835e1bda6SJim Ingham             else
9935e1bda6SJim Ingham                 try_all_threads = result;
10035e1bda6SJim Ingham         }
1016c68fb45SJim Ingham         break;
1026c68fb45SJim Ingham 
103184e9811SJim Ingham     case 'i':
104184e9811SJim Ingham         {
105184e9811SJim Ingham             bool success;
106184e9811SJim Ingham             bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
107184e9811SJim Ingham             if (success)
108184e9811SJim Ingham                 ignore_breakpoints = tmp_value;
109184e9811SJim Ingham             else
110184e9811SJim Ingham                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
111184e9811SJim Ingham             break;
112184e9811SJim Ingham         }
11335e1bda6SJim Ingham     case 't':
11435e1bda6SJim Ingham         {
11535e1bda6SJim Ingham             bool success;
11635e1bda6SJim Ingham             uint32_t result;
1175275aaa0SVince Harron             result = StringConvert::ToUInt32(option_arg, 0, 0, &success);
11835e1bda6SJim Ingham             if (success)
11935e1bda6SJim Ingham                 timeout = result;
12035e1bda6SJim Ingham             else
12135e1bda6SJim Ingham                 error.SetErrorStringWithFormat ("invalid timeout setting \"%s\"", option_arg);
12235e1bda6SJim Ingham         }
12335e1bda6SJim Ingham         break;
12435e1bda6SJim Ingham 
125399f1cafSJim Ingham     case 'u':
1263bfdaa2aSSean Callanan         {
127399f1cafSJim Ingham             bool success;
128184e9811SJim Ingham             bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
129184e9811SJim Ingham             if (success)
130184e9811SJim Ingham                 unwind_on_error = tmp_value;
131184e9811SJim Ingham             else
13286edbf41SGreg Clayton                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
133399f1cafSJim Ingham             break;
1343bfdaa2aSSean Callanan         }
1354d93b8cdSEnrico Granata 
1364d93b8cdSEnrico Granata     case 'v':
1374d93b8cdSEnrico Granata         if (!option_arg)
1384d93b8cdSEnrico Granata         {
1394d93b8cdSEnrico Granata             m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull;
1404d93b8cdSEnrico Granata             break;
1414d93b8cdSEnrico Granata         }
1424d93b8cdSEnrico Granata         m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
1434d93b8cdSEnrico Granata         if (!error.Success())
1444d93b8cdSEnrico Granata             error.SetErrorStringWithFormat ("unrecognized value for description-verbosity '%s'", option_arg);
1454d93b8cdSEnrico Granata         break;
1464d93b8cdSEnrico Granata 
14762afb9f6SGreg Clayton     case 'g':
14862afb9f6SGreg Clayton         debug = true;
14962afb9f6SGreg Clayton         unwind_on_error = false;
15062afb9f6SGreg Clayton         ignore_breakpoints = false;
15162afb9f6SGreg Clayton         break;
15262afb9f6SGreg Clayton 
153*a1e541bfSJim Ingham     case 'X':
154*a1e541bfSJim Ingham         {
155*a1e541bfSJim Ingham             bool success;
156*a1e541bfSJim Ingham             bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
157*a1e541bfSJim Ingham             if (success)
158*a1e541bfSJim Ingham                 auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo;
159*a1e541bfSJim Ingham             else
160*a1e541bfSJim Ingham                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
161*a1e541bfSJim Ingham             break;
162*a1e541bfSJim Ingham         }
163*a1e541bfSJim Ingham 
16430fdc8d8SChris Lattner     default:
16586edbf41SGreg Clayton         error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
16630fdc8d8SChris Lattner         break;
16730fdc8d8SChris Lattner     }
16830fdc8d8SChris Lattner 
16930fdc8d8SChris Lattner     return error;
17030fdc8d8SChris Lattner }
17130fdc8d8SChris Lattner 
17230fdc8d8SChris Lattner void
1731deb7962SGreg Clayton CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter)
17430fdc8d8SChris Lattner {
175184e9811SJim Ingham     Process *process = interpreter.GetExecutionContext().GetProcessPtr();
176c8ecc2a9SEugene Zelenko     if (process != nullptr)
177184e9811SJim Ingham     {
178184e9811SJim Ingham         ignore_breakpoints = process->GetIgnoreBreakpointsInExpressions();
179184e9811SJim Ingham         unwind_on_error    = process->GetUnwindOnErrorInExpressions();
180184e9811SJim Ingham     }
181184e9811SJim Ingham     else
182184e9811SJim Ingham     {
183fc03f8fcSGreg Clayton         ignore_breakpoints = true;
184399f1cafSJim Ingham         unwind_on_error = true;
185184e9811SJim Ingham     }
186184e9811SJim Ingham 
18730fdc8d8SChris Lattner     show_summary = true;
18835e1bda6SJim Ingham     try_all_threads = true;
18935e1bda6SJim Ingham     timeout = 0;
19062afb9f6SGreg Clayton     debug = false;
19115663c53SDawn Perchik     language = eLanguageTypeUnknown;
1924d93b8cdSEnrico Granata     m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
193*a1e541bfSJim Ingham     auto_apply_fixits = eLazyBoolCalculate;
19430fdc8d8SChris Lattner }
19530fdc8d8SChris Lattner 
196e0d378b3SGreg Clayton const OptionDefinition*
19730fdc8d8SChris Lattner CommandObjectExpression::CommandOptions::GetDefinitions ()
19830fdc8d8SChris Lattner {
19930fdc8d8SChris Lattner     return g_option_table;
20030fdc8d8SChris Lattner }
20130fdc8d8SChris Lattner 
202a7015092SGreg Clayton CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) :
2035a988416SJim Ingham     CommandObjectRaw(interpreter,
20430fdc8d8SChris Lattner                      "expression",
20515663c53SDawn Perchik                      "Evaluate an expression in the current program context, using user defined variables and variables currently in scope.",
206c8ecc2a9SEugene Zelenko                      nullptr,
207e87764f2SEnrico Granata                      eCommandProcessMustBePaused | eCommandTryTargetAPILock),
20844d93782SGreg Clayton     IOHandlerDelegate (IOHandlerDelegate::Completion::Expression),
2091deb7962SGreg Clayton     m_option_group (interpreter),
2101deb7962SGreg Clayton     m_format_options (eFormatDefault),
211f2bd5c3eSSean Callanan     m_repl_option (LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false, true),
2121deb7962SGreg Clayton     m_command_options (),
21330fdc8d8SChris Lattner     m_expr_line_count (0),
21430fdc8d8SChris Lattner     m_expr_lines ()
21530fdc8d8SChris Lattner {
21630fdc8d8SChris Lattner     SetHelpLong(
217ea671fbdSKate Stone R"(
218ea671fbdSKate Stone Timeouts:
219ea671fbdSKate Stone 
220ea671fbdSKate Stone )" "    If the expression can be evaluated statically (without running code) then it will be.  \
221ea671fbdSKate Stone Otherwise, by default the expression will run on the current thread with a short timeout: \
222ea671fbdSKate Stone currently .25 seconds.  If it doesn't return in that time, the evaluation will be interrupted \
223ea671fbdSKate Stone and resumed with all threads running.  You can use the -a option to disable retrying on all \
224ea671fbdSKate Stone threads.  You can use the -t option to set a shorter timeout." R"(
225ea671fbdSKate Stone 
226ea671fbdSKate Stone User defined variables:
227ea671fbdSKate Stone 
228ea671fbdSKate Stone )" "    You can define your own variables for convenience or to be used in subsequent expressions.  \
229ea671fbdSKate Stone You define them the same way you would define variables in C.  If the first character of \
230ea671fbdSKate Stone your user defined variable is a $, then the variable's value will be available in future \
231ea671fbdSKate Stone expressions, otherwise it will just be available in the current expression." R"(
232ea671fbdSKate Stone 
233ea671fbdSKate Stone Continuing evaluation after a breakpoint:
234ea671fbdSKate Stone 
235ea671fbdSKate Stone )" "    If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \
236ea671fbdSKate Stone you are done with your investigation, you can either remove the expression execution frames \
237ea671fbdSKate Stone from the stack with \"thread return -x\" or if you are still interested in the expression result \
238ea671fbdSKate Stone you can issue the \"continue\" command and the expression evaluation will complete and the \
239ea671fbdSKate Stone expression result will be available using the \"thread.completed-expression\" key in the thread \
240ea671fbdSKate Stone format." R"(
241ea671fbdSKate Stone 
242ea671fbdSKate Stone Examples:
243ea671fbdSKate Stone 
244ea671fbdSKate Stone     expr my_struct->a = my_array[3]
245ea671fbdSKate Stone     expr -f bin -- (index * 8) + 5
246ea671fbdSKate Stone     expr unsigned int $foo = 5
247ea671fbdSKate Stone     expr char c[] = \"foo\"; c[0])"
248ea671fbdSKate Stone     );
249405fe67fSCaroline Tice 
250405fe67fSCaroline Tice     CommandArgumentEntry arg;
251405fe67fSCaroline Tice     CommandArgumentData expression_arg;
252405fe67fSCaroline Tice 
253405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
254405fe67fSCaroline Tice     expression_arg.arg_type = eArgTypeExpression;
255405fe67fSCaroline Tice     expression_arg.arg_repetition = eArgRepeatPlain;
256405fe67fSCaroline Tice 
257405fe67fSCaroline Tice     // There is only one variant this argument could be; put it into the argument entry.
258405fe67fSCaroline Tice     arg.push_back (expression_arg);
259405fe67fSCaroline Tice 
260405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
261405fe67fSCaroline Tice     m_arguments.push_back (arg);
2621deb7962SGreg Clayton 
2635009f9d5SGreg Clayton     // Add the "--format" and "--gdb-format"
2645009f9d5SGreg Clayton     m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1);
2651deb7962SGreg Clayton     m_option_group.Append (&m_command_options);
266b576bba2SEnrico Granata     m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
267f2bd5c3eSSean Callanan     m_option_group.Append (&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
2681deb7962SGreg Clayton     m_option_group.Finalize();
26930fdc8d8SChris Lattner }
27030fdc8d8SChris Lattner 
271c8ecc2a9SEugene Zelenko CommandObjectExpression::~CommandObjectExpression() = default;
27230fdc8d8SChris Lattner 
27330fdc8d8SChris Lattner Options *
27430fdc8d8SChris Lattner CommandObjectExpression::GetOptions ()
27530fdc8d8SChris Lattner {
2761deb7962SGreg Clayton     return &m_option_group;
27730fdc8d8SChris Lattner }
27830fdc8d8SChris Lattner 
27930fdc8d8SChris Lattner bool
280c8ecc2a9SEugene Zelenko CommandObjectExpression::EvaluateExpression(const char *expr,
2816e8dc334SCaroline Tice                                             Stream *output_stream,
2826e8dc334SCaroline Tice                                             Stream *error_stream,
283c8ecc2a9SEugene Zelenko                                             CommandReturnObject *result)
28430fdc8d8SChris Lattner {
285ba7b8e2cSGreg Clayton     // Don't use m_exe_ctx as this might be called asynchronously
286ba7b8e2cSGreg Clayton     // after the command object DoExecute has finished when doing
287ba7b8e2cSGreg Clayton     // multi-line expression that use an input reader...
288ba7b8e2cSGreg Clayton     ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
289ba7b8e2cSGreg Clayton 
290ba7b8e2cSGreg Clayton     Target *target = exe_ctx.GetTargetPtr();
291c0a6e061SSean Callanan 
292c0a6e061SSean Callanan     if (!target)
293893c932aSJim Ingham         target = GetDummyTarget();
294c0a6e061SSean Callanan 
295c14ee32dSGreg Clayton     if (target)
2966961e878SSean Callanan     {
2978b2fe6dcSGreg Clayton         lldb::ValueObjectSP result_valobj_sp;
29892adcac9SSean Callanan         bool keep_in_memory = true;
299009d110dSDawn Perchik         StackFrame *frame = exe_ctx.GetFramePtr();
30092adcac9SSean Callanan 
30135e1bda6SJim Ingham         EvaluateExpressionOptions options;
3026fbc48bcSJim Ingham         options.SetCoerceToId(m_varobj_options.use_objc);
3036fbc48bcSJim Ingham         options.SetUnwindOnError(m_command_options.unwind_on_error);
3046fbc48bcSJim Ingham         options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);
3056fbc48bcSJim Ingham         options.SetKeepInMemory(keep_in_memory);
3066fbc48bcSJim Ingham         options.SetUseDynamic(m_varobj_options.use_dynamic);
3076fbc48bcSJim Ingham         options.SetTryAllThreads(m_command_options.try_all_threads);
3086fbc48bcSJim Ingham         options.SetDebug(m_command_options.debug);
30915663c53SDawn Perchik         options.SetLanguage(m_command_options.language);
31015663c53SDawn Perchik 
311*a1e541bfSJim Ingham         bool auto_apply_fixits;
312*a1e541bfSJim Ingham         if (m_command_options.auto_apply_fixits == eLazyBoolCalculate)
313*a1e541bfSJim Ingham             auto_apply_fixits = target->GetEnableAutoApplyFixIts();
314*a1e541bfSJim Ingham         else
315*a1e541bfSJim Ingham             auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes ? true : false;
316*a1e541bfSJim Ingham 
317*a1e541bfSJim Ingham         options.SetAutoApplyFixIts(auto_apply_fixits);
318*a1e541bfSJim Ingham 
31923f8c95aSGreg Clayton         // If there is any chance we are going to stop and want to see
32023f8c95aSGreg Clayton         // what went wrong with our expression, we should generate debug info
32123f8c95aSGreg Clayton         if (!m_command_options.ignore_breakpoints ||
32223f8c95aSGreg Clayton             !m_command_options.unwind_on_error)
32323f8c95aSGreg Clayton             options.SetGenerateDebugInfo(true);
32423f8c95aSGreg Clayton 
32562afb9f6SGreg Clayton         if (m_command_options.timeout > 0)
32662afb9f6SGreg Clayton             options.SetTimeoutUsec(m_command_options.timeout);
3276f78f386SJim Ingham         else
3286f78f386SJim Ingham             options.SetTimeoutUsec(0);
329d4439aa9SEnrico Granata 
330009d110dSDawn Perchik         target->EvaluateExpression(expr, frame, result_valobj_sp, options);
3318b2fe6dcSGreg Clayton 
3328b2fe6dcSGreg Clayton         if (result_valobj_sp)
3338b2fe6dcSGreg Clayton         {
334bf154daeSSean Callanan             Format format = m_format_options.GetFormat();
335bf154daeSSean Callanan 
336b71f3844SGreg Clayton             if (result_valobj_sp->GetError().Success())
33730fdc8d8SChris Lattner             {
338bf154daeSSean Callanan                 if (format != eFormatVoid)
339bf154daeSSean Callanan                 {
3401deb7962SGreg Clayton                     if (format != eFormatDefault)
3411deb7962SGreg Clayton                         result_valobj_sp->SetFormat (format);
34232c4085bSGreg Clayton 
3434d93b8cdSEnrico Granata                     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format));
34473e8c4d0SEnrico Granata                     options.SetVariableFormatDisplayLanguage(result_valobj_sp->GetPreferredDisplayLanguage());
345770eb05aSEnrico Granata 
3464d93b8cdSEnrico Granata                     result_valobj_sp->Dump(*output_stream,options);
3474d93b8cdSEnrico Granata 
348fcd43b71SJohnny Chen                     if (result)
349fcd43b71SJohnny Chen                         result->SetStatus (eReturnStatusSuccessFinishResult);
35030fdc8d8SChris Lattner                 }
351bf154daeSSean Callanan             }
35230fdc8d8SChris Lattner             else
35330fdc8d8SChris Lattner             {
354151c032cSJim Ingham                 if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult)
355bccce813SSean Callanan                 {
356bcf897faSSean Callanan                     if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid())
357bf154daeSSean Callanan                     {
358bcf897faSSean Callanan                         error_stream->PutCString("(void)\n");
359bcf897faSSean Callanan                     }
360bccce813SSean Callanan 
361bccce813SSean Callanan                     if (result)
362bccce813SSean Callanan                         result->SetStatus (eReturnStatusSuccessFinishResult);
363bccce813SSean Callanan                 }
364bccce813SSean Callanan                 else
365bccce813SSean Callanan                 {
3665fd05903SGreg Clayton                     const char *error_cstr = result_valobj_sp->GetError().AsCString();
3675fd05903SGreg Clayton                     if (error_cstr && error_cstr[0])
3685fd05903SGreg Clayton                     {
369c7bece56SGreg Clayton                         const size_t error_cstr_len = strlen (error_cstr);
3705fd05903SGreg Clayton                         const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';
3715fd05903SGreg Clayton                         if (strstr(error_cstr, "error:") != error_cstr)
3725fd05903SGreg Clayton                             error_stream->PutCString ("error: ");
3735fd05903SGreg Clayton                         error_stream->Write(error_cstr, error_cstr_len);
3745fd05903SGreg Clayton                         if (!ends_with_newline)
3755fd05903SGreg Clayton                             error_stream->EOL();
3765fd05903SGreg Clayton                     }
3775fd05903SGreg Clayton                     else
3785fd05903SGreg Clayton                     {
3795fd05903SGreg Clayton                         error_stream->PutCString ("error: unknown error\n");
3805fd05903SGreg Clayton                     }
3815fd05903SGreg Clayton 
382fcd43b71SJohnny Chen                     if (result)
383b71f3844SGreg Clayton                         result->SetStatus (eReturnStatusFailed);
38430fdc8d8SChris Lattner                 }
3858b2fe6dcSGreg Clayton             }
3868b2fe6dcSGreg Clayton         }
387bccce813SSean Callanan     }
3888b2fe6dcSGreg Clayton     else
3898b2fe6dcSGreg Clayton     {
3906e8dc334SCaroline Tice         error_stream->Printf ("error: invalid execution context for expression\n");
3918b2fe6dcSGreg Clayton         return false;
3928b2fe6dcSGreg Clayton     }
39330fdc8d8SChris Lattner 
39416ad5faeSSean Callanan     return true;
39530fdc8d8SChris Lattner }
39630fdc8d8SChris Lattner 
39744d93782SGreg Clayton void
39844d93782SGreg Clayton CommandObjectExpression::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
39944d93782SGreg Clayton {
40044d93782SGreg Clayton     io_handler.SetIsDone(true);
40144d93782SGreg Clayton //    StreamSP output_stream = io_handler.GetDebugger().GetAsyncOutputStream();
40244d93782SGreg Clayton //    StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream();
40344d93782SGreg Clayton     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
40444d93782SGreg Clayton     StreamFileSP error_sp(io_handler.GetErrorStreamFile());
40544d93782SGreg Clayton 
40644d93782SGreg Clayton     EvaluateExpression (line.c_str(),
40744d93782SGreg Clayton                         output_sp.get(),
40844d93782SGreg Clayton                         error_sp.get());
40944d93782SGreg Clayton     if (output_sp)
41044d93782SGreg Clayton         output_sp->Flush();
41144d93782SGreg Clayton     if (error_sp)
41244d93782SGreg Clayton         error_sp->Flush();
41344d93782SGreg Clayton }
41444d93782SGreg Clayton 
41544d93782SGreg Clayton LineStatus
41644d93782SGreg Clayton CommandObjectExpression::IOHandlerLinesUpdated (IOHandler &io_handler,
41744d93782SGreg Clayton                                                 StringList &lines,
41844d93782SGreg Clayton                                                 uint32_t line_idx,
41944d93782SGreg Clayton                                                 Error &error)
42044d93782SGreg Clayton {
42144d93782SGreg Clayton     if (line_idx == UINT32_MAX)
42244d93782SGreg Clayton     {
42344d93782SGreg Clayton         // Remove the last line from "lines" so it doesn't appear
42444d93782SGreg Clayton         // in our final expression
42544d93782SGreg Clayton         lines.PopBack();
42644d93782SGreg Clayton         error.Clear();
42744d93782SGreg Clayton         return LineStatus::Done;
42844d93782SGreg Clayton     }
42944d93782SGreg Clayton     else if (line_idx + 1 == lines.GetSize())
43044d93782SGreg Clayton     {
43144d93782SGreg Clayton         // The last line was edited, if this line is empty, then we are done
43244d93782SGreg Clayton         // getting our multiple lines.
43344d93782SGreg Clayton         if (lines[line_idx].empty())
43444d93782SGreg Clayton             return LineStatus::Done;
43544d93782SGreg Clayton     }
43644d93782SGreg Clayton     return LineStatus::Success;
43744d93782SGreg Clayton }
43844d93782SGreg Clayton 
439cf28a8b7SGreg Clayton void
440cf28a8b7SGreg Clayton CommandObjectExpression::GetMultilineExpression ()
44130fdc8d8SChris Lattner {
44230fdc8d8SChris Lattner     m_expr_lines.clear();
44330fdc8d8SChris Lattner     m_expr_line_count = 0;
44430fdc8d8SChris Lattner 
44544d93782SGreg Clayton     Debugger &debugger = GetCommandInterpreter().GetDebugger();
446e30f11d9SKate Stone     bool color_prompt = debugger.GetUseColor();
44744d93782SGreg Clayton     const bool multiple_lines = true; // Get multiple lines
44844d93782SGreg Clayton     IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger,
449e30f11d9SKate Stone                                                     IOHandler::Type::Expression,
45044d93782SGreg Clayton                                                     "lldb-expr",      // Name of input reader for history
451c8ecc2a9SEugene Zelenko                                                     nullptr,          // No prompt
452c8ecc2a9SEugene Zelenko                                                     nullptr,          // Continuation prompt
45344d93782SGreg Clayton                                                     multiple_lines,
454e30f11d9SKate Stone                                                     color_prompt,
455f6913cd7SGreg Clayton                                                     1,                // Show line numbers starting at 1
45644d93782SGreg Clayton                                                     *this));
457b6892508SGreg Clayton 
458b6892508SGreg Clayton     StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile());
459b6892508SGreg Clayton     if (output_sp)
460b6892508SGreg Clayton     {
461b6892508SGreg Clayton         output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
462b6892508SGreg Clayton         output_sp->Flush();
463b6892508SGreg Clayton     }
46444d93782SGreg Clayton     debugger.PushIOHandler(io_handler_sp);
465cf28a8b7SGreg Clayton }
466cf28a8b7SGreg Clayton 
467cf28a8b7SGreg Clayton bool
468c8ecc2a9SEugene Zelenko CommandObjectExpression::DoExecute(const char *command,
469c8ecc2a9SEugene Zelenko                                    CommandReturnObject &result)
470cf28a8b7SGreg Clayton {
471cf28a8b7SGreg Clayton     m_option_group.NotifyOptionParsingStarting();
472cf28a8b7SGreg Clayton 
473c8ecc2a9SEugene Zelenko     const char * expr = nullptr;
474cf28a8b7SGreg Clayton 
475cf28a8b7SGreg Clayton     if (command[0] == '\0')
476cf28a8b7SGreg Clayton     {
477cf28a8b7SGreg Clayton         GetMultilineExpression ();
47830fdc8d8SChris Lattner         return result.Succeeded();
47930fdc8d8SChris Lattner     }
48030fdc8d8SChris Lattner 
48130fdc8d8SChris Lattner     if (command[0] == '-')
48230fdc8d8SChris Lattner     {
48330fdc8d8SChris Lattner         // We have some options and these options MUST end with --.
484c8ecc2a9SEugene Zelenko         const char *end_options = nullptr;
48530fdc8d8SChris Lattner         const char *s = command;
48630fdc8d8SChris Lattner         while (s && s[0])
48730fdc8d8SChris Lattner         {
48830fdc8d8SChris Lattner             end_options = ::strstr (s, "--");
48930fdc8d8SChris Lattner             if (end_options)
49030fdc8d8SChris Lattner             {
49130fdc8d8SChris Lattner                 end_options += 2; // Get past the "--"
49230fdc8d8SChris Lattner                 if (::isspace (end_options[0]))
49330fdc8d8SChris Lattner                 {
49430fdc8d8SChris Lattner                     expr = end_options;
49530fdc8d8SChris Lattner                     while (::isspace (*expr))
49630fdc8d8SChris Lattner                         ++expr;
49730fdc8d8SChris Lattner                     break;
49830fdc8d8SChris Lattner                 }
49930fdc8d8SChris Lattner             }
50030fdc8d8SChris Lattner             s = end_options;
50130fdc8d8SChris Lattner         }
50230fdc8d8SChris Lattner 
50330fdc8d8SChris Lattner         if (end_options)
50430fdc8d8SChris Lattner         {
50500b7f95bSPavel Labath             Args args (llvm::StringRef(command, end_options - command));
506a7015092SGreg Clayton             if (!ParseOptions (args, result))
50730fdc8d8SChris Lattner                 return false;
508f6b8b581SGreg Clayton 
5091deb7962SGreg Clayton             Error error (m_option_group.NotifyOptionParsingFinished());
510f6b8b581SGreg Clayton             if (error.Fail())
511f6b8b581SGreg Clayton             {
512f6b8b581SGreg Clayton                 result.AppendError (error.AsCString());
513f6b8b581SGreg Clayton                 result.SetStatus (eReturnStatusFailed);
514f6b8b581SGreg Clayton                 return false;
515f6b8b581SGreg Clayton             }
516cf28a8b7SGreg Clayton 
517f2bd5c3eSSean Callanan             if (m_repl_option.GetOptionValue().GetCurrentValue())
518f2bd5c3eSSean Callanan             {
519f2bd5c3eSSean Callanan                 Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
520f2bd5c3eSSean Callanan                 if (target)
521f2bd5c3eSSean Callanan                 {
522f2bd5c3eSSean Callanan                     // Drop into REPL
523f2bd5c3eSSean Callanan                     m_expr_lines.clear();
524f2bd5c3eSSean Callanan                     m_expr_line_count = 0;
525f2bd5c3eSSean Callanan 
526f2bd5c3eSSean Callanan                     Debugger &debugger = target->GetDebugger();
527f2bd5c3eSSean Callanan 
528f2bd5c3eSSean Callanan                     // Check if the LLDB command interpreter is sitting on top of a REPL that
529f2bd5c3eSSean Callanan                     // launched it...
530f2bd5c3eSSean Callanan                     if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter, IOHandler::Type::REPL))
531f2bd5c3eSSean Callanan                     {
532f2bd5c3eSSean Callanan                         // the LLDB command interpreter is sitting on top of a REPL that launched it,
533f2bd5c3eSSean Callanan                         // so just say the command interpreter is done and fall back to the existing REPL
534f2bd5c3eSSean Callanan                         m_interpreter.GetIOHandler(false)->SetIsDone(true);
535f2bd5c3eSSean Callanan                     }
536f2bd5c3eSSean Callanan                     else
537f2bd5c3eSSean Callanan                     {
538f2bd5c3eSSean Callanan                         // We are launching the REPL on top of the current LLDB command interpreter,
539f2bd5c3eSSean Callanan                         // so just push one
540f2bd5c3eSSean Callanan                         bool initialize = false;
541f2bd5c3eSSean Callanan                         Error repl_error;
542f2bd5c3eSSean Callanan                         REPLSP repl_sp (target->GetREPL(repl_error, m_command_options.language, nullptr, false));
543f2bd5c3eSSean Callanan 
544f2bd5c3eSSean Callanan                         if (!repl_sp)
545f2bd5c3eSSean Callanan                         {
546f2bd5c3eSSean Callanan                             initialize = true;
547f2bd5c3eSSean Callanan                             repl_sp = target->GetREPL(repl_error, m_command_options.language, nullptr, true);
548f2bd5c3eSSean Callanan                             if (!repl_error.Success())
549f2bd5c3eSSean Callanan                             {
550f2bd5c3eSSean Callanan                                 result.SetError(repl_error);
551f2bd5c3eSSean Callanan                                 return result.Succeeded();
552f2bd5c3eSSean Callanan                             }
553f2bd5c3eSSean Callanan                         }
554f2bd5c3eSSean Callanan 
555f2bd5c3eSSean Callanan                         if (repl_sp)
556f2bd5c3eSSean Callanan                         {
557f2bd5c3eSSean Callanan                             if (initialize)
558f2bd5c3eSSean Callanan                             {
559f2bd5c3eSSean Callanan                                 repl_sp->SetCommandOptions(m_command_options);
560f2bd5c3eSSean Callanan                                 repl_sp->SetFormatOptions(m_format_options);
561f2bd5c3eSSean Callanan                                 repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
562f2bd5c3eSSean Callanan                             }
563f2bd5c3eSSean Callanan 
564f2bd5c3eSSean Callanan                             IOHandlerSP io_handler_sp (repl_sp->GetIOHandler());
565f2bd5c3eSSean Callanan 
566f2bd5c3eSSean Callanan                             io_handler_sp->SetIsDone(false);
567f2bd5c3eSSean Callanan 
568f2bd5c3eSSean Callanan                             debugger.PushIOHandler(io_handler_sp);
569f2bd5c3eSSean Callanan                         }
570f2bd5c3eSSean Callanan                         else
571f2bd5c3eSSean Callanan                         {
572f2bd5c3eSSean Callanan                             repl_error.SetErrorStringWithFormat("Couldn't create a REPL for %s", Language::GetNameForLanguageType(m_command_options.language));
573f2bd5c3eSSean Callanan                             result.SetError(repl_error);
574f2bd5c3eSSean Callanan                             return result.Succeeded();
575f2bd5c3eSSean Callanan                         }
576f2bd5c3eSSean Callanan                     }
577f2bd5c3eSSean Callanan                 }
578f2bd5c3eSSean Callanan             }
579cf28a8b7SGreg Clayton             // No expression following options
580c8ecc2a9SEugene Zelenko             else if (expr == nullptr || expr[0] == '\0')
581cf28a8b7SGreg Clayton             {
582cf28a8b7SGreg Clayton                 GetMultilineExpression ();
583cf28a8b7SGreg Clayton                 return result.Succeeded();
584cf28a8b7SGreg Clayton             }
58530fdc8d8SChris Lattner         }
58630fdc8d8SChris Lattner     }
58730fdc8d8SChris Lattner 
588c8ecc2a9SEugene Zelenko     if (expr == nullptr)
58930fdc8d8SChris Lattner         expr = command;
59030fdc8d8SChris Lattner 
5916e8dc334SCaroline Tice     if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result))
592fcd43b71SJohnny Chen         return true;
593fcd43b71SJohnny Chen 
594fcd43b71SJohnny Chen     result.SetStatus (eReturnStatusFailed);
595fcd43b71SJohnny Chen     return false;
59630fdc8d8SChris Lattner }
597