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);
}