summaryrefslogtreecommitdiff
path: root/lldb/source/Host/common
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Host/common')
-rw-r--r--lldb/source/Host/common/Editline.cpp30
-rw-r--r--lldb/source/Host/common/File.cpp34
-rw-r--r--lldb/source/Host/common/HostInfoBase.cpp38
3 files changed, 84 insertions, 18 deletions
diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp
index 5ed30fbb231d..1b1922e71076 100644
--- a/lldb/source/Host/common/Editline.cpp
+++ b/lldb/source/Host/common/Editline.cpp
@@ -10,10 +10,8 @@
#include <iomanip>
#include <optional>
-#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Editline.h"
-#include "lldb/Host/FileSystem.h"
-#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/CompletionRequest.h"
@@ -100,11 +98,6 @@ bool IsOnlySpaces(const EditLineStringType &content) {
return true;
}
-static size_t ColumnWidth(llvm::StringRef str) {
- std::string stripped = ansi::StripAnsiTerminalCodes(str);
- return llvm::sys::locale::columnWidth(stripped);
-}
-
static int GetOperation(HistoryOperation op) {
// The naming used by editline for the history operations is counter
// intuitive to how it's used in LLDB's editline implementation.
@@ -219,20 +212,19 @@ private:
const char *GetHistoryFilePath() {
// Compute the history path lazily.
if (m_path.empty() && m_history && !m_prefix.empty()) {
- llvm::SmallString<128> lldb_history_file;
- FileSystem::Instance().GetHomeDirectory(lldb_history_file);
- llvm::sys::path::append(lldb_history_file, ".lldb");
+ FileSpec lldb_dir = HostInfo::GetUserLLDBDir();
// LLDB stores its history in ~/.lldb/. If for some reason this directory
// isn't writable or cannot be created, history won't be available.
- if (!llvm::sys::fs::create_directory(lldb_history_file)) {
+ if (!llvm::sys::fs::create_directory(lldb_dir.GetPath())) {
#if LLDB_EDITLINE_USE_WCHAR
std::string filename = m_prefix + "-widehistory";
#else
std::string filename = m_prefix + "-history";
#endif
- llvm::sys::path::append(lldb_history_file, filename);
- m_path = std::string(lldb_history_file.str());
+ FileSpec lldb_history_file =
+ lldb_dir.CopyByAppendingPathComponent(filename);
+ m_path = lldb_history_file.GetPath();
}
}
@@ -332,8 +324,8 @@ std::string Editline::PromptForIndex(int line_index) {
if (m_set_continuation_prompt.length() > 0) {
continuation_prompt = m_set_continuation_prompt;
// Ensure that both prompts are the same length through space padding
- const size_t prompt_width = ColumnWidth(prompt);
- const size_t cont_prompt_width = ColumnWidth(continuation_prompt);
+ const size_t prompt_width = ansi::ColumnWidth(prompt);
+ const size_t cont_prompt_width = ansi::ColumnWidth(continuation_prompt);
const size_t padded_prompt_width =
std::max(prompt_width, cont_prompt_width);
if (prompt_width < padded_prompt_width)
@@ -358,7 +350,9 @@ void Editline::SetCurrentLine(int line_index) {
m_current_prompt = PromptForIndex(line_index);
}
-size_t Editline::GetPromptWidth() { return ColumnWidth(PromptForIndex(0)); }
+size_t Editline::GetPromptWidth() {
+ return ansi::ColumnWidth(PromptForIndex(0));
+}
bool Editline::IsEmacs() {
const char *editor;
@@ -448,7 +442,7 @@ void Editline::DisplayInput(int firstIndex) {
int Editline::CountRowsForLine(const EditLineStringType &content) {
std::string prompt =
PromptForIndex(0); // Prompt width is constant during an edit session
- int line_length = (int)(content.length() + ColumnWidth(prompt));
+ int line_length = (int)(content.length() + ansi::ColumnWidth(prompt));
return (line_length / m_terminal_width) + 1;
}
diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp
index 23b6dc9fe850..8fd1ca069dc0 100644
--- a/lldb/source/Host/common/File.cpp
+++ b/lldb/source/Host/common/File.cpp
@@ -36,6 +36,7 @@
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/raw_ostream.h"
using namespace lldb;
using namespace lldb_private;
@@ -247,6 +248,32 @@ uint32_t File::GetPermissions(Status &error) const {
return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
}
+NativeFile::NativeFile() = default;
+
+NativeFile::NativeFile(FILE *fh, bool transfer_ownership)
+ : m_stream(fh), m_own_stream(transfer_ownership) {
+#ifdef _WIN32
+ // In order to properly display non ASCII characters in Windows, we need to
+ // use Windows APIs to print to the console. This is only required if the
+ // stream outputs to a console.
+ int fd = _fileno(fh);
+ is_windows_console =
+ ::GetFileType((HANDLE)::_get_osfhandle(fd)) == FILE_TYPE_CHAR;
+#endif
+}
+
+NativeFile::NativeFile(int fd, OpenOptions options, bool transfer_ownership)
+ : m_descriptor(fd), m_own_descriptor(transfer_ownership),
+ m_options(options) {
+#ifdef _WIN32
+ // In order to properly display non ASCII characters in Windows, we need to
+ // use Windows APIs to print to the console. This is only required if the
+ // file outputs to a console.
+ is_windows_console =
+ ::GetFileType((HANDLE)::_get_osfhandle(fd)) == FILE_TYPE_CHAR;
+#endif
+}
+
bool NativeFile::IsValid() const {
std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex, m_stream_mutex);
return DescriptorIsValidUnlocked() || StreamIsValidUnlocked();
@@ -629,6 +656,13 @@ Status NativeFile::Write(const void *buf, size_t &num_bytes) {
}
if (ValueGuard stream_guard = StreamIsValid()) {
+#ifdef _WIN32
+ if (is_windows_console) {
+ llvm::raw_fd_ostream(_fileno(m_stream), false)
+ .write((char *)buf, num_bytes);
+ return error;
+ }
+#endif
bytes_written = ::fwrite(buf, 1, num_bytes, m_stream);
if (bytes_written == 0) {
diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp
index 89dfe4a9e9ba..a02ac77df66a 100644
--- a/lldb/source/Host/common/HostInfoBase.cpp
+++ b/lldb/source/Host/common/HostInfoBase.cpp
@@ -61,6 +61,10 @@ struct HostInfoBaseFields {
FileSpec m_lldb_clang_resource_dir;
llvm::once_flag m_lldb_system_plugin_dir_once;
FileSpec m_lldb_system_plugin_dir;
+ llvm::once_flag m_lldb_user_home_dir_once;
+ FileSpec m_lldb_user_home_dir;
+ llvm::once_flag m_lldb_user_lldb_dir_once;
+ FileSpec m_lldb_user_lldb_dir;
llvm::once_flag m_lldb_user_plugin_dir_once;
FileSpec m_lldb_user_plugin_dir;
llvm::once_flag m_lldb_process_tmp_dir_once;
@@ -161,6 +165,26 @@ FileSpec HostInfoBase::GetSystemPluginDir() {
return g_fields->m_lldb_system_plugin_dir;
}
+FileSpec HostInfoBase::GetUserHomeDir() {
+ llvm::call_once(g_fields->m_lldb_user_home_dir_once, []() {
+ if (!HostInfo::ComputeUserHomeDirectory(g_fields->m_lldb_user_home_dir))
+ g_fields->m_lldb_user_home_dir = FileSpec();
+ LLDB_LOG(GetLog(LLDBLog::Host), "user home dir -> `{0}`",
+ g_fields->m_lldb_user_home_dir);
+ });
+ return g_fields->m_lldb_user_home_dir;
+}
+
+FileSpec HostInfoBase::GetUserLLDBDir() {
+ llvm::call_once(g_fields->m_lldb_user_lldb_dir_once, []() {
+ if (!HostInfo::ComputeUserLLDBHomeDirectory(g_fields->m_lldb_user_lldb_dir))
+ g_fields->m_lldb_user_lldb_dir = FileSpec();
+ LLDB_LOG(GetLog(LLDBLog::Host), "user lldb home dir -> `{0}`",
+ g_fields->m_lldb_user_lldb_dir);
+ });
+ return g_fields->m_lldb_user_lldb_dir;
+}
+
FileSpec HostInfoBase::GetUserPluginDir() {
llvm::call_once(g_fields->m_lldb_user_plugin_dir_once, []() {
if (!HostInfo::ComputeUserPluginsDirectory(
@@ -316,6 +340,20 @@ bool HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
return false;
}
+bool HostInfoBase::ComputeUserHomeDirectory(FileSpec &file_spec) {
+ FileSpec temp_file("~");
+ FileSystem::Instance().Resolve(temp_file);
+ file_spec.SetDirectory(temp_file.GetPathAsConstString());
+ return true;
+}
+
+bool HostInfoBase::ComputeUserLLDBHomeDirectory(FileSpec &file_spec) {
+ FileSpec home_dir_spec = GetUserHomeDir();
+ home_dir_spec.AppendPathComponent(".lldb");
+ file_spec.SetDirectory(home_dir_spec.GetPathAsConstString());
+ return true;
+}
+
bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) {
// TODO(zturner): Figure out how to compute the user plugins directory for
// all platforms.