Skip to content

Add '<' meta command to read in code from external file #1856

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 42 additions & 2 deletions lldb/source/Expression/REPL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,11 @@ const char *REPL::IOHandlerGetHelpPrologue() {
"Valid statements, expressions, and declarations are immediately "
"compiled and executed.\n\n"
"The complete set of LLDB debugging commands are also available as "
"described below. Commands "
"described below.\n\nCommands "
"must be prefixed with a colon at the REPL prompt (:quit for "
"example.) Typing just a colon "
"followed by return will switch to the LLDB prompt.\n\n";
"followed by return will switch to the LLDB prompt.\n\n"
"Type “< path” to read in code from a text file “path”.\n\n";
}

bool REPL::IOHandlerIsInputComplete(IOHandler &io_handler, StringList &lines) {
Expand Down Expand Up @@ -179,6 +180,36 @@ int REPL::IOHandlerFixIndentation(IOHandler &io_handler,
return (int)desired_indent - actual_indent;
}

static bool ReadCode(const std::string &path, std::string &code,
lldb::StreamFileSP &error_sp) {
auto &fs = FileSystem::Instance();
llvm::Twine pathTwine(path);
if (!fs.Exists(pathTwine)) {
error_sp->Printf("no such file at path '%s'\n", path.c_str());
return false;
}
if (!fs.Readable(pathTwine)) {
error_sp->Printf("could not read file at path '%s'\n", path.c_str());
return false;
}
const size_t file_size = fs.GetByteSize(pathTwine);
const size_t max_size = code.max_size();
if (file_size > max_size) {
error_sp->Printf("file at path '%s' too large: "
"file_size = %llu, max_size = %llu\n",
path.c_str(), file_size, max_size);
return false;
}
auto data_sp = fs.CreateDataBuffer(pathTwine);
if (data_sp == nullptr) {
error_sp->Printf("could not create buffer for file at path '%s'\n",
path.c_str());
return false;
}
code.assign((const char *)data_sp->GetBytes(), data_sp->GetByteSize());
return true;
}

void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFileSP());
Expand Down Expand Up @@ -257,6 +288,15 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
}
}
} else {
if (code[0] == '<') {
// User wants to read code from a file.
// Interpret rest of line as a literal path.
auto path = llvm::StringRef(code.substr(1)).trim().str();
if (!ReadCode(path, code, error_sp)) {
return;
}
}

// Unwind any expression we might have been running in case our REPL
// expression crashed and the user was looking around
if (m_dedicated_repl_mode) {
Expand Down