From 2d53fcf03522bfc13f0a3817c260576bbe496c7d Mon Sep 17 00:00:00 2001 From: Ken Martin Date: Mon, 26 Apr 2004 11:11:57 -0400 Subject: [PATCH] macros now support varargs --- Source/cmMacroCommand.cxx | 33 +++++++++++++++++++++++++++++++-- Source/cmMacroCommand.h | 7 ++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 391434e9d..a393effff 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -58,8 +58,10 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf) // Expand the argument list to the macro. std::vector expandedArguments; mf.ExpandArguments(lff.m_Arguments, expandedArguments); - // make sure the number of arguments matches - if (expandedArguments.size() != m_Args.size() - 1) + + // make sure the number of arguments passed is at least the number + // required by the signature + if (expandedArguments.size() < m_Args.size() - 1) { cmOStringStream error; error << "Error in cmake code at\n" @@ -70,6 +72,10 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf) return true; } + // now set the new argcDef + char argcDef[64]; + sprintf(argcDef,"%i",expandedArguments.size()); + // Invoke all the functions that were collected in the block. cmListFileFunction newLFF; for(unsigned int c = 0; c < m_Functions.size(); ++c) @@ -85,6 +91,7 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf) k != m_Functions[c].m_Arguments.end(); ++k) { tmps = k->Value; + // replace formal arguments for (unsigned int j = 1; j < m_Args.size(); ++j) { variable = "${"; @@ -93,6 +100,28 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf) cmSystemTools::ReplaceString(tmps, variable.c_str(), expandedArguments[j-1].c_str()); } + // replace argc, argv arguments + for (unsigned int j = 1; j < m_Args.size(); ++j) + { + variable = "${ARGC}"; + cmSystemTools::ReplaceString(tmps, variable.c_str(),argcDef); + } + for (unsigned int j = 1; j < m_Args.size(); ++j) + { + // since this could be slow, first check if there is an ARGV + // only then do the inner loop. PS std::string sucks + char argvName[60]; + if (tmps.find("${ARGV") != std::string::npos) + { + for (unsigned int t = 0; t < expandedArguments.size(); ++t) + { + sprintf(argvName,"${ARGV%i}",t); + cmSystemTools::ReplaceString(tmps, argvName, + expandedArguments[t].c_str()); + } + } + } + arg.Value = tmps; arg.Quoted = k->Quoted; newLFF.m_Arguments.push_back(arg); diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h index c1c0df5e4..c614588b4 100644 --- a/Source/cmMacroCommand.h +++ b/Source/cmMacroCommand.h @@ -101,7 +101,12 @@ public: "but before the matching ENDMACRO, are not invoked until the macro " "is invoked. When it is invoked, the commands recorded in the " "macro are first modified by replacing formal parameters (${arg1}) with " - "the arguments passed, and then invoked as normal commands."; + "the arguments passed, and then invoked as normal commands. In " + "addition to referencing the formal parameters you can reference " + "the variable ARGC which will be set to the number of arguments " + "passed into the function as well as ARGV0 ARGV1 ARGV2 ... which " + "will have the actual values of the arguments passed in. This " + "fascilitates creating macros with optional arguments."; } cmTypeMacro(cmMacroCommand, cmCommand);