From 10efbaf8632e61e7d329a98c71641d1e839dfa4c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 23 Sep 2011 23:43:36 +0000 Subject: [PATCH] Don't translate CRLF files into LF files. Fixes PR6870, from Aaron Ballman! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140435 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Frontend/FrontendActions.cpp | 45 ++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index c80802e353..6f84da9630 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -22,6 +22,8 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" + using namespace clang; //===----------------------------------------------------------------------===// @@ -181,9 +183,48 @@ void PreprocessOnlyAction::ExecuteAction() { void PrintPreprocessedAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); - // Output file needs to be set to 'Binary', to avoid converting Unix style + // Output file may need to be set to 'Binary', to avoid converting Unix style // line feeds () to Microsoft style line feeds (). - raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); + // + // Look to see what type of line endings the file uses. If there's a + // CRLF, then we won't open the file up in binary mode. If there is + // just an LF or CR, then we will open the file up in binary mode. + // In this fashion, the output format should match the input format, unless + // the input format has inconsistent line endings. + // + // This should be a relatively fast operation since most files won't have + // all of their source code on a single line. However, that is still a + // concern, so if we scan for too long, we'll just assume the file should + // be opened in binary mode. + bool BinaryMode = true; + bool InvalidFile = false; + const SourceManager& SM = CI.getSourceManager(); + const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getMainFileID(), + &InvalidFile); + if (!InvalidFile) { + const char *cur = Buffer->getBufferStart(); + const char *end = Buffer->getBufferEnd(); + const char *next = (cur != end) ? cur + 1 : end; + + // Limit ourselves to only scanning 256 characters into the source + // file. This is mostly a sanity check in case the file has no + // newlines whatsoever. + if (end - cur > 256) end = cur + 256; + + while (next < end) { + if (*cur == 0x0D) { // CR + if (*next == 0x0A) // CRLF + BinaryMode = false; + + break; + } else if (*cur == 0x0A) // LF + break; + + ++cur, ++next; + } + } + + raw_ostream *OS = CI.createDefaultOutputFile(BinaryMode, getCurrentFile()); if (!OS) return; DoPrintPreprocessedInput(CI.getPreprocessor(), OS, -- 2.40.0