diff --git a/Source/cmCableCommand.cxx b/Source/cmCableCommand.cxx new file mode 100644 index 000000000..f7a28eadb --- /dev/null +++ b/Source/cmCableCommand.cxx @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) 2000 National Library of Medicine + All rights reserved. + + See COPYRIGHT.txt for copyright details. + +=========================================================================*/ +#include "cmCabilCommand.h" +#include "cmCacheManager.h" + +// cmCabilCommand + + +/** + * Constructor initializes to empty m_CabilData. + */ +cmCabilCommand::cmCabilCommand(): m_CabilData(0) +{ +} + + +/** + * Destructor frees the cmCabilData only if this command is its owner. + */ +cmCabilCommand::~cmCabilCommand() +{ + if(m_CabilData && m_CabilData->OwnerIs(this)) + { + delete m_CabilData; + } +} + + +/** + * Write a CABIL configuration file header. + */ +void cmCabilCommand::WriteConfigurationHeader(std::ostream& os) const +{ + os << "" << std::endl + << "" << std::endl; +} + + +/** + * Write a CABIL configuration file footer. + */ +void cmCabilCommand::WriteConfigurationFooter(std::ostream& os) const +{ + os << "" << std::endl; +} + + +/** + * Ensure that this cmCabilCommand has a valid m_CabilData pointer. + */ +void cmCabilCommand::SetupCabilData() +{ + // Only do something if the pointer is invalid. + if(m_CabilData) + { return; } + + // Look through the vector of commands from the makefile. + const std::vector& usedCommands = + m_Makefile->GetUsedCommands(); + for(std::vector::const_iterator commandIter = + usedCommands.begin(); commandIter != usedCommands.end(); ++commandIter) + { + // If this command is a cmCabilCommand, see if it has a cmCabilData + // instance. + cmCabilCommand* command = cmCabilCommand::SafeDownCast(*commandIter); + if(command) + { m_CabilData = command->m_CabilData; } + + // If we found an instance of cmCabilData, then we are done. + if(m_CabilData) + { return; } + } + + // We didn't find another cmCabilCommand with a valid cmCabilData. + // We must allocate the new cmCabilData ourselves, and with this + // command as its owner. + m_CabilData = new cmCabilData(this); +} diff --git a/Source/cmCableCommand.h b/Source/cmCableCommand.h new file mode 100644 index 000000000..b00c19930 --- /dev/null +++ b/Source/cmCableCommand.h @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) 2000 National Library of Medicine + All rights reserved. + + See COPYRIGHT.txt for copyright details. + +=========================================================================*/ +#ifndef cmCabilCommand_h +#define cmCabilCommand_h + +#include "cmStandardIncludes.h" +#include "cmCommand.h" +#include "cmCabilData.h" + +/** \class cmCabilCommand + * \brief Superclass for all CABIL_ command classes. + */ +class cmCabilCommand : public cmCommand +{ +public: + cmCabilCommand(); + virtual ~cmCabilCommand(); + + void WriteConfigurationHeader(std::ostream&) const; + void WriteConfigurationFooter(std::ostream&) const; + + cmTypeMacro(cmCabilCommand, cmCommand); +protected: + void SetupCabilData(); + + /** + * The cmCabilData holding common information for all cmCabilCommand + * instances. + */ + cmCabilData* m_CabilData; +}; + + + +#endif diff --git a/Source/cmCableData.cxx b/Source/cmCableData.cxx new file mode 100644 index 000000000..a1a811a46 --- /dev/null +++ b/Source/cmCableData.cxx @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) 2000 National Library of Medicine + All rights reserved. + + See COPYRIGHT.txt for copyright details. + +=========================================================================*/ +#include "cmCabilData.h" +#include "cmCacheManager.h" + + +/** + * Free all data that was stored here. + */ +cmCabilData::~cmCabilData() +{ + for(OutputFiles::iterator i = m_OutputFiles.begin(); + i != m_OutputFiles.end(); ++i) + { + delete i->second; + } +} + + +/** + * The constructor attempts to open the file for writing. + */ +cmCabilData::OutputFile +::OutputFile(std::string file, const cmCabilCommand* command): + m_FileStream(file.c_str()), + m_FirstReferencingCommand(command), + m_LastReferencingCommand(command) +{ + if(!m_FileStream) + { + cmSystemTools::Error("Error can not open for write: ", file.c_str()); + } +} + + +/** + * Destructor closes the file, if it was open. + */ +cmCabilData::OutputFile +::~OutputFile() +{ + if(m_FileStream) + m_FileStream.close(); +} + + +/** + * Get the output stream associated with this OutputFile. + */ +std::ostream& +cmCabilData::OutputFile +::GetStream() +{ + return m_FileStream; +} + + +void +cmCabilData::OutputFile +::SetLastReferencingCommand(const cmCabilCommand* command) +{ + m_LastReferencingCommand = command; +} + + +bool +cmCabilData::OutputFile +::FirstReferencingCommandIs(const cmCabilCommand* command) const +{ + return (m_FirstReferencingCommand == command); +} + + +bool +cmCabilData::OutputFile +::LastReferencingCommandIs(const cmCabilCommand* command) const +{ + return (m_LastReferencingCommand == command); +} + + +/** + * Get the OutputFile for the file with the given name. Automatically + * maintains first and last referencing commands. + */ +cmCabilData::OutputFile* +cmCabilData::GetOutputFile(const std::string& name, + const cmCabilCommand* command) +{ + OutputFiles::iterator f = m_OutputFiles.find(name); + // If the file hasn't yet been opened, create an entry for it. + if(f == m_OutputFiles.end()) + { + OutputFile* outputFile = new OutputFile(name, command); + m_OutputFiles[name] = outputFile; + + return outputFile; + } + + // The file has already been opened. Set the command as the last + // referencing command. + f->second->SetLastReferencingCommand(command); + + return f->second; +} + diff --git a/Source/cmCableData.h b/Source/cmCableData.h new file mode 100644 index 000000000..9cc8e392b --- /dev/null +++ b/Source/cmCableData.h @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) 2000 National Library of Medicine + All rights reserved. + + See COPYRIGHT.txt for copyright details. + +=========================================================================*/ +#ifndef cmCabilData_h +#define cmCabilData_h + +#include "cmStandardIncludes.h" +#include "cmCommand.h" + +class cmCabilCommand; + +/** \class cmCabilData + * \brief Hold data in one location for all cmCabilCommand subclasses. + */ +class cmCabilData +{ +public: + /** + * The cmCabilData instance is owned by one cmCabilCommand, which is given + * to this constructor. + */ + cmCabilData(const cmCabilCommand* owner): m_Owner(owner) {} + + ~cmCabilData(); + + /** + * Returns true if the given cmCabilCommand is the owner of this + * cmCabilData. + */ + bool OwnerIs(const cmCabilCommand* owner) const + { return (owner == m_Owner); } + + /** + * Hold an output stream for all commands that use it. Maintain the + * first and last commands that reference it so that they can write the + * header/footer lines, if necessary. + */ + class OutputFile + { + public: + OutputFile(std::string, const cmCabilCommand*); + ~OutputFile(); + std::ostream& GetStream(); + void SetLastReferencingCommand(const cmCabilCommand*); + bool FirstReferencingCommandIs(const cmCabilCommand*) const; + bool LastReferencingCommandIs(const cmCabilCommand*) const; + private: + std::ofstream m_FileStream; + const cmCabilCommand* m_FirstReferencingCommand; + const cmCabilCommand* m_LastReferencingCommand; + }; + + OutputFile* GetOutputFile(const std::string&, const cmCabilCommand*); + +private: + typedef std::map OutputFiles; + + /** + * The cmCabilCommand which created this instance of cmCabilCommand. + */ + const cmCabilCommand* m_Owner; + + /** + * Hold all output streams by file name. + */ + OutputFiles m_OutputFiles; +}; + +#endif diff --git a/Source/cmCableDefineSetCommand.cxx b/Source/cmCableDefineSetCommand.cxx new file mode 100644 index 000000000..e1f137711 --- /dev/null +++ b/Source/cmCableDefineSetCommand.cxx @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) 2000 National Library of Medicine + All rights reserved. + + See COPYRIGHT.txt for copyright details. + +=========================================================================*/ +#include "cmCabilDefineSetCommand.h" +#include "cmCacheManager.h" + + +// cmCabilDefineSetCommand +bool cmCabilDefineSetCommand::Invoke(std::vector& args) +{ + if(args.size() < 2) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + + std::vector::const_iterator arg = args.begin(); + + // The first argument is the name of the set. + m_SetName = *arg++; + + // The rest of the arguments are the elements to be placed in the set. + for(; arg != args.end(); ++arg) + { + m_Elements.push_back(*arg); + } + + return true; +} + + +/** + * Write the CABIL configuration code to define this Set. + */ +void cmCabilDefineSetCommand::WriteConfiguration(std::ostream& os) const +{ + os << " " << std::endl; + for(Elements::const_iterator e = m_Elements.begin(); + e != m_Elements.end(); ++e) + { + os << " " << e->c_str() << "" << std::endl; + } + os << " " << std::endl; +} diff --git a/Source/cmCableDefineSetCommand.h b/Source/cmCableDefineSetCommand.h new file mode 100644 index 000000000..345ac0633 --- /dev/null +++ b/Source/cmCableDefineSetCommand.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) 2000 National Library of Medicine + All rights reserved. + + See COPYRIGHT.txt for copyright details. + +=========================================================================*/ +#ifndef cmCabilDefineSetCommand_h +#define cmCabilDefineSetCommand_h + +#include "cmStandardIncludes.h" +#include "cmCabilCommand.h" + +/** \class cmCabilDefineSetCommand + * \brief Define a command that adds a CABIL Set definition. + * + * cmCabilDefineSetCommand is used to define a named CABIL Set. + * The set can be referenced in other CABIL command arguments + * with a '$' followed by the set name. + */ +class cmCabilDefineSetCommand : public cmCabilCommand +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmCabilDefineSetCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool Invoke(std::vector& args); + + /** + * This determines if the command gets propagated down + * to makefiles located in subdirectories. + */ + virtual bool IsInherited() + {return true;} + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() { return "CABIL_DEFINE_SET";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() + { + return "Define a CABIL Set."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() + { + return + "CABIL_DEFINE_SET(name_of_set member1 member2 ...)"; + } + + virtual void WriteConfiguration(std::ostream&) const; + + cmTypeMacro(cmCabilDefineSetCommand, cmCabilCommand); +private: + typedef std::vector Elements; + + /** + * The name of the set. + */ + std::string m_SetName; + + /** + * The elements to be defined in the set (before $ expansion). + */ + Elements m_Elements; +}; + + + +#endif diff --git a/Source/cmCableInstantiateCommand.cxx b/Source/cmCableInstantiateCommand.cxx new file mode 100644 index 000000000..bd2749856 --- /dev/null +++ b/Source/cmCableInstantiateCommand.cxx @@ -0,0 +1,101 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) 2000 National Library of Medicine + All rights reserved. + + See COPYRIGHT.txt for copyright details. + +=========================================================================*/ +#include "cmCabilInstantiateCommand.h" +#include "cmCacheManager.h" + +#include "cmCabilDefineSetCommand.h" + +// cmCabilInstantiateCommand +bool cmCabilInstantiateCommand::Invoke(std::vector& args) +{ + if(args.size() < 2) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + + // This command instance needs to use the cmCabilData instance. + this->SetupCabilData(); + + std::vector::const_iterator arg = args.begin(); + + // Get the output file into which the configuration code is to be + // written. The name of the file is the first argument. + m_OutputFile = m_CabilData->GetOutputFile(*arg++, this); + + // The rest of the arguments are the elements to be placed in the set. + for(; arg != args.end(); ++arg) + { + m_Elements.push_back(*arg); + } + + return true; +} + + +void cmCabilInstantiateCommand::FinalPass() +{ + // If this command is the first to reference its output file, write the + // header information. + if(m_OutputFile->FirstReferencingCommandIs(this)) + { + this->WriteConfigurationHeader(m_OutputFile->GetStream()); + + // Need to write out the Set definitions. + // Look through the vector of commands from the makefile. + const std::vector& usedCommands = + m_Makefile->GetUsedCommands(); + for(std::vector::const_iterator commandIter = + usedCommands.begin(); + commandIter != usedCommands.end(); ++commandIter) + { + // If this command is a cmCabilDefineSetCommand, ask it to write its + // configuration code to the output file. + cmCabilDefineSetCommand* command = + cmCabilDefineSetCommand::SafeDownCast(*commandIter); + if(command) + { + command->WriteConfiguration(m_OutputFile->GetStream()); + } + } + } + + // Write the instantiation block's code. + this->WriteConfiguration(m_OutputFile->GetStream()); + + // If this command is the last to reference its output file, write the + // footer information. + if(m_OutputFile->LastReferencingCommandIs(this)) + { + this->WriteConfigurationFooter(m_OutputFile->GetStream()); + } +} + + +/** + * Write the CABIL configuration code to define this InstantiationSet. + */ +void cmCabilInstantiateCommand::WriteConfiguration(std::ostream& os) const +{ + os << std::endl + << " " << std::endl; + for(Elements::const_iterator e = m_Elements.begin(); + e != m_Elements.end(); ++e) + { + os << " " << e->c_str() << "" << std::endl; + } + os << " " << std::endl; +} diff --git a/Source/cmCableInstantiateCommand.h b/Source/cmCableInstantiateCommand.h new file mode 100644 index 000000000..477fee2e8 --- /dev/null +++ b/Source/cmCableInstantiateCommand.h @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) 2000 National Library of Medicine + All rights reserved. + + See COPYRIGHT.txt for copyright details. + +=========================================================================*/ +#ifndef cmCabilInstantiateCommand_h +#define cmCabilInstantiateCommand_h + +#include "cmStandardIncludes.h" +#include "cmCabilCommand.h" + +/** \class cmCabilInstantiateCommand + * \brief Define a command that generates a rule for explicit template + * instantiations. + * + * cmCabilInstantiateCommand is used to generate a rule in a CABIL + * configuration file to create explicit template instantiations. + */ +class cmCabilInstantiateCommand : public cmCabilCommand +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmCabilInstantiateCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool Invoke(std::vector& args); + + /** + * This is called after all input commands have been processed. + */ + virtual void FinalPass(); + + /** + * This determines if the command gets propagated down + * to makefiles located in subdirectories. + */ + virtual bool IsInherited() + {return true;} + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() { return "CABIL_INSTANTIATE";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() + { + return "Define a rule for creating explicit template instantiations."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() + { + return + "CABIL_INSTANTIATE(cabil_config_file member1 member2 ...)"; + } + + virtual void WriteConfiguration(std::ostream&) const; + + cmTypeMacro(cmCabilInstantiateCommand, cmCabilCommand); +private: + typedef std::vector Elements; + + /** + * The output file to which to write the configuration. + */ + cmCabilData::OutputFile* m_OutputFile; + + /** + * The elements describing the set of instantiations. + */ + Elements m_Elements; +}; + + + +#endif diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 5049d5cbf..a2e6c5ab2 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -24,6 +24,10 @@ #include "cmWin32DefinesCommand.cxx" #include "cmWin32LibrariesCommand.cxx" #include "cmConfigureFileNoAutoconf.cxx" +#include "cmCabilCommand.cxx" +#include "cmCabilData.cxx" +#include "cmCabilDefineSetCommand.cxx" +#include "cmCabilInstantiateCommand.cxx" #include "cmFindFileCommand.cxx" #include "cmWrapTclCommand.cxx" @@ -50,6 +54,8 @@ void GetPredefinedCommands(std::list& commands) commands.push_back(new cmWin32DefinesCommand); commands.push_back(new cmWin32LibrariesCommand); commands.push_back(new cmConfigureFileNoAutoconf); + commands.push_back(new cmCabilDefineSetCommand); + commands.push_back(new cmCabilInstantiateCommand); commands.push_back(new cmFindFileCommand); commands.push_back(new cmWrapTclCommand); }