diff options
author | Ken Martin <ken.martin@kitware.com> | 2005-03-18 15:41:41 (GMT) |
---|---|---|
committer | Ken Martin <ken.martin@kitware.com> | 2005-03-18 15:41:41 (GMT) |
commit | 345cf0401235a1fd64bb9b1c353e0e3fc848d666 (patch) | |
tree | 6c1862e3516cd436f3068221ae9fcc11144724b8 /Source/cmMacroCommand.cxx | |
parent | 1f9df24ba7e76cbd7ecc1816a9f8d46b61816e95 (diff) | |
download | CMake-345cf0401235a1fd64bb9b1c353e0e3fc848d666.zip CMake-345cf0401235a1fd64bb9b1c353e0e3fc848d666.tar.gz CMake-345cf0401235a1fd64bb9b1c353e0e3fc848d666.tar.bz2 |
ENH: big change that includes immediate subdir support, removing the notion of inherited commands, makefiles no longer read in the parent makefiles but instead inherit thier parent makefiles current settings
Diffstat (limited to 'Source/cmMacroCommand.cxx')
-rw-r--r-- | Source/cmMacroCommand.cxx | 403 |
1 files changed, 238 insertions, 165 deletions
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 9db5f16..daf3989 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -16,214 +16,287 @@ =========================================================================*/ #include "cmMacroCommand.h" -bool cmMacroFunctionBlocker:: -IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf) +// define the class for macro commands +class cmMacroHelperCommand : public cmCommand { - // record commands until we hit the ENDMACRO - if (!m_Executing) +public: + cmMacroHelperCommand() {} + + ///! clean up any memory allocated by the macro + ~cmMacroHelperCommand() {}; + + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + cmMacroHelperCommand *newC = new cmMacroHelperCommand; + // we must copy when we clone + newC->m_Args = this->m_Args; + newC->m_Functions = this->m_Functions; + return newC; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args); + + virtual bool InitialPass(std::vector<std::string> const& args) + { return false; }; + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() { return this->m_Args[0].c_str(); } + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() + { + std::string docs = "Macro named: "; + docs += this->GetName(); + return docs.c_str(); + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() + { + return this->GetTerseDocumentation(); + } + + cmTypeMacro(cmMacroHelperCommand, cmCommand); + + std::vector<std::string> m_Args; + std::vector<cmListFileFunction> m_Functions; +}; + + +bool cmMacroHelperCommand::InvokeInitialPass +(const std::vector<cmListFileArgument>& args) +{ + // Expand the argument list to the macro. + std::vector<std::string> expandedArgs; + m_Makefile->ExpandArguments(args, expandedArgs); + + std::string tmps; + cmListFileArgument arg; + std::string variable; + + // make sure the number of arguments passed is at least the number + // required by the signature + if (expandedArgs.size() < m_Args.size() - 1) { - // at the ENDMACRO call we shift gears and start looking for invocations - if(lff.m_Name == "ENDMACRO") - { - std::vector<std::string> expandedArguments; - mf.ExpandArguments(lff.m_Arguments, expandedArguments); - if(!expandedArguments.empty() && (expandedArguments[0] == m_Args[0])) - { - m_Executing = true; - std::string name = m_Args[0]; - std::vector<std::string>::size_type cc; - name += "("; - for ( cc = 0; cc < m_Args.size(); cc ++ ) - { - name += " " + m_Args[cc]; - } - name += " )"; - mf.AddMacro(m_Args[0].c_str(), name.c_str()); - return true; - } - } - // if it wasn't an endmacro and we are not executing then we must be - // recording - m_Functions.push_back(lff); - return true; + std::string errorMsg = + "Macro invoked with incorrect arguments for macro named: "; + errorMsg += m_Args[0]; + this->SetError(errorMsg.c_str()); + return false; } - // otherwise the macro has been recorded and we are executing - // so we look for macro invocations - if(lff.m_Name == m_Args[0]) + // set the value of argc + cmOStringStream argcDefStream; + argcDefStream << expandedArgs.size(); + std::string argcDef = argcDefStream.str(); + + // declare varuiables for ARGV ARGN but do not compute until needed + std::string argvDef; + std::string argnDef; + bool argnDefInitialized = false; + bool argvDefInitialized = false; + + // Invoke all the functions that were collected in the block. + cmListFileFunction newLFF; + // for each function + for(unsigned int c = 0; c < m_Functions.size(); ++c) { - std::string tmps; - cmListFileArgument arg; - std::string variable; - // Expand the argument list to the macro. - std::vector<std::string> expandedArguments; - mf.ExpandArguments(lff.m_Arguments, expandedArguments); - - // make sure the number of arguments passed is at least the number - // required by the signature - if (expandedArguments.size() < m_Args.size() - 1) + // Replace the formal arguments and then invoke the command. + newLFF.m_Arguments.clear(); + newLFF.m_Arguments.reserve(m_Functions[c].m_Arguments.size()); + newLFF.m_Name = m_Functions[c].m_Name; + newLFF.m_FilePath = m_Functions[c].m_FilePath; + newLFF.m_Line = m_Functions[c].m_Line; + // for each argument of the current function + for (std::vector<cmListFileArgument>::const_iterator k = + m_Functions[c].m_Arguments.begin(); + k != m_Functions[c].m_Arguments.end(); ++k) { - cmOStringStream error; - error << "Error in cmake code at\n" - << lff.m_FilePath << ":" << lff.m_Line << ":\n" - << "Invocation of macro \"" - << lff.m_Name.c_str() << "\" with incorrect number of arguments."; - cmSystemTools::Error(error.str().c_str()); - return true; - } - - // set the value of argc - cmOStringStream argcDefStream; - argcDefStream << expandedArguments.size(); - std::string argcDef = argcDefStream.str(); - - // declare varuiables for ARGV ARGN but do not compute until needed - std::string argvDef; - std::string argnDef; - bool argnDefInitialized = false; - bool argvDefInitialized = false; - - // Invoke all the functions that were collected in the block. - cmListFileFunction newLFF; - // for each function - for(unsigned int c = 0; c < m_Functions.size(); ++c) - { - // Replace the formal arguments and then invoke the command. - newLFF.m_Arguments.clear(); - newLFF.m_Arguments.reserve(m_Functions[c].m_Arguments.size()); - newLFF.m_Name = m_Functions[c].m_Name; - newLFF.m_FilePath = m_Functions[c].m_FilePath; - newLFF.m_Line = m_Functions[c].m_Line; - // for each argument of the current function - for (std::vector<cmListFileArgument>::const_iterator k = - m_Functions[c].m_Arguments.begin(); - k != m_Functions[c].m_Arguments.end(); ++k) + tmps = k->Value; + // replace formal arguments + for (unsigned int j = 1; j < m_Args.size(); ++j) { - tmps = k->Value; - // replace formal arguments - for (unsigned int j = 1; j < m_Args.size(); ++j) - { - variable = "${"; - variable += m_Args[j]; - variable += "}"; - cmSystemTools::ReplaceString(tmps, variable.c_str(), - expandedArguments[j-1].c_str()); - } - // replace argc - cmSystemTools::ReplaceString(tmps, "${ARGC}",argcDef.c_str()); - - // repleace ARGN - if (tmps.find("${ARGN}") != std::string::npos) + variable = "${"; + variable += m_Args[j]; + variable += "}"; + cmSystemTools::ReplaceString(tmps, variable.c_str(), + expandedArgs[j-1].c_str()); + } + // replace argc + cmSystemTools::ReplaceString(tmps, "${ARGC}",argcDef.c_str()); + + // repleace ARGN + if (tmps.find("${ARGN}") != std::string::npos) + { + if (!argnDefInitialized) { - if (!argnDefInitialized) + std::vector<std::string>::const_iterator eit; + std::vector<std::string>::size_type cnt = 0; + for ( eit = expandedArgs.begin(); eit != expandedArgs.end(); ++eit ) { - std::vector<std::string>::iterator eit; - std::vector<std::string>::size_type cnt = 0; - for ( eit = expandedArguments.begin(); - eit != expandedArguments.end(); - ++ eit ) + if ( cnt >= m_Args.size()-1 ) { - if ( cnt >= m_Args.size()-1 ) + if ( argnDef.size() > 0 ) { - if ( argnDef.size() > 0 ) - { - argnDef += ";"; - } - argnDef += *eit; + argnDef += ";"; } - cnt ++; + argnDef += *eit; } - argnDefInitialized = true; + cnt ++; } - cmSystemTools::ReplaceString(tmps, "${ARGN}", argnDef.c_str()); + argnDefInitialized = true; } + cmSystemTools::ReplaceString(tmps, "${ARGN}", argnDef.c_str()); + } + + // if the current argument of the current function has ${ARGV in it + // then try replacing ARGV values + if (tmps.find("${ARGV") != std::string::npos) + { + char argvName[60]; - // if the current argument of the current function has ${ARGV in it - // then try replacing ARGV values - if (tmps.find("${ARGV") != std::string::npos) + // repleace ARGV, compute it only once + if (!argvDefInitialized) { - char argvName[60]; - - // repleace ARGV, compute it only once - if (!argvDefInitialized) + std::vector<std::string>::const_iterator eit; + for ( eit = expandedArgs.begin(); eit != expandedArgs.end(); ++eit ) { - std::vector<std::string>::iterator eit; - for ( eit = expandedArguments.begin(); - eit != expandedArguments.end(); - ++ eit ) + if ( argvDef.size() > 0 ) { - if ( argvDef.size() > 0 ) - { - argvDef += ";"; - } - argvDef += *eit; + argvDef += ";"; } - argvDefInitialized = true; - } - cmSystemTools::ReplaceString(tmps, "${ARGV}", argvDef.c_str()); - - // also replace the ARGV1 ARGV2 ... etc - for (unsigned int t = 0; t < expandedArguments.size(); ++t) - { - sprintf(argvName,"${ARGV%i}",t); - cmSystemTools::ReplaceString(tmps, argvName, - expandedArguments[t].c_str()); + argvDef += *eit; } + argvDefInitialized = true; } + cmSystemTools::ReplaceString(tmps, "${ARGV}", argvDef.c_str()); - arg.Value = tmps; - arg.Quoted = k->Quoted; - const char* def = - mf.GetDefinition("CMAKE_MACRO_REPORT_DEFINITION_LOCATION"); - if(def && !cmSystemTools::IsOff(def)) + // also replace the ARGV1 ARGV2 ... etc + for (unsigned int t = 0; t < expandedArgs.size(); ++t) { - // Report the location of the argument where the macro was - // defined. - arg.FilePath = k->FilePath; - arg.Line = k->Line; + sprintf(argvName,"${ARGV%i}",t); + cmSystemTools::ReplaceString(tmps, argvName, + expandedArgs[t].c_str()); + } + } + + arg.Value = tmps; + arg.Quoted = k->Quoted; + const char* def = + m_Makefile->GetDefinition("CMAKE_MACRO_REPORT_DEFINITION_LOCATION"); + if(def && !cmSystemTools::IsOff(def)) + { + // Report the location of the argument where the macro was + // defined. + arg.FilePath = k->FilePath; + arg.Line = k->Line; + } + else + { + // Report the location of the argument where the macro was + // invoked. + if (args.size()) + { + arg.FilePath = args[0].FilePath; + arg.Line = args[0].Line; } else { - // Report the location of the argument where the macro was - // invoked. - arg.FilePath = lff.m_FilePath; - arg.Line = lff.m_Line; + arg.FilePath = "Unknown"; + arg.Line = 0; } - newLFF.m_Arguments.push_back(arg); } - if(!mf.ExecuteCommand(newLFF)) + newLFF.m_Arguments.push_back(arg); + } + if(!m_Makefile->ExecuteCommand(newLFF)) + { + cmOStringStream error; + error << "Error in cmake code at\n" + << args[0].FilePath << ":" << args[0].Line << ":\n" + << "A command failed during the invocation of macro \"" + << this->m_Args[0].c_str() << "\"."; + cmSystemTools::Error(error.str().c_str()); + return false; + } + } + return true; +} + +bool cmMacroFunctionBlocker:: +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(lff.m_Name == "ENDMACRO") + { + std::vector<std::string> expandedArguments; + mf.ExpandArguments(lff.m_Arguments, expandedArguments); + if(!expandedArguments.empty() && (expandedArguments[0] == m_Args[0])) + { + std::string name = m_Args[0]; + std::vector<std::string>::size_type cc; + name += "("; + for ( cc = 0; cc < m_Args.size(); cc ++ ) { - cmOStringStream error; - error << "Error in cmake code at\n" - << lff.m_FilePath << ":" << lff.m_Line << ":\n" - << "A command failed during the invocation of macro \"" - << lff.m_Name.c_str() << "\"."; - cmSystemTools::Error(error.str().c_str()); + name += " " + m_Args[cc]; } + name += " )"; + mf.AddMacro(m_Args[0].c_str(), name.c_str()); + + // create a new command and add it to cmake + cmMacroHelperCommand *f = new cmMacroHelperCommand(); + f->m_Args = this->m_Args; + f->m_Functions = this->m_Functions; + mf.AddCommand(f); + + // remove the function blocker now that the macro is defined + mf.RemoveFunctionBlocker(lff); + return true; } - return true; } - - // if not an invocation then it is just an ordinary line - return false; + + // if it wasn't an endmacro and we are not executing then we must be + // recording + m_Functions.push_back(lff); + return true; } + bool cmMacroFunctionBlocker:: -ShouldRemove(const cmListFileFunction&, cmMakefile &) +ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf) { + if(lff.m_Name == "ENDMACRO") + { + std::vector<std::string> expandedArguments; + mf.ExpandArguments(lff.m_Arguments, expandedArguments); + if(!expandedArguments.empty() && (expandedArguments[0] == m_Args[0])) + { + return true; + } + } return false; } void cmMacroFunctionBlocker:: ScopeEnded(cmMakefile &mf) { - // macros never leave scope but we should have seen the ENDMACRO call by now - if (m_Executing != true) - { - cmSystemTools::Error("The end of a CMakeLists file was reached with a MACRO statement that was not closed properly. Within the directory: ", - mf.GetCurrentDirectory(), " with macro ", - m_Args[0].c_str()); - } + // macros should end with an EndMacro + cmSystemTools::Error("The end of a CMakeLists file was reached with a MACRO statement that was not closed properly. Within the directory: ", + mf.GetCurrentDirectory(), " with macro ", + m_Args[0].c_str()); } bool cmMacroCommand::InitialPass(std::vector<std::string> const& args) |