Fix gn format --stdin newlines on Windows

On Windows, gn format --stdin converts \n newlines to \r\n. The
conversion happens when the formatted file is printed to stdout, which
is opened in text mode. This change sets stdout to binary mode before
printing the formatted file on Windows.

This change also sets stderr to binary mode prior to printing the
parse tree, to remove \r\n from parse tree output.

Change-Id: Ie27b8a76e13ceb092c27304d164207bfab69c857
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/7540
Commit-Queue: Scott Graham <scottmg@chromium.org>
Reviewed-by: Scott Graham <scottmg@chromium.org>
diff --git a/src/gn/command_format.cc b/src/gn/command_format.cc
index 8483b93..3253fde 100644
--- a/src/gn/command_format.cc
+++ b/src/gn/command_format.cc
@@ -24,6 +24,12 @@
 #include "gn/string_utils.h"
 #include "gn/switches.h"
 #include "gn/tokenizer.h"
+#include "util/build_config.h"
+
+#if defined(OS_WIN)
+#include <fcntl.h>
+#include <io.h>
+#endif
 
 namespace commands {
 
@@ -1195,6 +1201,11 @@
 void DoFormat(const ParseNode* root,
               TreeDumpMode dump_tree,
               std::string* output) {
+#if defined(OS_WIN)
+    // Set stderr to binary mode to prevent converting newlines to \r\n.
+    _setmode(_fileno(stderr), _O_BINARY);
+#endif
+
   if (dump_tree == TreeDumpMode::kPlainText) {
     std::ostringstream os;
     RenderToText(root->GetJSONNode(), 0, os);
@@ -1282,6 +1293,10 @@
     std::string output;
     if (!FormatStringToString(input, dump_tree, &output))
       return 1;
+#if defined(OS_WIN)
+    // Set stdout to binary mode to prevent converting newlines to \r\n.
+    _setmode(_fileno(stdout), _O_BINARY);
+#endif
     printf("%s", output.c_str());
     return 0;
   }