Explorar o código

ENH: Moved ExpandListVariables out of individual commands. Argument evaluation rules are now very consistent. Double quotes can always be used to create exactly one argument, regardless of contents inside.

Brad King %!s(int64=23) %!d(string=hai) anos
pai
achega
4888c088ae
Modificáronse 53 ficheiros con 607 adicións e 629 borrados
  1. 2 4
      Source/cmAbstractFilesCommand.cxx
  2. 2 4
      Source/cmAddCustomCommandCommand.cxx
  3. 2 4
      Source/cmAddCustomTargetCommand.cxx
  4. 2 4
      Source/cmAddDefinitionsCommand.cxx
  5. 2 4
      Source/cmAddDependenciesCommand.cxx
  6. 3 5
      Source/cmAddExecutableCommand.cxx
  7. 2 4
      Source/cmAddLibraryCommand.cxx
  8. 1 2
      Source/cmAddTestCommand.cxx
  9. 6 4
      Source/cmCPluginAPI.cxx
  10. 16 2
      Source/cmCommand.h
  11. 4 6
      Source/cmCreateTestSourceList.cxx
  12. 5 2
      Source/cmEndForEachCommand.cxx
  13. 7 1
      Source/cmEndForEachCommand.h
  14. 2 4
      Source/cmFindFileCommand.cxx
  15. 2 4
      Source/cmFindLibraryCommand.cxx
  16. 2 4
      Source/cmFindPathCommand.cxx
  17. 2 5
      Source/cmFindProgramCommand.cxx
  18. 44 48
      Source/cmForEachCommand.cxx
  19. 4 9
      Source/cmForEachCommand.h
  20. 2 5
      Source/cmFunctionBlocker.h
  21. 2 4
      Source/cmITKWrapTclCommand.cxx
  22. 28 23
      Source/cmIfCommand.cxx
  23. 10 6
      Source/cmIfCommand.h
  24. 2 4
      Source/cmIncludeDirectoryCommand.cxx
  25. 2 4
      Source/cmInstallProgramsCommand.cxx
  26. 2 4
      Source/cmInstallTargetsCommand.cxx
  27. 2 4
      Source/cmLinkDirectoriesCommand.cxx
  28. 2 4
      Source/cmLinkLibrariesCommand.cxx
  29. 183 6
      Source/cmListFileCache.cxx
  30. 34 1
      Source/cmListFileCache.h
  31. 2 4
      Source/cmLoadCacheCommand.cxx
  32. 4 6
      Source/cmLoadCommandCommand.cxx
  33. 3 3
      Source/cmLocalUnixMakefileGenerator.cxx
  34. 33 36
      Source/cmMacroCommand.cxx
  35. 3 10
      Source/cmMacroCommand.h
  36. 48 68
      Source/cmMakefile.cxx
  37. 11 3
      Source/cmMakefile.h
  38. 2 4
      Source/cmMarkAsAdvancedCommand.cxx
  39. 2 4
      Source/cmMessageCommand.cxx
  40. 2 4
      Source/cmProjectCommand.cxx
  41. 4 6
      Source/cmRemoveCommand.cxx
  42. 2 4
      Source/cmSetSourceFilesPropertiesCommand.cxx
  43. 2 4
      Source/cmSourceFilesCommand.cxx
  44. 4 6
      Source/cmSourceFilesRemoveCommand.cxx
  45. 2 4
      Source/cmSubdirCommand.cxx
  46. 73 224
      Source/cmSystemTools.cxx
  47. 4 22
      Source/cmSystemTools.h
  48. 1 3
      Source/cmTarget.cxx
  49. 3 5
      Source/cmTargetLinkLibrariesCommand.cxx
  50. 2 4
      Source/cmUtilitySourceCommand.cxx
  51. 1 1
      Source/cmVariableRequiresCommand.cxx
  52. 2 4
      Source/cmWriteFileCommand.cxx
  53. 18 15
      Source/ctest.cxx

+ 2 - 4
Source/cmAbstractFilesCommand.cxx

@@ -19,7 +19,7 @@
 #include "cmSourceFile.h"
 #include "cmSourceFile.h"
 
 
 // cmAbstractFilesCommand
 // cmAbstractFilesCommand
-bool cmAbstractFilesCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmAbstractFilesCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
   const char* versionValue
   const char* versionValue
     = m_Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
     = m_Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
@@ -29,13 +29,11 @@ bool cmAbstractFilesCommand::InitialPass(std::vector<std::string> const& argsIn)
     return false;
     return false;
     }
     }
   
   
