| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #include "cmCMakeLanguageCommand.h"
- #include <algorithm>
- #include <array>
- #include <cstddef>
- #include <memory>
- #include <string>
- #include <cm/string_view>
- #include <cmext/string_view>
- #include "cmExecutionStatus.h"
- #include "cmListFileCache.h"
- #include "cmMakefile.h"
- #include "cmRange.h"
- #include "cmStringAlgorithms.h"
- #include "cmSystemTools.h"
- namespace {
- std::array<cm::static_string_view, 12> InvalidCommands{
- { // clang-format off
- "function"_s, "endfunction"_s,
- "macro"_s, "endmacro"_s,
- "if"_s, "elseif"_s, "else"_s, "endif"_s,
- "while"_s, "endwhile"_s,
- "foreach"_s, "endforeach"_s
- } // clang-format on
- };
- bool cmCMakeLanguageCommandEVAL(std::vector<cmListFileArgument> const& args,
- cmExecutionStatus& status)
- {
- cmMakefile& makefile = status.GetMakefile();
- cmListFileContext context = makefile.GetBacktrace().Top();
- std::vector<std::string> expandedArgs;
- makefile.ExpandArguments(args, expandedArgs);
- if (expandedArgs.size() < 2) {
- status.SetError("called with incorrect number of arguments");
- return false;
- }
- if (expandedArgs[1] != "CODE") {
- auto code_iter =
- std::find(expandedArgs.begin() + 2, expandedArgs.end(), "CODE");
- if (code_iter == expandedArgs.end()) {
- status.SetError("called without CODE argument");
- } else {
- status.SetError(
- "called with unsupported arguments between EVAL and CODE arguments");
- }
- return false;
- }
- const std::string code =
- cmJoin(cmMakeRange(expandedArgs.begin() + 2, expandedArgs.end()), " ");
- return makefile.ReadListFileAsString(
- code, cmStrCat(context.FilePath, ":", context.Line, ":EVAL"));
- }
- }
- bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
- cmExecutionStatus& status)
- {
- if (args.empty()) {
- status.SetError("called with incorrect number of arguments");
- return false;
- }
- cmMakefile& makefile = status.GetMakefile();
- cmListFileContext context = makefile.GetBacktrace().Top();
- bool result = false;
- std::vector<std::string> dispatchExpandedArgs;
- std::vector<cmListFileArgument> dispatchArgs;
- dispatchArgs.emplace_back(args[0]);
- makefile.ExpandArguments(dispatchArgs, dispatchExpandedArgs);
- if (dispatchExpandedArgs.empty()) {
- status.SetError("called with incorrect number of arguments");
- return false;
- }
- if (dispatchExpandedArgs[0] == "CALL") {
- if ((args.size() == 1 && dispatchExpandedArgs.size() != 2) ||
- dispatchExpandedArgs.size() > 2) {
- status.SetError("called with incorrect number of arguments");
- return false;
- }
- // First argument is the name of the function to call
- std::string callCommand;
- size_t startArg;
- if (dispatchExpandedArgs.size() == 1) {
- std::vector<std::string> functionExpandedArg;
- std::vector<cmListFileArgument> functionArg;
- functionArg.emplace_back(args[1]);
- makefile.ExpandArguments(functionArg, functionExpandedArg);
- if (functionExpandedArg.size() != 1) {
- status.SetError("called with incorrect number of arguments");
- return false;
- }
- callCommand = functionExpandedArg[0];
- startArg = 2;
- } else {
- callCommand = dispatchExpandedArgs[1];
- startArg = 1;
- }
- // ensure specified command is valid
- // start/end flow control commands are not allowed
- auto cmd = cmSystemTools::LowerCase(callCommand);
- if (std::find(InvalidCommands.cbegin(), InvalidCommands.cend(), cmd) !=
- InvalidCommands.cend()) {
- status.SetError(cmStrCat("invalid command specified: "_s, callCommand));
- return false;
- }
- cmListFileFunction func;
- func.Name = callCommand;
- func.Line = context.Line;
- // The rest of the arguments are passed to the function call above
- for (size_t i = startArg; i < args.size(); ++i) {
- cmListFileArgument lfarg;
- lfarg.Delim = args[i].Delim;
- lfarg.Line = context.Line;
- lfarg.Value = args[i].Value;
- func.Arguments.emplace_back(lfarg);
- }
- result = makefile.ExecuteCommand(func, status);
- } else if (dispatchExpandedArgs[0] == "EVAL") {
- return cmCMakeLanguageCommandEVAL(args, status);
- } else {
- status.SetError("called with unknown meta-operation");
- }
- return result;
- }
|