diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 520573898..2aa32d8c9 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -216,6 +216,8 @@ SET(SRCS cmMakefileExecutableTargetGenerator.cxx cmMakefileLibraryTargetGenerator.cxx cmMakefileUtilityTargetGenerator.cxx + cmNewLineStyle.h + cmNewLineStyle.cxx cmOrderDirectories.cxx cmOrderDirectories.h cmPolicies.h diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx index c1327fbf1..ea98326e2 100644 --- a/Source/cmConfigureFileCommand.cxx +++ b/Source/cmConfigureFileCommand.cxx @@ -65,6 +65,12 @@ bool cmConfigureFileCommand cmSystemTools::SetFatalErrorOccured(); return false; } + std::string errorMessage; + if (!this->NewLineStyle.ReadFromArguments(args, errorMessage)) + { + this->SetError(errorMessage.c_str()); + return false; + } this->CopyOnly = false; this->EscapeQuotes = false; @@ -78,6 +84,12 @@ bool cmConfigureFileCommand if(args[i] == "COPYONLY") { this->CopyOnly = true; + if (this->NewLineStyle.IsValid()) + { + this->SetError("COPYONLY could not be used in combination " + "with NEWLINE_STYLE"); + return false; + } } else if(args[i] == "ESCAPE_QUOTES") { @@ -122,7 +134,8 @@ int cmConfigureFileCommand::ConfigureFile() this->OutputFile.c_str(), this->CopyOnly, this->AtOnly, - this->EscapeQuotes); + this->EscapeQuotes, + this->NewLineStyle); } diff --git a/Source/cmConfigureFileCommand.h b/Source/cmConfigureFileCommand.h index 844a23cda..be33569fe 100644 --- a/Source/cmConfigureFileCommand.h +++ b/Source/cmConfigureFileCommand.h @@ -56,7 +56,8 @@ public: { return " configure_file( \n" - " [COPYONLY] [ESCAPE_QUOTES] [@ONLY])\n" + " [COPYONLY] [ESCAPE_QUOTES] [@ONLY] \n" + " [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])\n" "Copies a file to file and substitutes variable " "values referenced in the file content. " "If is a relative path it is evaluated with respect to " @@ -81,14 +82,20 @@ public: "either #define VAR or /* #undef VAR */ depending on " "the setting of VAR in CMake. Any occurrences of #cmakedefine01 VAR " "will be replaced with either #define VAR 1 or #define VAR 0 " - "depending on whether VAR evaluates to TRUE or FALSE in CMake"; + "depending on whether VAR evaluates to TRUE or FALSE in CMake.\n" + "With NEWLINE_STYLE the line ending could be adjusted: \n" + " 'UNIX' or 'LF' for \\n, 'DOS', 'WIN32' or 'CRLF' for \\r\\n.\n" + "COPYONLY must not be used with NEWLINE_STYLE.\n"; } virtual void FinalPass(); virtual bool HasFinalPass() const { return !this->Immediate; } + private: int ConfigureFile(); + cmNewLineStyle NewLineStyle; + std::string InputFile; std::string OutputFile; bool CopyOnly; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 573c430be..7939d7322 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3213,7 +3213,8 @@ void cmMakefile::ConfigureString(const std::string& input, } int cmMakefile::ConfigureFile(const char* infile, const char* outfile, - bool copyonly, bool atOnly, bool escapeQuotes) + bool copyonly, bool atOnly, bool escapeQuotes, + const cmNewLineStyle& newLine) { int res = 1; if ( !this->CanIWriteThisFile(outfile) ) @@ -3250,9 +3251,20 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile, } else { + std::string newLineCharacters; + std::ios_base::openmode omode = std::ios_base::out | std::ios_base::trunc; + if (newLine.IsValid()) + { + newLineCharacters = newLine.GetCharacters(); + omode |= std::ios::binary; + } + else + { + newLineCharacters = "\n"; + } std::string tempOutputFile = soutfile; tempOutputFile += ".tmp"; - std::ofstream fout(tempOutputFile.c_str()); + std::ofstream fout(tempOutputFile.c_str(), omode); if(!fout) { cmSystemTools::Error( @@ -3277,7 +3289,7 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile, { outLine = ""; this->ConfigureString(inLine, outLine, atOnly, escapeQuotes); - fout << outLine.c_str() << "\n"; + fout << outLine.c_str() << newLineCharacters; } // close the files before attempting to copy fin.close(); diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 7c3e4ee4b..123678783 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -19,6 +19,7 @@ #include "cmPropertyMap.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmNewLineStyle.h" #include "cmake.h" #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -703,7 +704,9 @@ public: * Copy file but change lines acording to ConfigureString */ int ConfigureFile(const char* infile, const char* outfile, - bool copyonly, bool atOnly, bool escapeQuotes); + bool copyonly, bool atOnly, bool escapeQuotes, + const cmNewLineStyle& = cmNewLineStyle()); + #if defined(CMAKE_BUILD_WITH_CMAKE) /** diff --git a/Source/cmNewLineStyle.cxx b/Source/cmNewLineStyle.cxx new file mode 100644 index 000000000..6f7b6a949 --- /dev/null +++ b/Source/cmNewLineStyle.cxx @@ -0,0 +1,95 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2011 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmNewLineStyle.h" + + + +cmNewLineStyle::cmNewLineStyle() : NewLineStyle(Invalid) +{ +} + + +bool cmNewLineStyle::IsValid() const +{ + return NewLineStyle != Invalid; +} + + +bool cmNewLineStyle::ReadFromArguments(const std::vector& args, + std::string& errorString) +{ + NewLineStyle = Invalid; + + for (size_t i = 0; i< args.size(); i++) + { + if (args[i] == "NEWLINE_STYLE") + { + size_t const styleIndex = i + 1; + if (args.size() > styleIndex) + { + const std::string eol = args[styleIndex]; + if (eol == "LF" || eol == "UNIX") + { + NewLineStyle = LF; + return true; + } + else if (eol == "CRLF" || eol == "WIN32" || eol == "DOS") + { + NewLineStyle = CRLF; + return true; + } + else + { + errorString = "NEWLINE_STYLE sets an unknown style, only LF, " + "CRLF, UNIX, DOS, and WIN32 are supported"; + return false; + } + } + else + { + errorString = "NEWLINE_STYLE must set a style: " + "LF, CRLF, UNIX, DOS, or WIN32"; + return false; + } + } + } + return true; +} + + +const std::string cmNewLineStyle::GetCharacters() const +{ + switch (NewLineStyle) + { + case Invalid: + return ""; + case LF: + return "\n"; + case CRLF: + return "\r\n"; + default: + ; + }; + return ""; +} + + +void cmNewLineStyle::SetStyle(Style style) +{ + NewLineStyle = style; +} + + +cmNewLineStyle::Style cmNewLineStyle::GetStyle() const +{ + return NewLineStyle; +} diff --git a/Source/cmNewLineStyle.h b/Source/cmNewLineStyle.h new file mode 100644 index 000000000..cae110604 --- /dev/null +++ b/Source/cmNewLineStyle.h @@ -0,0 +1,46 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2011 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmNewLineStyle_h +#define cmNewLineStyle_h + +#include "cmStandardIncludes.h" + +class cmNewLineStyle +{ +public: + + cmNewLineStyle(); + + enum Style + { + Invalid, + // LF = '\n', 0x0A, 10 + // CR = '\r', 0x0D, 13 + LF, // Unix + CRLF // Dos + }; + + void SetStyle(Style); + Style GetStyle() const; + + bool IsValid() const; + + bool ReadFromArguments(const std::vector& args, + std::string &errorString); + + const std::string GetCharacters() const; + +private: + Style NewLineStyle; +}; + +#endif diff --git a/Source/cmStandardIncludes.h b/Source/cmStandardIncludes.h index e8decbb96..ea299ca90 100644 --- a/Source/cmStandardIncludes.h +++ b/Source/cmStandardIncludes.h @@ -161,6 +161,11 @@ extern int putenv (char *__string) __THROW; #define for if(false) {} else for #endif +// Provide std::ios_base on ancient GCC 2.9x +#if defined(__GNUC__) && __GNUC__ < 3 +namespace std { typedef ios ios_base; } +#endif + // check for the 720 compiler on the SGI // which has some strange properties that I don't think are worth // checking for in a general way in configure diff --git a/Tests/CMakeTests/ConfigureFile-NewLineStyle-COPYONLY.cmake b/Tests/CMakeTests/ConfigureFile-NewLineStyle-COPYONLY.cmake new file mode 100644 index 000000000..3b09eb0c3 --- /dev/null +++ b/Tests/CMakeTests/ConfigureFile-NewLineStyle-COPYONLY.cmake @@ -0,0 +1,3 @@ +set(file_name ${CMAKE_CURRENT_SOURCE_DIR}/ConfigureFile-NewLineStyle.txt) +file(WRITE ${file_name} "Data\n") +configure_file(${file_name} ${file_name}.out COPYONLY NEWLINE_STYLE DOS) diff --git a/Tests/CMakeTests/ConfigureFile-NewLineStyle-NoArg.cmake b/Tests/CMakeTests/ConfigureFile-NewLineStyle-NoArg.cmake new file mode 100644 index 000000000..133a67a8a --- /dev/null +++ b/Tests/CMakeTests/ConfigureFile-NewLineStyle-NoArg.cmake @@ -0,0 +1,3 @@ +set(file_name ${CMAKE_CURRENT_SOURCE_DIR}/ConfigureFile-NewLineStyle.txt) +file(WRITE ${file_name} "Data\n") +configure_file(${file_name} ${file_name}.out NEWLINE_STYLE) diff --git a/Tests/CMakeTests/ConfigureFile-NewLineStyle-ValidArg.cmake b/Tests/CMakeTests/ConfigureFile-NewLineStyle-ValidArg.cmake new file mode 100644 index 000000000..b7e619ca2 --- /dev/null +++ b/Tests/CMakeTests/ConfigureFile-NewLineStyle-ValidArg.cmake @@ -0,0 +1,17 @@ +set(file_name ${CMAKE_CURRENT_SOURCE_DIR}/ConfigureFile-NewLineStyle.txt) + +function(test_eol style in out) + file(WRITE ${file_name} "${in}") + configure_file(${file_name} ${file_name}.out NEWLINE_STYLE ${style}) + file(READ ${file_name}.out new HEX) + if(NOT "${new}" STREQUAL "${out}") + message(FATAL_ERROR "No ${style} line endings") + endif() +endfunction() + +test_eol(DOS "a\n" "610d0a") +test_eol(WIN32 "b\n" "620d0a") +test_eol(CRLF "c\n" "630d0a") + +test_eol(UNIX "d\n" "640a") +test_eol(LF "e\n" "650a") diff --git a/Tests/CMakeTests/ConfigureFile-NewLineStyle-WrongArg.cmake b/Tests/CMakeTests/ConfigureFile-NewLineStyle-WrongArg.cmake new file mode 100644 index 000000000..e8887c127 --- /dev/null +++ b/Tests/CMakeTests/ConfigureFile-NewLineStyle-WrongArg.cmake @@ -0,0 +1,3 @@ +set(file_name ${CMAKE_CURRENT_SOURCE_DIR}/ConfigureFile-NewLineStyle.txt) +file(WRITE ${file_name} "Data\n") +configure_file(${file_name} ${file_name}.out NEWLINE_STYLE FOO) diff --git a/Tests/CMakeTests/ConfigureFileTest.cmake.in b/Tests/CMakeTests/ConfigureFileTest.cmake.in index c78a4705b..6cc61d90c 100644 --- a/Tests/CMakeTests/ConfigureFileTest.cmake.in +++ b/Tests/CMakeTests/ConfigureFileTest.cmake.in @@ -6,6 +6,14 @@ set(Relative-RESULT 0) set(Relative-STDERR "Relative test file") set(BadArg-RESULT 1) set(BadArg-STDERR "called with incorrect number of arguments") +set(NewLineStyle-NoArg-RESULT 1) +set(NewLineStyle-NoArg-STDERR "NEWLINE_STYLE must set a style:") +set(NewLineStyle-WrongArg-RESULT 1) +set(NewLineStyle-WrongArg-STDERR "NEWLINE_STYLE sets an unknown style") +set(NewLineStyle-ValidArg-RESULT 0) +set(NewLineStyle-ValidArg-STDERR ) +set(NewLineStyle-COPYONLY-RESULT 1) +set(NewLineStyle-COPYONLY-STDERR "COPYONLY could not be used in combination") include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake") check_cmake_test(ConfigureFile @@ -13,4 +21,8 @@ check_cmake_test(ConfigureFile DirOutput Relative BadArg + NewLineStyle-NoArg + NewLineStyle-WrongArg + NewLineStyle-ValidArg + NewLineStyle-COPYONLY ) diff --git a/bootstrap b/bootstrap index c9998882e..3daac2a37 100755 --- a/bootstrap +++ b/bootstrap @@ -215,6 +215,7 @@ CMAKE_CXX_SOURCES="\ cmMakefileLibraryTargetGenerator \ cmMakefileTargetGenerator \ cmMakefileUtilityTargetGenerator \ + cmNewLineStyle \ cmBootstrapCommands \ cmCommands \ cmTarget \