-  if(argsIn.size() < 1 )
+  if(args.size() < 1 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   bool ret = true;
   bool ret = true;
   std::string m = "could not find source file(s):\n";
   std::string m = "could not find source file(s):\n";

+ 2 - 4
Source/cmAddCustomCommandCommand.cxx

@@ -18,19 +18,17 @@
 
 
 
 
 // cmAddCustomCommandCommand
 // cmAddCustomCommandCommand
-bool cmAddCustomCommandCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmAddCustomCommandCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
   /* Let's complain at the end of this function about the lack of a particular
   /* Let's complain at the end of this function about the lack of a particular
      arg. For the moment, let's say that COMMAND, TARGET are always 
      arg. For the moment, let's say that COMMAND, TARGET are always 
      required.
      required.
   */
   */
-  if (argsIn.size() < 4)
+  if (args.size() < 4)
     {
     {
       this->SetError("called with wrong number of arguments.");
       this->SetError("called with wrong number of arguments.");
       return false;
       return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   std::string source, command, target, comment;
   std::string source, command, target, comment;
   std::vector<std::string> command_args, depends, outputs;
   std::vector<std::string> command_args, depends, outputs;

+ 2 - 4
Source/cmAddCustomTargetCommand.cxx

@@ -17,17 +17,15 @@
 #include "cmAddCustomTargetCommand.h"
 #include "cmAddCustomTargetCommand.h"
 
 
 // cmAddCustomTargetCommand
 // cmAddCustomTargetCommand
-bool cmAddCustomTargetCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmAddCustomTargetCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
   bool all = false;
   bool all = false;
   
   
-  if(argsIn.size() < 2 )
+  if(args.size() < 2 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   // all target option
   // all target option
   std::string arguments;
   std::string arguments;

+ 2 - 4
Source/cmAddDefinitionsCommand.cxx

@@ -17,15 +17,13 @@
 #include "cmAddDefinitionsCommand.h"
 #include "cmAddDefinitionsCommand.h"
 
 
 // cmAddDefinitionsCommand
 // cmAddDefinitionsCommand
-bool cmAddDefinitionsCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmAddDefinitionsCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
   // it is OK to have no arguments
   // it is OK to have no arguments
-  if(argsIn.size() < 1 )
+  if(args.size() < 1 )
     {
     {
     return true;
     return true;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   for(std::vector<std::string>::const_iterator i = args.begin();
   for(std::vector<std::string>::const_iterator i = args.begin();
       i != args.end(); ++i)
       i != args.end(); ++i)

+ 2 - 4
Source/cmAddDependenciesCommand.cxx

@@ -17,15 +17,13 @@
 #include "cmAddDependenciesCommand.h"
 #include "cmAddDependenciesCommand.h"
 
 
 // cmDependenciesCommand
 // cmDependenciesCommand
-bool cmAddDependenciesCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmAddDependenciesCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 2 )
+  if(args.size() < 2 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   std::string target_name = args[0];
   std::string target_name = args[0];
 
 

+ 3 - 5
Source/cmAddExecutableCommand.cxx

@@ -17,16 +17,14 @@
 #include "cmAddExecutableCommand.h"
 #include "cmAddExecutableCommand.h"
 
 
 // cmExecutableCommand
 // cmExecutableCommand
-bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 2 )
+  if(args.size() < 2 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
-  std::vector<std::string>::iterator s = args.begin();
+  std::vector<std::string>::const_iterator s = args.begin();
 
 
   std::string exename = *s;
   std::string exename = *s;
 
 

+ 2 - 4
Source/cmAddLibraryCommand.cxx

@@ -17,15 +17,13 @@
 #include "cmAddLibraryCommand.h"
 #include "cmAddLibraryCommand.h"
 
 
 // cmLibraryCommand
 // cmLibraryCommand
-bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 1 )
+  if(args.size() < 1 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
   // Library type defaults to value of BUILD_SHARED_LIBS, if it exists,
   // Library type defaults to value of BUILD_SHARED_LIBS, if it exists,
   // otherwise it defaults to static library.
   // otherwise it defaults to static library.
   int shared = !cmSystemTools::IsOff(m_Makefile->GetDefinition("BUILD_SHARED_LIBS"));
   int shared = !cmSystemTools::IsOff(m_Makefile->GetDefinition("BUILD_SHARED_LIBS"));

+ 1 - 2
Source/cmAddTestCommand.cxx

@@ -32,8 +32,7 @@ bool cmAddTestCommand::InitialPass(std::vector<std::string> const& args)
   // store the arguments for the final pass
   // store the arguments for the final pass
   // also expand any CMake variables
   // also expand any CMake variables
 
 
-  m_Args.erase(m_Args.begin(), m_Args.end());
-  cmSystemTools::ExpandListArguments(args, m_Args);
+  m_Args = args;
   return true;
   return true;
 }
 }
 
 

+ 6 - 4
Source/cmCPluginAPI.cxx

@@ -296,12 +296,14 @@ void cmExecuteCommand(void *arg, const char *name,
 {
 {
   cmMakefile *mf = static_cast<cmMakefile *>(arg);
   cmMakefile *mf = static_cast<cmMakefile *>(arg);
   std::vector<std::string> args2;
   std::vector<std::string> args2;
-  int i;
-  for (i = 0; i < numArgs; ++i)
+  cmListFileFunction lff;
+  lff.m_Name = name;
+  for(int i = 0; i < numArgs; ++i)
     {
     {
-    args2.push_back(args[i]);
+    // Assume all arguments are quoted.
+    lff.m_Arguments.push_back(cmListFileArgument(args[i], true));
     }
     }
-  mf->ExecuteCommand(std::string(name), args2);
+  mf->ExecuteCommand(lff);
 }
 }
 
 
 void cmExpandSourceListArguments(void *arg, 
 void cmExpandSourceListArguments(void *arg, 

+ 16 - 2
Source/cmCommand.h

@@ -18,7 +18,8 @@
 #define cmCommand_h
 #define cmCommand_h
 
 
 #include "cmStandardIncludes.h"
 #include "cmStandardIncludes.h"
-class cmMakefile;
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
 
 
 /** \class cmCommand
 /** \class cmCommand
  * \brief Superclass for all commands in CMake.
  * \brief Superclass for all commands in CMake.
@@ -50,6 +51,18 @@ public:
   void SetMakefile(cmMakefile*m) 
   void SetMakefile(cmMakefile*m) 
     {m_Makefile = m; }
     {m_Makefile = m; }
 
 
+  /**
+   * This is called by the cmMakefile when the command is first
+   * encountered in the CMakeLists.txt file.  It expands the command's
+   * arguments and then invokes the InitialPass.
+   */
+  virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args)
+    {
+    std::vector<std::string> expandedArguments;
+    m_Makefile->ExpandArguments(args, expandedArguments);
+    return this->InitialPass(expandedArguments);
+    }
+
   /**
   /**
    * This is called when the command is first encountered in
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
    * the CMakeLists.txt file.
@@ -159,13 +172,14 @@ private:
 
 
 // All subclasses of cmCommand should invoke this macro.
 // All subclasses of cmCommand should invoke this macro.
 #define cmTypeMacro(thisClass,superclass) \
 #define cmTypeMacro(thisClass,superclass) \
+typedef superclass Superclass; \
 static bool IsTypeOf(const char *type) \
 static bool IsTypeOf(const char *type) \
 { \
 { \
   if ( !strcmp(#thisClass,type) ) \
   if ( !strcmp(#thisClass,type) ) \
     { \
     { \
     return true; \
     return true; \
     } \
     } \
-  return superclass::IsTypeOf(type); \
+  return Superclass::IsTypeOf(type); \
 } \
 } \
 virtual bool IsA(const char *type) \
 virtual bool IsA(const char *type) \
 { \
 { \

+ 4 - 6
Source/cmCreateTestSourceList.cxx

@@ -18,18 +18,16 @@
 #include "cmSourceFile.h"
 #include "cmSourceFile.h"
 
 
 // cmCreateTestSourceList
 // cmCreateTestSourceList
-bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& argsIn)
+bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if (argsIn.size() < 3)
+  if (args.size() < 3)
     {
     {
     this->SetError("called with wrong number of arguments.");
     this->SetError("called with wrong number of arguments.");
     return false;
     return false;
     }
     }
 
 
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
   
   
-  std::vector<std::string>::iterator i = args.begin();
+  std::vector<std::string>::const_iterator i = args.begin();
   std::string extraInclude;
   std::string extraInclude;
   std::string function;
   std::string function;
   std::vector<std::string> tests;
   std::vector<std::string> tests;
@@ -120,7 +118,7 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& argsIn)
     "/* Forward declare test functions. */\n"
     "/* Forward declare test functions. */\n"
     "\n";
     "\n";
 
 
-  std::vector<std::string>::iterator testsBegin = i;
+  std::vector<std::string>::const_iterator testsBegin = i;
   std::vector<std::string> tests_func_name;
   std::vector<std::string> tests_func_name;
 
 
   // The rest of the arguments consist of a list of test source files.
   // The rest of the arguments consist of a list of test source files.

+ 5 - 2
Source/cmEndForEachCommand.cxx

@@ -16,7 +16,7 @@
 =========================================================================*/
 =========================================================================*/
 #include "cmEndForEachCommand.h"
 #include "cmEndForEachCommand.h"
 
 
-bool cmEndForEachCommand::InitialPass(std::vector<std::string> const& args)
+bool cmEndForEachCommand::InvokeInitialPass(std::vector<cmListFileArgument> const& args)
 {
 {
   if(args.size() < 1 )
   if(args.size() < 1 )
     {
     {
@@ -25,7 +25,10 @@ bool cmEndForEachCommand::InitialPass(std::vector<std::string> const& args)
     }
     }
 
 
   // remove any function blockers for this define
   // remove any function blockers for this define
-  m_Makefile->RemoveFunctionBlocker("ENDFOREACH",args);
+  cmListFileFunction lff;
+  lff.m_Name = "ENDFOREACH";
+  lff.m_Arguments = args;
+  m_Makefile->RemoveFunctionBlocker(lff);
   
   
   return true;
   return true;
 }
 }

+ 7 - 1
Source/cmEndForEachCommand.h

@@ -36,11 +36,17 @@ public:
     return new cmEndForEachCommand;
     return new cmEndForEachCommand;
     }
     }
 
 
+  /**
+   * Override cmCommand::InvokeInitialPass to get arguments before
+   * expansion.
+   */
+  virtual bool InvokeInitialPass(std::vector<cmListFileArgument> const&);
+  
   /**
   /**
    * This is called when the command is first encountered in
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
    * the CMakeLists.txt file.
    */
    */
-  virtual bool InitialPass(std::vector<std::string> const& args);
+  virtual bool InitialPass(std::vector<std::string> const&) {}
 
 
   /**
   /**
    * This determines if the command gets propagated down
    * This determines if the command gets propagated down

+ 2 - 4
Source/cmFindFileCommand.cxx

@@ -31,12 +31,12 @@ bool cmFindFileCommand::InitialPass(std::vector<std::string> const& argsIn)
   std::string helpString = "Where can the ";
   std::string helpString = "Where can the ";
   helpString += argsIn[1] + " file be found";
   helpString += argsIn[1] + " file be found";
   size_t size = argsIn.size();
   size_t size = argsIn.size();
-  std::vector<std::string> argst;
+  std::vector<std::string> args;
   for(unsigned int j = 0; j < size; ++j)
   for(unsigned int j = 0; j < size; ++j)
     {
     {
     if(argsIn[j] != "DOC")
     if(argsIn[j] != "DOC")
       {
       {
-      argst.push_back(argsIn[j]);
+      args.push_back(argsIn[j]);
       }
       }
     else
     else
       {
       {
@@ -47,8 +47,6 @@ bool cmFindFileCommand::InitialPass(std::vector<std::string> const& argsIn)
       break;
       break;
       }
       }
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argst, args);
 
 
   std::vector<std::string>::const_iterator i = args.begin();
   std::vector<std::string>::const_iterator i = args.begin();
   // Use the first argument as the name of something to be defined
   // Use the first argument as the name of something to be defined

+ 2 - 4
Source/cmFindLibraryCommand.cxx

@@ -27,12 +27,12 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn)
     } 
     } 
   std::string helpString;
   std::string helpString;
   size_t size = argsIn.size();
   size_t size = argsIn.size();
-  std::vector<std::string> argst;
+  std::vector<std::string> args;
   for(unsigned int j = 0; j < size; ++j)
   for(unsigned int j = 0; j < size; ++j)
     {
     {
     if(argsIn[j] != "DOC")
     if(argsIn[j] != "DOC")
       {
       {
-      argst.push_back(argsIn[j]);
+      args.push_back(argsIn[j]);
       }
       }
     else
     else
       {
       {
@@ -43,8 +43,6 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn)
       break;
       break;
       }
       }
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argst, args);
 
 
   std::vector<std::string> path;
   std::vector<std::string> path;
   std::vector<std::string> names;
   std::vector<std::string> names;

+ 2 - 4
Source/cmFindPathCommand.cxx

@@ -30,13 +30,13 @@ bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn)
   // already, if so use that value and don't look for the program
   // already, if so use that value and don't look for the program
   std::string helpString = "What is the path where the file ";
   std::string helpString = "What is the path where the file ";
   helpString += argsIn[1] + " can be found";
   helpString += argsIn[1] + " can be found";
-  std::vector<std::string> argst;
+  std::vector<std::string> args;
   size_t size = argsIn.size();
   size_t size = argsIn.size();
   for(unsigned int j = 0; j < size; ++j)
   for(unsigned int j = 0; j < size; ++j)
     {
     {
     if(argsIn[j] != "DOC")
     if(argsIn[j] != "DOC")
       {
       {
-      argst.push_back(argsIn[j]);
+      args.push_back(argsIn[j]);
       }
       }
     else
     else
       {
       {
@@ -47,8 +47,6 @@ bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn)
       break;
       break;
       }
       }
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argst, args);
 
 
   const char* cacheValue
   const char* cacheValue
     = m_Makefile->GetDefinition(args[0].c_str());
     = m_Makefile->GetDefinition(args[0].c_str());

+ 2 - 5
Source/cmFindProgramCommand.cxx

@@ -30,12 +30,12 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn)
     }
     }
   std::string doc = "Path to a program.";
   std::string doc = "Path to a program.";
   size_t size = argsIn.size();
   size_t size = argsIn.size();
-  std::vector<std::string> argst;
+  std::vector<std::string> args;
   for(unsigned int j = 0; j < size; ++j)
   for(unsigned int j = 0; j < size; ++j)
     {
     {
     if(argsIn[j] != "DOC")
     if(argsIn[j] != "DOC")
       {
       {
-      argst.push_back(argsIn[j]);
+      args.push_back(argsIn[j]);
       }
       }
     else
     else
       {
       {
@@ -46,9 +46,6 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn)
       break;
       break;
       }
       }
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argst, args);
-
 
 
   std::vector<std::string>::iterator i = args.begin();
   std::vector<std::string>::iterator i = args.begin();
   // Use the first argument as the name of something to be defined
   // Use the first argument as the name of something to be defined

+ 44 - 48
Source/cmForEachCommand.cxx

@@ -17,68 +17,71 @@
 #include "cmForEachCommand.h"
 #include "cmForEachCommand.h"
 
 
 bool cmForEachFunctionBlocker::
 bool cmForEachFunctionBlocker::
-IsFunctionBlocked(const char *name, const std::vector<std::string> &args, 
-                  cmMakefile &mf) 
+IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf) 
 {
 {
-  // prevent recusion and don't let this blobker blobk its own commands
+  // Prevent recusion and don't let this blobker block its own
+  // commands.
   if (m_Executing)
   if (m_Executing)
     {
     {
     return false;
     return false;
     }
     }
   
   
   // at end of for each execute recorded commands
   // at end of for each execute recorded commands
-  if (!strcmp(name,"ENDFOREACH") && args[0] == m_Args[0])
+  if (lff.m_Name == "ENDFOREACH")
     {
     {
-    m_Executing = true;
-    std::string variable = "${";
-    variable += m_Args[0];
-    variable += "}"; 
-    std::vector<std::string>::const_iterator j = m_Args.begin();
-    ++j;
-    
-    for( ; j != m_Args.end(); ++j)
-      {   
-      // perform string replace
-        for(unsigned int c = 0; c < m_Commands.size(); ++c)
-        {
-        std::vector<std::string> newArgs;
-        for (std::vector<std::string>::const_iterator k = 
-               m_CommandArguments[c].begin();
-             k != m_CommandArguments[c].end(); ++k)
+    std::vector<std::string> expandedArguments;
+    mf.ExpandArguments(lff.m_Arguments, expandedArguments);
+    if(!expandedArguments.empty() && (expandedArguments[0] == m_Args[0]))
+      {
+      m_Executing = true;
+      std::string variable = "${";
+      variable += m_Args[0];
+      variable += "}"; 
+      std::vector<std::string>::const_iterator j = m_Args.begin();
+      ++j;
+      
+      for( ; j != m_Args.end(); ++j)
+        {   
+        // Invoke all the functions that were collected in the block.
+        for(unsigned int c = 0; c < m_Functions.size(); ++c)
           {
           {
-          std::string tmps = *k;
-          cmSystemTools::ReplaceString(tmps, variable.c_str(),
-                                       j->c_str());
-          newArgs.push_back(tmps);
+          // Replace the loop variable and then invoke the command.
+          cmListFileFunction newLFF;
+          newLFF.m_Name = m_Functions[c].m_Name;
+          for (std::vector<cmListFileArgument>::const_iterator k = 
+                 m_Functions[c].m_Arguments.begin();
+               k != m_Functions[c].m_Arguments.end(); ++k)
+            {
+            std::string tmps = k->Value;
+            cmSystemTools::ReplaceString(tmps, variable.c_str(), j->c_str());
+            cmListFileArgument arg(tmps, k->Quoted);
+            newLFF.m_Arguments.push_back(arg);
+            }
+          mf.ExecuteCommand(newLFF);
           }
           }
-        // execute command
-        mf.ExecuteCommand(m_Commands[c],newArgs);
         }
         }
+      return false;
       }
       }
-    return false;
     }
     }
 
 
   // record the command
   // record the command
-  m_Commands.push_back(name);
-  std::vector<std::string> newArgs;
-  for(std::vector<std::string>::const_iterator j = args.begin();
-      j != args.end(); ++j)
-    {   
-    newArgs.push_back(*j);
-    }
-  m_CommandArguments.push_back(newArgs);
+  m_Functions.push_back(lff);
   
   
   // always return true
   // always return true
   return true;
   return true;
 }
 }
 
 
 bool cmForEachFunctionBlocker::
 bool cmForEachFunctionBlocker::
-ShouldRemove(const char *name, const std::vector<std::string> &args, 
-             cmMakefile &) 
+ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf)
 {
 {
-  if (!strcmp(name,"ENDFOREACH") && args[0] == m_Args[0])
+  if(lff.m_Name == "ENDFOREACH")
     {
     {
-    return true;
+    std::vector<std::string> expandedArguments;
+    mf.ExpandArguments(lff.m_Arguments, expandedArguments);
+    if(!expandedArguments.empty() && (expandedArguments[0] == m_Args[0]))
+      {
+      return true;
+      }
     }
     }
   return false;
   return false;
 }
 }
@@ -90,11 +93,8 @@ ScopeEnded(cmMakefile &mf)
                        mf.GetCurrentDirectory());
                        mf.GetCurrentDirectory());
 }
 }
 
 
-bool cmForEachCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmForEachCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
-
   if(args.size() < 1)
   if(args.size() < 1)
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
@@ -103,11 +103,7 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& argsIn)
   
   
   // create a function blocker
   // create a function blocker
   cmForEachFunctionBlocker *f = new cmForEachFunctionBlocker();
   cmForEachFunctionBlocker *f = new cmForEachFunctionBlocker();
-  for(std::vector<std::string>::const_iterator j = args.begin();
-      j != args.end(); ++j)
-    {   
-    f->m_Args.push_back(*j);
-    }
+  f->m_Args = args;
   m_Makefile->AddFunctionBlocker(f);
   m_Makefile->AddFunctionBlocker(f);
   
   
   return true;
   return true;

+ 4 - 9
Source/cmForEachCommand.h

@@ -20,6 +20,7 @@
 #include "cmStandardIncludes.h"
 #include "cmStandardIncludes.h"
 #include "cmCommand.h"
 #include "cmCommand.h"
 #include "cmFunctionBlocker.h"
 #include "cmFunctionBlocker.h"
+#include "cmListFileCache.h"
 
 
 /** \class cmForEachFunctionBlocker
 /** \class cmForEachFunctionBlocker
  * \brief subclass of function blocker
  * \brief subclass of function blocker
@@ -31,19 +32,13 @@ class cmForEachFunctionBlocker : public cmFunctionBlocker
 public:
 public:
   cmForEachFunctionBlocker() {m_Executing = false;}
   cmForEachFunctionBlocker() {m_Executing = false;}
   virtual ~cmForEachFunctionBlocker() {}
   virtual ~cmForEachFunctionBlocker() {}
-  virtual bool IsFunctionBlocked(const char *name, 
-                                 const std::vector<std::string> &args, 
+  virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
                                  cmMakefile &mf);
                                  cmMakefile &mf);
-  virtual bool ShouldRemove(const char *name, 
-                            const std::vector<std::string> &args, 
-                            cmMakefile &mf);
+  virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf);
   virtual void ScopeEnded(cmMakefile &mf);
   virtual void ScopeEnded(cmMakefile &mf);
   
   
-  virtual int NeedExpandedVariables () { return 0; };
-
   std::vector<std::string> m_Args;
   std::vector<std::string> m_Args;
-  std::vector<std::string> m_Commands;
-  std::vector<std::vector<std::string> > m_CommandArguments;
+  std::vector<cmListFileFunction> m_Functions;
   bool m_Executing;
   bool m_Executing;
 };
 };
 
 

+ 2 - 5
Source/cmFunctionBlocker.h

@@ -31,15 +31,14 @@ public:
   /**
   /**
    * should a function be blocked
    * should a function be blocked
    */
    */
-  virtual bool IsFunctionBlocked(const char *name, const std::vector<std::string> &args, 
+  virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
                                  cmMakefile&mf) = 0;
                                  cmMakefile&mf) = 0;
 
 
   /**
   /**
    * should this function blocker be removed, useful when one function adds a
    * should this function blocker be removed, useful when one function adds a
    * blocker and another must remove it 
    * blocker and another must remove it 
    */
    */
-  virtual bool ShouldRemove(const char *, 
-                            const std::vector<std::string>&,
+  virtual bool ShouldRemove(const cmListFileFunction& lff,
                             cmMakefile&) {return false;}
                             cmMakefile&) {return false;}
 
 
   /**
   /**
@@ -50,8 +49,6 @@ public:
   virtual void ScopeEnded(cmMakefile&) {}
   virtual void ScopeEnded(cmMakefile&) {}
 
 
   virtual ~cmFunctionBlocker() {}
   virtual ~cmFunctionBlocker() {}
-
-  virtual int NeedExpandedVariables () { return 1; };
 };
 };
 
 
 #endif
 #endif

+ 2 - 4
Source/cmITKWrapTclCommand.cxx

@@ -59,15 +59,13 @@ cmITKWrapTclCommand::AddDependencies(cmDependInformation const *info,
 }
 }
 
 
 // cmITKWrapTclCommand
 // cmITKWrapTclCommand
-bool cmITKWrapTclCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmITKWrapTclCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 2 )
+  if(args.size() < 2 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
   // keep the target name
   // keep the target name
   m_TargetName = args[0];
   m_TargetName = args[0];
   m_Target = &m_Makefile->GetTargets()[m_TargetName.c_str()];
   m_Target = &m_Makefile->GetTargets()[m_TargetName.c_str()];

+ 28 - 23
Source/cmIfCommand.cxx

@@ -17,9 +17,10 @@
 #include "cmIfCommand.h"
 #include "cmIfCommand.h"
 
 
 bool cmIfFunctionBlocker::
 bool cmIfFunctionBlocker::
-IsFunctionBlocked(const char *name, const std::vector<std::string> &args, 
-                  cmMakefile &mf)
+IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf)
 {
 {
+  const char* name = lff.m_Name.c_str();
+  const std::vector<cmListFileArgument>& args = lff.m_Arguments;
   // always let if statements through
   // always let if statements through
   if (!strcmp(name,"IF"))
   if (!strcmp(name,"IF"))
     {
     {
@@ -40,7 +41,7 @@ IsFunctionBlocked(const char *name, const std::vector<std::string> &args,
         }
         }
       // otherwise it must be an ENDIF statement, in that case remove the
       // otherwise it must be an ENDIF statement, in that case remove the
       // function blocker
       // function blocker
-      mf.RemoveFunctionBlocker("ENDIF",args);
+      mf.RemoveFunctionBlocker(lff);
       return true;
       return true;
       }
       }
     else if(args.empty())
     else if(args.empty())
@@ -50,10 +51,12 @@ IsFunctionBlocked(const char *name, const std::vector<std::string> &args,
       err += ".  Did you mean ";
       err += ".  Did you mean ";
       err += name;
       err += name;
       err += "( ";
       err += "( ";
-      for(std::vector<std::string>::const_iterator a = m_Args.begin();
+      for(std::vector<cmListFileArgument>::const_iterator a = m_Args.begin();
           a != m_Args.end();++a)
           a != m_Args.end();++a)
         {
         {
-        err += *a;
+        err += (a->Quoted?"\"":"");
+        err += a->Value;
+        err += (a->Quoted?"\"":"");
         err += " ";
         err += " ";
         }
         }
       err += ")?";
       err += ")?";
@@ -63,13 +66,12 @@ IsFunctionBlocked(const char *name, const std::vector<std::string> &args,
   return m_IsBlocking;
   return m_IsBlocking;
 }
 }
 
 
-bool cmIfFunctionBlocker::
-ShouldRemove(const char *name, const std::vector<std::string> &args, 
-             cmMakefile &) 
+bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
+                                       cmMakefile&)
 {
 {
-  if (!strcmp(name,"ENDIF"))
+  if (lff.m_Name == "ENDIF")
     {
     {
-    if (args == m_Args)
+    if (lff.m_Arguments == m_Args)
       {
       {
       return true;
       return true;
       }
       }
@@ -90,19 +92,24 @@ ScopeEnded(cmMakefile &mf)
   std::string errmsg = "The end of a CMakeLists file was reached with an IF statement that was not closed properly.\nWithin the directory: ";
   std::string errmsg = "The end of a CMakeLists file was reached with an IF statement that was not closed properly.\nWithin the directory: ";
   errmsg += mf.GetCurrentDirectory();
   errmsg += mf.GetCurrentDirectory();
   errmsg += "\nThe arguments are: ";
   errmsg += "\nThe arguments are: ";
-  for(std::vector<std::string>::const_iterator j = m_Args.begin();
+  for(std::vector<cmListFileArgument>::const_iterator j = m_Args.begin();
       j != m_Args.end(); ++j)
       j != m_Args.end(); ++j)
     {   
     {   
-    errmsg += *j;
+    errmsg += (j->Quoted?"\"":"");
+    errmsg += j->Value;
+    errmsg += (j->Quoted?"\"":"");
     errmsg += " ";
     errmsg += " ";
     }
     }
   cmSystemTools::Error(errmsg.c_str());
   cmSystemTools::Error(errmsg.c_str());
 }
 }
 
 
-bool cmIfCommand::InitialPass(std::vector<std::string> const& args)
+bool cmIfCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args)
 {
 {
   bool isValid;
   bool isValid;
-  bool isTrue = cmIfCommand::IsTrue(args,isValid,m_Makefile);
+  
+  std::vector<std::string> expandedArguments;
+  m_Makefile->ExpandArguments(args, expandedArguments);
+  bool isTrue = cmIfCommand::IsTrue(expandedArguments,isValid,m_Makefile);
   
   
   if (!isValid)
   if (!isValid)
     {
     {
@@ -110,7 +117,9 @@ bool cmIfCommand::InitialPass(std::vector<std::string> const& args)
     unsigned int i;
     unsigned int i;
     for(i =0; i < args.size(); ++i)
     for(i =0; i < args.size(); ++i)
       {
       {
-      err += args[i];
+      err += (args[i].Quoted?"\"":"");
+      err += args[i].Value;
+      err += (args[i].Quoted?"\"":"");
       err += " ";
       err += " ";
       }
       }
     this->SetError(err.c_str());
     this->SetError(err.c_str());
@@ -120,25 +129,21 @@ bool cmIfCommand::InitialPass(std::vector<std::string> const& args)
   cmIfFunctionBlocker *f = new cmIfFunctionBlocker();
   cmIfFunctionBlocker *f = new cmIfFunctionBlocker();
   // if is isn't true block the commands
   // if is isn't true block the commands
   f->m_IsBlocking = !isTrue;
   f->m_IsBlocking = !isTrue;
-  for(std::vector<std::string>::const_iterator j = args.begin();
-      j != args.end(); ++j)
-    {   
-    f->m_Args.push_back(*j);
-    }
+  f->m_Args = args;
   m_Makefile->AddFunctionBlocker(f);
   m_Makefile->AddFunctionBlocker(f);
   
   
   return true;
   return true;
 }
 }
 
 
-bool cmIfCommand::IsTrue(const std::vector<std::string> &args, bool &isValid,
-                         const cmMakefile *makefile)
+bool cmIfCommand::IsTrue(const std::vector<std::string> &args,
+                         bool &isValid, const cmMakefile *makefile)
 {
 {
   // check for the different signatures
   // check for the different signatures
   bool isTrue = true;
   bool isTrue = true;
   isValid = false;
   isValid = false;
   const char *def;
   const char *def;
   const char *def2;
   const char *def2;
-
+  
   if(args.size() < 1 )
   if(args.size() < 1 )
     {
     {
     isValid = true;
     isValid = true;

+ 10 - 6
Source/cmIfCommand.h

@@ -31,15 +31,13 @@ class cmIfFunctionBlocker : public cmFunctionBlocker
 public:
 public:
   cmIfFunctionBlocker() {}
   cmIfFunctionBlocker() {}
   virtual ~cmIfFunctionBlocker() {}
   virtual ~cmIfFunctionBlocker() {}
-  virtual bool IsFunctionBlocked(const char *name, 
-                                 const std::vector<std::string> &args, 
+  virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
                                  cmMakefile &mf);
                                  cmMakefile &mf);
-  virtual bool ShouldRemove(const char *name, 
-                            const std::vector<std::string> &args, 
+  virtual bool ShouldRemove(const cmListFileFunction& lff,
                             cmMakefile &mf);
                             cmMakefile &mf);
   virtual void ScopeEnded(cmMakefile &mf);
   virtual void ScopeEnded(cmMakefile &mf);
   
   
-  std::vector<std::string> m_Args;
+  std::vector<cmListFileArgument> m_Args;
   bool m_IsBlocking;
   bool m_IsBlocking;
 };
 };
 
 
@@ -59,11 +57,17 @@ public:
     return new cmIfCommand;
     return new cmIfCommand;
     }
     }
 
 
+  /**
+   * This overrides the default InvokeInitialPass implementation.
+   * It records the arguments before expansion.
+   */
+  virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args);
+    
   /**
   /**
    * This is called when the command is first encountered in
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
    * the CMakeLists.txt file.
    */
    */
-  virtual bool InitialPass(std::vector<std::string> const& args);
+  virtual bool InitialPass(std::vector<std::string> const& args) { return false; }
 
 
   /**
   /**
    * The name of the command as specified in CMakeList.txt.
    * The name of the command as specified in CMakeList.txt.

+ 2 - 4
Source/cmIncludeDirectoryCommand.cxx

@@ -17,14 +17,12 @@
 #include "cmIncludeDirectoryCommand.h"
 #include "cmIncludeDirectoryCommand.h"
 
 
 // cmIncludeDirectoryCommand
 // cmIncludeDirectoryCommand
-bool cmIncludeDirectoryCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmIncludeDirectoryCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 1 )
+  if(args.size() < 1 )
     {
     {
     return true;
     return true;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   std::vector<std::string>::const_iterator i = args.begin();
   std::vector<std::string>::const_iterator i = args.begin();
 
 

+ 2 - 4
Source/cmInstallProgramsCommand.cxx

@@ -17,15 +17,13 @@
 #include "cmInstallProgramsCommand.h"
 #include "cmInstallProgramsCommand.h"
 
 
 // cmExecutableCommand
 // cmExecutableCommand
-bool cmInstallProgramsCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmInstallProgramsCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 2)
+  if(args.size() < 2)
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   // Create an INSTALL_PROGRAMS target specifically for this path.
   // Create an INSTALL_PROGRAMS target specifically for this path.
   m_TargetName = "INSTALL_PROGRAMS_"+args[0];
   m_TargetName = "INSTALL_PROGRAMS_"+args[0];

+ 2 - 4
Source/cmInstallTargetsCommand.cxx

@@ -17,15 +17,13 @@
 #include "cmInstallTargetsCommand.h"
 #include "cmInstallTargetsCommand.h"
 
 
 // cmExecutableCommand
 // cmExecutableCommand
-bool cmInstallTargetsCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmInstallTargetsCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 2 )
+  if(args.size() < 2 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   cmTargets &tgts = m_Makefile->GetTargets();
   cmTargets &tgts = m_Makefile->GetTargets();
   std::vector<std::string>::const_iterator s = args.begin();
   std::vector<std::string>::const_iterator s = args.begin();

+ 2 - 4
Source/cmLinkDirectoriesCommand.cxx

@@ -17,14 +17,12 @@
 #include "cmLinkDirectoriesCommand.h"
 #include "cmLinkDirectoriesCommand.h"
 
 
 // cmLinkDirectoriesCommand
 // cmLinkDirectoriesCommand
-bool cmLinkDirectoriesCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmLinkDirectoriesCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
- if(argsIn.size() < 1 )
+ if(args.size() < 1 )
     {
     {
     return true;
     return true;
     }
     }
- std::vector<std::string> args;
- cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   for(std::vector<std::string>::const_iterator i = args.begin();
   for(std::vector<std::string>::const_iterator i = args.begin();
       i != args.end(); ++i)
       i != args.end(); ++i)

+ 2 - 4
Source/cmLinkLibrariesCommand.cxx

@@ -17,14 +17,12 @@
 #include "cmLinkLibrariesCommand.h"
 #include "cmLinkLibrariesCommand.h"
 
 
 // cmLinkLibrariesCommand
 // cmLinkLibrariesCommand
-bool cmLinkLibrariesCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmLinkLibrariesCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 1 )
+  if(args.size() < 1 )
     {
     {
     return true;
     return true;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
   // add libraries, nothe that there is an optional prefix 
   // add libraries, nothe that there is an optional prefix 
   // of debug and optimized than can be used
   // of debug and optimized than can be used
   for(std::vector<std::string>::const_iterator i = args.begin();
   for(std::vector<std::string>::const_iterator i = args.begin();

+ 183 - 6
Source/cmListFileCache.cxx

@@ -16,7 +16,7 @@
 =========================================================================*/
 =========================================================================*/
 #include "cmListFileCache.h"
 #include "cmListFileCache.h"
 #include "cmSystemTools.h"
 #include "cmSystemTools.h"
-
+#include "cmRegularExpression.h"
 
 
 cmListFileCache* cmListFileCache::Instance = 0;
 cmListFileCache* cmListFileCache::Instance = 0;
 
 
@@ -89,17 +89,17 @@ bool cmListFileCache::CacheFile(const char* path, bool requireProjectCommand)
     cmSystemTools::Error("cmListFileCache: error can not open file ", path);
     cmSystemTools::Error("cmListFileCache: error can not open file ", path);
     return false;
     return false;
     }
     }
