diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index e8de5b6f9..55d71ea1f 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -4,6 +4,19 @@ #include "cmAlgorithms.h" +static std::string escape_arg(const std::string& arg) +{ + // replace ";" with "\;" so output argument lists will split correctly + std::string escapedArg; + for (size_t i = 0; i < arg.size(); ++i) { + if (arg[i] == ';') { + escapedArg += '\\'; + } + escapedArg += arg[i]; + } + return escapedArg; +} + bool cmParseArgumentsCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { @@ -165,10 +178,18 @@ bool cmParseArgumentsCommand::InitialPass(std::vector const& args, insideValues = NONE; break; case MULTI: - multi[currentArgName].push_back(*argIter); + if (parseFromArgV) { + multi[currentArgName].push_back(escape_arg(*argIter)); + } else { + multi[currentArgName].push_back(*argIter); + } break; default: - unparsed.push_back(*argIter); + if (parseFromArgV) { + unparsed.push_back(escape_arg(*argIter)); + } else { + unparsed.push_back(*argIter); + } break; } } diff --git a/Tests/RunCMake/cmake_parse_arguments/ArgvN.cmake b/Tests/RunCMake/cmake_parse_arguments/ArgvN.cmake index 61bde0363..63a1b0112 100644 --- a/Tests/RunCMake/cmake_parse_arguments/ArgvN.cmake +++ b/Tests/RunCMake/cmake_parse_arguments/ArgvN.cmake @@ -1,5 +1,15 @@ include(${CMAKE_CURRENT_LIST_DIR}/test_utils.cmake) +function(test_multi list) + set(i 0) + foreach(value IN LISTS ${list}) + math(EXPR j "${i} + 1") + set(${list}[${i}] "${value}") + TEST(${list}[${i}] "${ARGV${j}}") + set(i ${j}) + endforeach() +endfunction() + function(test1) cmake_parse_arguments(PARSE_ARGV 0 pref "OPT1;OPT2" "SINGLE1;SINGLE2" "MULTI1;MULTI2") @@ -23,8 +33,16 @@ function(test2 arg1) TEST(pref_OPT2 FALSE) TEST(pref_SINGLE1 "foo;bar") TEST(pref_SINGLE2 UNDEFINED) - TEST(pref_MULTI1 bar foo bar) + test_multi(pref_MULTI1 bar "foo;bar") TEST(pref_MULTI2 UNDEFINED) TEST(pref_UNPARSED_ARGUMENTS UNDEFINED) endfunction() -test2("first named" OPT1 SINGLE1 "foo;bar" MULTI1 bar foo bar) +test2("first named" OPT1 SINGLE1 "foo;bar" MULTI1 bar "foo;bar") + +function(test3 arg1) + cmake_parse_arguments(PARSE_ARGV 0 + pref "" "" "") + + test_multi(pref_UNPARSED_ARGUMENTS "foo;bar" dog cat) +endfunction() +test3("foo;bar" dog cat)