aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Interpreter')
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp117
-rw-r--r--lldb/source/Interpreter/CommandObject.cpp18
-rw-r--r--lldb/source/Interpreter/CommandReturnObject.cpp8
-rw-r--r--lldb/source/Interpreter/InterpreterProperties.td4
-rw-r--r--lldb/source/Interpreter/OptionGroupMemoryTag.cpp60
-rw-r--r--lldb/source/Interpreter/OptionGroupPlatform.cpp27
-rw-r--r--lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp12
-rw-r--r--lldb/source/Interpreter/OptionValueDictionary.cpp25
-rw-r--r--lldb/source/Interpreter/OptionValueFileColonLine.cpp5
-rw-r--r--lldb/source/Interpreter/OptionValueFileSpec.cpp4
-rw-r--r--lldb/source/Interpreter/OptionValueProperties.cpp11
-rw-r--r--lldb/source/Interpreter/Options.cpp192
-rw-r--r--lldb/source/Interpreter/Property.cpp7
-rw-r--r--lldb/source/Interpreter/ScriptInterpreter.cpp8
-rw-r--r--lldb/source/Interpreter/embedded_interpreter.py73
15 files changed, 332 insertions, 239 deletions
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 59c23716bf89..6ef209b20fc6 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -45,6 +45,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Reproducer.h"
#include "lldb/Utility/State.h"
@@ -83,6 +84,10 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/ScopedPrinter.h"
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+
using namespace lldb;
using namespace lldb_private;
@@ -123,7 +128,8 @@ CommandInterpreter::CommandInterpreter(Debugger &debugger,
m_debugger(debugger), m_synchronous_execution(true),
m_skip_lldbinit_files(false), m_skip_app_init_files(false),
m_comment_char('#'), m_batch_command_mode(false),
- m_truncation_warning(eNoTruncation), m_command_source_depth(0) {
+ m_truncation_warning(eNoOmission), m_max_depth_warning(eNoOmission),
+ m_command_source_depth(0) {
SetEventName(eBroadcastBitThreadShouldExit, "thread-should-exit");
SetEventName(eBroadcastBitResetPrompt, "reset-prompt");
SetEventName(eBroadcastBitQuitCommandReceived, "quit");
@@ -206,7 +212,7 @@ bool CommandInterpreter::SetQuitExitCode(int exit_code) {
}
int CommandInterpreter::GetQuitExitCode(bool &exited) const {
- exited = m_quit_exit_code.hasValue();
+ exited = m_quit_exit_code.has_value();
if (exited)
return *m_quit_exit_code;
return 0;
@@ -239,6 +245,12 @@ bool CommandInterpreter::GetRepeatPreviousCommand() const {
nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
}
+bool CommandInterpreter::GetRequireCommandOverwrite() const {
+ const uint32_t idx = ePropertyRequireCommandOverwrite;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
+}
+
void CommandInterpreter::Initialize() {
LLDB_SCOPED_TIMER();
@@ -433,7 +445,7 @@ void CommandInterpreter::Initialize() {
if (cmd_obj_sp) {
alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
#if defined(__APPLE__)
-#if defined(TARGET_OS_IPHONE)
+#if TARGET_OS_IPHONE
AddAlias("r", cmd_obj_sp, "--");
AddAlias("run", cmd_obj_sp, "--");
#else
@@ -1434,7 +1446,7 @@ void CommandInterpreter::GetHelp(CommandReturnObject &result,
result.AppendMessage("Current user-defined container commands:");
result.AppendMessage("");
max_len = FindLongestCommandWord(m_user_mw_dict);
- for (pos = m_user_dict.begin(); pos != m_user_mw_dict.end(); ++pos) {
+ for (pos = m_user_mw_dict.begin(); pos != m_user_mw_dict.end(); ++pos) {
OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--",
pos->second->GetHelp(), max_len);
}
@@ -1825,7 +1837,7 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
std::string command_string(command_line);
std::string original_command_string(command_line);
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMANDS));
+ Log *log = GetLog(LLDBLog::Commands);
llvm::PrettyStackTraceFormat stack_trace("HandleCommand(command = \"%s\")",
command_line);
@@ -1943,16 +1955,21 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
// arguments.
if (cmd_obj != nullptr) {
- if (add_to_history) {
+ // If we got here when empty_command was true, then this command is a
+ // stored "repeat command" which we should give a chance to produce it's
+ // repeat command, even though we don't add repeat commands to the history.
+ if (add_to_history || empty_command) {
Args command_args(command_string);
- const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
- if (repeat_command != nullptr)
- m_repeat_command.assign(repeat_command);
+ llvm::Optional<std::string> repeat_command =
+ cmd_obj->GetRepeatCommand(command_args, 0);
+ if (repeat_command)
+ m_repeat_command.assign(*repeat_command);
else
m_repeat_command.assign(original_command_string);
+ }
+ if (add_to_history)
m_command_history.AppendString(original_command_string);
- }
std::string remainder;
const std::size_t actual_cmd_name_len = cmd_obj->GetCommandName().size();
@@ -2374,6 +2391,21 @@ void CommandInterpreter::SourceInitFileHome(CommandReturnObject &result,
SourceInitFile(FileSpec(init_file.str()), result);
}
+void CommandInterpreter::SourceInitFileGlobal(CommandReturnObject &result) {
+#ifdef LLDB_GLOBAL_INIT_DIRECTORY
+ if (!m_skip_lldbinit_files) {
+ FileSpec init_file(LLDB_GLOBAL_INIT_DIRECTORY);
+ if (init_file)
+ init_file.MakeAbsolute(HostInfo::GetShlibDir());
+
+ init_file.AppendPathComponent("lldbinit");
+ SourceInitFile(init_file, result);
+ return;
+ }
+#endif
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+}
+
const char *CommandInterpreter::GetCommandPrefix() {
const char *prefix = GetDebugger().GetIOHandlerCommandPrefix();
return prefix == nullptr ? "" : prefix;
@@ -2950,28 +2982,27 @@ bool CommandInterpreter::WasInterrupted() const {
return was_interrupted;
}
-void CommandInterpreter::PrintCommandOutput(Stream &stream,
- llvm::StringRef str) {
+void CommandInterpreter::PrintCommandOutput(IOHandler &io_handler,
+ llvm::StringRef str,
+ bool is_stdout) {
+
+ lldb::StreamFileSP stream = is_stdout ? io_handler.GetOutputStreamFileSP()
+ : io_handler.GetErrorStreamFileSP();
// Split the output into lines and poll for interrupt requests
- const char *data = str.data();
- size_t size = str.size();
- while (size > 0 && !WasInterrupted()) {
- size_t chunk_size = 0;
- for (; chunk_size < size; ++chunk_size) {
- lldbassert(data[chunk_size] != '\0');
- if (data[chunk_size] == '\n') {
- ++chunk_size;
- break;
- }
+ while (!str.empty() && !WasInterrupted()) {
+ llvm::StringRef line;
+ std::tie(line, str) = str.split('\n');
+ {
+ std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
+ stream->Write(line.data(), line.size());
+ stream->Write("\n", 1);
}
- chunk_size = stream.Write(data, chunk_size);
- lldbassert(size >= chunk_size);
- data += chunk_size;
- size -= chunk_size;
- }
- if (size > 0) {
- stream.Printf("\n... Interrupted.\n");
}
+
+ std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
+ if (!str.empty())
+ stream->Printf("\n... Interrupted.\n");
+ stream->Flush();
}
bool CommandInterpreter::EchoCommandNonInteractive(
@@ -3007,16 +3038,24 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
// When using a non-interactive file handle (like when sourcing commands
// from a file) we need to echo the command out so we don't just see the
// command output and no command...
- if (EchoCommandNonInteractive(line, io_handler.GetFlags()))
+ if (EchoCommandNonInteractive(line, io_handler.GetFlags())) {
+ std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
io_handler.GetOutputStreamFileSP()->Printf(
"%s%s\n", io_handler.GetPrompt(), line.c_str());
+ }
}
StartHandlingCommand();
- OverrideExecutionContext(m_debugger.GetSelectedExecutionContext());
- auto finalize = llvm::make_scope_exit([this]() {
- RestoreExecutionContext();
+ ExecutionContext exe_ctx = m_debugger.GetSelectedExecutionContext();
+ bool pushed_exe_ctx = false;
+ if (exe_ctx.HasTargetScope()) {
+ OverrideExecutionContext(exe_ctx);
+ pushed_exe_ctx = true;
+ }
+ auto finalize = llvm::make_scope_exit([this, pushed_exe_ctx]() {
+ if (pushed_exe_ctx)
+ RestoreExecutionContext();
});
lldb_private::CommandReturnObject result(m_debugger.GetUseColor());
@@ -3031,13 +3070,13 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
if (!result.GetImmediateOutputStream()) {
llvm::StringRef output = result.GetOutputData();
- PrintCommandOutput(*io_handler.GetOutputStreamFileSP(), output);
+ PrintCommandOutput(io_handler, output, true);
}
// Now emit the command error text from the command we just executed
if (!result.GetImmediateErrorStream()) {
llvm::StringRef error = result.GetErrorData();
- PrintCommandOutput(*io_handler.GetErrorStreamFileSP(), error);
+ PrintCommandOutput(io_handler, error, false);
}
}
@@ -3122,8 +3161,8 @@ bool CommandInterpreter::SaveTranscript(
}
auto error_out = [&](llvm::StringRef error_message, std::string description) {
- LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMANDS), "{0} ({1}:{2})",
- error_message, output_file, description);
+ LLDB_LOG(GetLog(LLDBLog::Commands), "{0} ({1}:{2})", error_message,
+ output_file, description);
result.AppendErrorWithFormatv(
"Failed to save session's transcripts to {0}!", *output_file);
return false;
@@ -3156,6 +3195,10 @@ bool CommandInterpreter::SaveTranscript(
return true;
}
+bool CommandInterpreter::IsInteractive() {
+ return (GetIOHandler() ? GetIOHandler()->GetIsInteractive() : false);
+}
+
FileSpec CommandInterpreter::GetCurrentSourceDir() {
if (m_command_source_dirs.empty())
return {};
diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp
index dcae27ff5479..c92fec53a55e 100644
--- a/lldb/source/Interpreter/CommandObject.cpp
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -132,7 +132,7 @@ bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
} else {
// No error string, output the usage information into result
options->GenerateOptionUsage(
- result.GetErrorStream(), this,
+ result.GetErrorStream(), *this,
GetCommandInterpreter().GetDebugger().GetTerminalWidth());
}
}
@@ -326,7 +326,7 @@ bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word,
if (!found_word && search_options && GetOptions() != nullptr) {
StreamString usage_help;
GetOptions()->GenerateOptionUsage(
- usage_help, this,
+ usage_help, *this,
GetCommandInterpreter().GetDebugger().GetTerminalWidth());
if (!usage_help.Empty()) {
llvm::StringRef usage_text = usage_help.GetString();
@@ -863,7 +863,7 @@ void CommandObject::GenerateHelpText(Stream &output_strm) {
Options *options = GetOptions();
if (options != nullptr) {
options->GenerateOptionUsage(
- output_strm, this,
+ output_strm, *this,
GetCommandInterpreter().GetDebugger().GetTerminalWidth());
}
llvm::StringRef long_help = GetHelpLong();
@@ -995,6 +995,11 @@ bool CommandObjectParsed::Execute(const char *args_string,
if (ParseOptions(cmd_args, result)) {
// Call the command-specific version of 'Execute', passing it the
// already processed arguments.
+ if (cmd_args.GetArgumentCount() != 0 && m_arguments.empty()) {
+ result.AppendErrorWithFormatv("'{0}' doesn't take any arguments.",
+ GetCommandName());
+ return false;
+ }
handled = DoExecute(cmd_args, result);
}
}
@@ -1126,7 +1131,12 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = {
{ eArgTypeCommand, "command", CommandCompletions::eNoCompletion, { nullptr, false }, "An LLDB Command line command element." },
{ eArgTypeColumnNum, "column", CommandCompletions::eNoCompletion, { nullptr, false }, "Column number in a source file." },
{ eArgTypeModuleUUID, "module-uuid", CommandCompletions::eModuleUUIDCompletion, { nullptr, false }, "A module UUID value." },
- { eArgTypeSaveCoreStyle, "corefile-style", CommandCompletions::eNoCompletion, { nullptr, false }, "The type of corefile that lldb will try to create, dependant on this target's capabilities." }
+ { eArgTypeSaveCoreStyle, "corefile-style", CommandCompletions::eNoCompletion, { nullptr, false }, "The type of corefile that lldb will try to create, dependant on this target's capabilities." },
+ { eArgTypeLogHandler, "log-handler", CommandCompletions::eNoCompletion, { nullptr, false }, "The log handle that will be used to write out log messages." },
+ { eArgTypeSEDStylePair, "substitution-pair", CommandCompletions::eNoCompletion, { nullptr, false }, "A sed-style pattern and target pair." },
+ { eArgTypeConnectURL, "process-connect-url", CommandCompletions::eNoCompletion, { nullptr, false }, "A URL-style specification for a remote connection." },
+ { eArgTypeTargetID, "target-id", CommandCompletions::eNoCompletion, { nullptr, false }, "The index ID for an lldb Target." },
+ { eArgTypeStopHookID, "stop-hook-id", CommandCompletions::eNoCompletion, { nullptr, false }, "The ID you receive when you create a stop-hook." }
// clang-format on
};
diff --git a/lldb/source/Interpreter/CommandReturnObject.cpp b/lldb/source/Interpreter/CommandReturnObject.cpp
index 1b1e6996764c..4433c43ff6d4 100644
--- a/lldb/source/Interpreter/CommandReturnObject.cpp
+++ b/lldb/source/Interpreter/CommandReturnObject.cpp
@@ -106,7 +106,13 @@ void CommandReturnObject::AppendError(llvm::StringRef in_string) {
void CommandReturnObject::SetError(const Status &error,
const char *fallback_error_cstr) {
- AppendError(error.AsCString(fallback_error_cstr));
+ if (error.Fail())
+ AppendError(error.AsCString(fallback_error_cstr));
+}
+
+void CommandReturnObject::SetError(llvm::Error error) {
+ if (error)
+ AppendError(llvm::toString(std::move(error)));
}
// Similar to AppendError, but do not prepend 'Status: ' to message, and don't
diff --git a/lldb/source/Interpreter/InterpreterProperties.td b/lldb/source/Interpreter/InterpreterProperties.td
index 1c6f0206c489..c0acc044fb7f 100644
--- a/lldb/source/Interpreter/InterpreterProperties.td
+++ b/lldb/source/Interpreter/InterpreterProperties.td
@@ -36,4 +36,8 @@ let Definition = "interpreter" in {
Global,
DefaultTrue,
Desc<"If true, LLDB will repeat the previous command if no command was passed to the interpreter. If false, LLDB won't repeat the previous command but only return a new prompt.">;
+ def RequireCommandOverwrite: Property<"require-overwrite", "Boolean">,
+ Global,
+ DefaultTrue,
+ Desc<"If true, require --overwrite in 'command script add' before overwriting existing user commands.">;
}
diff --git a/lldb/source/Interpreter/OptionGroupMemoryTag.cpp b/lldb/source/Interpreter/OptionGroupMemoryTag.cpp
new file mode 100644
index 000000000000..6752b6c8acf2
--- /dev/null
+++ b/lldb/source/Interpreter/OptionGroupMemoryTag.cpp
@@ -0,0 +1,60 @@
+//===-- OptionGroupMemoryTag.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/OptionGroupMemoryTag.h"
+
+#include "lldb/Host/OptionParser.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static const uint32_t SHORT_OPTION_SHOW_TAGS = 0x54414753; // 'tags'
+
+OptionGroupMemoryTag::OptionGroupMemoryTag(bool note_binary /*=false*/)
+ : m_show_tags(false, false), m_option_definition{
+ LLDB_OPT_SET_1,
+ false,
+ "show-tags",
+ SHORT_OPTION_SHOW_TAGS,
+ OptionParser::eNoArgument,
+ nullptr,
+ {},
+ 0,
+ eArgTypeNone,
+ note_binary
+ ? "Include memory tags in output "
+ "(does not apply to binary output)."
+ : "Include memory tags in output."} {}
+
+llvm::ArrayRef<OptionDefinition> OptionGroupMemoryTag::GetDefinitions() {
+ return llvm::makeArrayRef(m_option_definition);
+}
+
+Status
+OptionGroupMemoryTag::SetOptionValue(uint32_t option_idx,
+ llvm::StringRef option_arg,
+ ExecutionContext *execution_context) {
+ assert(option_idx == 0 && "Only one option in memory tag group!");
+
+ switch (m_option_definition.short_option) {
+ case SHORT_OPTION_SHOW_TAGS:
+ m_show_tags.SetCurrentValue(true);
+ m_show_tags.SetOptionWasSet();
+ break;
+
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+
+ return {};
+}
+
+void OptionGroupMemoryTag::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_show_tags.Clear();
+}
diff --git a/lldb/source/Interpreter/OptionGroupPlatform.cpp b/lldb/source/Interpreter/OptionGroupPlatform.cpp
index 4242e010fa64..acdf3f293496 100644
--- a/lldb/source/Interpreter/OptionGroupPlatform.cpp
+++ b/lldb/source/Interpreter/OptionGroupPlatform.cpp
@@ -18,27 +18,34 @@ using namespace lldb_private;
PlatformSP OptionGroupPlatform::CreatePlatformWithOptions(
CommandInterpreter &interpreter, const ArchSpec &arch, bool make_selected,
Status &error, ArchSpec &platform_arch) const {
+ PlatformList &platforms = interpreter.GetDebugger().GetPlatformList();
+
PlatformSP platform_sp;
if (!m_platform_name.empty()) {
- platform_sp = Platform::Create(ConstString(m_platform_name.c_str()), error);
+ platform_sp = platforms.Create(m_platform_name);
+ if (!platform_sp) {
+ error.SetErrorStringWithFormatv(
+ "unable to find a plug-in for the platform named \"{0}\"",
+ m_platform_name);
+ }
if (platform_sp) {
- if (platform_arch.IsValid() &&
- !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) {
- error.SetErrorStringWithFormat("platform '%s' doesn't support '%s'",
- platform_sp->GetName().GetCString(),
- arch.GetTriple().getTriple().c_str());
+ if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(
+ arch, {}, false, &platform_arch)) {
+ error.SetErrorStringWithFormatv("platform '{0}' doesn't support '{1}'",
+ platform_sp->GetPluginName(),
+ arch.GetTriple().getTriple());
platform_sp.reset();
return platform_sp;
}
}
} else if (arch.IsValid()) {
- platform_sp = Platform::Create(arch, &platform_arch, error);
+ platform_sp = platforms.GetOrCreate(arch, {}, &platform_arch, error);
}
if (platform_sp) {
- interpreter.GetDebugger().GetPlatformList().Append(platform_sp,
- make_selected);
+ if (make_selected)
+ platforms.SetSelectedPlatform(platform_sp);
if (!m_os_version.empty())
platform_sp->SetOSVersion(m_os_version);
@@ -122,7 +129,7 @@ bool OptionGroupPlatform::PlatformMatches(
const lldb::PlatformSP &platform_sp) const {
if (platform_sp) {
if (!m_platform_name.empty()) {
- if (platform_sp->GetName() != ConstString(m_platform_name.c_str()))
+ if (platform_sp->GetName() != m_platform_name)
return false;
}
diff --git a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
index 04861b539650..57b593020b14 100644
--- a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
+++ b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -104,6 +104,8 @@ Status OptionGroupValueObjectDisplay::SetOptionValue(
max_depth = UINT32_MAX;
error.SetErrorStringWithFormat("invalid max depth '%s'",
option_arg.str().c_str());
+ } else {
+ max_depth_is_default = false;
}
break;
@@ -163,6 +165,7 @@ void OptionGroupValueObjectDisplay::OptionParsingStarting(
flat_output = false;
use_objc = false;
max_depth = UINT32_MAX;
+ max_depth_is_default = true;
ptr_depth = 0;
elem_count = 0;
use_synth = true;
@@ -172,9 +175,12 @@ void OptionGroupValueObjectDisplay::OptionParsingStarting(
TargetSP target_sp =
execution_context ? execution_context->GetTargetSP() : TargetSP();
- if (target_sp)
+ if (target_sp) {
use_dynamic = target_sp->GetPreferDynamicValue();
- else {
+ auto max_depth_config = target_sp->GetMaximumDepthOfChildrenToDisplay();
+ max_depth = std::get<uint32_t>(max_depth_config);
+ max_depth_is_default = std::get<bool>(max_depth_config);
+ } else {
// If we don't have any targets, then dynamic values won't do us much good.
use_dynamic = lldb::eNoDynamicValues;
}
@@ -190,7 +196,7 @@ DumpValueObjectOptions OptionGroupValueObjectDisplay::GetAsDumpOptions(
options.SetShowSummary(false);
else
options.SetOmitSummaryDepth(no_summary_depth);
- options.SetMaximumDepth(max_depth)
+ options.SetMaximumDepth(max_depth, max_depth_is_default)
.SetShowTypes(show_types)
.SetShowLocation(show_location)
.SetUseObjectiveC(use_objc)
diff --git a/lldb/source/Interpreter/OptionValueDictionary.cpp b/lldb/source/Interpreter/OptionValueDictionary.cpp
index 26fed4a987e1..6baafc9213e1 100644
--- a/lldb/source/Interpreter/OptionValueDictionary.cpp
+++ b/lldb/source/Interpreter/OptionValueDictionary.cpp
@@ -8,11 +8,12 @@
#include "lldb/Interpreter/OptionValueDictionary.h"
-#include "llvm/ADT/StringRef.h"
#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Interpreter/OptionValueEnumeration.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/State.h"
+#include "llvm/ADT/StringRef.h"
using namespace lldb;
using namespace lldb_private;
@@ -161,16 +162,26 @@ Status OptionValueDictionary::SetArgs(const Args &args,
return error;
}
- lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
- value.str().c_str(), m_type_mask, error));
- if (value_sp) {
+ if (m_type_mask == 1u << eTypeEnum) {
+ auto enum_value =
+ std::make_shared<OptionValueEnumeration>(m_enum_values, 0);
+ error = enum_value->SetValueFromString(value);
if (error.Fail())
return error;
m_value_was_set = true;
- SetValueForKey(ConstString(key), value_sp, true);
+ SetValueForKey(ConstString(key), enum_value, true);
} else {
- error.SetErrorString("dictionaries that can contain multiple types "
- "must subclass OptionValueArray");
+ lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
+ value.str().c_str(), m_type_mask, error));
+ if (value_sp) {
+ if (error.Fail())
+ return error;
+ m_value_was_set = true;
+ SetValueForKey(ConstString(key), value_sp, true);
+ } else {
+ error.SetErrorString("dictionaries that can contain multiple types "
+ "must subclass OptionValueArray");
+ }
}
}
break;
diff --git a/lldb/source/Interpreter/OptionValueFileColonLine.cpp b/lldb/source/Interpreter/OptionValueFileColonLine.cpp
index fb0b516c8616..e500005a815d 100644
--- a/lldb/source/Interpreter/OptionValueFileColonLine.cpp
+++ b/lldb/source/Interpreter/OptionValueFileColonLine.cpp
@@ -24,9 +24,8 @@ using namespace lldb_private;
OptionValueFileColonLine::OptionValueFileColonLine() = default;
OptionValueFileColonLine::OptionValueFileColonLine(llvm::StringRef input)
- : m_line_number(LLDB_INVALID_LINE_NUMBER),
- m_column_number(LLDB_INVALID_COLUMN_NUMBER),
- m_completion_mask(CommandCompletions::eSourceFileCompletion) {
+
+{
SetValueFromString(input, eVarSetOperationAssign);
}
diff --git a/lldb/source/Interpreter/OptionValueFileSpec.cpp b/lldb/source/Interpreter/OptionValueFileSpec.cpp
index 3987a36b1b65..f35a6b886f98 100644
--- a/lldb/source/Interpreter/OptionValueFileSpec.cpp
+++ b/lldb/source/Interpreter/OptionValueFileSpec.cpp
@@ -22,14 +22,14 @@ OptionValueFileSpec::OptionValueFileSpec(bool resolve) : m_resolve(resolve) {}
OptionValueFileSpec::OptionValueFileSpec(const FileSpec &value, bool resolve)
: m_current_value(value), m_default_value(value),
- m_completion_mask(CommandCompletions::eDiskFileCompletion),
+
m_resolve(resolve) {}
OptionValueFileSpec::OptionValueFileSpec(const FileSpec &current_value,
const FileSpec &default_value,
bool resolve)
: m_current_value(current_value), m_default_value(default_value),
- m_completion_mask(CommandCompletions::eDiskFileCompletion),
+
m_resolve(resolve) {}
void OptionValueFileSpec::DumpValue(const ExecutionContext *exe_ctx,
diff --git a/lldb/source/Interpreter/OptionValueProperties.cpp b/lldb/source/Interpreter/OptionValueProperties.cpp
index 6e6580574edf..b216557b808f 100644
--- a/lldb/source/Interpreter/OptionValueProperties.cpp
+++ b/lldb/source/Interpreter/OptionValueProperties.cpp
@@ -412,6 +412,17 @@ OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
return nullptr;
}
+OptionValueUInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueUInt64(
+ const ExecutionContext *exe_ctx, uint32_t idx) const {
+ const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
+ if (property) {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->GetAsUInt64();
+ }
+ return nullptr;
+}
+
int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64(
const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
diff --git a/lldb/source/Interpreter/Options.cpp b/lldb/source/Interpreter/Options.cpp
index feebe338bc9a..26d9d2a17867 100644
--- a/lldb/source/Interpreter/Options.cpp
+++ b/lldb/source/Interpreter/Options.cpp
@@ -20,6 +20,7 @@
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/StreamString.h"
+#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
@@ -223,21 +224,25 @@ Option *Options::GetLongOptions() {
option_seen.find(short_opt);
StreamString strm;
if (defs[i].HasShortOption())
- Host::SystemLog(Host::eSystemLogError,
- "option[%u] --%s has a short option -%c that "
- "conflicts with option[%u] --%s, short option won't "
- "be used for --%s\n",
- (int)i, defs[i].long_option, short_opt, pos->second,
- m_getopt_table[pos->second].definition->long_option,
- defs[i].long_option);
+ Debugger::ReportError(
+ llvm::formatv(
+ "option[{0}] --{1} has a short option -{2} that "
+ "conflicts with option[{3}] --{4}, short option won't "
+ "be used for --{5}",
+ i, defs[i].long_option, short_opt, pos->second,
+ m_getopt_table[pos->second].definition->long_option,
+ defs[i].long_option)
+ .str());
else
- Host::SystemLog(Host::eSystemLogError,
- "option[%u] --%s has a short option 0x%x that "
- "conflicts with option[%u] --%s, short option won't "
- "be used for --%s\n",
- (int)i, defs[i].long_option, short_opt, pos->second,
- m_getopt_table[pos->second].definition->long_option,
- defs[i].long_option);
+ Debugger::ReportError(
+ llvm::formatv(
+ "option[{0}] --{1} has a short option {2:x} that "
+ "conflicts with option[{3}] --{4}, short option won't "
+ "be used for --{5}n",
+ (int)i, defs[i].long_option, short_opt, pos->second,
+ m_getopt_table[pos->second].definition->long_option,
+ defs[i].long_option)
+ .str());
}
}
@@ -387,26 +392,19 @@ static bool PrintOption(const OptionDefinition &opt_def,
return true;
}
-void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd,
+void Options::GenerateOptionUsage(Stream &strm, CommandObject &cmd,
uint32_t screen_width) {
- const bool only_print_args = cmd->IsDashDashCommand();
-
auto opt_defs = GetDefinitions();
const uint32_t save_indent_level = strm.GetIndentLevel();
- llvm::StringRef name;
-
+ llvm::StringRef name = cmd.GetCommandName();
StreamString arguments_str;
-
- if (cmd) {
- name = cmd->GetCommandName();
- cmd->GetFormattedCommandArguments(arguments_str);
- } else
- name = "";
+ cmd.GetFormattedCommandArguments(arguments_str);
const uint32_t num_options = NumCommandOptions();
if (num_options == 0)
return;
+ const bool only_print_args = cmd.IsDashDashCommand();
if (!only_print_args)
strm.PutCString("\nCommand Options Usage:\n");
@@ -418,113 +416,73 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd,
// [options-for-level-1]
// etc.
- uint32_t num_option_sets = GetRequiredOptions().size();
-
- uint32_t i;
-
if (!only_print_args) {
+ uint32_t num_option_sets = GetRequiredOptions().size();
for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set) {
- uint32_t opt_set_mask;
-
- opt_set_mask = 1 << opt_set;
if (opt_set > 0)
strm.Printf("\n");
strm.Indent(name);
// Different option sets may require different args.
StreamString args_str;
- if (cmd)
- cmd->GetFormattedCommandArguments(args_str, opt_set_mask);
+ uint32_t opt_set_mask = 1 << opt_set;
+ cmd.GetFormattedCommandArguments(args_str, opt_set_mask);
// First go through and print all options that take no arguments as a
// single string. If a command has "-a" "-b" and "-c", this will show up
// as [-abc]
- std::set<int> options;
- std::set<int>::const_iterator options_pos, options_end;
- for (auto &def : opt_defs) {
- if (def.usage_mask & opt_set_mask && def.HasShortOption()) {
- // Add current option to the end of out_stream.
+ // We use a set here so that they will be sorted.
+ std::set<int> required_options;
+ std::set<int> optional_options;
- if (def.required && def.option_has_arg == OptionParser::eNoArgument) {
- options.insert(def.short_option);
+ for (auto &def : opt_defs) {
+ if (def.usage_mask & opt_set_mask && def.HasShortOption() &&
+ def.option_has_arg == OptionParser::eNoArgument) {
+ if (def.required) {
+ required_options.insert(def.short_option);
+ } else {
+ optional_options.insert(def.short_option);
}
}
}
- if (!options.empty()) {
- // We have some required options with no arguments
+ if (!required_options.empty()) {
strm.PutCString(" -");
- for (i = 0; i < 2; ++i)
- for (options_pos = options.begin(), options_end = options.end();
- options_pos != options_end; ++options_pos) {
- if (i == 0 && ::islower(*options_pos))
- continue;
- if (i == 1 && ::isupper(*options_pos))
- continue;
- strm << (char)*options_pos;
- }
- }
-
- options.clear();
- for (auto &def : opt_defs) {
- if (def.usage_mask & opt_set_mask && def.HasShortOption()) {
- // Add current option to the end of out_stream.
-
- if (!def.required &&
- def.option_has_arg == OptionParser::eNoArgument) {
- options.insert(def.short_option);
- }
- }
+ for (int short_option : required_options)
+ strm.PutChar(short_option);
}
- if (!options.empty()) {
- // We have some required options with no arguments
+ if (!optional_options.empty()) {
strm.PutCString(" [-");
- for (i = 0; i < 2; ++i)
- for (options_pos = options.begin(), options_end = options.end();
- options_pos != options_end; ++options_pos) {
- if (i == 0 && ::islower(*options_pos))
- continue;
- if (i == 1 && ::isupper(*options_pos))
- continue;
- strm << (char)*options_pos;
- }
+ for (int short_option : optional_options)
+ strm.PutChar(short_option);
strm.PutChar(']');
}
// First go through and print the required options (list them up front).
-
for (auto &def : opt_defs) {
- if (def.usage_mask & opt_set_mask && def.HasShortOption()) {
- if (def.required && def.option_has_arg != OptionParser::eNoArgument)
- PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
- }
+ if (def.usage_mask & opt_set_mask && def.HasShortOption() &&
+ def.required && def.option_has_arg != OptionParser::eNoArgument)
+ PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
}
// Now go through again, and this time only print the optional options.
-
for (auto &def : opt_defs) {
- if (def.usage_mask & opt_set_mask) {
- // Add current option to the end of out_stream.
-
- if (!def.required && def.option_has_arg != OptionParser::eNoArgument)
- PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
- }
+ if (def.usage_mask & opt_set_mask && !def.required &&
+ def.option_has_arg != OptionParser::eNoArgument)
+ PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
}
if (args_str.GetSize() > 0) {
- if (cmd->WantsRawCommandString() && !only_print_args)
+ if (cmd.WantsRawCommandString())
strm.Printf(" --");
-
strm << " " << args_str.GetString();
- if (only_print_args)
- break;
}
}
}
- if (cmd && (only_print_args || cmd->WantsRawCommandString()) &&
+ if ((only_print_args || cmd.WantsRawCommandString()) &&
arguments_str.GetSize() > 0) {
if (!only_print_args)
strm.PutChar('\n');
@@ -540,63 +498,49 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd,
// -short <argument> ( --long_name <argument> )
// help text
- // This variable is used to keep track of which options' info we've printed
- // out, because some options can be in more than one usage level, but we
- // only want to print the long form of its information once.
-
- std::multimap<int, uint32_t> options_seen;
strm.IndentMore(5);
- // Put the unique command options in a vector & sort it, so we can output
- // them alphabetically (by short_option) when writing out detailed help for
- // each option.
-
- i = 0;
- for (auto &def : opt_defs)
- options_seen.insert(std::make_pair(def.short_option, i++));
+ // Put the command options in a sorted container, so we can output
+ // them alphabetically by short_option.
+ std::multimap<int, uint32_t> options_ordered;
+ for (auto def : llvm::enumerate(opt_defs))
+ options_ordered.insert(
+ std::make_pair(def.value().short_option, def.index()));
- // Go through the unique'd and alphabetically sorted vector of options,
- // find the table entry for each option and write out the detailed help
- // information for that option.
+ // Go through each option, find the table entry and write out the detailed
+ // help information for that option.
bool first_option_printed = false;
- for (auto pos : options_seen) {
- i = pos.second;
- // Print out the help information for this option.
-
+ for (auto pos : options_ordered) {
// Put a newline separation between arguments
if (first_option_printed)
strm.EOL();
else
first_option_printed = true;
- CommandArgumentType arg_type = opt_defs[i].argument_type;
-
- StreamString arg_name_str;
- arg_name_str.Printf("<%s>", CommandObject::GetArgumentName(arg_type));
+ OptionDefinition opt_def = opt_defs[pos.second];
strm.Indent();
- if (opt_defs[i].short_option && opt_defs[i].HasShortOption()) {
- PrintOption(opt_defs[i], eDisplayShortOption, nullptr, nullptr, false,
+ if (opt_def.short_option && opt_def.HasShortOption()) {
+ PrintOption(opt_def, eDisplayShortOption, nullptr, nullptr, false,
strm);
- PrintOption(opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm);
+ PrintOption(opt_def, eDisplayLongOption, " ( ", " )", false, strm);
} else {
// Short option is not printable, just print long option
- PrintOption(opt_defs[i], eDisplayLongOption, nullptr, nullptr, false,
- strm);
+ PrintOption(opt_def, eDisplayLongOption, nullptr, nullptr, false, strm);
}
strm.EOL();
strm.IndentMore(5);
- if (opt_defs[i].usage_text)
- OutputFormattedUsageText(strm, opt_defs[i], screen_width);
- if (!opt_defs[i].enum_values.empty()) {
+ if (opt_def.usage_text)
+ OutputFormattedUsageText(strm, opt_def, screen_width);
+ if (!opt_def.enum_values.empty()) {
strm.Indent();
strm.Printf("Values: ");
bool is_first = true;
- for (const auto &enum_value : opt_defs[i].enum_values) {
+ for (const auto &enum_value : opt_def.enum_values) {
if (is_first) {
strm.Printf("%s", enum_value.string_value);
is_first = false;
diff --git a/lldb/source/Interpreter/Property.cpp b/lldb/source/Interpreter/Property.cpp
index fe3a8a31394b..681596224d31 100644
--- a/lldb/source/Interpreter/Property.cpp
+++ b/lldb/source/Interpreter/Property.cpp
@@ -68,9 +68,10 @@ Property::Property(const PropertyDefinition &definition)
}
case OptionValue::eTypeDictionary:
// "definition.default_uint_value" is always a OptionValue::Type
- m_value_sp =
- std::make_shared<OptionValueDictionary>(OptionValue::ConvertTypeToMask(
- (OptionValue::Type)definition.default_uint_value));
+ m_value_sp = std::make_shared<OptionValueDictionary>(
+ OptionValue::ConvertTypeToMask(
+ (OptionValue::Type)definition.default_uint_value),
+ definition.enum_values);
break;
case OptionValue::eTypeEnum:
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
index fbdcbb8da868..bc8a542afc87 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -109,13 +109,13 @@ ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {
Status ScriptInterpreter::SetBreakpointCommandCallback(
std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
const char *callback_text) {
- Status return_error;
+ Status error;
for (BreakpointOptions &bp_options : bp_options_vec) {
- return_error = SetBreakpointCommandCallback(bp_options, callback_text);
- if (return_error.Success())
+ error = SetBreakpointCommandCallback(bp_options, callback_text);
+ if (!error.Success())
break;
}
- return return_error;
+ return error;
}
Status ScriptInterpreter::SetBreakpointCommandCallbackFunction(
diff --git a/lldb/source/Interpreter/embedded_interpreter.py b/lldb/source/Interpreter/embedded_interpreter.py
index 9312dbfaca4e..fd2cc06bc286 100644
--- a/lldb/source/Interpreter/embedded_interpreter.py
+++ b/lldb/source/Interpreter/embedded_interpreter.py
@@ -1,4 +1,4 @@
-import sys
+import sys
if sys.version_info[0] < 3:
import __builtin__ as builtins
else:
@@ -23,36 +23,6 @@ else:
else:
readline.parse_and_bind('tab: complete')
-g_builtin_override_called = False
-
-
-class LLDBQuitter(object):
-
- def __init__(self, name):
- self.name = name
-
- def __repr__(self):
- self()
-
- def __call__(self, code=None):
- global g_builtin_override_called
- g_builtin_override_called = True
- raise SystemExit(-1)
-
-
-def setquit():
- '''Redefine builtin functions 'quit()' and 'exit()' to print a message and raise an EOFError exception.'''
- # This function will be called prior to each interactive
- # interpreter loop or each single line, so we set the global
- # g_builtin_override_called to False so we know if a SystemExit
- # is thrown, we can catch it and tell the difference between
- # a call to "quit()" or "exit()" and something like
- # "sys.exit(123)"
- global g_builtin_override_called
- g_builtin_override_called = False
- builtins.quit = LLDBQuitter('quit')
- builtins.exit = LLDBQuitter('exit')
-
# When running one line, we might place the string to run in this string
# in case it would be hard to correctly escape a string's contents
@@ -70,6 +40,22 @@ def get_terminal_size(fd):
return hw
+class LLDBExit(SystemExit):
+ pass
+
+
+def strip_and_check_exit(line):
+ line = line.rstrip()
+ if line in ('exit', 'quit'):
+ raise LLDBExit
+ return line
+
+
+def readfunc(prompt):
+ line = input(prompt)
+ return strip_and_check_exit(line)
+
+
def readfunc_stdio(prompt):
sys.stdout.write(prompt)
sys.stdout.flush()
@@ -78,12 +64,11 @@ def readfunc_stdio(prompt):
# ends with an incomplete line. An empty line indicates EOF.
if not line:
raise EOFError
- return line.rstrip()
+ return strip_and_check_exit(line)
def run_python_interpreter(local_dict):
# Pass in the dictionary, for continuity from one session to the next.
- setquit()
try:
fd = sys.stdin.fileno()
interacted = False
@@ -116,24 +101,30 @@ def run_python_interpreter(local_dict):
# We have a real interactive terminal
code.interact(
banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.",
+ readfunc=readfunc,
local=local_dict)
+ except LLDBExit:
+ pass
except SystemExit as e:
- global g_builtin_override_called
- if not g_builtin_override_called:
- print('Script exited with %s' % (e))
+ if e.code:
+ print('Script exited with code %s' % e.code)
def run_one_line(local_dict, input_string):
global g_run_one_line_str
- setquit()
try:
+ input_string = strip_and_check_exit(input_string)
repl = code.InteractiveConsole(local_dict)
if input_string:
+ # A newline is appended to support one-line statements containing
+ # control flow. For example "if True: print(1)" silently does
+ # nothing, but works with a newline: "if True: print(1)\n".
+ input_string += "\n"
repl.runsource(input_string)
elif g_run_one_line_str:
repl.runsource(g_run_one_line_str)
-
+ except LLDBExit:
+ pass
except SystemExit as e:
- global g_builtin_override_called
- if not g_builtin_override_called:
- print('Script exited with %s' % (e))
+ if e.code:
+ print('Script exited with code %s' % e.code)