+  long line=0;
   cmListFile inFile;
   cmListFile inFile;
   inFile.m_ModifiedTime = cmSystemTools::ModifiedTime(path);
   inFile.m_ModifiedTime = cmSystemTools::ModifiedTime(path);
   bool parseError;
   bool parseError;
   while ( fin )
   while ( fin )
     {
     {
     cmListFileFunction inFunction;
     cmListFileFunction inFunction;
-    if(cmSystemTools::ParseFunction(fin, 
-                                    inFunction.m_Name,
-                                    inFunction.m_Arguments,
-                                    path, parseError))
+    if(cmListFileCache::ParseFunction(fin, inFunction, path, parseError,
+                                      &line))
       {
       {
+      inFunction.m_FilePath = path;
       inFile.m_Functions.push_back(inFunction);
       inFile.m_Functions.push_back(inFunction);
       }
       }
     if (parseError)
     if (parseError)
@@ -126,7 +126,8 @@ bool cmListFileCache::CacheFile(const char* path, bool requireProjectCommand)
       {
       {
       cmListFileFunction project;
       cmListFileFunction project;
       project.m_Name = "PROJECT";
       project.m_Name = "PROJECT";
-      project.m_Arguments.push_back("Project");
+      cmListFileArgument prj("Project", false);
+      project.m_Arguments.push_back(prj);
       inFile.m_Functions.insert(inFile.m_Functions.begin(),project);
       inFile.m_Functions.insert(inFile.m_Functions.begin(),project);
       }
       }
     }
     }
