This patch adds the infrastructure to have language specific REPL init
files. It's the foundation work to a following patch that will introduce
Swift REPL init file.
When lldb is launched with the `--repl` option, it will look for a REPL
init file in the home directory and source it. This overrides the
default `~/.lldbinit`, which content might make the REPL behave
unexpectedly. If the REPL init file doesn't exists, lldb will fall back
to the default init file.
rdar://
65836048
Differential Revision: https://reviews.llvm.org/D86242
Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
:program:`lldb` reads things like settings, aliases and commands from the
.lldbinit file.
-First, it will read the application specific init file whose name is
-~/.lldbinit followed by a "-" and the name of the current program. This would
-be ~/.lldbinit-lldb for the command line :program:`lldb` and ~/.lldbinit-Xcode
-for Xcode. If there is no application specific init file, the global
-~/.lldbinit is read.
+First, :program:`lldb` will try to read the application specific init file
+whose name is ~/.lldbinit followed by a "-" and the name of the current
+program. This would be ~/.lldbinit-lldb for the command line :program:`lldb`
+and ~/.lldbinit-Xcode for Xcode. If there is no application specific init
+file, :program:`lldb` will look for an init file in the home directory.
+If launched with a `REPL`_ option, it will first look for a REPL configuration
+file, specific to the REPL language. If this file doesn't exist, or :program:`lldb`
+wasn't launch with `REPL`_, meaning there is neither a REPL init file nor an
+application specific init file, `lldb` will fallback to the global ~/.lldbinit.
Secondly, it will look for an .lldbinit file in the current working directory.
For security reasons, :program:`lldb` will print a warning and not source this
const char *auto_repeat_command);
void SourceInitFileInHomeDirectory(lldb::SBCommandReturnObject &result);
+ void SourceInitFileInHomeDirectory(lldb::SBCommandReturnObject &result,
+ bool is_repl);
void
SourceInitFileInCurrentWorkingDirectory(lldb::SBCommandReturnObject &result);
}
void SourceInitFileCwd(CommandReturnObject &result);
- void SourceInitFileHome(CommandReturnObject &result);
+ void SourceInitFileHome(CommandReturnObject &result, bool is_repl = false);
bool AddCommand(llvm::StringRef name, const lldb::CommandObjectSP &cmd_sp,
bool can_replace);
}
}
+void SBCommandInterpreter::SourceInitFileInHomeDirectory(
+ SBCommandReturnObject &result, bool is_repl) {
+ LLDB_RECORD_METHOD(void, SBCommandInterpreter, SourceInitFileInHomeDirectory,
+ (lldb::SBCommandReturnObject &, bool), result, is_repl);
+
+ result.Clear();
+ if (IsValid()) {
+ TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
+ std::unique_lock<std::recursive_mutex> lock;
+ if (target_sp)
+ lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
+ m_opaque_ptr->SourceInitFileHome(result.ref(), is_repl);
+ } else {
+ result->AppendError("SBCommandInterpreter is not valid");
+ result->SetStatus(eReturnStatusFailed);
+ }
+}
+
void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory(
SBCommandReturnObject &result) {
LLDB_RECORD_METHOD(void, SBCommandInterpreter,
SourceInitFileInHomeDirectory,
(lldb::SBCommandReturnObject &));
LLDB_REGISTER_METHOD(void, SBCommandInterpreter,
+ SourceInitFileInHomeDirectory,
+ (lldb::SBCommandReturnObject &, bool));
+ LLDB_REGISTER_METHOD(void, SBCommandInterpreter,
SourceInitFileInCurrentWorkingDirectory,
(lldb::SBCommandReturnObject &));
LLDB_REGISTER_METHOD(lldb::SBBroadcaster, SBCommandInterpreter,
interp.get()->SkipLLDBInitFiles(false);
interp.get()->SkipAppInitFiles(false);
SBCommandReturnObject result;
- interp.SourceInitFileInHomeDirectory(result);
+ interp.SourceInitFileInHomeDirectory(result, false);
} else {
interp.get()->SkipLLDBInitFiles(true);
interp.get()->SkipAppInitFiles(true);
FileSystem::Instance().Resolve(init_file);
}
+static void GetHomeREPLInitFile(llvm::SmallVectorImpl<char> &init_file,
+ LanguageType language) {
+ std::string init_file_name;
+
+ switch (language) {
+ // TODO: Add support for a language used with a REPL.
+ default:
+ return;
+ }
+
+ llvm::sys::path::home_directory(init_file);
+ llvm::sys::path::append(init_file, init_file_name);
+
+ FileSystem::Instance().Resolve(init_file);
+}
+
static void GetCwdInitFile(llvm::SmallVectorImpl<char> &init_file) {
llvm::StringRef s = ".lldbinit";
init_file.assign(s.begin(), s.end());
/// We will first see if there is an application specific ".lldbinit" file
/// whose name is "~/.lldbinit" followed by a "-" and the name of the program.
-/// If this file doesn't exist, we fall back to just the "~/.lldbinit" file.
-void CommandInterpreter::SourceInitFileHome(CommandReturnObject &result) {
+/// If this file doesn't exist, we fall back to the REPL init file or the
+/// default home init file in "~/.lldbinit".
+void CommandInterpreter::SourceInitFileHome(CommandReturnObject &result,
+ bool is_repl) {
if (m_skip_lldbinit_files) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return;
}
llvm::SmallString<128> init_file;
- GetHomeInitFile(init_file);
+
+ if (is_repl) {
+ LanguageType language = {};
+ TargetSP target_sp = GetDebugger().GetSelectedTarget();
+ if (target_sp)
+ language = target_sp->GetLanguage();
+ GetHomeREPLInitFile(init_file, language);
+ }
+
+ if (init_file.empty())
+ GetHomeInitFile(init_file);
if (!m_skip_app_init_files) {
llvm::StringRef program_name =
// Before we handle any options from the command line, we parse the
// .lldbinit file in the user's home directory.
SBCommandReturnObject result;
- sb_interpreter.SourceInitFileInHomeDirectory(result);
+ sb_interpreter.SourceInitFileInHomeDirectory(result, m_option_data.m_repl);
if (m_option_data.m_debug_mode) {
result.PutError(m_debugger.GetErrorFile());
result.PutOutput(m_debugger.GetOutputFile());