#endif
}
+#ifdef _WIN32
+// Stdout/stderr are normally opened in text mode, which would convert newlines
+// a second time, since we treat outputs as binary data.
+// Make sure to switch to binary mode.
+namespace {
+struct BinaryModeHelper
+{
+ BinaryModeHelper(int fd_) : fd(fd_), oldmode(_setmode(fd, _O_BINARY))
+ {
+ }
+ ~BinaryModeHelper()
+ {
+ _setmode(fd, oldmode);
+ }
+ int fd;
+ int oldmode;
+};
+} // namespace
+#endif
+
void
-send_to_stderr(const Context& ctx, const std::string& text)
+send_to_fd(const Context& ctx, const std::string& text, int fd)
{
const std::string* text_to_send = &text;
std::string modified_text;
+#ifdef _WIN32
+ BinaryModeHelper helper(fd);
+#endif
+
if (ctx.args_info.strip_diagnostics_colors) {
try {
modified_text = strip_ansi_csi_seqs(text);
}
try {
- write_fd(STDERR_FILENO, text_to_send->data(), text_to_send->length());
+ write_fd(fd, text_to_send->data(), text_to_send->length());
} catch (core::Error& e) {
throw core::Error("Failed to write to stderr: {}", e.what());
}
#include <utility>
#include <vector>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
class Context;
namespace Util {
bool same_program_name(nonstd::string_view program_name,
nonstd::string_view canonical_program_name);
-// Send `text` to STDERR_FILENO, optionally stripping ANSI color sequences if
-// `ctx.args_info.strip_diagnostics_colors` is true and rewriting paths to
-// absolute if `ctx.config.absolute_paths_in_stderr` is true. Throws
+// Send `text` to file descriptor 'fd', optionally stripping ANSI color
+// sequences if `ctx.args_info.strip_diagnostics_colors` is true and rewriting
+// paths to absolute if `ctx.config.absolute_paths_in_stderr` is true. Throws
// `core::Error` on error.
-void send_to_stderr(const Context& ctx, const std::string& text);
+void send_to_fd(const Context& ctx, const std::string& text, int fd);
+inline void
+send_to_stderr(const Context& ctx, const std::string& text)
+{
+ send_to_fd(ctx, text, STDERR_FILENO);
+}
// Set the FD_CLOEXEC on file descriptor `fd`. This is a NOP on Windows.
void set_cloexec_flag(int fd);