@@ -143,3 +144,179 @@ void cmListFileCache::FlushCache(const char* path)
     return;
     return;
     }
     }
 }
 }
+
+inline void RemoveComments(char* ptr)
+{
+  while(*ptr)
+    {
+    if(*ptr == '#')
+      {
+      *ptr = 0;
+      break;
+      }
+    ++ptr;
+    }
+}
+
+bool cmListFileCache::ParseFunction(std::ifstream& fin,
+                                    cmListFileFunction& function,
+                                    const char* filename,
+                                    bool& parseError,
+                                    long* line)
+{
+  parseError = false;
+  std::string& name = function.m_Name;
+  std::vector<cmListFileArgument>& arguments = function.m_Arguments;
+  name = "";
+  arguments = std::vector<cmListFileArgument>();
+  const int BUFFER_SIZE = 4096;
+  char inbuffer[BUFFER_SIZE];
+  if(!fin)
+    {
+    return false;
+    }
+  if(fin.getline(inbuffer, BUFFER_SIZE ) )
+    {
+    if(line) { ++*line; }
+    RemoveComments(inbuffer);
+    cmRegularExpression blankLine("^[ \t\r]*$");
+    cmRegularExpression oneLiner("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)\\)[ \t\r]*$");
+    cmRegularExpression multiLine("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)$");
+    cmRegularExpression lastLine("^(.*)\\)[ \t\r]*$");
+
+    // check for blank line or comment
+    if(blankLine.find(inbuffer) )
+      {
+      return false;
+      }
+    // look for a oneline fun(arg arg2) 
+    else if(oneLiner.find(inbuffer))
+      {
+      // the arguments are the second match
+      std::string args = oneLiner.match(2);
+      name = oneLiner.match(1);
+      // break up the arguments
+      cmListFileCache::GetArguments(args, arguments);
+      if(line)
+        {
+        function.m_Line = *line;
+        }
+      return true;
+      }
+    // look for a start of a multiline with no trailing ")"  fun(arg arg2 
+    else if(multiLine.find(inbuffer))
+      {
+      name = multiLine.match(1);
+      std::string args = multiLine.match(2);
+      cmListFileCache::GetArguments(args, arguments);
+      if(line)
+        {
+        function.m_Line = *line;
+        }
+      // Read lines until the closing paren is hit
+      bool done = false;
+      while(!done)
+        {
+        // read lines until the end paren is found
+        if(fin.getline(inbuffer, BUFFER_SIZE ) )
+          {
+          ++line;
+          RemoveComments(inbuffer);
+          // Check for comment lines and ignore them.
+          if(blankLine.find(inbuffer))
+            { continue; }
+          // Is this the last line?
+          if(lastLine.find(inbuffer))
+            {
+            done = true;
+            std::string gargs = lastLine.match(1);
+            cmListFileCache::GetArguments(gargs, arguments);
+            }
+          else
+            {
+            std::string line = inbuffer;
+            cmListFileCache::GetArguments(line, arguments);
+            }
+          }
+        else
+          {
+          parseError = true;
+          cmSystemTools::Error("Parse error in read function missing end )\nIn File: ",
+                               filename, "\nCurrent line:", inbuffer);
+          return false;
+          }
+        }
+      return true;
+      }
+    else
+      {
+      parseError = true;
+      cmSystemTools::Error("Parse error in read function\nIn file:", 
+                           filename, "\nCurrent line:", inbuffer);
+      return false;
+      }
+    }
+  return false;
+
+}
+
+void cmListFileCache::GetArguments(std::string& line,
+                                 std::vector<cmListFileArgument>& arguments)
+{
+  // Match a normal argument (not quoted, no spaces).
+  cmRegularExpression normalArgument("[ \t]*(([^ \t\r\\]|[\\].)+)[ \t\r]*");
+  // Match a quoted argument (surrounded by double quotes, spaces allowed).
+  cmRegularExpression quotedArgument("[ \t]*(\"([^\"\\]|[\\].)*\")[ \t\r]*");
+
+  bool done = false;
+  while(!done)
+    {
+    std::string arg;
+    std::string::size_type endpos=0;
+    bool quoted = false;
+    bool foundQuoted = quotedArgument.find(line.c_str());
+    bool foundNormal = normalArgument.find(line.c_str());
+
+    if(foundQuoted && foundNormal)
+      {
+      // Both matches were found.  Take the earlier one.
+      // Favor double-quoted version if there is a tie.
+      if(normalArgument.start(1) < quotedArgument.start(1))
+        {
+        arg = normalArgument.match(1);
+        endpos = normalArgument.end(1);
+        }
+      else
+        {
+        arg = quotedArgument.match(1);
+        endpos = quotedArgument.end(1);
+        // Strip off the double quotes on the ends.
+        arg = arg.substr(1, arg.length()-2);
+        quoted = true;
+        }
+      }    
+    else if(foundQuoted)
+      {
+      arg = quotedArgument.match(1);
+      endpos = quotedArgument.end(1);
+      // Strip off the double quotes on the ends.
+      arg = arg.substr(1, arg.length()-2);
+      quoted = true;
+      }
+    else if(foundNormal)
+      {
+      arg = normalArgument.match(1);
+      endpos = normalArgument.end(1);
+      }
+    else
+      {
+      done = true;
+      }
+    if(!done)
+      {
+      cmListFileArgument a(cmSystemTools::RemoveEscapes(arg.c_str()), quoted);
+      arguments.push_back(a);
+      line = line.substr(endpos, line.length() - endpos);
+      }
+    }
+}

+ 34 - 1
Source/cmListFileCache.h

@@ -26,10 +26,25 @@
  * cmake list files.
  * cmake list files.
  */
  */
 
 
+struct cmListFileArgument
+{
+  cmListFileArgument(): Value(), Quoted(false) {}
+  cmListFileArgument(const cmListFileArgument& r): Value(r.Value), Quoted(r.Quoted) {}
+  cmListFileArgument(const std::string& v, bool q): Value(v), Quoted(q) {}
+  bool operator == (const cmListFileArgument& r) const
+    {
+    return (this->Value == r.Value) && (this->Quoted == r.Quoted);
+    }
+  std::string Value;
+  bool Quoted;
+};
+
 struct cmListFileFunction
 struct cmListFileFunction
 {
 {
   std::string m_Name;
   std::string m_Name;
-  std::vector<std::string> m_Arguments;
+  std::vector<cmListFileArgument> m_Arguments;
+  std::string m_FilePath;
+  long m_Line;
 };
 };
 
 
 struct cmListFile
 struct cmListFile
@@ -60,7 +75,25 @@ public:
 
 
   //! Flush cache file out of cache.
   //! Flush cache file out of cache.
   void FlushCache(const char* path);
   void FlushCache(const char* path);
+    
+  /**
+   * Read a CMake command (or function) from an input file.  This
+   * returns the name of the function and a list of its 
+   * arguments.  The last argument is the name of the file that 
+   * the ifstream points to, and is used for debug info only.
+   */
+  static bool ParseFunction(std::ifstream&, cmListFileFunction& function,
+                            const char* filename, bool& parseError,
+                            long* line = 0);
 
 
+  /**
+   *  Extract white-space separated arguments from a string.
+   *  Double quoted strings are accepted with spaces.
+   *  This is called by ParseFunction.
+   */
+  static void GetArguments(std::string& line,
+                           std::vector<cmListFileArgument>& arguments);
+  
 private:
 private:
   // Cache the file
   // Cache the file
   bool CacheFile(const char* path, bool requireProjectCommand);
   bool CacheFile(const char* path, bool requireProjectCommand);

+ 2 - 4
Source/cmLoadCacheCommand.cxx

@@ -18,14 +18,12 @@
 
 
 
 
 // cmLoadCacheCommand
 // cmLoadCacheCommand
-bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if (argsIn.size()< 1)
+  if (args.size()< 1)
     {
     {
     this->SetError("called with wrong number of arguments.");
     this->SetError("called with wrong number of arguments.");
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   if(args.size() >= 2 && args[1] == "READ_WITH_PREFIX")
   if(args.size() >= 2 && args[1] == "READ_WITH_PREFIX")
     {
     {

+ 4 - 6
Source/cmLoadCommandCommand.cxx

@@ -166,18 +166,16 @@ cmLoadedCommand::~cmLoadedCommand()
 }
 }
 
 
 // cmLoadCommandCommand
 // cmLoadCommandCommand
-bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 1 )
+  if(args.size() < 1 )
     {
     {
     return true;
     return true;
     }
     }
   
   
   // the file must exist
   // the file must exist
   std::string fullPath = cmDynamicLoader::LibPrefix();
   std::string fullPath = cmDynamicLoader::LibPrefix();
-  fullPath += "cm" + argsIn[0] + cmDynamicLoader::LibExtension();
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
+  fullPath += "cm" + args[0] + cmDynamicLoader::LibExtension();
 
 
   // search for the file
   // search for the file
   std::vector<std::string> path;
   std::vector<std::string> path;
@@ -197,7 +195,7 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& argsIn)
     {
     {
     fullPath = "Attempt to load command failed from file : ";
     fullPath = "Attempt to load command failed from file : ";
     fullPath += cmDynamicLoader::LibPrefix();
     fullPath += cmDynamicLoader::LibPrefix();
-    fullPath += "cm" + argsIn[0] + cmDynamicLoader::LibExtension();
+    fullPath += "cm" + args[0] + cmDynamicLoader::LibExtension();
     this->SetError(fullPath.c_str());
     this->SetError(fullPath.c_str());
     return false;
     return false;
     }
     }

+ 3 - 3
Source/cmLocalUnixMakefileGenerator.cxx

@@ -812,7 +812,7 @@ void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout,
   // expand multi-command semi-colon separated lists
   // expand multi-command semi-colon separated lists
   // of commands into separate commands
   // of commands into separate commands
   std::vector<std::string> commands;
   std::vector<std::string> commands;
-  cmSystemTools::ExpandListArguments(rules, commands);
+  cmSystemTools::ExpandList(rules, commands);
   // collect custom commands for this target and add them to the list
   // collect custom commands for this target and add them to the list
   std::string customCommands = this->CreateTargetRules(t, name);
   std::string customCommands = this->CreateTargetRules(t, name);
   if(customCommands.size() > 0)
   if(customCommands.size() > 0)
@@ -986,7 +986,7 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout,
   std::string comment = "executable";
   std::string comment = "executable";
   
   
   std::vector<std::string> commands;
   std::vector<std::string> commands;
-  cmSystemTools::ExpandListArguments(rules, commands);
+  cmSystemTools::ExpandList(rules, commands);
   std::string customCommands = this->CreateTargetRules(t, name);
   std::string customCommands = this->CreateTargetRules(t, name);
   if(customCommands.size() > 0)
   if(customCommands.size() > 0)
     {
     {
@@ -2339,7 +2339,7 @@ OutputBuildObjectFromSource(std::ostream& fout,
   // expand multi-command semi-colon separated lists
   // expand multi-command semi-colon separated lists
   // of commands into separate commands
   // of commands into separate commands
   std::vector<std::string> commands;
   std::vector<std::string> commands;
-  cmSystemTools::ExpandListArguments(rules, commands);
+  cmSystemTools::ExpandList(rules, commands);
   for(std::vector<std::string>::iterator i = commands.begin();
   for(std::vector<std::string>::iterator i = commands.begin();
       i != commands.end(); ++i)
       i != commands.end(); ++i)
     {
     {

+ 33 - 36
Source/cmMacroCommand.cxx

@@ -17,66 +17,67 @@
 #include "cmMacroCommand.h"
 #include "cmMacroCommand.h"
 
 
 bool cmMacroFunctionBlocker::
 bool cmMacroFunctionBlocker::
-IsFunctionBlocked(const char *name, const std::vector<std::string> &args, 
-                  cmMakefile &mf) 
+IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf) 
 {
 {
   // record commands until we hit the ENDMACRO
   // record commands until we hit the ENDMACRO
   // at the ENDMACRO call we shift gears and start looking for invocations
   // at the ENDMACRO call we shift gears and start looking for invocations
-  if (!strcmp(name,"ENDMACRO") && args[0] == m_Args[0])
+  if(lff.m_Name == "ENDMACRO")
     {
     {
-    m_Executing = true;
-    return true;
+    std::vector<std::string> expandedArguments;
+    mf.ExpandArguments(lff.m_Arguments, expandedArguments);
+    if(!expandedArguments.empty() && (expandedArguments[0] == m_Args[0]))
+      {
+      m_Executing = true;
+      return true;
+      }
     }
     }
   
   
   if (!m_Executing)
   if (!m_Executing)
     {
     {
     // if it wasn't an endmacro and we are not executing then we must be
     // if it wasn't an endmacro and we are not executing then we must be
     // recording
     // recording
-    m_Commands.push_back(name);
-    std::vector<std::string> newArgs;
-    for(std::vector<std::string>::const_iterator j = args.begin();
-        j != args.end(); ++j)
-      {   
-      newArgs.push_back(*j);
-      }
-    m_CommandArguments.push_back(newArgs);
+    m_Functions.push_back(lff);
     return true;
     return true;
     }
     }
   
   
   // otherwise the macro has been recorded and we are executing
   // otherwise the macro has been recorded and we are executing
   // so we look for macro invocations
   // so we look for macro invocations
-  if (!strcmp(name,m_Args[0].c_str()))
+  if(lff.m_Name == m_Args[0])
     {
     {
+    // 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
     // make sure the number of arguments matches
-    if (args.size() != m_Args.size() - 1)
+    if (expandedArguments.size() != m_Args.size() - 1)
       {
       {
       cmSystemTools::Error("A macro was invoked without the correct number of arguments. The macro name was: ", m_Args[0].c_str());
       cmSystemTools::Error("A macro was invoked without the correct number of arguments. The macro name was: ", m_Args[0].c_str());
       }
       }
-    // for each recorded command
-    for(unsigned int c = 0; c < m_Commands.size(); ++c)
+    
+    // Invoke all the functions that were collected in the block.
+    for(unsigned int c = 0; c < m_Functions.size(); ++c)
       {
       {
-      // perform argument replacement
-      std::vector<std::string> newArgs;
-      // for each argument of this command
-      for (std::vector<std::string>::const_iterator k = 
-             m_CommandArguments[c].begin();
-           k != m_CommandArguments[c].end(); ++k)
+      // Replace the formal arguments and then invoke the command.
+      cmListFileFunction newLFF;
+      newLFF.m_Name = m_Functions[c].m_Name;
+      for (std::vector<cmListFileArgument>::const_iterator k = 
+             m_Functions[c].m_Arguments.begin();
+           k != m_Functions[c].m_Arguments.end(); ++k)
         {
         {
-        // replace any matches with the formal arguments
-        std::string tmps = *k;
-        // for each formal macro argument
+        std::string tmps = k->Value;
         for (unsigned int j = 1; j < m_Args.size(); ++j)
         for (unsigned int j = 1; j < m_Args.size(); ++j)
           {
           {
           std::string variable = "${";
           std::string variable = "${";
           variable += m_Args[j];
           variable += m_Args[j];
           variable += "}"; 
           variable += "}"; 
           cmSystemTools::ReplaceString(tmps, variable.c_str(),
           cmSystemTools::ReplaceString(tmps, variable.c_str(),
-                                       args[j-1].c_str());
+                                       expandedArguments[j-1].c_str());
           }
           }
-        newArgs.push_back(tmps);
+        cmListFileArgument arg(tmps, k->Quoted);
+        newLFF.m_Arguments.push_back(arg);
+        newLFF.m_FilePath = m_Functions[c].m_FilePath;
+        newLFF.m_Line = m_Functions[c].m_Line;
         }
         }
-      // execute command
-      mf.ExecuteCommand(m_Commands[c],newArgs);
+      mf.ExecuteCommand(newLFF);
       }
       }
     return true;
     return true;
     }
     }
@@ -86,8 +87,7 @@ IsFunctionBlocked(const char *name, const std::vector<std::string> &args,
 }
 }
 
 
 bool cmMacroFunctionBlocker::
 bool cmMacroFunctionBlocker::
-ShouldRemove(const char *, const std::vector<std::string> &, 
-             cmMakefile &) 
+ShouldRemove(const cmListFileFunction&, cmMakefile &) 
 {
 {
   return false;
   return false;
 }
 }
@@ -98,11 +98,8 @@ ScopeEnded(cmMakefile &)
   // macros never leave scope
   // macros never leave scope
 }
 }
 
 
-bool cmMacroCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmMacroCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
-
   if(args.size() < 1)
   if(args.size() < 1)
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");

+ 3 - 10
Source/cmMacroCommand.h

@@ -31,19 +31,12 @@ class cmMacroFunctionBlocker : public cmFunctionBlocker
 public:
 public:
   cmMacroFunctionBlocker() {m_Executing = false;}
   cmMacroFunctionBlocker() {m_Executing = false;}
   virtual ~cmMacroFunctionBlocker() {}
   virtual ~cmMacroFunctionBlocker() {}
-  virtual bool IsFunctionBlocked(const char *name, 
-                                 const std::vector<std::string> &args, 
-                                 cmMakefile &mf);
-  virtual bool ShouldRemove(const char *name, 
-                            const std::vector<std::string> &args, 
-                            cmMakefile &mf);
+  virtual bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile &mf);
+  virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile &mf);
   virtual void ScopeEnded(cmMakefile &mf);
   virtual void ScopeEnded(cmMakefile &mf);
   
   
-  virtual int NeedExpandedVariables () { return 0; };
-
   std::vector<std::string> m_Args;
   std::vector<std::string> m_Args;
-  std::vector<std::string> m_Commands;
-  std::vector<std::vector<std::string> > m_CommandArguments;
+  std::vector<cmListFileFunction> m_Functions;
   bool m_Executing;
   bool m_Executing;
 };
 };
 
 

+ 48 - 68
Source/cmMakefile.cxx

@@ -157,14 +157,14 @@ bool cmMakefile::CommandExists(const char* name) const
   return m_LocalGenerator->GetGlobalGenerator()->GetCMakeInstance()->CommandExists(name);
   return m_LocalGenerator->GetGlobalGenerator()->GetCMakeInstance()->CommandExists(name);
 }
 }
       
       
