Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp
39587 views
1
//===-- CommandObjectExpression.cpp ---------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "llvm/ADT/StringRef.h"
10
11
#include "CommandObjectExpression.h"
12
#include "lldb/Core/Debugger.h"
13
#include "lldb/Expression/ExpressionVariable.h"
14
#include "lldb/Expression/REPL.h"
15
#include "lldb/Expression/UserExpression.h"
16
#include "lldb/Host/OptionParser.h"
17
#include "lldb/Interpreter/CommandInterpreter.h"
18
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
19
#include "lldb/Interpreter/CommandReturnObject.h"
20
#include "lldb/Interpreter/OptionArgParser.h"
21
#include "lldb/Target/Language.h"
22
#include "lldb/Target/Process.h"
23
#include "lldb/Target/StackFrame.h"
24
#include "lldb/Target/Target.h"
25
#include "lldb/lldb-enumerations.h"
26
#include "lldb/lldb-private-enumerations.h"
27
28
using namespace lldb;
29
using namespace lldb_private;
30
31
CommandObjectExpression::CommandOptions::CommandOptions() = default;
32
33
CommandObjectExpression::CommandOptions::~CommandOptions() = default;
34
35
#define LLDB_OPTIONS_expression
36
#include "CommandOptions.inc"
37
38
Status CommandObjectExpression::CommandOptions::SetOptionValue(
39
uint32_t option_idx, llvm::StringRef option_arg,
40
ExecutionContext *execution_context) {
41
Status error;
42
43
const int short_option = GetDefinitions()[option_idx].short_option;
44
45
switch (short_option) {
46
case 'l':
47
language = Language::GetLanguageTypeFromString(option_arg);
48
if (language == eLanguageTypeUnknown) {
49
StreamString sstr;
50
sstr.Printf("unknown language type: '%s' for expression. "
51
"List of supported languages:\n",
52
option_arg.str().c_str());
53
54
Language::PrintSupportedLanguagesForExpressions(sstr, " ", "\n");
55
error.SetErrorString(sstr.GetString());
56
}
57
break;
58
59
case 'a': {
60
bool success;
61
bool result;
62
result = OptionArgParser::ToBoolean(option_arg, true, &success);
63
if (!success)
64
error.SetErrorStringWithFormat(
65
"invalid all-threads value setting: \"%s\"",
66
option_arg.str().c_str());
67
else
68
try_all_threads = result;
69
} break;
70
71
case 'i': {
72
bool success;
73
bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
74
if (success)
75
ignore_breakpoints = tmp_value;
76
else
77
error.SetErrorStringWithFormat(
78
"could not convert \"%s\" to a boolean value.",
79
option_arg.str().c_str());
80
break;
81
}
82
83
case 'j': {
84
bool success;
85
bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
86
if (success)
87
allow_jit = tmp_value;
88
else
89
error.SetErrorStringWithFormat(
90
"could not convert \"%s\" to a boolean value.",
91
option_arg.str().c_str());
92
break;
93
}
94
95
case 't':
96
if (option_arg.getAsInteger(0, timeout)) {
97
timeout = 0;
98
error.SetErrorStringWithFormat("invalid timeout setting \"%s\"",
99
option_arg.str().c_str());
100
}
101
break;
102
103
case 'u': {
104
bool success;
105
bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
106
if (success)
107
unwind_on_error = tmp_value;
108
else
109
error.SetErrorStringWithFormat(
110
"could not convert \"%s\" to a boolean value.",
111
option_arg.str().c_str());
112
break;
113
}
114
115
case 'v':
116
if (option_arg.empty()) {
117
m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull;
118
break;
119
}
120
m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity)
121
OptionArgParser::ToOptionEnum(
122
option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
123
if (!error.Success())
124
error.SetErrorStringWithFormat(
125
"unrecognized value for description-verbosity '%s'",
126
option_arg.str().c_str());
127
break;
128
129
case 'g':
130
debug = true;
131
unwind_on_error = false;
132
ignore_breakpoints = false;
133
break;
134
135
case 'p':
136
top_level = true;
137
break;
138
139
case 'X': {
140
bool success;
141
bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
142
if (success)
143
auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo;
144
else
145
error.SetErrorStringWithFormat(
146
"could not convert \"%s\" to a boolean value.",
147
option_arg.str().c_str());
148
break;
149
}
150
151
case '\x01': {
152
bool success;
153
bool persist_result =
154
OptionArgParser::ToBoolean(option_arg, true, &success);
155
if (success)
156
suppress_persistent_result = !persist_result ? eLazyBoolYes : eLazyBoolNo;
157
else
158
error.SetErrorStringWithFormat(
159
"could not convert \"%s\" to a boolean value.",
160
option_arg.str().c_str());
161
break;
162
}
163
164
default:
165
llvm_unreachable("Unimplemented option");
166
}
167
168
return error;
169
}
170
171
void CommandObjectExpression::CommandOptions::OptionParsingStarting(
172
ExecutionContext *execution_context) {
173
auto process_sp =
174
execution_context ? execution_context->GetProcessSP() : ProcessSP();
175
if (process_sp) {
176
ignore_breakpoints = process_sp->GetIgnoreBreakpointsInExpressions();
177
unwind_on_error = process_sp->GetUnwindOnErrorInExpressions();
178
} else {
179
ignore_breakpoints = true;
180
unwind_on_error = true;
181
}
182
183
show_summary = true;
184
try_all_threads = true;
185
timeout = 0;
186
debug = false;
187
language = eLanguageTypeUnknown;
188
m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
189
auto_apply_fixits = eLazyBoolCalculate;
190
top_level = false;
191
allow_jit = true;
192
suppress_persistent_result = eLazyBoolCalculate;
193
}
194
195
llvm::ArrayRef<OptionDefinition>
196
CommandObjectExpression::CommandOptions::GetDefinitions() {
197
return llvm::ArrayRef(g_expression_options);
198
}
199
200
EvaluateExpressionOptions
201
CommandObjectExpression::CommandOptions::GetEvaluateExpressionOptions(
202
const Target &target, const OptionGroupValueObjectDisplay &display_opts) {
203
EvaluateExpressionOptions options;
204
options.SetCoerceToId(display_opts.use_objc);
205
options.SetUnwindOnError(unwind_on_error);
206
options.SetIgnoreBreakpoints(ignore_breakpoints);
207
options.SetKeepInMemory(true);
208
options.SetUseDynamic(display_opts.use_dynamic);
209
options.SetTryAllThreads(try_all_threads);
210
options.SetDebug(debug);
211
options.SetLanguage(language);
212
options.SetExecutionPolicy(
213
allow_jit ? EvaluateExpressionOptions::default_execution_policy
214
: lldb_private::eExecutionPolicyNever);
215
216
bool auto_apply_fixits;
217
if (this->auto_apply_fixits == eLazyBoolCalculate)
218
auto_apply_fixits = target.GetEnableAutoApplyFixIts();
219
else
220
auto_apply_fixits = this->auto_apply_fixits == eLazyBoolYes;
221
222
options.SetAutoApplyFixIts(auto_apply_fixits);
223
options.SetRetriesWithFixIts(target.GetNumberOfRetriesWithFixits());
224
225
if (top_level)
226
options.SetExecutionPolicy(eExecutionPolicyTopLevel);
227
228
// If there is any chance we are going to stop and want to see what went
229
// wrong with our expression, we should generate debug info
230
if (!ignore_breakpoints || !unwind_on_error)
231
options.SetGenerateDebugInfo(true);
232
233
if (timeout > 0)
234
options.SetTimeout(std::chrono::microseconds(timeout));
235
else
236
options.SetTimeout(std::nullopt);
237
return options;
238
}
239
240
bool CommandObjectExpression::CommandOptions::ShouldSuppressResult(
241
const OptionGroupValueObjectDisplay &display_opts) const {
242
// Explicitly disabling persistent results takes precedence over the
243
// m_verbosity/use_objc logic.
244
if (suppress_persistent_result != eLazyBoolCalculate)
245
return suppress_persistent_result == eLazyBoolYes;
246
247
return display_opts.use_objc &&
248
m_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact;
249
}
250
251
CommandObjectExpression::CommandObjectExpression(
252
CommandInterpreter &interpreter)
253
: CommandObjectRaw(interpreter, "expression",
254
"Evaluate an expression on the current "
255
"thread. Displays any returned value "
256
"with LLDB's default formatting.",
257
"",
258
eCommandProcessMustBePaused | eCommandTryTargetAPILock),
259
IOHandlerDelegate(IOHandlerDelegate::Completion::Expression),
260
m_format_options(eFormatDefault),
261
m_repl_option(LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false,
262
true),
263
m_expr_line_count(0) {
264
SetHelpLong(
265
R"(
266
Single and multi-line expressions:
267
268
)"
269
" The expression provided on the command line must be a complete expression \
270
with no newlines. To evaluate a multi-line expression, \
271
hit a return after an empty expression, and lldb will enter the multi-line expression editor. \
272
Hit return on an empty line to end the multi-line expression."
273
274
R"(
275
276
Timeouts:
277
278
)"
279
" If the expression can be evaluated statically (without running code) then it will be. \
280
Otherwise, by default the expression will run on the current thread with a short timeout: \
281
currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted \
282
and resumed with all threads running. You can use the -a option to disable retrying on all \
283
threads. You can use the -t option to set a shorter timeout."
284
R"(
285
286
User defined variables:
287
288
)"
289
" You can define your own variables for convenience or to be used in subsequent expressions. \
290
You define them the same way you would define variables in C. If the first character of \
291
your user defined variable is a $, then the variable's value will be available in future \
292
expressions, otherwise it will just be available in the current expression."
293
R"(
294
295
Continuing evaluation after a breakpoint:
296
297
)"
298
" If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \
299
you are done with your investigation, you can either remove the expression execution frames \
300
from the stack with \"thread return -x\" or if you are still interested in the expression result \
301
you can issue the \"continue\" command and the expression evaluation will complete and the \
302
expression result will be available using the \"thread.completed-expression\" key in the thread \
303
format."
304
305
R"(
306
307
Examples:
308
309
expr my_struct->a = my_array[3]
310
expr -f bin -- (index * 8) + 5
311
expr unsigned int $foo = 5
312
expr char c[] = \"foo\"; c[0])");
313
314
AddSimpleArgumentList(eArgTypeExpression);
315
316
// Add the "--format" and "--gdb-format"
317
m_option_group.Append(&m_format_options,
318
OptionGroupFormat::OPTION_GROUP_FORMAT |
319
OptionGroupFormat::OPTION_GROUP_GDB_FMT,
320
LLDB_OPT_SET_1);
321
m_option_group.Append(&m_command_options);
322
m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL,
323
LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
324
m_option_group.Append(&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
325
m_option_group.Finalize();
326
}
327
328
CommandObjectExpression::~CommandObjectExpression() = default;
329
330
Options *CommandObjectExpression::GetOptions() { return &m_option_group; }
331
332
void CommandObjectExpression::HandleCompletion(CompletionRequest &request) {
333
EvaluateExpressionOptions options;
334
options.SetCoerceToId(m_varobj_options.use_objc);
335
options.SetLanguage(m_command_options.language);
336
options.SetExecutionPolicy(lldb_private::eExecutionPolicyNever);
337
options.SetAutoApplyFixIts(false);
338
options.SetGenerateDebugInfo(false);
339
340
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
341
342
// Get out before we start doing things that expect a valid frame pointer.
343
if (exe_ctx.GetFramePtr() == nullptr)
344
return;
345
346
Target *exe_target = exe_ctx.GetTargetPtr();
347
Target &target = exe_target ? *exe_target : GetDummyTarget();
348
349
unsigned cursor_pos = request.GetRawCursorPos();
350
// Get the full user input including the suffix. The suffix is necessary
351
// as OptionsWithRaw will use it to detect if the cursor is cursor is in the
352
// argument part of in the raw input part of the arguments. If we cut of
353
// of the suffix then "expr -arg[cursor] --" would interpret the "-arg" as
354
// the raw input (as the "--" is hidden in the suffix).
355
llvm::StringRef code = request.GetRawLineWithUnusedSuffix();
356
357
const std::size_t original_code_size = code.size();
358
359
// Remove the first token which is 'expr' or some alias/abbreviation of that.
360
code = llvm::getToken(code).second.ltrim();
361
OptionsWithRaw args(code);
362
code = args.GetRawPart();
363
364
// The position where the expression starts in the command line.
365
assert(original_code_size >= code.size());
366
std::size_t raw_start = original_code_size - code.size();
367
368
// Check if the cursor is actually in the expression string, and if not, we
369
// exit.
370
// FIXME: We should complete the options here.
371
if (cursor_pos < raw_start)
372
return;
373
374
// Make the cursor_pos again relative to the start of the code string.
375
assert(cursor_pos >= raw_start);
376
cursor_pos -= raw_start;
377
378
auto language = exe_ctx.GetFrameRef().GetLanguage();
379
380
Status error;
381
lldb::UserExpressionSP expr(target.GetUserExpressionForLanguage(
382
code, llvm::StringRef(), language, UserExpression::eResultTypeAny,
383
options, nullptr, error));
384
if (error.Fail())
385
return;
386
387
expr->Complete(exe_ctx, request, cursor_pos);
388
}
389
390
static lldb_private::Status
391
CanBeUsedForElementCountPrinting(ValueObject &valobj) {
392
CompilerType type(valobj.GetCompilerType());
393
CompilerType pointee;
394
if (!type.IsPointerType(&pointee))
395
return Status("as it does not refer to a pointer");
396
if (pointee.IsVoidType())
397
return Status("as it refers to a pointer to void");
398
return Status();
399
}
400
401
bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
402
Stream &output_stream,
403
Stream &error_stream,
404
CommandReturnObject &result) {
405
// Don't use m_exe_ctx as this might be called asynchronously after the
406
// command object DoExecute has finished when doing multi-line expression
407
// that use an input reader...
408
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
409
Target *exe_target = exe_ctx.GetTargetPtr();
410
Target &target = exe_target ? *exe_target : GetDummyTarget();
411
412
lldb::ValueObjectSP result_valobj_sp;
413
StackFrame *frame = exe_ctx.GetFramePtr();
414
415
if (m_command_options.top_level && !m_command_options.allow_jit) {
416
result.AppendErrorWithFormat(
417
"Can't disable JIT compilation for top-level expressions.\n");
418
return false;
419
}
420
421
EvaluateExpressionOptions eval_options =
422
m_command_options.GetEvaluateExpressionOptions(target, m_varobj_options);
423
// This command manually removes the result variable, make sure expression
424
// evaluation doesn't do it first.
425
eval_options.SetSuppressPersistentResult(false);
426
427
ExpressionResults success = target.EvaluateExpression(
428
expr, frame, result_valobj_sp, eval_options, &m_fixed_expression);
429
430
// Only mention Fix-Its if the expression evaluator applied them.
431
// Compiler errors refer to the final expression after applying Fix-It(s).
432
if (!m_fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) {
433
error_stream << " Evaluated this expression after applying Fix-It(s):\n";
434
error_stream << " " << m_fixed_expression << "\n";
435
}
436
437
if (result_valobj_sp) {
438
Format format = m_format_options.GetFormat();
439
440
if (result_valobj_sp->GetError().Success()) {
441
if (format != eFormatVoid) {
442
if (format != eFormatDefault)
443
result_valobj_sp->SetFormat(format);
444
445
if (m_varobj_options.elem_count > 0) {
446
Status error(CanBeUsedForElementCountPrinting(*result_valobj_sp));
447
if (error.Fail()) {
448
result.AppendErrorWithFormat(
449
"expression cannot be used with --element-count %s\n",
450
error.AsCString(""));
451
return false;
452
}
453
}
454
455
bool suppress_result =
456
m_command_options.ShouldSuppressResult(m_varobj_options);
457
458
DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
459
m_command_options.m_verbosity, format));
460
options.SetHideRootName(suppress_result);
461
options.SetVariableFormatDisplayLanguage(
462
result_valobj_sp->GetPreferredDisplayLanguage());
463
464
if (llvm::Error error =
465
result_valobj_sp->Dump(output_stream, options)) {
466
result.AppendError(toString(std::move(error)));
467
return false;
468
}
469
470
if (suppress_result)
471
if (auto result_var_sp =
472
target.GetPersistentVariable(result_valobj_sp->GetName())) {
473
auto language = result_valobj_sp->GetPreferredDisplayLanguage();
474
if (auto *persistent_state =
475
target.GetPersistentExpressionStateForLanguage(language))
476
persistent_state->RemovePersistentVariable(result_var_sp);
477
}
478
result.SetStatus(eReturnStatusSuccessFinishResult);
479
}
480
} else {
481
if (result_valobj_sp->GetError().GetError() ==
482
UserExpression::kNoResult) {
483
if (format != eFormatVoid && GetDebugger().GetNotifyVoid()) {
484
error_stream.PutCString("(void)\n");
485
}
486
487
result.SetStatus(eReturnStatusSuccessFinishResult);
488
} else {
489
const char *error_cstr = result_valobj_sp->GetError().AsCString();
490
if (error_cstr && error_cstr[0]) {
491
const size_t error_cstr_len = strlen(error_cstr);
492
const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';
493
if (strstr(error_cstr, "error:") != error_cstr)
494
error_stream.PutCString("error: ");
495
error_stream.Write(error_cstr, error_cstr_len);
496
if (!ends_with_newline)
497
error_stream.EOL();
498
} else {
499
error_stream.PutCString("error: unknown error\n");
500
}
501
502
result.SetStatus(eReturnStatusFailed);
503
}
504
}
505
} else {
506
error_stream.Printf("error: unknown error\n");
507
}
508
509
return (success != eExpressionSetupError &&
510
success != eExpressionParseError);
511
}
512
513
void CommandObjectExpression::IOHandlerInputComplete(IOHandler &io_handler,
514
std::string &line) {
515
io_handler.SetIsDone(true);
516
StreamFileSP output_sp = io_handler.GetOutputStreamFileSP();
517
StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
518
519
CommandReturnObject return_obj(
520
GetCommandInterpreter().GetDebugger().GetUseColor());
521
EvaluateExpression(line.c_str(), *output_sp, *error_sp, return_obj);
522
if (output_sp)
523
output_sp->Flush();
524
if (error_sp)
525
error_sp->Flush();
526
}
527
528
bool CommandObjectExpression::IOHandlerIsInputComplete(IOHandler &io_handler,
529
StringList &lines) {
530
// An empty lines is used to indicate the end of input
531
const size_t num_lines = lines.GetSize();
532
if (num_lines > 0 && lines[num_lines - 1].empty()) {
533
// Remove the last empty line from "lines" so it doesn't appear in our
534
// resulting input and return true to indicate we are done getting lines
535
lines.PopBack();
536
return true;
537
}
538
return false;
539
}
540
541
void CommandObjectExpression::GetMultilineExpression() {
542
m_expr_lines.clear();
543
m_expr_line_count = 0;
544
545
Debugger &debugger = GetCommandInterpreter().GetDebugger();
546
bool color_prompt = debugger.GetUseColor();
547
const bool multiple_lines = true; // Get multiple lines
548
IOHandlerSP io_handler_sp(
549
new IOHandlerEditline(debugger, IOHandler::Type::Expression,
550
"lldb-expr", // Name of input reader for history
551
llvm::StringRef(), // No prompt
552
llvm::StringRef(), // Continuation prompt
553
multiple_lines, color_prompt,
554
1, // Show line numbers starting at 1
555
*this));
556
557
StreamFileSP output_sp = io_handler_sp->GetOutputStreamFileSP();
558
if (output_sp) {
559
output_sp->PutCString(
560
"Enter expressions, then terminate with an empty line to evaluate:\n");
561
output_sp->Flush();
562
}
563
debugger.RunIOHandlerAsync(io_handler_sp);
564
}
565
566
static EvaluateExpressionOptions
567
GetExprOptions(ExecutionContext &ctx,
568
CommandObjectExpression::CommandOptions command_options) {
569
command_options.OptionParsingStarting(&ctx);
570
571
// Default certain settings for REPL regardless of the global settings.
572
command_options.unwind_on_error = false;
573
command_options.ignore_breakpoints = false;
574
command_options.debug = false;
575
576
EvaluateExpressionOptions expr_options;
577
expr_options.SetUnwindOnError(command_options.unwind_on_error);
578
expr_options.SetIgnoreBreakpoints(command_options.ignore_breakpoints);
579
expr_options.SetTryAllThreads(command_options.try_all_threads);
580
581
if (command_options.timeout > 0)
582
expr_options.SetTimeout(std::chrono::microseconds(command_options.timeout));
583
else
584
expr_options.SetTimeout(std::nullopt);
585
586
return expr_options;
587
}
588
589
void CommandObjectExpression::DoExecute(llvm::StringRef command,
590
CommandReturnObject &result) {
591
m_fixed_expression.clear();
592
auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
593
m_option_group.NotifyOptionParsingStarting(&exe_ctx);
594
595
if (command.empty()) {
596
GetMultilineExpression();
597
return;
598
}
599
600
OptionsWithRaw args(command);
601
llvm::StringRef expr = args.GetRawPart();
602
603
if (args.HasArgs()) {
604
if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, exe_ctx))
605
return;
606
607
if (m_repl_option.GetOptionValue().GetCurrentValue()) {
608
Target &target = GetSelectedOrDummyTarget();
609
// Drop into REPL
610
m_expr_lines.clear();
611
m_expr_line_count = 0;
612
613
Debugger &debugger = target.GetDebugger();
614
615
// Check if the LLDB command interpreter is sitting on top of a REPL
616
// that launched it...
617
if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter,
618
IOHandler::Type::REPL)) {
619
// the LLDB command interpreter is sitting on top of a REPL that
620
// launched it, so just say the command interpreter is done and
621
// fall back to the existing REPL
622
m_interpreter.GetIOHandler(false)->SetIsDone(true);
623
} else {
624
// We are launching the REPL on top of the current LLDB command
625
// interpreter, so just push one
626
bool initialize = false;
627
Status repl_error;
628
REPLSP repl_sp(target.GetREPL(repl_error, m_command_options.language,
629
nullptr, false));
630
631
if (!repl_sp) {
632
initialize = true;
633
repl_sp = target.GetREPL(repl_error, m_command_options.language,
634
nullptr, true);
635
if (!repl_error.Success()) {
636
result.SetError(repl_error);
637
return;
638
}
639
}
640
641
if (repl_sp) {
642
if (initialize) {
643
repl_sp->SetEvaluateOptions(
644
GetExprOptions(exe_ctx, m_command_options));
645
repl_sp->SetFormatOptions(m_format_options);
646
repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
647
}
648
649
IOHandlerSP io_handler_sp(repl_sp->GetIOHandler());
650
io_handler_sp->SetIsDone(false);
651
debugger.RunIOHandlerAsync(io_handler_sp);
652
} else {
653
repl_error.SetErrorStringWithFormat(
654
"Couldn't create a REPL for %s",
655
Language::GetNameForLanguageType(m_command_options.language));
656
result.SetError(repl_error);
657
return;
658
}
659
}
660
}
661
// No expression following options
662
else if (expr.empty()) {
663
GetMultilineExpression();
664
return;
665
}
666
}
667
668
Target &target = GetSelectedOrDummyTarget();
669
if (EvaluateExpression(expr, result.GetOutputStream(),
670
result.GetErrorStream(), result)) {
671
672
if (!m_fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) {
673
CommandHistory &history = m_interpreter.GetCommandHistory();
674
// FIXME: Can we figure out what the user actually typed (e.g. some alias
675
// for expr???)
676
// If we can it would be nice to show that.
677
std::string fixed_command("expression ");
678
if (args.HasArgs()) {
679
// Add in any options that might have been in the original command:
680
fixed_command.append(std::string(args.GetArgStringWithDelimiter()));
681
fixed_command.append(m_fixed_expression);
682
} else
683
fixed_command.append(m_fixed_expression);
684
history.AppendString(fixed_command);
685
}
686
return;
687
}
688
result.SetStatus(eReturnStatusFailed);
689
}
690
691