Commit 0de867dd authored by Gregor Jasny's avatar Gregor Jasny Committed by Brad King

continue: Add a new CMake language command for loop continuation (#14013)

Inspired-by: Doug Barbieri
Signed-off-by: Gregor Jasny's avatarGregor Jasny <gjasny@googlemail.com>
parent 8e75f1d2
......@@ -8,3 +8,5 @@ Break from an enclosing foreach or while loop.
break()
Breaks from an enclosing foreach loop or while loop
See also the :command:`continue` command.
continue
--------
Continue to the top of enclosing foreach or while loop.
::
continue()
The ``continue`` command allows a cmake script to abort the rest of a block
in a :command:`foreach` or :command:`while` loop, and start at the top of
the next iteration. See also the :command:`break` command.
......@@ -31,6 +31,7 @@ These commands may be used freely in CMake projects.
/command/cmake_minimum_required
/command/cmake_policy
/command/configure_file
/command/continue
/command/create_test_sourcelist
/command/define_property
/command/elseif
......
......@@ -469,8 +469,10 @@ Loops
The :command:`foreach`/:command:`endforeach` and
:command:`while`/:command:`endwhile` commands delimit code
blocks to be executed in a loop. The :command:`break` command
may be used inside such blocks to terminate the loop early.
blocks to be executed in a loop. Inside such blocks the
:command:`break` command may be used to terminate the loop
early whereas the :command:`continue` command may be used
to start with the next iteration immediately.
Command Definitions
-------------------
......
add-continue-command
--------------------
* A new :command:`continue` command was added that can be called inside loop
contexts to end the current iteration and start the next one at the top of
the loop block.
......@@ -28,6 +28,7 @@
#include "cmCMakePolicyCommand.cxx"
#include "cmCommandArgumentsHelper.cxx"
#include "cmConfigureFileCommand.cxx"
#include "cmContinueCommand.cxx"
#include "cmCoreTryCompile.cxx"
#include "cmCreateTestSourceList.cxx"
#include "cmDefinePropertyCommand.cxx"
......@@ -70,6 +71,7 @@ void GetBootstrapCommands1(std::list<cmCommand*>& commands)
commands.push_back(new cmCMakeMinimumRequired);
commands.push_back(new cmCMakePolicyCommand);
commands.push_back(new cmConfigureFileCommand);
commands.push_back(new cmContinueCommand);
commands.push_back(new cmCreateTestSourceList);
commands.push_back(new cmDefinePropertyCommand);
commands.push_back(new cmElseCommand);
......
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2000-2014 Kitware, Inc., Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "cmContinueCommand.h"
// cmContinueCommand
bool cmContinueCommand::InitialPass(std::vector<std::string> const &args,
cmExecutionStatus &status)
{
if(!this->Makefile->IsLoopBlock())
{
this->Makefile->IssueMessage(cmake::FATAL_ERROR,
"A CONTINUE command was found outside of a "
"proper FOREACH or WHILE loop scope.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
status.SetContinueInvoked(true);
if(!args.empty())
{
this->Makefile->IssueMessage(cmake::FATAL_ERROR,
"The CONTINUE command does not accept any "
"arguments.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
return true;
}
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2000-2014 Kitware, Inc., Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef cmContinueCommand_h
#define cmContinueCommand_h
#include "cmCommand.h"
/** \class cmContinueCommand
* \brief Continue from an enclosing foreach or while loop
*
* cmContinueCommand returns from an enclosing foreach or while loop
*/
class cmContinueCommand : public cmCommand
{
public:
/**
* This is a virtual constructor for the command.
*/
virtual cmCommand* Clone()
{
return new cmContinueCommand;
}
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
virtual bool InitialPass(std::vector<std::string> const& args,
cmExecutionStatus &status);
/**
* This determines if the command is invoked when in script mode.
*/
virtual bool IsScriptable() const { return true; }
/**
* The name of the command as specified in CMakeList.txt.
*/
virtual std::string GetName() const { return "continue"; }
cmTypeMacro(cmContinueCommand, cmCommand);
};
#endif
......@@ -36,10 +36,16 @@ public:
virtual bool GetBreakInvoked()
{ return this->BreakInvoked; }
virtual void SetContinueInvoked(bool val)
{ this->ContinueInvoked = val; }
virtual bool GetContinueInvoked()
{ return this->ContinueInvoked; }
virtual void Clear()
{
this->ReturnInvoked = false;
this->BreakInvoked = false;
this->ContinueInvoked = false;
this->NestedError = false;
}
virtual void SetNestedError(bool val) { this->NestedError = val; }
......@@ -49,6 +55,7 @@ public:
protected:
bool ReturnInvoked;
bool BreakInvoked;
bool ContinueInvoked;
bool NestedError;
};
......
......@@ -69,6 +69,10 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
mf.AddDefinition(this->Args[0],oldDef.c_str());
return true;
}
if (status.GetContinueInvoked())
{
break;
}
if(cmSystemTools::GetFatalErrorOccured() )
{
return true;
......
......@@ -151,6 +151,11 @@ IsFunctionBlocked(const cmListFileFunction& lff,
inStatus.SetBreakInvoked(true);
return true;
}
if (status.GetContinueInvoked())
{
inStatus.SetContinueInvoked(true);
return true;
}
}
}
return true;
......
......@@ -83,6 +83,10 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
{
return true;
}
if (status.GetContinueInvoked())
{
break;
}
if(cmSystemTools::GetFatalErrorOccured() )
{
return true;
......
......@@ -102,6 +102,7 @@ add_RunCMake_test(add_dependencies)
add_RunCMake_test(build_command)
add_RunCMake_test(export)
add_RunCMake_test(cmake_minimum_required)
add_RunCMake_test(continue)
add_RunCMake_test(file)
add_RunCMake_test(find_package)
add_RunCMake_test(get_filename_component)
......
cmake_minimum_required(VERSION 3.1)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
list(APPEND foo 1 2 3 4 5)
message(STATUS "start")
foreach(iter IN LISTS foo)
if("${iter}" EQUAL 1 OR "${iter}" EQUAL 3 OR "${iter}" EQUAL 5)
continue()
endif()
message(STATUS "${iter}")
endforeach()
message(STATUS "end")
message(STATUS "start")
foreach(iter RANGE 1 5)
if("${iter}" EQUAL 1 OR "${iter}" EQUAL 3 OR "${iter}" EQUAL 5)
continue()
endif()
message(STATUS "${iter}")
endforeach()
message(STATUS "end")
-- start
-- 7 2
-- 7 4
-- 9 2
-- 9 4
-- end
message(STATUS "start")
foreach(outer RANGE 7 9)
if("${outer}" EQUAL 8)
continue()
endif()
foreach(inner RANGE 1 5)
if("${inner}" EQUAL 1 OR "${inner}" EQUAL 3 OR "${inner}" EQUAL 5)
continue()
endif()
message(STATUS "${outer} ${inner}")
endforeach()
endforeach()
message(STATUS "end")
-- start
-- a
-- aa
-- aaaa
-- aaaaa
-- end
message(STATUS "start")
unset(iter)
while(NOT "${iter}" STREQUAL "aaaaa")
set(iter "${iter}a")
if("${iter}" STREQUAL "aaa")
continue()
endif()
message(STATUS "${iter}")
endwhile()
message(STATUS "end")
CMake Error at NoArgumentsToContinue.cmake:2 \(continue\):
The CONTINUE command does not accept any arguments.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
foreach(i RANGE 1 2)
continue(1)
endforeach()
CMake Error at NoEnclosingBlock.cmake:1 \(continue\):
A CONTINUE command was found outside of a proper FOREACH or WHILE loop
scope.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
CMake Error at NoEnclosingBlockInFunction.cmake:2 \(continue\):
A CONTINUE command was found outside of a proper FOREACH or WHILE loop
scope.
Call Stack \(most recent call first\):
NoEnclosingBlockInFunction.cmake:6 \(foo\)
CMakeLists.txt:3 \(include\)
function(foo)
continue()
endfunction(foo)
foreach(i RANGE 1 2)
foo()
message(STATUS "Hello World")
endforeach()
include(RunCMake)
run_cmake(ContinueForeach)
run_cmake(ContinueForEachInLists)
run_cmake(ContinueNestedForeach)
run_cmake(ContinueWhile)
run_cmake(NoArgumentsToContinue)
run_cmake(NoEnclosingBlock)
run_cmake(NoEnclosingBlockInFunction)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment