Browse Source

macros now support varargs

Ken Martin 21 years ago
parent
commit
2d53fcf035
2 changed files with 37 additions and 3 deletions
  1. 31 2
      Source/cmMacroCommand.cxx
  2. 6 1
      Source/cmMacroCommand.h

+ 31 - 2
Source/cmMacroCommand.cxx

@@ -58,8 +58,10 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf)
     // Expand the argument list to the macro.
     std::vector<std::string> 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);

+ 6 - 1
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);