Store command type

To enable checks on command type (i.e. macro or function).
This commit is contained in:
Marc Chevrier
2026-04-29 10:36:20 -04:00
committed by Brad King
parent f15a0ea5d4
commit 37fae65a70
5 changed files with 113 additions and 18 deletions
+2 -1
View File
@@ -19,6 +19,7 @@
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -175,7 +176,7 @@ bool cmFunctionFunctionBlocker::Replay(
mf.RecordPolicies(f.Policies);
mf.RecordDiagnostics(f.Diagnostics);
return mf.GetState()->AddScriptedCommand(
this->Args.front(),
this->Args.front(), cmStateEnums::CommandType::Function,
BT<cmState::Command>(std::move(f),
mf.GetBacktrace().Push(this->GetStartingContext())),
mf);
+2 -1
View File
@@ -19,6 +19,7 @@
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -179,7 +180,7 @@ bool cmMacroFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
mf.RecordPolicies(f.Policies);
mf.RecordDiagnostics(f.Diagnostics);
return mf.GetState()->AddScriptedCommand(
this->Args[0],
this->Args[0], cmStateEnums::CommandType::Macro,
BT<cmState::Command>(std::move(f),
mf.GetBacktrace().Push(this->GetStartingContext())),
mf);
+69 -13
View File
@@ -414,7 +414,10 @@ void cmState::AddBuiltinCommand(std::string const& name, Command command)
{
assert(name == cmSystemTools::LowerCase(name));
assert(this->BuiltinCommands.find(name) == this->BuiltinCommands.end());
this->BuiltinCommands.emplace(name, std::move(command));
this->BuiltinCommands.emplace(
name,
CommandDescriptor{ cmStateEnums::CommandType::Function,
std::move(command) });
}
static bool InvokeBuiltinCommand(cmState::BuiltinCommand command,
@@ -522,8 +525,31 @@ void cmState::AddUnexpectedFlowControlCommand(std::string const& name,
this->AddUnexpectedCommand(name, error);
}
bool cmState::AddScriptedCommand(std::string const& name, BT<Command> command,
cmMakefile& mf)
cmState::CommandDescriptor::CommandDescriptor(CommandType type,
Command command)
: Type(type)
, Script(std::move(command))
{
}
cmState::CommandDescriptor::CommandDescriptor(
CommandDescriptor&& descriptor) noexcept
: Type(descriptor.Type)
, Script(std::move(descriptor.Script))
{
}
cmState::CommandDescriptor& cmState::CommandDescriptor::operator=(
CommandDescriptor&& descriptor) noexcept
{
this->Type = descriptor.Type;
this->Script = std::move(descriptor.Script);
return *this;
}
bool cmState::AddScriptedCommand(std::string const& name,
cmStateEnums::CommandType type,
BT<Command> command, cmMakefile& mf)
{
std::string sName = cmSystemTools::LowerCase(name);
@@ -538,30 +564,60 @@ bool cmState::AddScriptedCommand(std::string const& name, BT<Command> command,
}
// if the command already exists, give a new name to the old command.
if (Command oldCmd = this->GetCommandByExactName(sName)) {
this->ScriptedCommands["_" + sName] = oldCmd;
if (CommandDescriptor const* oldCmd =
this->GetCommandDescriptorByExactName(sName)) {
this->ScriptedCommands["_" + sName] = *oldCmd;
}
this->ScriptedCommands[sName] = std::move(command.Value);
this->ScriptedCommands[sName] =
CommandDescriptor{ type, std::move(command.Value) };
return true;
}
cmState::CommandDescriptor const* cmState::GetCommandDescriptorByExactName(
std::string const& name) const
{
auto pos = this->ScriptedCommands.find(name);
if (pos != this->ScriptedCommands.end()) {
return &pos->second;
}
pos = this->BuiltinCommands.find(name);
if (pos != this->BuiltinCommands.end()) {
return &pos->second;
}
return nullptr;
}
cmState::Command cmState::GetCommand(std::string const& name) const
{
return this->GetCommandByExactName(cmSystemTools::LowerCase(name));
}
cm::optional<cmStateEnums::CommandType> cmState::GetCommandType(
std::string const& name) const
{
return this->GetCommandTypeByExactName(cmSystemTools::LowerCase(name));
}
cmState::Command cmState::GetCommandByExactName(std::string const& name) const
{
auto pos = this->ScriptedCommands.find(name);
if (pos != this->ScriptedCommands.end()) {
return pos->second;
CommandDescriptor const* descriptor =
this->GetCommandDescriptorByExactName(name);
if (!descriptor) {
return nullptr;
}
pos = this->BuiltinCommands.find(name);
if (pos != this->BuiltinCommands.end()) {
return pos->second;
return descriptor->Script;
}
cm::optional<cmStateEnums::CommandType> cmState::GetCommandTypeByExactName(
std::string const& name) const
{
CommandDescriptor const* descriptor =
this->GetCommandDescriptorByExactName(name);
if (!descriptor) {
return cm::nullopt;
}
return nullptr;
return descriptor->Type;
}
std::vector<std::string> cmState::GetCommandNames() const
+34 -3
View File
@@ -172,8 +172,14 @@ public:
// Returns a command from its name, case insensitive, or nullptr
Command GetCommand(std::string const& name) const;
// Returns a command type from its name, case insensitive, or cm::nullopt
cm::optional<cmStateEnums::CommandType> GetCommandType(
std::string const& name) const;
// Returns a command from its name, or nullptr
Command GetCommandByExactName(std::string const& name) const;
// Returns a command type from its name, or cm::nullopt
cm::optional<cmStateEnums::CommandType> GetCommandTypeByExactName(
std::string const& name) const;
void AddBuiltinCommand(std::string const& name, Command command);
void AddBuiltinCommand(std::string const& name, BuiltinCommand command);
@@ -186,7 +192,8 @@ public:
void AddUnexpectedCommand(std::string const& name, char const* error);
void AddUnexpectedFlowControlCommand(std::string const& name,
char const* error);
bool AddScriptedCommand(std::string const& name, BT<Command> command,
bool AddScriptedCommand(std::string const& name,
cmStateEnums::CommandType type, BT<Command> command,
cmMakefile& mf);
void RemoveBuiltinCommand(std::string const& name);
void RemoveUserDefinedCommands();
@@ -277,8 +284,32 @@ private:
cmPropertyDefinitionMap PropertyDefinitions;
std::vector<std::string> EnabledLanguages;
std::unordered_map<std::string, Command> BuiltinCommands;
std::unordered_map<std::string, Command> ScriptedCommands;
class CommandDescriptor
{
public:
using CommandType = cmStateEnums::CommandType;
CommandDescriptor()
: Type(CommandType::Macro)
, Script(nullptr)
{
}
CommandDescriptor(CommandType type, Command command);
CommandDescriptor(CommandDescriptor&& descriptor) noexcept;
CommandDescriptor& operator=(CommandDescriptor&& descriptor) noexcept;
CommandDescriptor& operator=(CommandDescriptor const& descriptor) =
default;
CommandType Type;
Command Script;
};
CommandDescriptor const* GetCommandDescriptorByExactName(
std::string const& name) const;
std::unordered_map<std::string, CommandDescriptor> BuiltinCommands;
std::unordered_map<std::string, CommandDescriptor> ScriptedCommands;
std::unordered_set<std::string> FlowControlCommands;
cmPropertyMap GlobalProperties;
std::unique_ptr<cmCacheManager> CacheManager;
+6
View File
@@ -41,6 +41,12 @@ enum SnapshotUnwindState
UNWINDING
};
enum class CommandType
{
Macro,
Function
};
// There are multiple overlapping ranges represented here. Be aware that adding
// a value to this enumeration may cause failures in numerous places which
// assume details about the ordering.