ENH: Add RANGE support to FOREACH
This commit is contained in:
parent
ae50b4bc6a
commit
8750f1c277
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue