diff options
Diffstat (limited to 'Source')
53 files changed, 607 insertions, 629 deletions
diff --git a/Source/cmAbstractFilesCommand.cxx b/Source/cmAbstractFilesCommand.cxx index e74653ef86..e0601cbdb9 100644 --- a/Source/cmAbstractFilesCommand.cxx +++ b/Source/cmAbstractFilesCommand.cxx @@ -19,7 +19,7 @@ #include "cmSourceFile.h" // cmAbstractFilesCommand -bool cmAbstractFilesCommand::InitialPass(std::vector<std::string> const& argsIn) +bool cmAbstractFilesCommand::InitialPass(std::vector<std::string> const& args) { const char* versionValue = m_Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); @@ -29,13 +29,11 @@ bool cmAbstractFilesCommand::InitialPass(std::vector<std::string> const& argsIn) return false; } - if(argsIn.size() < 1 ) + if(args.size() < 1 ) { this->SetError("called with incorrect number of arguments"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); bool ret = true; std::string m = "could not find source file(s):\n"; diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index 6b1c09c8f6..a0a017dfda 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -18,19 +18,17 @@ // 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 arg. For the moment, let's say that COMMAND, TARGET are always required. */ - if (argsIn.size() < 4) + if (args.size() < 4) { this->SetError("called with wrong number of arguments."); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); std::string source, command, target, comment; std::vector<std::string> command_args, depends, outputs; diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index c14264da1a..77ab3ef0ec 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -17,17 +17,15 @@ #include "cmAddCustomTargetCommand.h" // cmAddCustomTargetCommand -bool cmAddCustomTargetCommand::InitialPass(std::vector<std::string> const& argsIn) +bool cmAddCustomTargetCommand::InitialPass(std::vector<std::string> const& args) { bool all = false; - if(argsIn.size() < 2 ) + if(args.size() < 2 ) { this->SetError("called with incorrect number of arguments"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); // all target option std::string arguments; diff --git a/Source/cmAddDefinitionsCommand.cxx b/Source/cmAddDefinitionsCommand.cxx index 4cb42dd7e5..5067e3f790 100644 --- a/Source/cmAddDefinitionsCommand.cxx +++ b/Source/cmAddDefinitionsCommand.cxx @@ -17,15 +17,13 @@ #include "cmAddDefinitionsCommand.h" // 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 - if(argsIn.size() < 1 ) + if(args.size() < 1 ) { return true; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); for(std::vector<std::string>::const_iterator i = args.begin(); i != args.end(); ++i) diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx index 57034d44bb..cfae2ceed9 100644 --- a/Source/cmAddDependenciesCommand.cxx +++ b/Source/cmAddDependenciesCommand.cxx @@ -17,15 +17,13 @@ #include "cmAddDependenciesCommand.h" // 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); std::string target_name = args[0]; diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx index cfae79f684..09aae189eb 100644 --- a/Source/cmAddExecutableCommand.cxx +++ b/Source/cmAddExecutableCommand.cxx @@ -17,16 +17,14 @@ #include "cmAddExecutableCommand.h" // 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"); 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; diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index b61b6acf60..cb7c2d7caa 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -17,15 +17,13 @@ #include "cmAddLibraryCommand.h" // 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); // Library type defaults to value of BUILD_SHARED_LIBS, if it exists, // otherwise it defaults to static library. int shared = !cmSystemTools::IsOff(m_Makefile->GetDefinition("BUILD_SHARED_LIBS")); diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx index 09417a18fc..5802779956 100644 --- a/Source/cmAddTestCommand.cxx +++ b/Source/cmAddTestCommand.cxx @@ -32,8 +32,7 @@ bool cmAddTestCommand::InitialPass(std::vector<std::string> const& args) // store the arguments for the final pass // also expand any CMake variables - m_Args.erase(m_Args.begin(), m_Args.end()); - cmSystemTools::ExpandListArguments(args, m_Args); + m_Args = args; return true; } diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 56da7d39e5..7116f4d1ae 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -296,12 +296,14 @@ void cmExecuteCommand(void *arg, const char *name, { cmMakefile *mf = static_cast<cmMakefile *>(arg); 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, diff --git a/Source/cmCommand.h b/Source/cmCommand.h index 66228da7b3..44e95d2968 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -18,7 +18,8 @@ #define cmCommand_h #include "cmStandardIncludes.h" -class cmMakefile; +#include "cmListFileCache.h" +#include "cmMakefile.h" /** \class cmCommand * \brief Superclass for all commands in CMake. @@ -51,6 +52,18 @@ public: {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 * the CMakeLists.txt file. */ @@ -159,13 +172,14 @@ private: // All subclasses of cmCommand should invoke this macro. #define cmTypeMacro(thisClass,superclass) \ +typedef superclass Superclass; \ static bool IsTypeOf(const char *type) \ { \ if ( !strcmp(#thisClass,type) ) \ { \ return true; \ } \ - return superclass::IsTypeOf(type); \ + return Superclass::IsTypeOf(type); \ } \ virtual bool IsA(const char *type) \ { \ diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx index 5ed0f4475e..8de88656c7 100644 --- a/Source/cmCreateTestSourceList.cxx +++ b/Source/cmCreateTestSourceList.cxx @@ -18,18 +18,16 @@ #include "cmSourceFile.h" // 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."); 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 function; std::vector<std::string> tests; @@ -120,7 +118,7 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& argsIn) "/* Forward declare test functions. */\n" "\n"; - std::vector<std::string>::iterator testsBegin = i; + std::vector<std::string>::const_iterator testsBegin = i; std::vector<std::string> tests_func_name; // The rest of the arguments consist of a list of test source files. diff --git a/Source/cmEndForEachCommand.cxx b/Source/cmEndForEachCommand.cxx index 7a0dca9515..f29feb908d 100644 --- a/Source/cmEndForEachCommand.cxx +++ b/Source/cmEndForEachCommand.cxx @@ -16,7 +16,7 @@ =========================================================================*/ #include "cmEndForEachCommand.h" -bool cmEndForEachCommand::InitialPass(std::vector<std::string> const& args) +bool cmEndForEachCommand::InvokeInitialPass(std::vector<cmListFileArgument> const& args) { if(args.size() < 1 ) { @@ -25,7 +25,10 @@ bool cmEndForEachCommand::InitialPass(std::vector<std::string> const& args) } // 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; } diff --git a/Source/cmEndForEachCommand.h b/Source/cmEndForEachCommand.h index 101dcb35ef..e2501778cc 100644 --- a/Source/cmEndForEachCommand.h +++ b/Source/cmEndForEachCommand.h @@ -37,10 +37,16 @@ public: } /** + * 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 * 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 diff --git a/Source/cmFindFileCommand.cxx b/Source/cmFindFileCommand.cxx index f04429e274..54f4d27eb0 100644 --- a/Source/cmFindFileCommand.cxx +++ b/Source/cmFindFileCommand.cxx @@ -31,12 +31,12 @@ bool cmFindFileCommand::InitialPass(std::vector<std::string> const& argsIn) std::string helpString = "Where can the "; helpString += argsIn[1] + " file be found"; size_t size = argsIn.size(); - std::vector<std::string> argst; + std::vector<std::string> args; for(unsigned int j = 0; j < size; ++j) { if(argsIn[j] != "DOC") { - argst.push_back(argsIn[j]); + args.push_back(argsIn[j]); } else { @@ -47,8 +47,6 @@ bool cmFindFileCommand::InitialPass(std::vector<std::string> const& argsIn) break; } } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argst, args); std::vector<std::string>::const_iterator i = args.begin(); // Use the first argument as the name of something to be defined diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index ff7bf449ed..70c97a46e8 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -27,12 +27,12 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn) } std::string helpString; size_t size = argsIn.size(); - std::vector<std::string> argst; + std::vector<std::string> args; for(unsigned int j = 0; j < size; ++j) { if(argsIn[j] != "DOC") { - argst.push_back(argsIn[j]); + args.push_back(argsIn[j]); } else { @@ -43,8 +43,6 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn) break; } } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argst, args); std::vector<std::string> path; std::vector<std::string> names; diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index e23ffad88a..dd7c870ccd 100644 --- a/Source/cmFindPathCommand.cxx +++ b/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 std::string helpString = "What is the path where the file "; helpString += argsIn[1] + " can be found"; - std::vector<std::string> argst; + std::vector<std::string> args; size_t size = argsIn.size(); for(unsigned int j = 0; j < size; ++j) { if(argsIn[j] != "DOC") { - argst.push_back(argsIn[j]); + args.push_back(argsIn[j]); } else { @@ -47,8 +47,6 @@ bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn) break; } } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argst, args); const char* cacheValue = m_Makefile->GetDefinition(args[0].c_str()); diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 1ec03a9b02..84f7dab2ac 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -30,12 +30,12 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn) } std::string doc = "Path to a program."; size_t size = argsIn.size(); - std::vector<std::string> argst; + std::vector<std::string> args; for(unsigned int j = 0; j < size; ++j) { if(argsIn[j] != "DOC") { - argst.push_back(argsIn[j]); + args.push_back(argsIn[j]); } else { @@ -46,9 +46,6 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn) break; } } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argst, args); - std::vector<std::string>::iterator i = args.begin(); // Use the first argument as the name of something to be defined diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 9c344e1788..e8d1ac61e7 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -17,68 +17,71 @@ #include "cmForEachCommand.h" 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) { return false; } // 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 - 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 return true; } 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; } @@ -90,11 +93,8 @@ ScopeEnded(cmMakefile &mf) 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) { 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 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); return true; diff --git a/Source/cmForEachCommand.h b/Source/cmForEachCommand.h index 8e73d82b67..95911e6ce9 100644 --- a/Source/cmForEachCommand.h +++ b/Source/cmForEachCommand.h @@ -20,6 +20,7 @@ #include "cmStandardIncludes.h" #include "cmCommand.h" #include "cmFunctionBlocker.h" +#include "cmListFileCache.h" /** \class cmForEachFunctionBlocker * \brief subclass of function blocker @@ -31,19 +32,13 @@ class cmForEachFunctionBlocker : public cmFunctionBlocker public: cmForEachFunctionBlocker() {m_Executing = false;} virtual ~cmForEachFunctionBlocker() {} - virtual bool IsFunctionBlocked(const char *name, - const std::vector<std::string> &args, + virtual bool IsFunctionBlocked(const cmListFileFunction& lff, 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 int NeedExpandedVariables () { return 0; }; - 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; }; diff --git a/Source/cmFunctionBlocker.h b/Source/cmFunctionBlocker.h index 95ee945bc8..09b80cacae 100644 --- a/Source/cmFunctionBlocker.h +++ b/Source/cmFunctionBlocker.h @@ -31,15 +31,14 @@ public: /** * 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; /** * should this function blocker be removed, useful when one function adds a * 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;} /** @@ -50,8 +49,6 @@ public: virtual void ScopeEnded(cmMakefile&) {} virtual ~cmFunctionBlocker() {} - - virtual int NeedExpandedVariables () { return 1; }; }; #endif diff --git a/Source/cmITKWrapTclCommand.cxx b/Source/cmITKWrapTclCommand.cxx index e762ce598c..c7a2cc82c3 100644 --- a/Source/cmITKWrapTclCommand.cxx +++ b/Source/cmITKWrapTclCommand.cxx @@ -59,15 +59,13 @@ cmITKWrapTclCommand::AddDependencies(cmDependInformation const *info, } // 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); // keep the target name m_TargetName = args[0]; m_Target = &m_Makefile->GetTargets()[m_TargetName.c_str()]; diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 98491e9111..df1b06cba4 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -17,9 +17,10 @@ #include "cmIfCommand.h" 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 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 // function blocker - mf.RemoveFunctionBlocker("ENDIF",args); + mf.RemoveFunctionBlocker(lff); return true; } else if(args.empty()) @@ -50,10 +51,12 @@ IsFunctionBlocked(const char *name, const std::vector<std::string> &args, err += ". Did you mean "; err += name; 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) { - err += *a; + err += (a->Quoted?"\"":""); + err += a->Value; + err += (a->Quoted?"\"":""); err += " "; } err += ")?"; @@ -63,13 +66,12 @@ IsFunctionBlocked(const char *name, const std::vector<std::string> &args, 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; } @@ -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: "; errmsg += mf.GetCurrentDirectory(); 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) { - errmsg += *j; + errmsg += (j->Quoted?"\"":""); + errmsg += j->Value; + errmsg += (j->Quoted?"\"":""); errmsg += " "; } 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 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) { @@ -110,7 +117,9 @@ bool cmIfCommand::InitialPass(std::vector<std::string> const& args) unsigned int i; for(i =0; i < args.size(); ++i) { - err += args[i]; + err += (args[i].Quoted?"\"":""); + err += args[i].Value; + err += (args[i].Quoted?"\"":""); err += " "; } this->SetError(err.c_str()); @@ -120,25 +129,21 @@ bool cmIfCommand::InitialPass(std::vector<std::string> const& args) cmIfFunctionBlocker *f = new cmIfFunctionBlocker(); // if is isn't true block the commands 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); 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 bool isTrue = true; isValid = false; const char *def; const char *def2; - + if(args.size() < 1 ) { isValid = true; diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h index 3e30a4ea53..152fcc2981 100644 --- a/Source/cmIfCommand.h +++ b/Source/cmIfCommand.h @@ -31,15 +31,13 @@ class cmIfFunctionBlocker : public cmFunctionBlocker public: cmIfFunctionBlocker() {} virtual ~cmIfFunctionBlocker() {} - virtual bool IsFunctionBlocked(const char *name, - const std::vector<std::string> &args, + virtual bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf); - virtual bool ShouldRemove(const char *name, - const std::vector<std::string> &args, + virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf); virtual void ScopeEnded(cmMakefile &mf); - std::vector<std::string> m_Args; + std::vector<cmListFileArgument> m_Args; bool m_IsBlocking; }; @@ -60,10 +58,16 @@ public: } /** + * 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 * 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. diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index 6d2d5d36ed..48bede4e89 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -17,14 +17,12 @@ #include "cmIncludeDirectoryCommand.h" // 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; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); std::vector<std::string>::const_iterator i = args.begin(); diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index 396742dd7c..00dffd2d3d 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -17,15 +17,13 @@ #include "cmInstallProgramsCommand.h" // 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); // Create an INSTALL_PROGRAMS target specifically for this path. m_TargetName = "INSTALL_PROGRAMS_"+args[0]; diff --git a/Source/cmInstallTargetsCommand.cxx b/Source/cmInstallTargetsCommand.cxx index a01fd864f9..155375490f 100644 --- a/Source/cmInstallTargetsCommand.cxx +++ b/Source/cmInstallTargetsCommand.cxx @@ -17,15 +17,13 @@ #include "cmInstallTargetsCommand.h" // 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); cmTargets &tgts = m_Makefile->GetTargets(); std::vector<std::string>::const_iterator s = args.begin(); diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx index 717c71f16d..67994f7e34 100644 --- a/Source/cmLinkDirectoriesCommand.cxx +++ b/Source/cmLinkDirectoriesCommand.cxx @@ -17,14 +17,12 @@ #include "cmLinkDirectoriesCommand.h" // 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; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); for(std::vector<std::string>::const_iterator i = args.begin(); i != args.end(); ++i) diff --git a/Source/cmLinkLibrariesCommand.cxx b/Source/cmLinkLibrariesCommand.cxx index 35b1ec37f5..d45f24667e 100644 --- a/Source/cmLinkLibrariesCommand.cxx +++ b/Source/cmLinkLibrariesCommand.cxx @@ -17,14 +17,12 @@ #include "cmLinkLibrariesCommand.h" // 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; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); // add libraries, nothe that there is an optional prefix // of debug and optimized than can be used for(std::vector<std::string>::const_iterator i = args.begin(); diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 0893cf65ed..fce13db34b 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -16,7 +16,7 @@ =========================================================================*/ #include "cmListFileCache.h" #include "cmSystemTools.h" - +#include "cmRegularExpression.h" 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); return false; } + long line=0; cmListFile inFile; inFile.m_ModifiedTime = cmSystemTools::ModifiedTime(path); bool parseError; while ( fin ) { 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); } if (parseError) @@ -126,7 +126,8 @@ bool cmListFileCache::CacheFile(const char* path, bool requireProjectCommand) { cmListFileFunction 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); } } @@ -143,3 +144,179 @@ void cmListFileCache::FlushCache(const char* path) 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); + } + } +} diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 2520eca1d4..9dc8073eb7 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -26,10 +26,25 @@ * 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 { std::string m_Name; - std::vector<std::string> m_Arguments; + std::vector<cmListFileArgument> m_Arguments; + std::string m_FilePath; + long m_Line; }; struct cmListFile @@ -60,7 +75,25 @@ public: //! Flush cache file out of cache. 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: // Cache the file bool CacheFile(const char* path, bool requireProjectCommand); diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx index 0ec5cab3e9..ef3fe26209 100644 --- a/Source/cmLoadCacheCommand.cxx +++ b/Source/cmLoadCacheCommand.cxx @@ -18,14 +18,12 @@ // 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."); } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); if(args.size() >= 2 && args[1] == "READ_WITH_PREFIX") { diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index d5a2f3afe2..b307148ab5 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -166,18 +166,16 @@ cmLoadedCommand::~cmLoadedCommand() } // 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; } // the file must exist 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 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 += cmDynamicLoader::LibPrefix(); - fullPath += "cm" + argsIn[0] + cmDynamicLoader::LibExtension(); + fullPath += "cm" + args[0] + cmDynamicLoader::LibExtension(); this->SetError(fullPath.c_str()); return false; } diff --git a/Source/cmLocalUnixMakefileGenerator.cxx b/Source/cmLocalUnixMakefileGenerator.cxx index 5e72e0f9a7..5092045cc3 100644 --- a/Source/cmLocalUnixMakefileGenerator.cxx +++ b/Source/cmLocalUnixMakefileGenerator.cxx @@ -812,7 +812,7 @@ void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout, // expand multi-command semi-colon separated lists // of commands into separate 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 std::string customCommands = this->CreateTargetRules(t, name); if(customCommands.size() > 0) @@ -986,7 +986,7 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout, std::string comment = "executable"; std::vector<std::string> commands; - cmSystemTools::ExpandListArguments(rules, commands); + cmSystemTools::ExpandList(rules, commands); std::string customCommands = this->CreateTargetRules(t, name); if(customCommands.size() > 0) { @@ -2339,7 +2339,7 @@ OutputBuildObjectFromSource(std::ostream& fout, // expand multi-command semi-colon separated lists // of commands into separate commands std::vector<std::string> commands; - cmSystemTools::ExpandListArguments(rules, commands); + cmSystemTools::ExpandList(rules, commands); for(std::vector<std::string>::iterator i = commands.begin(); i != commands.end(); ++i) { diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 2cdcb09e8d..58871a23c3 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -17,66 +17,67 @@ #include "cmMacroCommand.h" 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 // 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 it wasn't an endmacro and we are not executing then we must be // 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; } // otherwise the macro has been recorded and we are executing // 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 - 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()); } - // 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) { std::string variable = "${"; variable += m_Args[j]; variable += "}"; 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; } @@ -86,8 +87,7 @@ IsFunctionBlocked(const char *name, const std::vector<std::string> &args, } bool cmMacroFunctionBlocker:: -ShouldRemove(const char *, const std::vector<std::string> &, - cmMakefile &) +ShouldRemove(const cmListFileFunction&, cmMakefile &) { return false; } @@ -98,11 +98,8 @@ ScopeEnded(cmMakefile &) // 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) { this->SetError("called with incorrect number of arguments"); diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h index 0705be7eab..e090ec723d 100644 --- a/Source/cmMacroCommand.h +++ b/Source/cmMacroCommand.h @@ -31,19 +31,12 @@ class cmMacroFunctionBlocker : public cmFunctionBlocker public: cmMacroFunctionBlocker() {m_Executing = false;} 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 int NeedExpandedVariables () { return 0; }; - 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; }; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 9c5dc9f546..db4a1baa4b 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -157,14 +157,14 @@ bool cmMakefile::CommandExists(const char* name) const 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 - if(this->IsFunctionBlocked(name.c_str(), arguments)) + if(this->IsFunctionBlocked(lff)) { return; } + std::string name = lff.m_Name; // execute the command cmCommand *rm = 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(!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 { @@ -216,18 +202,13 @@ void cmMakefile::ExecuteCommand(std::string const &name, 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 cable@public.kitware.com for more information."); - } 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(); 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 @@ -1161,8 +1140,7 @@ cmMakefile::FindSourceGroup(const char* source, 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 (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 - 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 std::list<cmFunctionBlocker *>::reverse_iterator pos; for (pos = m_FunctionBlockers.rbegin(); 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 { - 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 std::list<cmFunctionBlocker *>::reverse_iterator pos; for (pos = m_FunctionBlockers.rbegin(); pos != m_FunctionBlockers.rend(); ++pos) { - if ((*pos)->ShouldRemove(name, args, *this)) + if ((*pos)->ShouldRemove(lff, *this)) { cmFunctionBlocker* b = *pos; m_FunctionBlockers.remove(b); @@ -1348,7 +1327,6 @@ void cmMakefile::ExpandSourceListArguments( } // now expand the args - std::vector<std::string> tmpArgs; unsigned int i; for(i = 0; i < arguments.size(); ++i) { @@ -1356,14 +1334,16 @@ void cmMakefile::ExpandSourceListArguments( const char *def = this->GetDefinition(arguments[i].c_str()); 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 { - 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, diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index dbb62af489..de8e3eb85e 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -22,6 +22,7 @@ #include "cmSystemTools.h" #include "cmSourceGroup.h" #include "cmTarget.h" +#include "cmListFileCache.h" #include "cmCacheManager.h" class cmFunctionBlocker; @@ -77,7 +78,7 @@ public: { m_FunctionBlockers.push_back(fb);} void RemoveFunctionBlocker(cmFunctionBlocker *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 @@ -511,7 +512,7 @@ public: /** * 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. */ bool CommandExists(const char* name) const; @@ -535,6 +536,13 @@ public: ///! Display progress or status message. 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: // add link libraries and directories to the target void AddGlobalLinkInformation(const char* name, cmTarget& target); @@ -581,7 +589,7 @@ protected: DefinitionMap m_Definitions; std::vector<cmCommand*> m_UsedCommands; cmLocalGenerator* m_LocalGenerator; - bool IsFunctionBlocked(const char *name, std::vector<std::string> const& args); + bool IsFunctionBlocked(const cmListFileFunction& lff); private: /** diff --git a/Source/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx index b50202aea1..3195387553 100644 --- a/Source/cmMarkAsAdvancedCommand.cxx +++ b/Source/cmMarkAsAdvancedCommand.cxx @@ -17,15 +17,13 @@ #include "cmMarkAsAdvancedCommand.h" // 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); unsigned int i =0; const char* value = "1"; diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 45c6dc9df7..c6e8e16037 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -17,15 +17,13 @@ #include "cmMessageCommand.h" // 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); std::string message; std::vector<std::string>::const_iterator i = args.begin(); diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index a9ec7babfd..8f48fd61d5 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -17,15 +17,13 @@ #include "cmProjectCommand.h" // 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); m_Makefile->SetProjectName(args[0].c_str()); std::string bindir = args[0]; diff --git a/Source/cmRemoveCommand.cxx b/Source/cmRemoveCommand.cxx index 136b973005..44c33d4b2a 100644 --- a/Source/cmRemoveCommand.cxx +++ b/Source/cmRemoveCommand.cxx @@ -37,19 +37,17 @@ bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args) // expand the variable 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 // check for REMOVE(VAR v1 v2 ... vn) std::vector<std::string> argsExpanded; - std::vector<std::string> temp2; + std::vector<std::string> temp; 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 std::string value; diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx index 64f6a25494..3933321141 100644 --- a/Source/cmSetSourceFilesPropertiesCommand.cxx +++ b/Source/cmSetSourceFilesPropertiesCommand.cxx @@ -18,15 +18,13 @@ // cmSetSourceFilesPropertiesCommand 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); // first collect up the list of files std::vector<std::string> propertyPairs; diff --git a/Source/cmSourceFilesCommand.cxx b/Source/cmSourceFilesCommand.cxx index 8fe4e1cd3e..fc1171cd33 100644 --- a/Source/cmSourceFilesCommand.cxx +++ b/Source/cmSourceFilesCommand.cxx @@ -17,7 +17,7 @@ #include "cmSourceFilesCommand.h" // cmSourceFilesCommand -bool cmSourceFilesCommand::InitialPass(std::vector<std::string> const& argsIn) +bool cmSourceFilesCommand::InitialPass(std::vector<std::string> const& args) { const char* versionValue = m_Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); @@ -27,13 +27,11 @@ bool cmSourceFilesCommand::InitialPass(std::vector<std::string> const& argsIn) return false; } - if(argsIn.size() < 1 ) + if(args.size() < 1 ) { this->SetError("called with incorrect number of arguments"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); std::string sourceListValue; // was the list already populated diff --git a/Source/cmSourceFilesRemoveCommand.cxx b/Source/cmSourceFilesRemoveCommand.cxx index cff9ffb7ff..7fb9b7af48 100644 --- a/Source/cmSourceFilesRemoveCommand.cxx +++ b/Source/cmSourceFilesRemoveCommand.cxx @@ -40,19 +40,17 @@ bool cmSourceFilesRemoveCommand::InitialPass(std::vector<std::string> const& arg // expand the variable 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 // check for REMOVE(VAR v1 v2 ... vn) std::vector<std::string> argsExpanded; - std::vector<std::string> temp2; + std::vector<std::string> temp; 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 std::string value; diff --git a/Source/cmSubdirCommand.cxx b/Source/cmSubdirCommand.cxx index 10bb916085..7fcf81417e 100644 --- a/Source/cmSubdirCommand.cxx +++ b/Source/cmSubdirCommand.cxx @@ -17,15 +17,13 @@ #include "cmSubdirCommand.h" // 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); bool res = true; for(std::vector<std::string>::const_iterator i = args.begin(); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index ff27805dd7..28163a8815 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -843,168 +843,6 @@ std::string cmSystemTools::ConvertToWindowsOutputPath(const char* path) 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 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::string newarg; 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) { - 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; } } } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 0e41691e77..f9ff94ff51 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -56,8 +56,10 @@ public: * strings into multiple arguements. A new vector is created * 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 @@ -117,25 +119,6 @@ public: ///! Return true if a file exists in the current directory. 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 @@ -389,5 +372,4 @@ private: static std::string s_Windows9xComspecSubstitute; }; - #endif diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 92fd063980..1e9755742c 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -75,10 +75,8 @@ void cmTarget::GenerateSourceFilesFromSourceLists( cmMakefile &mf) // if the definition exists if (varValue) { - std::vector<std::string> tval; - tval.push_back(varValue); std::vector<std::string> args; - cmSystemTools::ExpandListArguments(tval, args); + cmSystemTools::ExpandListArgument(varValue, args); unsigned int i; for (i = 0; i < args.size(); ++i) { diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index aabbcf73c9..70ba944a0c 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -17,21 +17,19 @@ #include "cmTargetLinkLibrariesCommand.h" // cmTargetLinkLibrariesCommand -bool cmTargetLinkLibrariesCommand::InitialPass(std::vector<std::string> const& argsIn) +bool cmTargetLinkLibrariesCommand::InitialPass(std::vector<std::string> const& args) { // must have one argument - if(argsIn.size() < 1) + if(args.size() < 1) { this->SetError("called with incorrect number of arguments"); return false; } // but we might not have any libs after variable expansion - if(argsIn.size() < 2) + if(args.size() < 2) { return true; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); // add libraries, nothe that there is an optional prefix // of debug and optimized than can be used std::vector<std::string>::const_iterator i = args.begin(); diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index 1a3376242d..10cefb86bb 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -17,15 +17,13 @@ #include "cmUtilitySourceCommand.h" // 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); std::vector<std::string>::const_iterator arg = args.begin(); diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx index 2433ca22f9..81e1f860b0 100644 --- a/Source/cmVariableRequiresCommand.cxx +++ b/Source/cmVariableRequiresCommand.cxx @@ -25,7 +25,7 @@ bool cmVariableRequiresCommand::InitialPass(std::vector<std::string> const& args this->SetError("called with incorrect number of arguments"); return false; } - cmSystemTools::ExpandListArguments(args, m_Arguments); + m_Arguments = args; return true; } diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx index ab7f957326..79a8b4698e 100644 --- a/Source/cmWriteFileCommand.cxx +++ b/Source/cmWriteFileCommand.cxx @@ -17,15 +17,13 @@ #include "cmWriteFileCommand.h" // 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"); return false; } - std::vector<std::string> args; - cmSystemTools::ExpandListArguments(argsIn, args); std::string message; std::vector<std::string>::const_iterator i = args.begin(); diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 4fba9b15c0..20a183e1e1 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -17,6 +17,7 @@ #include "ctest.h" #include "cmRegularExpression.h" #include "cmSystemTools.h" +#include "cmListFileCache.h" #include <stdio.h> #include <time.h> @@ -1111,17 +1112,19 @@ void ctest::ProcessDirectory(std::vector<std::string> &passed, bool parseError; 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") { 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) { std::string nwd = cwd + "/"; - nwd += *j; + nwd += j->Value; if (cmSystemTools::FileIsDirectory(nwd.c_str())) { cmSystemTools::ChangeDirectory(nwd.c_str()); @@ -1136,17 +1139,17 @@ void ctest::ProcessDirectory(std::vector<std::string> &passed, { if (this->m_UseExcludeRegExp && this->m_UseExcludeRegExpFirst && - ereg.find(args[0].c_str())) + ereg.find(args[0].Value.c_str())) { continue; } - if (this->m_UseIncludeRegExp && !ireg.find(args[0].c_str())) + if (this->m_UseIncludeRegExp && !ireg.find(args[0].Value.c_str())) { continue; } if (this->m_UseExcludeRegExp && !this->m_UseExcludeRegExpFirst && - ereg.find(args[0].c_str())) + ereg.find(args[0].Value.c_str())) { continue; } @@ -1159,30 +1162,30 @@ void ctest::ProcessDirectory(std::vector<std::string> &passed, std::cerr << "Changing directory into " << nwd.c_str() << "\n"; 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); //std::cerr << "Testing " << args[0] << " ... "; // 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()); // continue if we did not find the executable if (testCommand == "") { std::cerr << "Unable to find executable: " << - args[1].c_str() << "\n"; + args[1].Value.c_str() << "\n"; continue; } // add the arguments - std::vector<std::string>::iterator j = args.begin(); + std::vector<cmListFileArgument>::const_iterator j = args.begin(); ++j; ++j; for(;j != args.end(); ++j) { testCommand += " "; - testCommand += cmSystemTools::EscapeSpaces(j->c_str()); + testCommand += cmSystemTools::EscapeSpaces(j->Value.c_str()); } /** * 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"; } } - failed.push_back(args[0]); + failed.push_back(args[0].Value); } else { @@ -1236,7 +1239,7 @@ void ctest::ProcessDirectory(std::vector<std::string> &passed, std::cerr << output.c_str() << "\n"; } } - passed.push_back(args[0]); + passed.push_back(args[0].Value); } cres.m_Output = output; cres.m_ReturnValue = retVal; |