diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 8b9daa2d1..4a06cb4fb 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -58,6 +58,10 @@ bool cmFileCommand::InitialPass(std::vector const& args) { return this->HandleInstallCommand(args); } + else if ( subCommand == "RELATIVE_PATH" ) + { + return this->HandleRelativePathCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e.c_str()); @@ -696,3 +700,38 @@ bool cmFileCommand::HandleInstallCommand( return true; } + +//---------------------------------------------------------------------------- +bool cmFileCommand::HandleRelativePathCommand( + std::vector const& args) +{ + if(args.size() != 4 ) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + + const std::string& outVar = args[1]; + const std::string& directoryName = args[2]; + const std::string& fileName = args[3]; + + if(!cmSystemTools::FileIsFullPath(directoryName.c_str())) + { + std::string errstring = "RelativePath must be passed a full path to the directory: " + directoryName; + this->SetError(errstring.c_str()); + return false; + } + if(!cmSystemTools::FileIsFullPath(fileName.c_str())) + { + std::string errstring = "RelativePath must be passed a full path to the directory: " + directoryName; + this->SetError(errstring.c_str()); + return false; + } + + std::string res = cmSystemTools::RelativePath(directoryName.c_str(), fileName.c_str()); + m_Makefile->AddDefinition(outVar.c_str(), + res.c_str()); + return true; +} + + diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 71bca9091..92431807d 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -70,6 +70,7 @@ public: " FILE(GLOB variable [globbing expressions]...)\n" " FILE(GLOB_RECURSE variable [globbing expressions]...)\n" " FILE(MAKE_DIRECTORY [directory]...)\n" + " FILE(RELATIVE_PATH variable directory file)\n" "WRITE will write a message into a file called 'filename'. It " "overwrites the file if it already exists, and creates the file " "if it does not exists.\n" @@ -93,7 +94,8 @@ public: "match the files.\n" "Example of recursive globbing:\n" " /dir/*.py - match all python files /dir and subdirectories\n" - "MAKE_DIRECTORY will create a directory at the specified location"; + "MAKE_DIRECTORY will create a directory at the specified location\n" + "RELATIVE_PATH will determine relative path from directory to the given file"; } cmTypeMacro(cmFileCommand, cmCommand); @@ -104,6 +106,7 @@ protected: bool HandleGlobCommand(std::vector const& args, bool recurse); bool HandleMakeDirectoryCommand(std::vector const& args); bool HandleInstallCommand(std::vector const& args); + bool HandleRelativePathCommand(std::vector const& args); }; diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 76d60e06a..dc592ba23 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -16,6 +16,7 @@ =========================================================================*/ #include "cmStringCommand.h" #include +#include #include // required for atoi #include @@ -33,6 +34,10 @@ bool cmStringCommand::InitialPass(std::vector const& args) { return this->HandleRegexCommand(args); } + else if(subCommand == "REPLACE") + { + return this->HandleReplaceCommand(args); + } else if(subCommand == "TOLOWER") { return this->HandleToUpperLowerCommand(args, false); @@ -492,3 +497,28 @@ bool cmStringCommand::HandleCompareCommand(std::vector const& args) this->SetError(e.c_str()); return false; } + +//---------------------------------------------------------------------------- +bool cmStringCommand::HandleReplaceCommand(std::vector const& args) +{ + if(args.size() < 5) + { + this->SetError("sub-command REPLACE requires four arguments."); + return false; + } + + const std::string& matchExpression = args[1]; + const std::string& replaceExpression = args[2]; + const std::string& variableName = args[3]; + + std::string input = args[4]; + for(unsigned int i=5; i < args.size(); ++i) + { + input += args[i]; + } + + cmsys::SystemTools::ReplaceString(input, matchExpression.c_str(), replaceExpression.c_str()); + + m_Makefile->AddDefinition(variableName.c_str(), input.c_str()); + return true; +} diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index 91463c44b..cbdf811f5 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -71,6 +71,9 @@ public: " STRING(REGEX REPLACE \n" " \n" " [...])\n" + " STRING(REPLACE \n" + " \n" + " [...])\n" " STRING(COMPARE EQUAL )\n" " STRING(COMPARE NOTEQUAL )\n" " STRING(COMPARE LESS )\n" @@ -90,6 +93,12 @@ public: "subexpressions of the match using \\1, \\2, ..., \\9. Note that " "two backslashes (\\\\1) are required in CMake code to get a " "backslash through argument parsing.\n" + "REPLACE will match the given expression " + "and substitute the replacement expression for the match " + "in the output. The replace expression may refer to paren-delimited " + "subexpressions of the match using \\1, \\2, ..., \\9. Note that " + "two backslashes (\\\\1) are required in CMake code to get a " + "backslash through argument parsing.\n" "COMPARE EQUAL/NOTEQUAL/LESS/GREATER will compare the strings and " "store true or false in the output variable.\n" "ASCII will convert all numbers into corresponding ASCII characters.\n" @@ -108,6 +117,7 @@ protected: bool RegexReplace(std::vector const& args); bool HandleToUpperLowerCommand(std::vector const& args, bool toUpper); bool HandleCompareCommand(std::vector const& args); + bool HandleReplaceCommand(std::vector const& args); class RegexReplacement { diff --git a/Tests/StringFileTest/CMakeLists.txt b/Tests/StringFileTest/CMakeLists.txt index 298f69439..373e811ab 100644 --- a/Tests/StringFileTest/CMakeLists.txt +++ b/Tests/StringFileTest/CMakeLists.txt @@ -20,6 +20,9 @@ STRING(COMPARE GREATER "max" "min" ncgvar) STRING(ASCII 67 109 97 107 101 savar) STRING(TOUPPER "CMake" tuvar) STRING(TOLOWER "CMake" tlvar) +STRING(REPLACE "Autoconf" "CMake" repvar "People should use Autoconf") + +FILE(RELATIVE_PATH relpath "/usr/local/bin" "/usr/X11R6/bin/xnest") # Escaping test SET(var "\\ \" \ \t \n \r \# \( \) \0") @@ -49,6 +52,8 @@ FOREACH(var rmvar rmallvar rrepvar + repvar + relpath nceqvar ceqvar cneqvar diff --git a/Tests/StringFileTest/StringFile.cxx b/Tests/StringFileTest/StringFile.cxx index bc2312be0..67d7c5f69 100644 --- a/Tests/StringFileTest/StringFile.cxx +++ b/Tests/StringFileTest/StringFile.cxx @@ -9,6 +9,7 @@ int main(int, char*[]) res += CheckMethod(rmvar, "CMake"); res += CheckMethod(rmallvar, "CMake;cmake;CMake"); res += CheckMethod(rrepvar, "People should use CMake and CMake"); + res += CheckMethod(repvar, "People should use CMake"); res += CheckMethod(nceqvar, "0"); res += CheckMethod(ceqvar, "1"); res += CheckMethod(cneqvar, "1"); @@ -20,6 +21,7 @@ int main(int, char*[]) res += CheckMethod(savar, "Cmake"); res += CheckMethod(tuvar, "CMAKE"); res += CheckMethod(tlvar, "cmake"); + res += CheckMethod(relpath, "../../X11R6/bin/xnest"); return res; }