diff --git a/Help/command/string.rst b/Help/command/string.rst index 07d0ff3f2..351385bf1 100644 --- a/Help/command/string.rst +++ b/Help/command/string.rst @@ -73,8 +73,13 @@ TOUPPER/TOLOWER will convert string to upper/lower characters. LENGTH will return a given string's length. -SUBSTRING will return a substring of a given string. If length is -1 +SUBSTRING will return a substring of a given string. If length is -1 the remainder of the string starting at begin will be returned. +If string is shorter than length then end of string is used instead. + +.. note:: + CMake 3.1 and below reported an error if length pointed past + the end of string. STRIP will return a substring of a given string with leading and trailing spaces removed. diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 90a8f8546..ce7c854aa 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -711,12 +711,10 @@ bool cmStringCommand::HandleSubstringCommand(std::vector const& this->SetError(ostr.str()); return false; } - int leftOverLength = intStringLength - begin; - if ( end < -1 || end > leftOverLength ) + if ( end < -1 ) { cmOStringStream ostr; - ostr << "end index: " << end << " is out of range -1 - " - << leftOverLength; + ostr << "end index: " << end << " should be -1 or greater"; this->SetError(ostr.str()); return false; } diff --git a/Tests/CMakeTests/StringTest.cmake.in b/Tests/CMakeTests/StringTest.cmake.in index a9fe428e3..92e70c3ac 100644 --- a/Tests/CMakeTests/StringTest.cmake.in +++ b/Tests/CMakeTests/StringTest.cmake.in @@ -63,7 +63,7 @@ check_cmake_test(String # Execute each test listed in StringTestScript.cmake: # set(scriptname "@CMAKE_CURRENT_SOURCE_DIR@/StringTestScript.cmake") -set(number_of_tests_expected 69) +set(number_of_tests_expected 70) include("@CMAKE_CURRENT_SOURCE_DIR@/ExecuteScriptTests.cmake") execute_all_script_tests(${scriptname} number_of_tests_executed) @@ -75,6 +75,6 @@ message(STATUS "scriptname='${scriptname}'") message(STATUS "number_of_tests_executed='${number_of_tests_executed}'") message(STATUS "number_of_tests_expected='${number_of_tests_expected}'") -if(number_of_tests_executed LESS number_of_tests_expected) +if(NOT number_of_tests_executed EQUAL number_of_tests_expected) message(FATAL_ERROR "error: some test cases were skipped") endif() diff --git a/Tests/CMakeTests/StringTestScript.cmake b/Tests/CMakeTests/StringTestScript.cmake index a562e71d3..44d56531f 100644 --- a/Tests/CMakeTests/StringTestScript.cmake +++ b/Tests/CMakeTests/StringTestScript.cmake @@ -122,14 +122,17 @@ elseif(testname STREQUAL substring_not_enough_args) # fail elseif(testname STREQUAL substring_begin_too_large) # fail string(SUBSTRING "abcdefg" 25 100 v) -elseif(testname STREQUAL substring_end_too_large) # fail +elseif(testname STREQUAL substring_end_larger_than_strlen) # pass string(SUBSTRING "abcdefg" 1 100 v) elseif(testname STREQUAL substring_begin_less_than_zero) # fail - string(SUBSTRING "abcdefg" -2 4 v) + string(SUBSTRING "abcdefg" -1 4 v) -elseif(testname STREQUAL substring_end_less_than_begin) # fail - string(SUBSTRING "abcdefg" 6 3 v) +elseif(testname STREQUAL substring_end_less_than_zero) # pass + string(SUBSTRING "abcdefg" 0 -1 v) + +elseif(testname STREQUAL substring_end_less_than_begin) # pass + string(SUBSTRING "abcdefg" 6 0 v) elseif(testname STREQUAL length_not_enough_args) # fail string(LENGTH)