-void cmMakefile::ExecuteCommand(std::string const &name,
-                                std::vector<std::string> const& arguments)
+void cmMakefile::ExecuteCommand(const cmListFileFunction& lff)
 {
 {
   // quick return if blocked
   // quick return if blocked
-  if(this->IsFunctionBlocked(name.c_str(), arguments))
+  if(this->IsFunctionBlocked(lff))
     {
     {
     return;
     return;
     }
     }
+  std::string name = lff.m_Name;
   // execute the command
   // execute the command
   cmCommand *rm = 
   cmCommand *rm = 
     m_LocalGenerator->GetGlobalGenerator()->GetCMakeInstance()->GetCommand(name.c_str());
     m_LocalGenerator->GetGlobalGenerator()->GetCMakeInstance()->GetCommand(name.c_str());
@@ -179,27 +179,13 @@ void cmMakefile::ExecuteCommand(std::string const &name,
       // if the command is inherited then InitialPass it.
       // if the command is inherited then InitialPass it.
       if(!m_Inheriting || usedCommand->IsInherited())
       if(!m_Inheriting || usedCommand->IsInherited())
         {
         {
-        std::vector<std::string> expandedArguments;
-        for(std::vector<std::string>::const_iterator i = arguments.begin();
-            i != arguments.end(); ++i)
+        if(!usedCommand->InvokeInitialPass(lff.m_Arguments))
           {
           {
-          std::string tmps = *i;
-          this->ExpandVariablesInString(tmps);
-          if (tmps.find_first_not_of(" ") != std::string::npos)
-            {
-            // we found something in the args
-            expandedArguments.push_back(tmps);
-            }
-          }
-        if(!usedCommand->InitialPass(expandedArguments))
-          {
-          std::string error;
-          error = usedCommand->GetName();
-          error += ": Error : \n";
-          error += usedCommand->GetError();
-          error += " from CMakeLists.txt file in directory: ";
-          error += m_cmCurrentDirectory;
-          cmSystemTools::Error(error.c_str());
+          cmOStringStream error;
+          error << "Error in cmake code at\n"
+                << lff.m_FilePath << ":" << lff.m_Line << ":\n"
+                << usedCommand->GetError();
+          cmSystemTools::Error(error.str().c_str());
           }
           }
         else
         else
           {
           {
@@ -216,18 +202,13 @@ void cmMakefile::ExecuteCommand(std::string const &name,
       delete usedCommand;
       delete usedCommand;
       }
       }
     }
     }
-  else if((name == "CABLE_WRAP_TCL") || (name == "CABLE_CLASS_SET") ||
-          (name == "CONFIGURE_GCCXML"))
-    {
-    cmSystemTools::Error("The command ", name.c_str(),
-                         " is not implemented in this version of CMake.\n"
-                         "Contact [email protected] for more information.");
-    }
   else
   else
     {
     {
-    cmSystemTools::Error("unknown CMake command:", name.c_str(), 
-                         "\nReading cmake file in directory:" , 
-                         m_cmCurrentDirectory.c_str());
+    cmOStringStream error;
+    error << "Error in cmake code at\n"
+          << lff.m_FilePath << ":" << lff.m_Line << ":\n"
+          << "Unknown CMake command \"" << lff.m_Name.c_str() << "\".";
+    cmSystemTools::Error(error.str().c_str());
     }
     }
 }
 }
 
 
@@ -335,9 +316,7 @@ bool cmMakefile::ReadListFile(const char* filename, const char* external)
   const size_t numberFunctions = lf->m_Functions.size();
   const size_t numberFunctions = lf->m_Functions.size();
   for(size_t i =0; i < numberFunctions; ++i)
   for(size_t i =0; i < numberFunctions; ++i)
     {
     {
-    cmListFileFunction& curFunction = lf->m_Functions[i];
-    this->ExecuteCommand(curFunction.m_Name,
-                         curFunction.m_Arguments);
+    this->ExecuteCommand(lf->m_Functions[i]);
     }
     }
 
 
   // send scope ended to and funciton blockers
   // send scope ended to and funciton blockers
@@ -1161,8 +1140,7 @@ cmMakefile::FindSourceGroup(const char* source,
   return groups.front();
   return groups.front();
 }
 }
 
 
-bool cmMakefile::IsFunctionBlocked(const char *name,
-                                   std::vector<std::string> const&args)
+bool cmMakefile::IsFunctionBlocked(const cmListFileFunction& lff)
 {
 {
   // if there are no blockers get out of here
   // if there are no blockers get out of here
   if (m_FunctionBlockers.begin() == m_FunctionBlockers.end())
   if (m_FunctionBlockers.begin() == m_FunctionBlockers.end())
@@ -1171,51 +1149,52 @@ bool cmMakefile::IsFunctionBlocked(const char *name,
     }
     }
 
 
   // loop over all function blockers to see if any block this command
   // loop over all function blockers to see if any block this command
-  std::vector<std::string> expandedArguments;
-  for(std::vector<std::string>::const_iterator i = args.begin();
-      i != args.end(); ++i)
-    {
-    std::string tmps = *i;
-    this->ExpandVariablesInString(tmps);
-    if (tmps.find_first_not_of(" ") != std::string::npos)
-      {
-      // we found something in the args
-      expandedArguments.push_back(tmps);
-      }
-    }
   // evaluate in reverse, this is critical for balanced IF statements etc
   // evaluate in reverse, this is critical for balanced IF statements etc
   std::list<cmFunctionBlocker *>::reverse_iterator pos;
   std::list<cmFunctionBlocker *>::reverse_iterator pos;
   for (pos = m_FunctionBlockers.rbegin(); 
   for (pos = m_FunctionBlockers.rbegin(); 
        pos != m_FunctionBlockers.rend(); ++pos)
        pos != m_FunctionBlockers.rend(); ++pos)
     {
     {
-    if ((*pos)->NeedExpandedVariables()) 
+    if((*pos)->IsFunctionBlocked(lff, *this))
       {
       {
-      if ((*pos)->IsFunctionBlocked(name, expandedArguments, *this))
-        {
-        return true;
-        }
+      return true;
+      }
+    }
+  
+  return false;
+}
+
+void cmMakefile::ExpandArguments(
+  std::vector<cmListFileArgument> const& inArgs,
+  std::vector<std::string>& outArgs)
+{
+  std::vector<cmListFileArgument>::const_iterator i;
+  for(i = inArgs.begin(); i != inArgs.end(); ++i)
+    {
+    // Expand the variables in the argument.
+    std::string value = i->Value;
+    this->ExpandVariablesInString(value);
+    
+    // If the argument is quoted, it should be one argument.
+    // Otherwise, it may be a list of arguments.
+    if(i->Quoted)
+      {
+      outArgs.push_back(value);
       }
       }
     else
     else
       {
       {
-      if ((*pos)->IsFunctionBlocked(name, args, *this))
-        {
-        return true;
-        }
+      cmSystemTools::ExpandListArgument(value, outArgs);
       }
       }
     }
     }
-  
-  return false;
 }
 }
 
 
