xref: /src/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- CommandObjectExpression.cpp ---------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f3fbd1c0SDimitry Andric #include "llvm/ADT/StringRef.h"
10f3fbd1c0SDimitry Andric 
11f3fbd1c0SDimitry Andric #include "CommandObjectExpression.h"
1214f1b3e8SDimitry Andric #include "lldb/Core/Debugger.h"
137fa27ce4SDimitry Andric #include "lldb/Expression/ExpressionVariable.h"
14e81d9d49SDimitry Andric #include "lldb/Expression/REPL.h"
1514f1b3e8SDimitry Andric #include "lldb/Expression/UserExpression.h"
1674a628f7SDimitry Andric #include "lldb/Host/OptionParser.h"
17f034231aSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
184b4fe385SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
19f034231aSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
20f73363f1SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
2114f1b3e8SDimitry Andric #include "lldb/Target/Language.h"
22f034231aSEd Maste #include "lldb/Target/Process.h"
23f034231aSEd Maste #include "lldb/Target/StackFrame.h"
24f034231aSEd Maste #include "lldb/Target/Target.h"
257fa27ce4SDimitry Andric #include "lldb/lldb-enumerations.h"
267fa27ce4SDimitry Andric #include "lldb/lldb-private-enumerations.h"
27f034231aSEd Maste 
28f034231aSEd Maste using namespace lldb;
29f034231aSEd Maste using namespace lldb_private;
30f034231aSEd Maste 
31145449b1SDimitry Andric CommandObjectExpression::CommandOptions::CommandOptions() = default;
32f034231aSEd Maste 
33f3fbd1c0SDimitry Andric CommandObjectExpression::CommandOptions::~CommandOptions() = default;
34f034231aSEd Maste 
35ead24645SDimitry Andric #define LLDB_OPTIONS_expression
36ead24645SDimitry Andric #include "CommandOptions.inc"
37f034231aSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)38b76161e4SDimitry Andric Status CommandObjectExpression::CommandOptions::SetOptionValue(
3914f1b3e8SDimitry Andric     uint32_t option_idx, llvm::StringRef option_arg,
4014f1b3e8SDimitry Andric     ExecutionContext *execution_context) {
41b76161e4SDimitry Andric   Status error;
42f034231aSEd Maste 
4314f1b3e8SDimitry Andric   const int short_option = GetDefinitions()[option_idx].short_option;
44f034231aSEd Maste 
4514f1b3e8SDimitry Andric   switch (short_option) {
46e81d9d49SDimitry Andric   case 'l':
47e81d9d49SDimitry Andric     language = Language::GetLanguageTypeFromString(option_arg);
48e3b55780SDimitry Andric     if (language == eLanguageTypeUnknown) {
49e3b55780SDimitry Andric       StreamString sstr;
50e3b55780SDimitry Andric       sstr.Printf("unknown language type: '%s' for expression. "
51e3b55780SDimitry Andric                   "List of supported languages:\n",
5214f1b3e8SDimitry Andric                   option_arg.str().c_str());
53e3b55780SDimitry Andric 
54e3b55780SDimitry Andric       Language::PrintSupportedLanguagesForExpressions(sstr, "  ", "\n");
55e3b55780SDimitry Andric       error.SetErrorString(sstr.GetString());
56e3b55780SDimitry Andric     }
57e81d9d49SDimitry Andric     break;
58f034231aSEd Maste 
5914f1b3e8SDimitry Andric   case 'a': {
60f034231aSEd Maste     bool success;
61f034231aSEd Maste     bool result;
62f73363f1SDimitry Andric     result = OptionArgParser::ToBoolean(option_arg, true, &success);
63f034231aSEd Maste     if (!success)
6414f1b3e8SDimitry Andric       error.SetErrorStringWithFormat(
6514f1b3e8SDimitry Andric           "invalid all-threads value setting: \"%s\"",
6614f1b3e8SDimitry Andric           option_arg.str().c_str());
67f034231aSEd Maste     else
68f034231aSEd Maste       try_all_threads = result;
6914f1b3e8SDimitry Andric   } break;
70f034231aSEd Maste 
7114f1b3e8SDimitry Andric   case 'i': {
72f034231aSEd Maste     bool success;
73f73363f1SDimitry Andric     bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
74f034231aSEd Maste     if (success)
75f034231aSEd Maste       ignore_breakpoints = tmp_value;
76f034231aSEd Maste     else
7714f1b3e8SDimitry Andric       error.SetErrorStringWithFormat(
7814f1b3e8SDimitry Andric           "could not convert \"%s\" to a boolean value.",
7914f1b3e8SDimitry Andric           option_arg.str().c_str());
80f034231aSEd Maste     break;
81f034231aSEd Maste   }
82f3fbd1c0SDimitry Andric 
8314f1b3e8SDimitry Andric   case 'j': {
84f3fbd1c0SDimitry Andric     bool success;
85f73363f1SDimitry Andric     bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
86f3fbd1c0SDimitry Andric     if (success)
87f3fbd1c0SDimitry Andric       allow_jit = tmp_value;
88f3fbd1c0SDimitry Andric     else
8914f1b3e8SDimitry Andric       error.SetErrorStringWithFormat(
9014f1b3e8SDimitry Andric           "could not convert \"%s\" to a boolean value.",
9114f1b3e8SDimitry Andric           option_arg.str().c_str());
92f3fbd1c0SDimitry Andric     break;
93f3fbd1c0SDimitry Andric   }
94f3fbd1c0SDimitry Andric 
95f034231aSEd Maste   case 't':
9614f1b3e8SDimitry Andric     if (option_arg.getAsInteger(0, timeout)) {
9714f1b3e8SDimitry Andric       timeout = 0;
9814f1b3e8SDimitry Andric       error.SetErrorStringWithFormat("invalid timeout setting \"%s\"",
9914f1b3e8SDimitry Andric                                      option_arg.str().c_str());
100f034231aSEd Maste     }
101f034231aSEd Maste     break;
102f034231aSEd Maste 
10314f1b3e8SDimitry Andric   case 'u': {
104f034231aSEd Maste     bool success;
105f73363f1SDimitry Andric     bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
106f034231aSEd Maste     if (success)
107f034231aSEd Maste       unwind_on_error = tmp_value;
108f034231aSEd Maste     else
10914f1b3e8SDimitry Andric       error.SetErrorStringWithFormat(
11014f1b3e8SDimitry Andric           "could not convert \"%s\" to a boolean value.",
11114f1b3e8SDimitry Andric           option_arg.str().c_str());
112f034231aSEd Maste     break;
113f034231aSEd Maste   }
114f21a844fSEd Maste 
115f21a844fSEd Maste   case 'v':
11614f1b3e8SDimitry Andric     if (option_arg.empty()) {
117f21a844fSEd Maste       m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull;
118f21a844fSEd Maste       break;
119f21a844fSEd Maste     }
120f73363f1SDimitry Andric     m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity)
121f73363f1SDimitry Andric         OptionArgParser::ToOptionEnum(
12214f1b3e8SDimitry Andric             option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
123f21a844fSEd Maste     if (!error.Success())
12414f1b3e8SDimitry Andric       error.SetErrorStringWithFormat(
12514f1b3e8SDimitry Andric           "unrecognized value for description-verbosity '%s'",
12614f1b3e8SDimitry Andric           option_arg.str().c_str());
127f21a844fSEd Maste     break;
128f21a844fSEd Maste 
129f21a844fSEd Maste   case 'g':
130f21a844fSEd Maste     debug = true;
131f21a844fSEd Maste     unwind_on_error = false;
132f21a844fSEd Maste     ignore_breakpoints = false;
133f21a844fSEd Maste     break;
134f21a844fSEd Maste 
135f3fbd1c0SDimitry Andric   case 'p':
136f3fbd1c0SDimitry Andric     top_level = true;
137f3fbd1c0SDimitry Andric     break;
138f3fbd1c0SDimitry Andric 
13914f1b3e8SDimitry Andric   case 'X': {
140f3fbd1c0SDimitry Andric     bool success;
141f73363f1SDimitry Andric     bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
142f3fbd1c0SDimitry Andric     if (success)
143f3fbd1c0SDimitry Andric       auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo;
144f3fbd1c0SDimitry Andric     else
14514f1b3e8SDimitry Andric       error.SetErrorStringWithFormat(
14614f1b3e8SDimitry Andric           "could not convert \"%s\" to a boolean value.",
14714f1b3e8SDimitry Andric           option_arg.str().c_str());
148f3fbd1c0SDimitry Andric     break;
149f3fbd1c0SDimitry Andric   }
150f3fbd1c0SDimitry Andric 
1517fa27ce4SDimitry Andric   case '\x01': {
1527fa27ce4SDimitry Andric     bool success;
1537fa27ce4SDimitry Andric     bool persist_result =
1547fa27ce4SDimitry Andric         OptionArgParser::ToBoolean(option_arg, true, &success);
1557fa27ce4SDimitry Andric     if (success)
1567fa27ce4SDimitry Andric       suppress_persistent_result = !persist_result ? eLazyBoolYes : eLazyBoolNo;
1577fa27ce4SDimitry Andric     else
1587fa27ce4SDimitry Andric       error.SetErrorStringWithFormat(
1597fa27ce4SDimitry Andric           "could not convert \"%s\" to a boolean value.",
1607fa27ce4SDimitry Andric           option_arg.str().c_str());
1617fa27ce4SDimitry Andric     break;
1627fa27ce4SDimitry Andric   }
1637fa27ce4SDimitry Andric 
164f034231aSEd Maste   default:
165ead24645SDimitry Andric     llvm_unreachable("Unimplemented option");
166f034231aSEd Maste   }
167f034231aSEd Maste 
168f034231aSEd Maste   return error;
169f034231aSEd Maste }
170f034231aSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)17114f1b3e8SDimitry Andric void CommandObjectExpression::CommandOptions::OptionParsingStarting(
17214f1b3e8SDimitry Andric     ExecutionContext *execution_context) {
17314f1b3e8SDimitry Andric   auto process_sp =
17414f1b3e8SDimitry Andric       execution_context ? execution_context->GetProcessSP() : ProcessSP();
17514f1b3e8SDimitry Andric   if (process_sp) {
17614f1b3e8SDimitry Andric     ignore_breakpoints = process_sp->GetIgnoreBreakpointsInExpressions();
17714f1b3e8SDimitry Andric     unwind_on_error = process_sp->GetUnwindOnErrorInExpressions();
17814f1b3e8SDimitry Andric   } else {
1790cac4ca3SEd Maste     ignore_breakpoints = true;
180f034231aSEd Maste     unwind_on_error = true;
181f034231aSEd Maste   }
182f034231aSEd Maste 
183f034231aSEd Maste   show_summary = true;
184f034231aSEd Maste   try_all_threads = true;
185f034231aSEd Maste   timeout = 0;
186f21a844fSEd Maste   debug = false;
187e81d9d49SDimitry Andric   language = eLanguageTypeUnknown;
188f21a844fSEd Maste   m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
189f3fbd1c0SDimitry Andric   auto_apply_fixits = eLazyBoolCalculate;
190f3fbd1c0SDimitry Andric   top_level = false;
191f3fbd1c0SDimitry Andric   allow_jit = true;
1927fa27ce4SDimitry Andric   suppress_persistent_result = eLazyBoolCalculate;
193f034231aSEd Maste }
194f034231aSEd Maste 
19514f1b3e8SDimitry Andric llvm::ArrayRef<OptionDefinition>
GetDefinitions()19614f1b3e8SDimitry Andric CommandObjectExpression::CommandOptions::GetDefinitions() {
197e3b55780SDimitry Andric   return llvm::ArrayRef(g_expression_options);
198f034231aSEd Maste }
199f034231aSEd Maste 
2007fa27ce4SDimitry Andric EvaluateExpressionOptions
GetEvaluateExpressionOptions(const Target & target,const OptionGroupValueObjectDisplay & display_opts)2017fa27ce4SDimitry Andric CommandObjectExpression::CommandOptions::GetEvaluateExpressionOptions(
2027fa27ce4SDimitry Andric     const Target &target, const OptionGroupValueObjectDisplay &display_opts) {
2037fa27ce4SDimitry Andric   EvaluateExpressionOptions options;
2047fa27ce4SDimitry Andric   options.SetCoerceToId(display_opts.use_objc);
2057fa27ce4SDimitry Andric   options.SetUnwindOnError(unwind_on_error);
2067fa27ce4SDimitry Andric   options.SetIgnoreBreakpoints(ignore_breakpoints);
2077fa27ce4SDimitry Andric   options.SetKeepInMemory(true);
2087fa27ce4SDimitry Andric   options.SetUseDynamic(display_opts.use_dynamic);
2097fa27ce4SDimitry Andric   options.SetTryAllThreads(try_all_threads);
2107fa27ce4SDimitry Andric   options.SetDebug(debug);
2117fa27ce4SDimitry Andric   options.SetLanguage(language);
2127fa27ce4SDimitry Andric   options.SetExecutionPolicy(
2137fa27ce4SDimitry Andric       allow_jit ? EvaluateExpressionOptions::default_execution_policy
2147fa27ce4SDimitry Andric                 : lldb_private::eExecutionPolicyNever);
2157fa27ce4SDimitry Andric 
2167fa27ce4SDimitry Andric   bool auto_apply_fixits;
2177fa27ce4SDimitry Andric   if (this->auto_apply_fixits == eLazyBoolCalculate)
2187fa27ce4SDimitry Andric     auto_apply_fixits = target.GetEnableAutoApplyFixIts();
2197fa27ce4SDimitry Andric   else
2207fa27ce4SDimitry Andric     auto_apply_fixits = this->auto_apply_fixits == eLazyBoolYes;
2217fa27ce4SDimitry Andric 
2227fa27ce4SDimitry Andric   options.SetAutoApplyFixIts(auto_apply_fixits);
2237fa27ce4SDimitry Andric   options.SetRetriesWithFixIts(target.GetNumberOfRetriesWithFixits());
2247fa27ce4SDimitry Andric 
2257fa27ce4SDimitry Andric   if (top_level)
2267fa27ce4SDimitry Andric     options.SetExecutionPolicy(eExecutionPolicyTopLevel);
2277fa27ce4SDimitry Andric 
2287fa27ce4SDimitry Andric   // If there is any chance we are going to stop and want to see what went
2297fa27ce4SDimitry Andric   // wrong with our expression, we should generate debug info
2307fa27ce4SDimitry Andric   if (!ignore_breakpoints || !unwind_on_error)
2317fa27ce4SDimitry Andric     options.SetGenerateDebugInfo(true);
2327fa27ce4SDimitry Andric 
2337fa27ce4SDimitry Andric   if (timeout > 0)
2347fa27ce4SDimitry Andric     options.SetTimeout(std::chrono::microseconds(timeout));
2357fa27ce4SDimitry Andric   else
2367fa27ce4SDimitry Andric     options.SetTimeout(std::nullopt);
2377fa27ce4SDimitry Andric   return options;
2387fa27ce4SDimitry Andric }
2397fa27ce4SDimitry Andric 
ShouldSuppressResult(const OptionGroupValueObjectDisplay & display_opts) const2407fa27ce4SDimitry Andric bool CommandObjectExpression::CommandOptions::ShouldSuppressResult(
2417fa27ce4SDimitry Andric     const OptionGroupValueObjectDisplay &display_opts) const {
2427fa27ce4SDimitry Andric   // Explicitly disabling persistent results takes precedence over the
2437fa27ce4SDimitry Andric   // m_verbosity/use_objc logic.
2447fa27ce4SDimitry Andric   if (suppress_persistent_result != eLazyBoolCalculate)
2457fa27ce4SDimitry Andric     return suppress_persistent_result == eLazyBoolYes;
2467fa27ce4SDimitry Andric 
2477fa27ce4SDimitry Andric   return display_opts.use_objc &&
2487fa27ce4SDimitry Andric          m_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact;
2497fa27ce4SDimitry Andric }
2507fa27ce4SDimitry Andric 
CommandObjectExpression(CommandInterpreter & interpreter)25114f1b3e8SDimitry Andric CommandObjectExpression::CommandObjectExpression(
25214f1b3e8SDimitry Andric     CommandInterpreter &interpreter)
253706b4fc4SDimitry Andric     : CommandObjectRaw(interpreter, "expression",
254706b4fc4SDimitry Andric                        "Evaluate an expression on the current "
25514f1b3e8SDimitry Andric                        "thread.  Displays any returned value "
25614f1b3e8SDimitry Andric                        "with LLDB's default formatting.",
257706b4fc4SDimitry Andric                        "",
258706b4fc4SDimitry Andric                        eCommandProcessMustBePaused | eCommandTryTargetAPILock),
259866dcdacSEd Maste       IOHandlerDelegate(IOHandlerDelegate::Completion::Expression),
2606f8fc217SDimitry Andric       m_format_options(eFormatDefault),
26114f1b3e8SDimitry Andric       m_repl_option(LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false,
26214f1b3e8SDimitry Andric                     true),
26308e8dd7bSDimitry Andric       m_expr_line_count(0) {
264f034231aSEd Maste   SetHelpLong(
265027f1c96SDimitry Andric       R"(
266ef5d0b5eSDimitry Andric Single and multi-line expressions:
267ef5d0b5eSDimitry Andric 
268ef5d0b5eSDimitry Andric )"
269ef5d0b5eSDimitry Andric       "    The expression provided on the command line must be a complete expression \
270ef5d0b5eSDimitry Andric with no newlines.  To evaluate a multi-line expression, \
271ef5d0b5eSDimitry Andric hit a return after an empty expression, and lldb will enter the multi-line expression editor. \
272ef5d0b5eSDimitry Andric Hit return on an empty line to end the multi-line expression."
273ef5d0b5eSDimitry Andric 
274ef5d0b5eSDimitry Andric       R"(
275ef5d0b5eSDimitry Andric 
276027f1c96SDimitry Andric Timeouts:
277027f1c96SDimitry Andric 
27814f1b3e8SDimitry Andric )"
27914f1b3e8SDimitry Andric       "    If the expression can be evaluated statically (without running code) then it will be.  \
280027f1c96SDimitry Andric Otherwise, by default the expression will run on the current thread with a short timeout: \
281027f1c96SDimitry Andric currently .25 seconds.  If it doesn't return in that time, the evaluation will be interrupted \
282027f1c96SDimitry Andric and resumed with all threads running.  You can use the -a option to disable retrying on all \
28314f1b3e8SDimitry Andric threads.  You can use the -t option to set a shorter timeout."
28414f1b3e8SDimitry Andric       R"(
285027f1c96SDimitry Andric 
286027f1c96SDimitry Andric User defined variables:
287027f1c96SDimitry Andric 
28814f1b3e8SDimitry Andric )"
28914f1b3e8SDimitry Andric       "    You can define your own variables for convenience or to be used in subsequent expressions.  \
290027f1c96SDimitry Andric You define them the same way you would define variables in C.  If the first character of \
291027f1c96SDimitry Andric your user defined variable is a $, then the variable's value will be available in future \
29214f1b3e8SDimitry Andric expressions, otherwise it will just be available in the current expression."
29314f1b3e8SDimitry Andric       R"(
294027f1c96SDimitry Andric 
295027f1c96SDimitry Andric Continuing evaluation after a breakpoint:
296027f1c96SDimitry Andric 
29714f1b3e8SDimitry Andric )"
29814f1b3e8SDimitry Andric       "    If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \
299027f1c96SDimitry Andric you are done with your investigation, you can either remove the expression execution frames \
300027f1c96SDimitry Andric from the stack with \"thread return -x\" or if you are still interested in the expression result \
301027f1c96SDimitry Andric you can issue the \"continue\" command and the expression evaluation will complete and the \
302027f1c96SDimitry Andric expression result will be available using the \"thread.completed-expression\" key in the thread \
30314f1b3e8SDimitry Andric format."
304ef5d0b5eSDimitry Andric 
30514f1b3e8SDimitry Andric       R"(
306027f1c96SDimitry Andric 
307027f1c96SDimitry Andric Examples:
308027f1c96SDimitry Andric 
309027f1c96SDimitry Andric     expr my_struct->a = my_array[3]
310027f1c96SDimitry Andric     expr -f bin -- (index * 8) + 5
311027f1c96SDimitry Andric     expr unsigned int $foo = 5
31214f1b3e8SDimitry Andric     expr char c[] = \"foo\"; c[0])");
313f034231aSEd Maste 
314ac9a064cSDimitry Andric   AddSimpleArgumentList(eArgTypeExpression);
315f034231aSEd Maste 
316f034231aSEd Maste   // Add the "--format" and "--gdb-format"
31714f1b3e8SDimitry Andric   m_option_group.Append(&m_format_options,
31814f1b3e8SDimitry Andric                         OptionGroupFormat::OPTION_GROUP_FORMAT |
31914f1b3e8SDimitry Andric                             OptionGroupFormat::OPTION_GROUP_GDB_FMT,
32014f1b3e8SDimitry Andric                         LLDB_OPT_SET_1);
321f034231aSEd Maste   m_option_group.Append(&m_command_options);
32214f1b3e8SDimitry Andric   m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL,
32314f1b3e8SDimitry Andric                         LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
324e81d9d49SDimitry Andric   m_option_group.Append(&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
325f034231aSEd Maste   m_option_group.Finalize();
326f034231aSEd Maste }
327f034231aSEd Maste 
328f3fbd1c0SDimitry Andric CommandObjectExpression::~CommandObjectExpression() = default;
329f034231aSEd Maste 
GetOptions()33014f1b3e8SDimitry Andric Options *CommandObjectExpression::GetOptions() { return &m_option_group; }
331f034231aSEd Maste 
HandleCompletion(CompletionRequest & request)332ead24645SDimitry Andric void CommandObjectExpression::HandleCompletion(CompletionRequest &request) {
33394994d37SDimitry Andric   EvaluateExpressionOptions options;
33494994d37SDimitry Andric   options.SetCoerceToId(m_varobj_options.use_objc);
33594994d37SDimitry Andric   options.SetLanguage(m_command_options.language);
33694994d37SDimitry Andric   options.SetExecutionPolicy(lldb_private::eExecutionPolicyNever);
33794994d37SDimitry Andric   options.SetAutoApplyFixIts(false);
33894994d37SDimitry Andric   options.SetGenerateDebugInfo(false);
33994994d37SDimitry Andric 
340344a3780SDimitry Andric   ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
34194994d37SDimitry Andric 
342344a3780SDimitry Andric   // Get out before we start doing things that expect a valid frame pointer.
343344a3780SDimitry Andric   if (exe_ctx.GetFramePtr() == nullptr)
344ead24645SDimitry Andric     return;
34594994d37SDimitry Andric 
346b60736ecSDimitry Andric   Target *exe_target = exe_ctx.GetTargetPtr();
347b60736ecSDimitry Andric   Target &target = exe_target ? *exe_target : GetDummyTarget();
34894994d37SDimitry Andric 
34994994d37SDimitry Andric   unsigned cursor_pos = request.GetRawCursorPos();
350cfca06d7SDimitry Andric   // Get the full user input including the suffix. The suffix is necessary
351cfca06d7SDimitry Andric   // as OptionsWithRaw will use it to detect if the cursor is cursor is in the
352cfca06d7SDimitry Andric   // argument part of in the raw input part of the arguments. If we cut of
353cfca06d7SDimitry Andric   // of the suffix then "expr -arg[cursor] --" would interpret the "-arg" as
354cfca06d7SDimitry Andric   // the raw input (as the "--" is hidden in the suffix).
355cfca06d7SDimitry Andric   llvm::StringRef code = request.GetRawLineWithUnusedSuffix();
35694994d37SDimitry Andric 
35794994d37SDimitry Andric   const std::size_t original_code_size = code.size();
35894994d37SDimitry Andric 
35994994d37SDimitry Andric   // Remove the first token which is 'expr' or some alias/abbreviation of that.
36094994d37SDimitry Andric   code = llvm::getToken(code).second.ltrim();
36194994d37SDimitry Andric   OptionsWithRaw args(code);
36294994d37SDimitry Andric   code = args.GetRawPart();
36394994d37SDimitry Andric 
36494994d37SDimitry Andric   // The position where the expression starts in the command line.
36594994d37SDimitry Andric   assert(original_code_size >= code.size());
36694994d37SDimitry Andric   std::size_t raw_start = original_code_size - code.size();
36794994d37SDimitry Andric 
36894994d37SDimitry Andric   // Check if the cursor is actually in the expression string, and if not, we
36994994d37SDimitry Andric   // exit.
37094994d37SDimitry Andric   // FIXME: We should complete the options here.
37194994d37SDimitry Andric   if (cursor_pos < raw_start)
372ead24645SDimitry Andric     return;
37394994d37SDimitry Andric 
37494994d37SDimitry Andric   // Make the cursor_pos again relative to the start of the code string.
37594994d37SDimitry Andric   assert(cursor_pos >= raw_start);
37694994d37SDimitry Andric   cursor_pos -= raw_start;
37794994d37SDimitry Andric 
37894994d37SDimitry Andric   auto language = exe_ctx.GetFrameRef().GetLanguage();
37994994d37SDimitry Andric 
38094994d37SDimitry Andric   Status error;
381b60736ecSDimitry Andric   lldb::UserExpressionSP expr(target.GetUserExpressionForLanguage(
38294994d37SDimitry Andric       code, llvm::StringRef(), language, UserExpression::eResultTypeAny,
3835f29bb8aSDimitry Andric       options, nullptr, error));
38494994d37SDimitry Andric   if (error.Fail())
385ead24645SDimitry Andric     return;
38694994d37SDimitry Andric 
38794994d37SDimitry Andric   expr->Complete(exe_ctx, request, cursor_pos);
38894994d37SDimitry Andric }
38994994d37SDimitry Andric 
390b76161e4SDimitry Andric static lldb_private::Status
CanBeUsedForElementCountPrinting(ValueObject & valobj)39114f1b3e8SDimitry Andric CanBeUsedForElementCountPrinting(ValueObject &valobj) {
392f3fbd1c0SDimitry Andric   CompilerType type(valobj.GetCompilerType());
393f3fbd1c0SDimitry Andric   CompilerType pointee;
394f3fbd1c0SDimitry Andric   if (!type.IsPointerType(&pointee))
395b76161e4SDimitry Andric     return Status("as it does not refer to a pointer");
396f3fbd1c0SDimitry Andric   if (pointee.IsVoidType())
397b76161e4SDimitry Andric     return Status("as it refers to a pointer to void");
398b76161e4SDimitry Andric   return Status();
399f3fbd1c0SDimitry Andric }
400f3fbd1c0SDimitry Andric 
EvaluateExpression(llvm::StringRef expr,Stream & output_stream,Stream & error_stream,CommandReturnObject & result)401cfca06d7SDimitry Andric bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
402cfca06d7SDimitry Andric                                                  Stream &output_stream,
403cfca06d7SDimitry Andric                                                  Stream &error_stream,
404cfca06d7SDimitry Andric                                                  CommandReturnObject &result) {
405cfca06d7SDimitry Andric   // Don't use m_exe_ctx as this might be called asynchronously after the
406cfca06d7SDimitry Andric   // command object DoExecute has finished when doing multi-line expression
407cfca06d7SDimitry Andric   // that use an input reader...
408cfca06d7SDimitry Andric   ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
409b60736ecSDimitry Andric   Target *exe_target = exe_ctx.GetTargetPtr();
410b60736ecSDimitry Andric   Target &target = exe_target ? *exe_target : GetDummyTarget();
411cfca06d7SDimitry Andric 
412cfca06d7SDimitry Andric   lldb::ValueObjectSP result_valobj_sp;
413cfca06d7SDimitry Andric   StackFrame *frame = exe_ctx.GetFramePtr();
414cfca06d7SDimitry Andric 
415344a3780SDimitry Andric   if (m_command_options.top_level && !m_command_options.allow_jit) {
416344a3780SDimitry Andric     result.AppendErrorWithFormat(
417344a3780SDimitry Andric         "Can't disable JIT compilation for top-level expressions.\n");
418344a3780SDimitry Andric     return false;
419344a3780SDimitry Andric   }
420344a3780SDimitry Andric 
4217fa27ce4SDimitry Andric   EvaluateExpressionOptions eval_options =
4227fa27ce4SDimitry Andric       m_command_options.GetEvaluateExpressionOptions(target, m_varobj_options);
4237fa27ce4SDimitry Andric   // This command manually removes the result variable, make sure expression
4247fa27ce4SDimitry Andric   // evaluation doesn't do it first.
4257fa27ce4SDimitry Andric   eval_options.SetSuppressPersistentResult(false);
4267fa27ce4SDimitry Andric 
427b60736ecSDimitry Andric   ExpressionResults success = target.EvaluateExpression(
4287fa27ce4SDimitry Andric       expr, frame, result_valobj_sp, eval_options, &m_fixed_expression);
429f3fbd1c0SDimitry Andric 
430b1c73532SDimitry Andric   // Only mention Fix-Its if the expression evaluator applied them.
431b1c73532SDimitry Andric   // Compiler errors refer to the final expression after applying Fix-It(s).
432b60736ecSDimitry Andric   if (!m_fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) {
433b1c73532SDimitry Andric     error_stream << "  Evaluated this expression after applying Fix-It(s):\n";
434b1c73532SDimitry Andric     error_stream << "    " << m_fixed_expression << "\n";
435f3fbd1c0SDimitry Andric   }
436f034231aSEd Maste 
43714f1b3e8SDimitry Andric   if (result_valobj_sp) {
438f034231aSEd Maste     Format format = m_format_options.GetFormat();
439f034231aSEd Maste 
44014f1b3e8SDimitry Andric     if (result_valobj_sp->GetError().Success()) {
44114f1b3e8SDimitry Andric       if (format != eFormatVoid) {
442f034231aSEd Maste         if (format != eFormatDefault)
443f034231aSEd Maste           result_valobj_sp->SetFormat(format);
444f034231aSEd Maste 
44514f1b3e8SDimitry Andric         if (m_varobj_options.elem_count > 0) {
446b76161e4SDimitry Andric           Status error(CanBeUsedForElementCountPrinting(*result_valobj_sp));
44714f1b3e8SDimitry Andric           if (error.Fail()) {
448cfca06d7SDimitry Andric             result.AppendErrorWithFormat(
44914f1b3e8SDimitry Andric                 "expression cannot be used with --element-count %s\n",
45014f1b3e8SDimitry Andric                 error.AsCString(""));
451f3fbd1c0SDimitry Andric             return false;
452f3fbd1c0SDimitry Andric           }
453f3fbd1c0SDimitry Andric         }
454f3fbd1c0SDimitry Andric 
4557fa27ce4SDimitry Andric         bool suppress_result =
4567fa27ce4SDimitry Andric             m_command_options.ShouldSuppressResult(m_varobj_options);
4577fa27ce4SDimitry Andric 
45814f1b3e8SDimitry Andric         DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
45914f1b3e8SDimitry Andric             m_command_options.m_verbosity, format));
4607fa27ce4SDimitry Andric         options.SetHideRootName(suppress_result);
46114f1b3e8SDimitry Andric         options.SetVariableFormatDisplayLanguage(
46214f1b3e8SDimitry Andric             result_valobj_sp->GetPreferredDisplayLanguage());
463f034231aSEd Maste 
464ac9a064cSDimitry Andric         if (llvm::Error error =
465ac9a064cSDimitry Andric                 result_valobj_sp->Dump(output_stream, options)) {
466ac9a064cSDimitry Andric           result.AppendError(toString(std::move(error)));
467ac9a064cSDimitry Andric           return false;
468ac9a064cSDimitry Andric         }
469f21a844fSEd Maste 
4707fa27ce4SDimitry Andric         if (suppress_result)
4717fa27ce4SDimitry Andric           if (auto result_var_sp =
4727fa27ce4SDimitry Andric                   target.GetPersistentVariable(result_valobj_sp->GetName())) {
4737fa27ce4SDimitry Andric             auto language = result_valobj_sp->GetPreferredDisplayLanguage();
4747fa27ce4SDimitry Andric             if (auto *persistent_state =
4757fa27ce4SDimitry Andric                     target.GetPersistentExpressionStateForLanguage(language))
4767fa27ce4SDimitry Andric               persistent_state->RemovePersistentVariable(result_var_sp);
4777fa27ce4SDimitry Andric           }
478cfca06d7SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
479f034231aSEd Maste       }
48014f1b3e8SDimitry Andric     } else {
48114f1b3e8SDimitry Andric       if (result_valobj_sp->GetError().GetError() ==
48214f1b3e8SDimitry Andric           UserExpression::kNoResult) {
4835f29bb8aSDimitry Andric         if (format != eFormatVoid && GetDebugger().GetNotifyVoid()) {
484cfca06d7SDimitry Andric           error_stream.PutCString("(void)\n");
485f034231aSEd Maste         }
486f034231aSEd Maste 
487cfca06d7SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
48814f1b3e8SDimitry Andric       } else {
489f034231aSEd Maste         const char *error_cstr = result_valobj_sp->GetError().AsCString();
49014f1b3e8SDimitry Andric         if (error_cstr && error_cstr[0]) {
491f034231aSEd Maste           const size_t error_cstr_len = strlen(error_cstr);
492ead24645SDimitry Andric           const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';
493f034231aSEd Maste           if (strstr(error_cstr, "error:") != error_cstr)
494cfca06d7SDimitry Andric             error_stream.PutCString("error: ");
495cfca06d7SDimitry Andric           error_stream.Write(error_cstr, error_cstr_len);
496f034231aSEd Maste           if (!ends_with_newline)
497cfca06d7SDimitry Andric             error_stream.EOL();
49814f1b3e8SDimitry Andric         } else {
499cfca06d7SDimitry Andric           error_stream.PutCString("error: unknown error\n");
500f034231aSEd Maste         }
501f034231aSEd Maste 
502cfca06d7SDimitry Andric         result.SetStatus(eReturnStatusFailed);
503f034231aSEd Maste       }
504f034231aSEd Maste     }
505e3b55780SDimitry Andric   } else {
506e3b55780SDimitry Andric     error_stream.Printf("error: unknown error\n");
507f034231aSEd Maste   }
508f034231aSEd Maste 
509cfca06d7SDimitry Andric   return (success != eExpressionSetupError &&
510cfca06d7SDimitry Andric           success != eExpressionParseError);
511f034231aSEd Maste }
512f034231aSEd Maste 
IOHandlerInputComplete(IOHandler & io_handler,std::string & line)51314f1b3e8SDimitry Andric void CommandObjectExpression::IOHandlerInputComplete(IOHandler &io_handler,
51414f1b3e8SDimitry Andric                                                      std::string &line) {
515866dcdacSEd Maste   io_handler.SetIsDone(true);
516ead24645SDimitry Andric   StreamFileSP output_sp = io_handler.GetOutputStreamFileSP();
517ead24645SDimitry Andric   StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
518866dcdacSEd Maste 
519cfca06d7SDimitry Andric   CommandReturnObject return_obj(
520cfca06d7SDimitry Andric       GetCommandInterpreter().GetDebugger().GetUseColor());
521cfca06d7SDimitry Andric   EvaluateExpression(line.c_str(), *output_sp, *error_sp, return_obj);
522866dcdacSEd Maste   if (output_sp)
523866dcdacSEd Maste     output_sp->Flush();
524866dcdacSEd Maste   if (error_sp)
525866dcdacSEd Maste     error_sp->Flush();
526866dcdacSEd Maste }
527866dcdacSEd Maste 
IOHandlerIsInputComplete(IOHandler & io_handler,StringList & lines)52814f1b3e8SDimitry Andric bool CommandObjectExpression::IOHandlerIsInputComplete(IOHandler &io_handler,
52914f1b3e8SDimitry Andric                                                        StringList &lines) {
530f3fbd1c0SDimitry Andric   // An empty lines is used to indicate the end of input
531f3fbd1c0SDimitry Andric   const size_t num_lines = lines.GetSize();
53214f1b3e8SDimitry Andric   if (num_lines > 0 && lines[num_lines - 1].empty()) {
533f73363f1SDimitry Andric     // Remove the last empty line from "lines" so it doesn't appear in our
534f73363f1SDimitry Andric     // resulting input and return true to indicate we are done getting lines
535866dcdacSEd Maste     lines.PopBack();
536f3fbd1c0SDimitry Andric     return true;
537866dcdacSEd Maste   }
538f3fbd1c0SDimitry Andric   return false;
539866dcdacSEd Maste }
540866dcdacSEd Maste 
GetMultilineExpression()54114f1b3e8SDimitry Andric void CommandObjectExpression::GetMultilineExpression() {
5420cac4ca3SEd Maste   m_expr_lines.clear();
5430cac4ca3SEd Maste   m_expr_line_count = 0;
5440cac4ca3SEd Maste 
5450cac4ca3SEd Maste   Debugger &debugger = GetCommandInterpreter().GetDebugger();
546205afe67SEd Maste   bool color_prompt = debugger.GetUseColor();
5470cac4ca3SEd Maste   const bool multiple_lines = true; // Get multiple lines
54814f1b3e8SDimitry Andric   IOHandlerSP io_handler_sp(
54914f1b3e8SDimitry Andric       new IOHandlerEditline(debugger, IOHandler::Type::Expression,
5500cac4ca3SEd Maste                             "lldb-expr", // Name of input reader for history
55114f1b3e8SDimitry Andric                             llvm::StringRef(), // No prompt
55214f1b3e8SDimitry Andric                             llvm::StringRef(), // Continuation prompt
55314f1b3e8SDimitry Andric                             multiple_lines, color_prompt,
5540cac4ca3SEd Maste                             1, // Show line numbers starting at 1
555e3b55780SDimitry Andric                             *this));
5560cac4ca3SEd Maste 
557ead24645SDimitry Andric   StreamFileSP output_sp = io_handler_sp->GetOutputStreamFileSP();
55814f1b3e8SDimitry Andric   if (output_sp) {
55914f1b3e8SDimitry Andric     output_sp->PutCString(
56014f1b3e8SDimitry Andric         "Enter expressions, then terminate with an empty line to evaluate:\n");
5610cac4ca3SEd Maste     output_sp->Flush();
5620cac4ca3SEd Maste   }
563cfca06d7SDimitry Andric   debugger.RunIOHandlerAsync(io_handler_sp);
5640cac4ca3SEd Maste }
5650cac4ca3SEd Maste 
5665f29bb8aSDimitry Andric static EvaluateExpressionOptions
GetExprOptions(ExecutionContext & ctx,CommandObjectExpression::CommandOptions command_options)5675f29bb8aSDimitry Andric GetExprOptions(ExecutionContext &ctx,
5685f29bb8aSDimitry Andric                CommandObjectExpression::CommandOptions command_options) {
5695f29bb8aSDimitry Andric   command_options.OptionParsingStarting(&ctx);
5705f29bb8aSDimitry Andric 
5715f29bb8aSDimitry Andric   // Default certain settings for REPL regardless of the global settings.
5725f29bb8aSDimitry Andric   command_options.unwind_on_error = false;
5735f29bb8aSDimitry Andric   command_options.ignore_breakpoints = false;
5745f29bb8aSDimitry Andric   command_options.debug = false;
5755f29bb8aSDimitry Andric 
5765f29bb8aSDimitry Andric   EvaluateExpressionOptions expr_options;
5775f29bb8aSDimitry Andric   expr_options.SetUnwindOnError(command_options.unwind_on_error);
5785f29bb8aSDimitry Andric   expr_options.SetIgnoreBreakpoints(command_options.ignore_breakpoints);
5795f29bb8aSDimitry Andric   expr_options.SetTryAllThreads(command_options.try_all_threads);
5805f29bb8aSDimitry Andric 
5815f29bb8aSDimitry Andric   if (command_options.timeout > 0)
5825f29bb8aSDimitry Andric     expr_options.SetTimeout(std::chrono::microseconds(command_options.timeout));
5835f29bb8aSDimitry Andric   else
584e3b55780SDimitry Andric     expr_options.SetTimeout(std::nullopt);
5855f29bb8aSDimitry Andric 
5865f29bb8aSDimitry Andric   return expr_options;
5875f29bb8aSDimitry Andric }
5885f29bb8aSDimitry Andric 
DoExecute(llvm::StringRef command,CommandReturnObject & result)589b1c73532SDimitry Andric void CommandObjectExpression::DoExecute(llvm::StringRef command,
59014f1b3e8SDimitry Andric                                         CommandReturnObject &result) {
591f3fbd1c0SDimitry Andric   m_fixed_expression.clear();
59214f1b3e8SDimitry Andric   auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
59314f1b3e8SDimitry Andric   m_option_group.NotifyOptionParsingStarting(&exe_ctx);
594f034231aSEd Maste 
595f73363f1SDimitry Andric   if (command.empty()) {
5960cac4ca3SEd Maste     GetMultilineExpression();
597b1c73532SDimitry Andric     return;
598f034231aSEd Maste   }
599f034231aSEd Maste 
600f73363f1SDimitry Andric   OptionsWithRaw args(command);
601f73363f1SDimitry Andric   llvm::StringRef expr = args.GetRawPart();
602f034231aSEd Maste 
603f73363f1SDimitry Andric   if (args.HasArgs()) {
604f73363f1SDimitry Andric     if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, exe_ctx))
605b1c73532SDimitry Andric       return;
606f034231aSEd Maste 
60714f1b3e8SDimitry Andric     if (m_repl_option.GetOptionValue().GetCurrentValue()) {
608706b4fc4SDimitry Andric       Target &target = GetSelectedOrDummyTarget();
609e81d9d49SDimitry Andric       // Drop into REPL
610e81d9d49SDimitry Andric       m_expr_lines.clear();
611e81d9d49SDimitry Andric       m_expr_line_count = 0;
612e81d9d49SDimitry Andric 
613706b4fc4SDimitry Andric       Debugger &debugger = target.GetDebugger();
614e81d9d49SDimitry Andric 
61514f1b3e8SDimitry Andric       // Check if the LLDB command interpreter is sitting on top of a REPL
616f73363f1SDimitry Andric       // that launched it...
617f73363f1SDimitry Andric       if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter,
618f73363f1SDimitry Andric                                           IOHandler::Type::REPL)) {
61914f1b3e8SDimitry Andric         // the LLDB command interpreter is sitting on top of a REPL that
620f73363f1SDimitry Andric         // launched it, so just say the command interpreter is done and
621f73363f1SDimitry Andric         // fall back to the existing REPL
622e81d9d49SDimitry Andric         m_interpreter.GetIOHandler(false)->SetIsDone(true);
62314f1b3e8SDimitry Andric       } else {
62414f1b3e8SDimitry Andric         // We are launching the REPL on top of the current LLDB command
625f73363f1SDimitry Andric         // interpreter, so just push one
626e81d9d49SDimitry Andric         bool initialize = false;
627b76161e4SDimitry Andric         Status repl_error;
628706b4fc4SDimitry Andric         REPLSP repl_sp(target.GetREPL(repl_error, m_command_options.language,
629f73363f1SDimitry Andric                                        nullptr, false));
630e81d9d49SDimitry Andric 
63114f1b3e8SDimitry Andric         if (!repl_sp) {
632e81d9d49SDimitry Andric           initialize = true;
633706b4fc4SDimitry Andric           repl_sp = target.GetREPL(repl_error, m_command_options.language,
63414f1b3e8SDimitry Andric                                     nullptr, true);
63514f1b3e8SDimitry Andric           if (!repl_error.Success()) {
636e81d9d49SDimitry Andric             result.SetError(repl_error);
637b1c73532SDimitry Andric             return;
638e81d9d49SDimitry Andric           }
639e81d9d49SDimitry Andric         }
640e81d9d49SDimitry Andric 
64114f1b3e8SDimitry Andric         if (repl_sp) {
64214f1b3e8SDimitry Andric           if (initialize) {
6435f29bb8aSDimitry Andric             repl_sp->SetEvaluateOptions(
6445f29bb8aSDimitry Andric                 GetExprOptions(exe_ctx, m_command_options));
645e81d9d49SDimitry Andric             repl_sp->SetFormatOptions(m_format_options);
646e81d9d49SDimitry Andric             repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
647e81d9d49SDimitry Andric           }
648e81d9d49SDimitry Andric 
649e81d9d49SDimitry Andric           IOHandlerSP io_handler_sp(repl_sp->GetIOHandler());
650e81d9d49SDimitry Andric           io_handler_sp->SetIsDone(false);
651cfca06d7SDimitry Andric           debugger.RunIOHandlerAsync(io_handler_sp);
65214f1b3e8SDimitry Andric         } else {
65314f1b3e8SDimitry Andric           repl_error.SetErrorStringWithFormat(
65414f1b3e8SDimitry Andric               "Couldn't create a REPL for %s",
65514f1b3e8SDimitry Andric               Language::GetNameForLanguageType(m_command_options.language));
656e81d9d49SDimitry Andric           result.SetError(repl_error);
657b1c73532SDimitry Andric           return;
658e81d9d49SDimitry Andric         }
659e81d9d49SDimitry Andric       }
660e81d9d49SDimitry Andric     }
6610cac4ca3SEd Maste     // No expression following options
662f73363f1SDimitry Andric     else if (expr.empty()) {
6630cac4ca3SEd Maste       GetMultilineExpression();
664b1c73532SDimitry Andric       return;
6650cac4ca3SEd Maste     }
666f034231aSEd Maste   }
667f034231aSEd Maste 
668ead24645SDimitry Andric   Target &target = GetSelectedOrDummyTarget();
669cfca06d7SDimitry Andric   if (EvaluateExpression(expr, result.GetOutputStream(),
670cfca06d7SDimitry Andric                          result.GetErrorStream(), result)) {
67114f1b3e8SDimitry Andric 
672ead24645SDimitry Andric     if (!m_fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) {
673f3fbd1c0SDimitry Andric       CommandHistory &history = m_interpreter.GetCommandHistory();
67414f1b3e8SDimitry Andric       // FIXME: Can we figure out what the user actually typed (e.g. some alias
67514f1b3e8SDimitry Andric       // for expr???)
676f3fbd1c0SDimitry Andric       // If we can it would be nice to show that.
677f3fbd1c0SDimitry Andric       std::string fixed_command("expression ");
678f73363f1SDimitry Andric       if (args.HasArgs()) {
679f3fbd1c0SDimitry Andric         // Add in any options that might have been in the original command:
680cfca06d7SDimitry Andric         fixed_command.append(std::string(args.GetArgStringWithDelimiter()));
681f3fbd1c0SDimitry Andric         fixed_command.append(m_fixed_expression);
682f73363f1SDimitry Andric       } else
683f73363f1SDimitry Andric         fixed_command.append(m_fixed_expression);
684f3fbd1c0SDimitry Andric       history.AppendString(fixed_command);
685f3fbd1c0SDimitry Andric     }
686b1c73532SDimitry Andric     return;
687f3fbd1c0SDimitry Andric   }
688f034231aSEd Maste   result.SetStatus(eReturnStatusFailed);
689f034231aSEd Maste }
690