123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #include "cmWhileCommand.h"
- #include "cmConditionEvaluator.h"
- #include "cmExecutionStatus.h"
- #include "cmExpandedCommandArgument.h"
- #include "cmMakefile.h"
- #include "cmSystemTools.h"
- #include "cmake.h"
- #include <memory> // IWYU pragma: keep
- cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf)
- : Makefile(mf)
- , Depth(0)
- {
- this->Makefile->PushLoopBlock();
- }
- cmWhileFunctionBlocker::~cmWhileFunctionBlocker()
- {
- this->Makefile->PopLoopBlock();
- }
- bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
- cmMakefile& mf,
- cmExecutionStatus& inStatus)
- {
- // at end of for each execute recorded commands
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "while")) {
- // record the number of while commands past this one
- this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endwhile")) {
- // if this is the endwhile for this while loop then execute
- if (!this->Depth) {
- // Remove the function blocker for this scope or bail.
- std::unique_ptr<cmFunctionBlocker> fb(
- mf.RemoveFunctionBlocker(this, lff));
- if (!fb.get()) {
- return false;
- }
- std::string errorString;
- std::vector<cmExpandedCommandArgument> expandedArguments;
- mf.ExpandArguments(this->Args, expandedArguments);
- cmake::MessageType messageType;
- cmListFileContext execContext = this->GetStartingContext();
- cmCommandContext commandContext;
- commandContext.Line = execContext.Line;
- commandContext.Name = execContext.Name;
- cmConditionEvaluator conditionEvaluator(mf, this->GetStartingContext(),
- mf.GetBacktrace(commandContext));
- bool isTrue =
- conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
- while (isTrue) {
- if (!errorString.empty()) {
- std::string err = "had incorrect arguments: ";
- for (cmListFileArgument const& arg : this->Args) {
- err += (arg.Delim ? "\"" : "");
- err += arg.Value;
- err += (arg.Delim ? "\"" : "");
- err += " ";
- }
- err += "(";
- err += errorString;
- err += ").";
- mf.IssueMessage(messageType, err);
- if (messageType == cmake::FATAL_ERROR) {
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
- }
- // Invoke all the functions that were collected in the block.
- for (cmListFileFunction const& fn : this->Functions) {
- cmExecutionStatus status;
- mf.ExecuteCommand(fn, status);
- if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
- return true;
- }
- if (status.GetBreakInvoked()) {
- return true;
- }
- if (status.GetContinueInvoked()) {
- break;
- }
- if (cmSystemTools::GetFatalErrorOccured()) {
- return true;
- }
- }
- expandedArguments.clear();
- mf.ExpandArguments(this->Args, expandedArguments);
- isTrue = conditionEvaluator.IsTrue(expandedArguments, errorString,
- messageType);
- }
- return true;
- }
- // decrement for each nested while that ends
- this->Depth--;
- }
- // record the command
- this->Functions.push_back(lff);
- // always return true
- return true;
- }
- bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
- cmMakefile&)
- {
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endwhile")) {
- // if the endwhile has arguments, then make sure
- // they match the arguments of the matching while
- if (lff.Arguments.empty() || lff.Arguments == this->Args) {
- return true;
- }
- }
- return false;
- }
- bool cmWhileCommand::InvokeInitialPass(
- const std::vector<cmListFileArgument>& args, cmExecutionStatus&)
- {
- if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
- return false;
- }
- // create a function blocker
- cmWhileFunctionBlocker* f = new cmWhileFunctionBlocker(this->Makefile);
- f->Args = args;
- this->Makefile->AddFunctionBlocker(f);
- return true;
- }
|