-void cmMakefile::RemoveFunctionBlocker(const char *name,
-                                       const std::vector<std::string> &args)
+void cmMakefile::RemoveFunctionBlocker(const cmListFileFunction& lff)
 {
 {
   // loop over all function blockers to see if any block this command
   // loop over all function blockers to see if any block this command
   std::list<cmFunctionBlocker *>::reverse_iterator pos;
   std::list<cmFunctionBlocker *>::reverse_iterator pos;
   for (pos = m_FunctionBlockers.rbegin(); 
   for (pos = m_FunctionBlockers.rbegin(); 
        pos != m_FunctionBlockers.rend(); ++pos)
        pos != m_FunctionBlockers.rend(); ++pos)
     {
     {
-    if ((*pos)->ShouldRemove(name, args, *this))
+    if ((*pos)->ShouldRemove(lff, *this))
       {
       {
       cmFunctionBlocker* b = *pos;
       cmFunctionBlocker* b = *pos;
       m_FunctionBlockers.remove(b);
       m_FunctionBlockers.remove(b);
@@ -1348,7 +1327,6 @@ void cmMakefile::ExpandSourceListArguments(
     }
     }
   
   
   // now expand the args
   // now expand the args
-  std::vector<std::string> tmpArgs;
   unsigned int i;
   unsigned int i;
   for(i = 0; i < arguments.size(); ++i)
   for(i = 0; i < arguments.size(); ++i)
     {
     {
@@ -1356,14 +1334,16 @@ void cmMakefile::ExpandSourceListArguments(
     const char *def = this->GetDefinition(arguments[i].c_str());
     const char *def = this->GetDefinition(arguments[i].c_str());
     if (def && oldVersion && i >= start)
     if (def && oldVersion && i >= start)
       {
       {
-      tmpArgs.push_back(def);
+      // Definition lookup could result in a list that needs to be
+      // expanded.
+      cmSystemTools::ExpandListArgument(def, newargs);
       }
       }
     else
     else
       {
       {
-      tmpArgs.push_back(arguments[i]);
+      // List expansion will have been done already.
+      newargs.push_back(arguments[i]);
       }
       }
     }
     }
-  cmSystemTools::ExpandListArguments(tmpArgs, newargs);
 }
 }
 
 
 int cmMakefile::TryCompile(const char *srcdir, const char *bindir, 
 int cmMakefile::TryCompile(const char *srcdir, const char *bindir, 

+ 11 - 3
Source/cmMakefile.h

@@ -22,6 +22,7 @@
 #include "cmSystemTools.h"
 #include "cmSystemTools.h"
 #include "cmSourceGroup.h"
 #include "cmSourceGroup.h"
 #include "cmTarget.h"
 #include "cmTarget.h"
+#include "cmListFileCache.h"
 #include "cmCacheManager.h"
 #include "cmCacheManager.h"
 
 
 class cmFunctionBlocker;
 class cmFunctionBlocker;
@@ -77,7 +78,7 @@ public:
     { m_FunctionBlockers.push_back(fb);}
     { m_FunctionBlockers.push_back(fb);}
   void RemoveFunctionBlocker(cmFunctionBlocker *fb)
   void RemoveFunctionBlocker(cmFunctionBlocker *fb)
     { m_FunctionBlockers.remove(fb);}
     { m_FunctionBlockers.remove(fb);}
-  void RemoveFunctionBlocker(const char *name, const std::vector<std::string> &args);
+  void RemoveFunctionBlocker(const cmListFileFunction& lff);
   
   
   /**
   /**
    * Try running cmake and building a file. This is used for dynalically
    * Try running cmake and building a file. This is used for dynalically
@@ -511,7 +512,7 @@ public:
   /**
   /**
    * execute a single CMake command
    * execute a single CMake command
    */
    */
-  void ExecuteCommand(std::string const &name, std::vector<std::string> const& args);
+  void ExecuteCommand(const cmListFileFunction& lff);
   
   
   /** Check if a command exists. */
   /** Check if a command exists. */
   bool CommandExists(const char* name) const;
   bool CommandExists(const char* name) const;
@@ -535,6 +536,13 @@ public:
 
 
   ///! Display progress or status message.
   ///! Display progress or status message.
   void DisplayStatus(const char*, float);
   void DisplayStatus(const char*, float);
+  
+  /**
+   * Expand the given list file arguments into the full set after
+   * variable replacement and list expansion.
+   */
+  void ExpandArguments(std::vector<cmListFileArgument> const& inArgs,
+                       std::vector<std::string>& outArgs);
 protected:
 protected:
   // add link libraries and directories to the target
   // add link libraries and directories to the target
   void AddGlobalLinkInformation(const char* name, cmTarget& target);
   void AddGlobalLinkInformation(const char* name, cmTarget& target);
@@ -581,7 +589,7 @@ protected:
   DefinitionMap m_Definitions;
   DefinitionMap m_Definitions;
   std::vector<cmCommand*> m_UsedCommands;
   std::vector<cmCommand*> m_UsedCommands;
   cmLocalGenerator* m_LocalGenerator;
   cmLocalGenerator* m_LocalGenerator;
-  bool IsFunctionBlocked(const char *name, std::vector<std::string> const& args);
+  bool IsFunctionBlocked(const cmListFileFunction& lff);
   
   
 private:
 private:
   /**
   /**

+ 2 - 4
Source/cmMarkAsAdvancedCommand.cxx

@@ -17,15 +17,13 @@
 #include "cmMarkAsAdvancedCommand.h"
 #include "cmMarkAsAdvancedCommand.h"
 
 
 // cmMarkAsAdvancedCommand
 // cmMarkAsAdvancedCommand
-bool cmMarkAsAdvancedCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmMarkAsAdvancedCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 1 )
+  if(args.size() < 1 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   unsigned int i =0;
   unsigned int i =0;
   const char* value = "1";
   const char* value = "1";

+ 2 - 4
Source/cmMessageCommand.cxx

@@ -17,15 +17,13 @@
 #include "cmMessageCommand.h"
 #include "cmMessageCommand.h"
 
 
 // cmLibraryCommand
 // cmLibraryCommand
-bool cmMessageCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmMessageCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 1 )
+  if(args.size() < 1 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
   std::string message;
   std::string message;
   std::vector<std::string>::const_iterator i = args.begin();
   std::vector<std::string>::const_iterator i = args.begin();
 
 

+ 2 - 4
Source/cmProjectCommand.cxx

@@ -17,15 +17,13 @@
 #include "cmProjectCommand.h"
 #include "cmProjectCommand.h"
 
 
 // cmProjectCommand
 // cmProjectCommand
-bool cmProjectCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmProjectCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 1 )
+  if(args.size() < 1 )
     {
     {
     this->SetError("PROJECT called with incorrect number of arguments");
     this->SetError("PROJECT called with incorrect number of arguments");
     return false;
     return false;
     } 
     } 
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
   m_Makefile->SetProjectName(args[0].c_str());
   m_Makefile->SetProjectName(args[0].c_str());
 
 
   std::string bindir = args[0];
   std::string bindir = args[0];

+ 4 - 6
Source/cmRemoveCommand.cxx

@@ -37,19 +37,17 @@ bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args)
   
   
   // expand the variable
   // expand the variable
   std::vector<std::string> varArgsExpanded;
   std::vector<std::string> varArgsExpanded;
-  std::vector<std::string> temp;
-  temp.push_back(std::string(cacheValue));
-  cmSystemTools::ExpandListArguments(temp, varArgsExpanded);
+  cmSystemTools::ExpandListArgument(cacheValue, varArgsExpanded);
   
   
   // expand the args
   // expand the args
   // check for REMOVE(VAR v1 v2 ... vn) 
   // check for REMOVE(VAR v1 v2 ... vn) 
   std::vector<std::string> argsExpanded;
   std::vector<std::string> argsExpanded;
-  std::vector<std::string> temp2;
+  std::vector<std::string> temp;
   for(unsigned int j = 1; j < args.size(); ++j)
   for(unsigned int j = 1; j < args.size(); ++j)
     {
     {
-    temp2.push_back(args[j]);
+    temp.push_back(args[j]);
     }
     }
-  cmSystemTools::ExpandListArguments(temp2, argsExpanded);
+  cmSystemTools::ExpandList(temp, argsExpanded);
   
   
   // now create the new value
   // now create the new value
   std::string value;
   std::string value;

+ 2 - 4
Source/cmSetSourceFilesPropertiesCommand.cxx

@@ -18,15 +18,13 @@
 
 
 // cmSetSourceFilesPropertiesCommand
 // cmSetSourceFilesPropertiesCommand
 bool cmSetSourceFilesPropertiesCommand::InitialPass(
 bool cmSetSourceFilesPropertiesCommand::InitialPass(
-  std::vector<std::string> const& argsIn)
+  std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 2 )
+  if(args.size() < 2 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   // first collect up the list of files
   // first collect up the list of files
   std::vector<std::string> propertyPairs;
   std::vector<std::string> propertyPairs;

+ 2 - 4
Source/cmSourceFilesCommand.cxx

@@ -17,7 +17,7 @@
 #include "cmSourceFilesCommand.h"
 #include "cmSourceFilesCommand.h"
 
 
 // cmSourceFilesCommand
 // cmSourceFilesCommand
-bool cmSourceFilesCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmSourceFilesCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
   const char* versionValue
   const char* versionValue
     = m_Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
     = m_Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
@@ -27,13 +27,11 @@ bool cmSourceFilesCommand::InitialPass(std::vector<std::string> const& argsIn)
     return false;
     return false;
     }
     }
 
 
-  if(argsIn.size() < 1 )
+  if(args.size() < 1 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
   std::string sourceListValue;
   std::string sourceListValue;
   
   
   // was the list already populated
   // was the list already populated

+ 4 - 6
Source/cmSourceFilesRemoveCommand.cxx

@@ -40,19 +40,17 @@ bool cmSourceFilesRemoveCommand::InitialPass(std::vector<std::string> const& arg
 
 
   // expand the variable
   // expand the variable
   std::vector<std::string> varArgsExpanded;
   std::vector<std::string> varArgsExpanded;
-  std::vector<std::string> temp;
-  temp.push_back(std::string(cacheValue));
-  cmSystemTools::ExpandListArguments(temp, varArgsExpanded);
+  cmSystemTools::ExpandListArgument(cacheValue, varArgsExpanded);
   
   
   // expand the args
   // expand the args
   // check for REMOVE(VAR v1 v2 ... vn) 
   // check for REMOVE(VAR v1 v2 ... vn) 
   std::vector<std::string> argsExpanded;
   std::vector<std::string> argsExpanded;
-  std::vector<std::string> temp2;
+  std::vector<std::string> temp;
   for(unsigned int j = 1; j < args.size(); ++j)
   for(unsigned int j = 1; j < args.size(); ++j)
     {
     {
-    temp2.push_back(args[j]);
+    temp.push_back(args[j]);
     }
     }
-  cmSystemTools::ExpandListArguments(temp2, argsExpanded);
+  cmSystemTools::ExpandList(temp, argsExpanded);
   
   
   // now create the new value
   // now create the new value
   std::string value;
   std::string value;

+ 2 - 4
Source/cmSubdirCommand.cxx

@@ -17,15 +17,13 @@
 #include "cmSubdirCommand.h"
 #include "cmSubdirCommand.h"
 
 
 // cmSubdirCommand
 // cmSubdirCommand
-bool cmSubdirCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmSubdirCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 1 )
+  if(args.size() < 1 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
   bool res = true;
   bool res = true;
 
 
   for(std::vector<std::string>::const_iterator i = args.begin();
   for(std::vector<std::string>::const_iterator i = args.begin();

+ 73 - 224
Source/cmSystemTools.cxx

@@ -843,168 +843,6 @@ std::string cmSystemTools::ConvertToWindowsOutputPath(const char* path)
   return ret;
   return ret;
 }
 }
 
 
-inline void RemoveComments(char* ptr)
-{
-  while(*ptr)
-    {
-    if(*ptr == '#')
-      {
-      *ptr = 0;
-      break;
-      }
-    ++ptr;
-    }
-}
-
-bool cmSystemTools::ParseFunction(std::ifstream& fin,
-                                  std::string& name,
-                                  std::vector<std::string>& arguments,
-                                  const char* filename,
-                                  bool& parseError)
-{
-  parseError = false;
-  name = "";
-  arguments = std::vector<std::string>();
-  const int BUFFER_SIZE = 4096;
-  char inbuffer[BUFFER_SIZE];
-  if(!fin)
-    {
-    return false;
-    }
-  if(fin.getline(inbuffer, BUFFER_SIZE ) )
-    {
-    RemoveComments(inbuffer);
-    cmRegularExpression blankLine("^[ \t\r]*$");
-//    cmRegularExpression comment("^[ \t]*#.*$");
-    cmRegularExpression oneLiner("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)\\)[ \t\r]*$");
-    cmRegularExpression multiLine("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)$");
-    cmRegularExpression lastLine("^(.*)\\)[ \t\r]*$");
-
-    // check for blank line or comment
-    if(blankLine.find(inbuffer) )
-      {
-      return false;
-      }
-    // look for a oneline fun(arg arg2) 
-    else if(oneLiner.find(inbuffer))
-      {
-      // the arguments are the second match
-      std::string args = oneLiner.match(2);
-      name = oneLiner.match(1);
-      // break up the arguments
-      cmSystemTools::GetArguments(args, arguments);
-      return true;
-      }
-    // look for a start of a multiline with no trailing ")"  fun(arg arg2 
-    else if(multiLine.find(inbuffer))
-      {
-      name = multiLine.match(1);
-      std::string args = multiLine.match(2);
-      cmSystemTools::GetArguments(args, arguments);
-      // Read lines until the closing paren is hit
-      bool done = false;
-      while(!done)
-        {
-        // read lines until the end paren is found
-        if(fin.getline(inbuffer, BUFFER_SIZE ) )
-          {
-          RemoveComments(inbuffer);
-          // Check for comment lines and ignore them.
-          if(blankLine.find(inbuffer))
-            { continue; }
-          // Is this the last line?
-          if(lastLine.find(inbuffer))
-            {
-            done = true;
-            std::string gargs = lastLine.match(1);
-            cmSystemTools::GetArguments(gargs, arguments);
-            }
-          else
-            {
-            std::string line = inbuffer;
-            cmSystemTools::GetArguments(line, arguments);
-            }
-          }
-        else
-          {
-          parseError = true;
-          cmSystemTools::Error("Parse error in read function missing end )\nIn File: ",
-                               filename, "\nCurrent line:", inbuffer);
-          return false;
-          }
-        }
-      return true;
-      }
-    else
-      {
-      parseError = true;
-      cmSystemTools::Error("Parse error in read function\nIn file:", 
-                           filename, "\nCurrent line:", inbuffer);
-      return false;
-      }
-    }
-  return false;
-
-}
-
-void cmSystemTools::GetArguments(std::string& line,
-                                 std::vector<std::string>& arguments)
-{
-  // Match a normal argument (not quoted, no spaces).
-  cmRegularExpression normalArgument("[ \t]*(([^ \t\r\\]|[\\].)+)[ \t\r]*");
-  // Match a quoted argument (surrounded by double quotes, spaces allowed).
-  cmRegularExpression quotedArgument("[ \t]*(\"([^\"\\]|[\\].)*\")[ \t\r]*");
-
-  bool done = false;
-  while(!done)
-    {
-    std::string arg;
-    std::string::size_type endpos=0;
-    bool foundQuoted = quotedArgument.find(line.c_str());
-    bool foundNormal = normalArgument.find(line.c_str());
-
-    if(foundQuoted && foundNormal)
-      {
-      // Both matches were found.  Take the earlier one.
-      // Favor double-quoted version if there is a tie.
-      if(normalArgument.start(1) < quotedArgument.start(1))
-        {
-        arg = normalArgument.match(1);
-        endpos = normalArgument.end(1);
-        }
-      else
-        {
-        arg = quotedArgument.match(1);
-        endpos = quotedArgument.end(1);
-        // Strip off the double quotes on the ends.
-        arg = arg.substr(1, arg.length()-2);
-        }
-      }    
-    else if (foundQuoted)
-      {
-      arg = quotedArgument.match(1);
-      endpos = quotedArgument.end(1);
-      // Strip off the double quotes on the ends.
-      arg = arg.substr(1, arg.length()-2);
-      }
-    else if(foundNormal)
-      {
-      arg = normalArgument.match(1);
-      endpos = normalArgument.end(1);
-      }
-    else
-      {
-      done = true;
-      }
-    if(!done)
-      {
-      arguments.push_back(cmSystemTools::RemoveEscapes(arg.c_str()));
-      line = line.substr(endpos, line.length() - endpos);
-      }
-    }
-}
-
-
 std::string cmSystemTools::RemoveEscapes(const char* s)
 std::string cmSystemTools::RemoveEscapes(const char* s)
 {
 {
   std::string result = "";
   std::string result = "";
@@ -2141,90 +1979,101 @@ void cmSystemTools::GlobDirs(const char *fullPath,
 }
 }
 
 
 
 
-void cmSystemTools::ExpandListArguments(std::vector<std::string> const& arguments, 
-                                        std::vector<std::string>& newargs)
+void cmSystemTools::ExpandList(std::vector<std::string> const& arguments, 
+                               std::vector<std::string>& newargs)
 {
 {
   std::vector<std::string>::const_iterator i;
   std::vector<std::string>::const_iterator i;
-  std::string newarg;
   for(i = arguments.begin();i != arguments.end(); ++i)
   for(i = arguments.begin();i != arguments.end(); ++i)
     {
     {
-    // if there are no ; in the name then just copy the current string
-    if(i->find(';') == std::string::npos)
-      {
-      newargs.push_back(*i);
-      }
-    else
+    cmSystemTools::ExpandListArgument(*i, newargs);
+    }
+}
+
+void cmSystemTools::ExpandListArgument(const std::string& arg,
+                                       std::vector<std::string>& newargs)
+{
+  std::string newarg;
+  // If argument is empty, it is an empty list.
+  if(arg.length() == 0)
+    {
+    return;
+    }
+  // if there are no ; in the name then just copy the current string
+  if(arg.find(';') == std::string::npos)
+    {
+    newargs.push_back(arg);
+    }
+  else
+    {
+    std::string::size_type start = 0;
+    std::string::size_type endpos = 0;
+    const std::string::size_type size = arg.size();
+    // break up ; separated sections of the string into separate strings
+    while(endpos != size)
       {
       {
-      std::string::size_type start = 0;
-      std::string::size_type endpos = 0;
-      const std::string::size_type size = i->size();
-      // break up ; separated sections of the string into separate strings
-      while(endpos != size)
+      endpos = arg.find(';', start); 
+      if(endpos == std::string::npos)
         {
         {
-        endpos = i->find(';', start); 
+        endpos = arg.size();
+        }
+      else
+        {
+        // skip right over escaped ; ( \; )
+        while((endpos != std::string::npos)
+              && (endpos > 0) 
+              && ((arg)[endpos-1] == '\\') )
+          {
+          endpos = arg.find(';', endpos+1);
+          }
         if(endpos == std::string::npos)
         if(endpos == std::string::npos)
           {
           {
-          endpos = i->size();
+          endpos = arg.size();
           }
           }
-        else
+        }
+      std::string::size_type len = endpos - start;
+      if (len > 0)
+        {
+        // check for a closing ] after the start position
+        if(arg.find('[', start) == std::string::npos)
           {
           {
-          // skip right over escaped ; ( \; )
-          while((endpos != std::string::npos)
-                && (endpos > 0) 
-                && ((*i)[endpos-1] == '\\') )
-            {
-            endpos = i->find(';', endpos+1);
-            }
-          if(endpos == std::string::npos)
-            {
-            endpos = i->size();
-            }
+          // if there is no [ in the string then keep it
+          newarg = arg.substr(start, len);
           }
           }
-        std::string::size_type len = endpos - start;
-        if (len > 0)
+        else
           {
           {
-          // check for a closing ] after the start position
-          if(i->find('[', start) == std::string::npos)
+          int opencount = 0;
+          int closecount = 0;
+          for(std::string::size_type j = start; j < endpos; ++j)
             {
             {
-            // if there is no [ in the string then keep it
-            newarg = i->substr(start, len);
-            }
-          else
-            {
-            int opencount = 0;
-            int closecount = 0;
-            for(std::string::size_type j = start; j < endpos; ++j)
+            if(arg.at(j) == '[')
               {
               {
-              if(i->at(j) == '[')
-                {
-                ++opencount;
-                }
-              else if (i->at(j) == ']')
-                {
-                ++closecount;
-                }
+              ++opencount;
               }
               }
-            if(opencount != closecount)
+            else if (arg.at(j) == ']')
               {
               {
-              // skip this one
-              endpos = i->find(';', endpos+1);  
-              if(endpos == std::string::npos)
-                {
-                endpos = i->size();
-                }
-              len = endpos - start;
+              ++closecount;
               }
               }
-            newarg = i->substr(start, len);
             }
             }
-          std::string::size_type pos = newarg.find("\\;");
-          if(pos != std::string::npos)
+          if(opencount != closecount)
             {
             {
-            newarg.erase(pos, 1);
+            // skip this one
+            endpos = arg.find(';', endpos+1);  
+            if(endpos == std::string::npos)
+              {
+              endpos = arg.size();
+              }
+            len = endpos - start;
             }
             }
-          newargs.push_back(newarg);
+          newarg = arg.substr(start, len);
           }
           }
-        start = endpos+1;
+        std::string::size_type pos = newarg.find("\\;");
+        if(pos != std::string::npos)
+          {
+          newarg.erase(pos, 1);
+          }
+        newargs.push_back(newarg);
         }
         }
+      start = endpos+1;
       }
       }
     }
     }
 }
 }

+ 4 - 22
Source/cmSystemTools.h

@@ -56,8 +56,10 @@ public:
    *  strings into multiple arguements.  A new vector is created 
    *  strings into multiple arguements.  A new vector is created 
    *  containing the expanded versions of all arguments in argsIn.
    *  containing the expanded versions of all arguments in argsIn.
    */
    */
-  static void ExpandListArguments(std::vector<std::string> const& argsIn,
-                                  std::vector<std::string>& argsOut);
+  static void ExpandList(std::vector<std::string> const& argsIn,
+                         std::vector<std::string>& argsOut);
+  static void ExpandListArgument(const std::string& arg,
+                                 std::vector<std::string>& argsOut);
 
 
   /**
   /**
    * Read a registry value
    * Read a registry value
@@ -117,25 +119,6 @@ public:
   
   
   ///! Return true if a file exists in the current directory.
   ///! Return true if a file exists in the current directory.
   static bool FileExists(const char* filename);
   static bool FileExists(const char* filename);
-
-  /**
-   * Read a CMake command (or function) from an input file.  This
-   * returns the name of the function and a list of its 
-   * arguments.  The last argument is the name of the file that 
-   * the ifstream points to, and is used for debug info only.
-   */
-  static bool ParseFunction(std::ifstream&, 
-                            std::string& name,
-                            std::vector<std::string>& arguments,
-                            const char* filename, bool& parseError);
-
-  /**
-   *  Extract white-space separated arguments from a string.
-   *  Double quoted strings are accepted with spaces.
-   *  This is called by ParseFunction.
-   */
-  static void GetArguments(std::string& line,
-                           std::vector<std::string>& arguments);
   
   
   /**
   /**
    * Given a string, replace any escape sequences with the corresponding
    * Given a string, replace any escape sequences with the corresponding
@@ -389,5 +372,4 @@ private:
   static std::string s_Windows9xComspecSubstitute;
   static std::string s_Windows9xComspecSubstitute;
 };
 };
 
 
-
 #endif
 #endif

+ 1 - 3
Source/cmTarget.cxx

@@ -75,10 +75,8 @@ void cmTarget::GenerateSourceFilesFromSourceLists( cmMakefile &mf)
         // if the definition exists
         // if the definition exists
         if (varValue)
         if (varValue)
           {
           {
-          std::vector<std::string> tval;
-          tval.push_back(varValue);
           std::vector<std::string> args;
           std::vector<std::string> args;
-          cmSystemTools::ExpandListArguments(tval, args);
+          cmSystemTools::ExpandListArgument(varValue, args);
           unsigned int i;
           unsigned int i;
           for (i = 0; i < args.size(); ++i)
           for (i = 0; i < args.size(); ++i)
             {
             {

+ 3 - 5
Source/cmTargetLinkLibrariesCommand.cxx

@@ -17,21 +17,19 @@
 #include "cmTargetLinkLibrariesCommand.h"
 #include "cmTargetLinkLibrariesCommand.h"
 
 
 // cmTargetLinkLibrariesCommand
 // cmTargetLinkLibrariesCommand
-bool cmTargetLinkLibrariesCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmTargetLinkLibrariesCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
   // must have one argument
   // must have one argument
-  if(argsIn.size() < 1)
+  if(args.size() < 1)
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
   // but we might not have any libs after variable expansion
   // but we might not have any libs after variable expansion
-  if(argsIn.size() < 2)
+  if(args.size() < 2)
     {
     {
     return true;
     return true;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
   // add libraries, nothe that there is an optional prefix 
   // add libraries, nothe that there is an optional prefix 
   // of debug and optimized than can be used
   // of debug and optimized than can be used
   std::vector<std::string>::const_iterator i = args.begin();
   std::vector<std::string>::const_iterator i = args.begin();

+ 2 - 4
Source/cmUtilitySourceCommand.cxx

@@ -17,15 +17,13 @@
 #include "cmUtilitySourceCommand.h"
 #include "cmUtilitySourceCommand.h"
 
 
 // cmUtilitySourceCommand
 // cmUtilitySourceCommand
-bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 3)
+  if(args.size() < 3)
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
 
 
   std::vector<std::string>::const_iterator arg = args.begin();
   std::vector<std::string>::const_iterator arg = args.begin();
   
   

+ 1 - 1
Source/cmVariableRequiresCommand.cxx

@@ -25,7 +25,7 @@ bool cmVariableRequiresCommand::InitialPass(std::vector<std::string> const& args
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  cmSystemTools::ExpandListArguments(args, m_Arguments);
+  m_Arguments = args;
   return true;
   return true;
 }
 }
 
 

+ 2 - 4
Source/cmWriteFileCommand.cxx

@@ -17,15 +17,13 @@
 #include "cmWriteFileCommand.h"
 #include "cmWriteFileCommand.h"
 
 
 // cmLibraryCommand
 // cmLibraryCommand
-bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& argsIn)
+bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args)
 {
 {
-  if(argsIn.size() < 2 )
+  if(args.size() < 2 )
     {
     {
     this->SetError("called with incorrect number of arguments");
     this->SetError("called with incorrect number of arguments");
     return false;
     return false;
     }
     }
-  std::vector<std::string> args;
-  cmSystemTools::ExpandListArguments(argsIn, args);
   std::string message;
   std::string message;
   std::vector<std::string>::const_iterator i = args.begin();
   std::vector<std::string>::const_iterator i = args.begin();
 
 

+ 18 - 15
Source/ctest.cxx

@@ -17,6 +17,7 @@
 #include "ctest.h"
 #include "ctest.h"
 #include "cmRegularExpression.h"
 #include "cmRegularExpression.h"
 #include "cmSystemTools.h"
 #include "cmSystemTools.h"
+#include "cmListFileCache.h"
 
 
 #include <stdio.h>
 #include <stdio.h>
 #include <time.h>
 #include <time.h>
@@ -1111,17 +1112,19 @@ void ctest::ProcessDirectory(std::vector<std::string> &passed,
   bool parseError;
   bool parseError;
   while ( fin )
   while ( fin )
     {
     {
-    if(cmSystemTools::ParseFunction(fin, name, args, "DartTestfile.txt",
-                                    parseError))
+    cmListFileFunction lff;
+    if(cmListFileCache::ParseFunction(fin, lff, "DartTestfile.txt", parseError))
       {
       {
+      const std::string& name = lff.m_Name;
+      const std::vector<cmListFileArgument>& args = lff.m_Arguments;
       if (name == "SUBDIRS")
       if (name == "SUBDIRS")
         {
         {
         std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
         std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
-        for(std::vector<std::string>::iterator j = args.begin();
+        for(std::vector<cmListFileArgument>::const_iterator j = args.begin();
             j != args.end(); ++j)
             j != args.end(); ++j)
           {   
           {   
           std::string nwd = cwd + "/";
           std::string nwd = cwd + "/";
-          nwd += *j;
+          nwd += j->Value;
           if (cmSystemTools::FileIsDirectory(nwd.c_str()))
           if (cmSystemTools::FileIsDirectory(nwd.c_str()))
             {
             {
             cmSystemTools::ChangeDirectory(nwd.c_str());
             cmSystemTools::ChangeDirectory(nwd.c_str());
@@ -1136,17 +1139,17 @@ void ctest::ProcessDirectory(std::vector<std::string> &passed,
         {
         {
         if (this->m_UseExcludeRegExp && 
         if (this->m_UseExcludeRegExp && 
             this->m_UseExcludeRegExpFirst && 
             this->m_UseExcludeRegExpFirst && 
-            ereg.find(args[0].c_str()))
+            ereg.find(args[0].Value.c_str()))
           {
           {
           continue;
           continue;
           }
           }
-        if (this->m_UseIncludeRegExp && !ireg.find(args[0].c_str()))
+        if (this->m_UseIncludeRegExp && !ireg.find(args[0].Value.c_str()))
           {
           {
           continue;
           continue;
           }
           }
         if (this->m_UseExcludeRegExp && 
         if (this->m_UseExcludeRegExp && 
             !this->m_UseExcludeRegExpFirst && 
             !this->m_UseExcludeRegExpFirst && 
-            ereg.find(args[0].c_str()))
+            ereg.find(args[0].Value.c_str()))
           {
           {
           continue;
           continue;
           }
           }
@@ -1159,30 +1162,30 @@ void ctest::ProcessDirectory(std::vector<std::string> &passed,
           std::cerr << "Changing directory into " << nwd.c_str() << "\n";
           std::cerr << "Changing directory into " << nwd.c_str() << "\n";
           firstTest = 0;
           firstTest = 0;
           }
           }
-        cres.m_Name = args[0];
-        fprintf(stderr,"Testing %-30s ",args[0].c_str());
+        cres.m_Name = args[0].Value;
+        fprintf(stderr,"Testing %-30s ",args[0].Value.c_str());
         fflush(stderr);
         fflush(stderr);
         //std::cerr << "Testing " << args[0] << " ... ";
         //std::cerr << "Testing " << args[0] << " ... ";
         // find the test executable
         // find the test executable
-        std::string testCommand = this->FindExecutable(args[1].c_str());
+        std::string testCommand = this->FindExecutable(args[1].Value.c_str());
         testCommand = cmSystemTools::ConvertToOutputPath(testCommand.c_str());
         testCommand = cmSystemTools::ConvertToOutputPath(testCommand.c_str());
 
 
         // continue if we did not find the executable
         // continue if we did not find the executable
         if (testCommand == "")
         if (testCommand == "")
           {
           {
           std::cerr << "Unable to find executable: " << 
           std::cerr << "Unable to find executable: " << 
-            args[1].c_str() << "\n";
+            args[1].Value.c_str() << "\n";
           continue;
           continue;
           }
           }
         
         
         // add the arguments
         // add the arguments
-        std::vector<std::string>::iterator j = args.begin();
+        std::vector<cmListFileArgument>::const_iterator j = args.begin();
         ++j;
         ++j;
         ++j;
         ++j;
         for(;j != args.end(); ++j)
         for(;j != args.end(); ++j)
           {   
           {   
           testCommand += " ";
           testCommand += " ";
-          testCommand += cmSystemTools::EscapeSpaces(j->c_str());
+          testCommand += cmSystemTools::EscapeSpaces(j->Value.c_str());
           }
           }
         /**
         /**
          * Run an executable command and put the stdout in output.
          * Run an executable command and put the stdout in output.
@@ -1219,7 +1222,7 @@ void ctest::ProcessDirectory(std::vector<std::string> &passed,
               std::cerr << output.c_str() << "\n";
               std::cerr << output.c_str() << "\n";
               }
               }
             }
             }
-          failed.push_back(args[0]); 
+          failed.push_back(args[0].Value); 
           }
           }
         else
         else
           {
           {
@@ -1236,7 +1239,7 @@ void ctest::ProcessDirectory(std::vector<std::string> &passed,
               std::cerr << output.c_str() << "\n";
               std::cerr << output.c_str() << "\n";
               }
               }
             }
             }
-          passed.push_back(args[0]); 
+          passed.push_back(args[0].Value); 
           }
           }
         cres.m_Output = output;
         cres.m_Output = output;
         cres.m_ReturnValue = retVal;
         cres.m_ReturnValue = retVal;