diff options
author | Andy Cedilnik <andy.cedilnik@kitware.com> | 2004-04-29 19:12:40 (GMT) |
---|---|---|
committer | Andy Cedilnik <andy.cedilnik@kitware.com> | 2004-04-29 19:12:40 (GMT) |
commit | 8750f1c277d8bf3fdf2d2986f473c5f09e293ea5 (patch) | |
tree | c5db04b06c7c9ae256b6404fab2b664edb1ad5dd | |
parent | ae50b4bc6afa62663317e630aef509a29c4f9021 (diff) | |
download | CMake-8750f1c277d8bf3fdf2d2986f473c5f09e293ea5.zip CMake-8750f1c277d8bf3fdf2d2986f473c5f09e293ea5.tar.gz CMake-8750f1c277d8bf3fdf2d2986f473c5f09e293ea5.tar.bz2 |
ENH: Add RANGE support to FOREACH
-rw-r--r-- | Source/cmForEachCommand.cxx | 74 | ||||
-rw-r--r-- | Source/cmForEachCommand.h | 12 | ||||
-rw-r--r-- | Tests/StringFileTest/CMakeLists.txt | 19 |
3 files changed, 103 insertions, 2 deletions
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index cd6e1e2..24f17fa 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -106,7 +106,79 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& args) // create a function blocker cmForEachFunctionBlocker *f = new cmForEachFunctionBlocker(); - f->m_Args = args; + if ( args.size() > 1 ) + { + if ( args[1] == "RANGE" ) + { + int start = 0; + int stop = 0; + int step = 0; + if ( args.size() == 3 ) + { + stop = atoi(args[2].c_str()); + } + if ( args.size() == 4 ) + { + start = atoi(args[2].c_str()); + stop = atoi(args[3].c_str()); + } + if ( args.size() == 5 ) + { + start = atoi(args[2].c_str()); + stop = atoi(args[3].c_str()); + step = atoi(args[4].c_str()); + } + if ( step == 0 ) + { + if ( start > stop ) + { + step = -1; + } + else + { + step = 1; + } + } + if ( + (start > stop && step > 0) || + (start < stop && step < 0) || + step == 0 + ) + { + cmOStringStream str; + str << "called with incorrect range specification: start "; + str << start << ", stop " << stop << ", step " << step; + this->SetError(str.str().c_str()); + return false; + } + std::vector<std::string> range; + char buffer[100]; + range.push_back(args[0]); + int cc; + for ( cc = start; ; cc += step ) + { + if ( (step > 0 && cc > stop) || (step < 0 && cc < stop) ) + { + break; + } + sprintf(buffer, "%d", cc); + range.push_back(buffer); + if ( cc == stop ) + { + break; + } + } + f->m_Args = range; + } + else + { + f->m_Args = args; + } + } + else + { + f->m_Args = args; + } m_Makefile->AddFunctionBlocker(f); return true; diff --git a/Source/cmForEachCommand.h b/Source/cmForEachCommand.h index bb767e9..64602c9 100644 --- a/Source/cmForEachCommand.h +++ b/Source/cmForEachCommand.h @@ -98,12 +98,22 @@ public: " COMMAND2(ARGS ...)\n" " ...\n" " ENDFOREACH(loop_var)\n" + " FOREACH(loop_var RANGE total)\n" + " FOREACH(loop_var RANGE start stop [step])\n" "All commands between FOREACH and the matching ENDFOREACH are recorded " "without being invoked. Once the ENDFOREACH is evaluated, the " "recorded list of commands is invoked once for each argument listed " "in the original FOREACH command. Each recorded command is modified " "before invocation to replace any occurrence of \"${loop_var}\" with " - "the current value in the list."; + "the current value in the list.\n" + "Foreach can also iterate over the range of numbers generated by " + "foreach. There are three types of this iteration:\n" + "* When specifying single number, the range will have elements " + "0 to \"total\".\n" + "* When specifying two numbers, the range will have elements from " + "the first number to the second number.\n" + "* The third optional number is the increment used to iterate from " + "the first number to the second number."; } cmTypeMacro(cmForEachCommand, cmCommand); diff --git a/Tests/StringFileTest/CMakeLists.txt b/Tests/StringFileTest/CMakeLists.txt index 74b99ec..c0a904d 100644 --- a/Tests/StringFileTest/CMakeLists.txt +++ b/Tests/StringFileTest/CMakeLists.txt @@ -73,3 +73,22 @@ FILE(GLOB src_files "${expr}") MESSAGE("Globbed files [${src_files}].") ADD_EXECUTABLE(StringFileTest ${src_files}) + +# Test FOREACH range +MESSAGE("Cheack if FOREACH with RANGE works") +MACRO(TEST_RANGE ARGS CHECK) + SET(r) + FOREACH(a RANGE ${ARGS}) + SET(r ${r} ${a}) + ENDFOREACH(a) + MESSAGE("FOREACH with RANGE ${ARGS} produces ${r}") + IF("x${r}x" MATCHES "^x${CHECK}x$") + ELSE("x${r}x" MATCHES "^x${CHECK}x$") + MESSAGE(SEND_ERROR "The range resulted in: ${r} should be ${CHECK}") + ENDIF("x${r}x" MATCHES "^x${CHECK}x$") +ENDMACRO(TEST_RANGE) +TEST_RANGE("5" "0;1;2;3;4;5") +TEST_RANGE("3;5" "3;4;5") +TEST_RANGE("5;3" "5;4;3") +TEST_RANGE("3;10;2" "3;5;7;9") +TEST_RANGE("10;0;-3" "10;7;4;1") |