Browse Source

ENH: Adding CABLE_CLASS_SET and CABLE_WRAP_TCL commands. They cannot yet be used with the main branch of CABLE, though.

Brad King 24 years ago
parent
commit
f08a1b8885

+ 2 - 0
Source/Makefile.in

@@ -25,6 +25,7 @@ cmCommands.o \
 cmTarget.o \
 cmCustomCommand.o \
 cmCacheManager.o \
+cmCableClassSet.o \
 cmSourceGroup.o
 
 DEPENDS = $(srcdir)/*.h  ${CMAKE_CONFIG_DIR}/CMake/Source/cmConfigure.h
@@ -43,6 +44,7 @@ cmUnixMakefileGenerator.o : $(DEPENDS)
 cmCommands.o : $(DEPENDS) $(srcdir)/*Command*.cxx
 cmTarget.o : $(DEPENDS)
 cmCacheManager.o : $(DEPENDS)
+cmCableClassSet.o: $(DEPENDS)
 cmSourceGroup.o : $(DEPENDS)
 
 

+ 199 - 0
Source/cmCableClassSet.cxx

@@ -0,0 +1,199 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+Copyright (c) 2001 Insight Consortium
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+ * The name of the Insight Consortium, nor the names of any consortium members,
+   nor of any contributors, may be used to endorse or promote products derived
+   from this software without specific prior written permission.
+
+  * Modified source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================*/
+#include "cmCableClassSet.h"
+
+
+/**
+ * Add to the set of required sources to define the class.
+ */
+void cmCableClass::AddSource(const char* source)
+{
+  m_Sources.insert(source);
+}
+
+
+/**
+ * Add a class to the set.
+ */
+void cmCableClassSet::AddClass(const char* name,
+                               const cmCableClass& cableClass)
+{
+  m_CableClassMap.insert(CableClassMap::value_type(name, cableClass));
+}
+
+
+/**
+ * Add a source to every class in the set.  This should only be done after
+ * all classes have been inserted.
+ */
+void cmCableClassSet::AddSource(const char* name)
+{
+  for(CableClassMap::iterator c = m_CableClassMap.begin();
+      c != m_CableClassMap.end(); ++c)
+    {
+    c->second.AddSource(name);
+    }
+}
+
+/**
+ * Get the size of the internal CableClassMap used to store the set.
+ */
+unsigned int cmCableClassSet::Size() const
+{
+  return m_CableClassMap.size();
+}
+
+
+/**
+ * Get a begin iterator to the internal CableClassMap used to store the
+ * set.
+ */
+cmCableClassSet::CableClassMap::const_iterator cmCableClassSet::Begin() const
+{
+  return m_CableClassMap.begin();
+}
+
+
+/**
+ * Get an end iterator to the internal CableClassMap used to store the
+ * set.
+ */
+cmCableClassSet::CableClassMap::const_iterator cmCableClassSet::End() const
+{
+  return m_CableClassMap.end();
+}
+
+/**
+ * Parse the given string to extract the class information specified.
+ *
+ * The format of the string is
+ *   [tag:]class_name[;source1;source2;...]
+ *
+ */
+void cmCableClassSet::ParseAndAddElement(const char* element,
+                                         cmMakefile* makefile)
+{
+  // A regular expression to match the tagged element specification.
+  cmRegularExpression tagGiven("^([A-Za-z_0-9]*)[ \t]*:[ \t]*([^:].*|::.*)$");
+
+  // A regular expression to match the element when more source files are given.
+  cmRegularExpression sourcesRemain("^([^;]*);(.*)$");
+
+  std::string tag;
+  std::string elementWithoutTag;
+  std::string className;
+  std::string sourceString;
+
+  if(tagGiven.find(element))
+    {
+    // A tag was given.  Use it.
+    tag = tagGiven.match(1);
+    elementWithoutTag = tagGiven.match(2);
+    }
+  else
+    {
+    // No tag was given.  Try to generate one.
+    //if(!this->GenerateTag(element, tag))
+    //  { return false; }
+    elementWithoutTag = element;
+    }
+  
+  if(sourcesRemain.find(elementWithoutTag.c_str()))
+    {
+    className = sourcesRemain.match(1);
+    sourceString = sourcesRemain.match(2);
+    }
+  else
+    {
+    className = elementWithoutTag;
+    }
+  
+  cmCableClass::Sources sources;
+  
+  while(sourcesRemain.find(sourceString.c_str()))
+    {
+    sources.insert(sourcesRemain.match(1));
+    sourceString = sourcesRemain.match(2);
+    }
+  if(sourceString != "")
+    {
+    sources.insert(sourceString);
+    }
+  
+  // A regular expression to match a class name that is just a set.
+  cmRegularExpression setDereference("^\\$(.*)$");
+  if(setDereference.find(className))
+    {
+    std::string setName = setDereference.match(1);
+    cmData* d = makefile->LookupData(setName.c_str());
+    cmCableClassSet* classSet = dynamic_cast<cmCableClassSet*>(d);
+    if(classSet)
+      {
+      this->AddCableClassSet(*classSet, sources);
+      }
+    else
+      {
+      cmSystemTools::Error("Unknown CABLE class set ", setName.c_str());
+      }
+    }
+  else
+    {
+    cmCableClass cableClass;
+    cableClass.AddSources(sources.begin(), sources.end());
+    this->AddClass(className.c_str(), cableClass);
+    }
+}
+
+
+/**
+ * Add all elements from the given cmCableClassSet to this set, with the given
+ * sources added to each element.
+ */
+void cmCableClassSet::AddCableClassSet(const cmCableClassSet& set,
+                                       const cmCableClass::Sources& sources)
+{
+  for(CableClassMap::const_iterator c = set.Begin(); c != set.End(); ++c)
+    {
+    cmCableClass cableClass = c->second;
+    cableClass.AddSources(sources.begin(), sources.end());
+    this->AddClass(c->first.c_str(), cableClass);
+    }
+}

+ 105 - 0
Source/cmCableClassSet.h

@@ -0,0 +1,105 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+Copyright (c) 2001 Insight Consortium
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+ * The name of the Insight Consortium, nor the names of any consortium members,
+   nor of any contributors, may be used to endorse or promote products derived
+   from this software without specific prior written permission.
+
+  * Modified source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================*/
+#ifndef cmCableClassSet_h
+#define cmCableClassSet_h
+
+#include "cmStandardIncludes.h"
+#include "cmData.h"
+#include "cmMakefile.h"
+
+
+/** \class cmCableClass
+ * \brief Holds one class and the set of header files needed to use it.
+ */
+class cmCableClass
+{
+public:
+  typedef std::set<std::string> Sources;
+  
+  template <typename InputIterator>
+  void AddSources(InputIterator first, InputIterator last)
+    { for(InputIterator i = first; i != last; ++i) { m_Sources.insert(*i); } }
+  void AddSource(const char*);
+
+  Sources::const_iterator SourcesBegin() const { return m_Sources.begin(); }
+  Sources::const_iterator SourcesEnd() const { return m_Sources.end(); }
+  
+private:
+  /**
+   * Store the set of source files (headers) needed to define this class.
+   */
+  Sources m_Sources;
+};
+
+
+/** \class cmCableClassSet
+ * \brief Holds a set of classes, each with their own set of required headers.
+ */
+class cmCableClassSet: public cmData
+{
+public:
+  cmCableClassSet(const char* name): cmData(name) {}
+  virtual ~cmCableClassSet() {}
+
+  /**
+   * The set is stored internally as a map from class name to cmCableClass
+   * instance.
+   */
+  typedef std::map<std::string, cmCableClass> CableClassMap;
+  
+  void AddClass(const char*, const cmCableClass&);
+  void AddSource(const char* name);
+  unsigned int Size() const;
+  CableClassMap::const_iterator Begin() const;
+  CableClassMap::const_iterator End() const;
+
+  void ParseAndAddElement(const char*, cmMakefile*);
+  void AddCableClassSet(const cmCableClassSet&, const cmCableClass::Sources&);
+  
+private:
+  /**
+   * The set is stored internally as a map from class name to cmCableClass
+   * instance.
+   */
+  CableClassMap m_CableClassMap;
+};
+
+#endif

+ 81 - 0
Source/cmCableClassSetCommand.cxx

@@ -0,0 +1,81 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+Copyright (c) 2001 Insight Consortium
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+ * The name of the Insight Consortium, nor the names of any consortium members,
+   nor of any contributors, may be used to endorse or promote products derived
+   from this software without specific prior written permission.
+
+  * Modified source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================*/
+#include "cmCableClassSetCommand.h"
+#include "cmCacheManager.h"
+#include "cmTarget.h"
+
+// cmCableClassSetCommand
+bool cmCableClassSetCommand::Invoke(std::vector<std::string>& args)
+{
+  if(args.size() < 2)
+    {
+    this->SetError("called with incorrect number of arguments");
+    return false;
+    }
+  
+  // The first argument is the name of the set.
+  std::vector<std::string>::const_iterator arg = args.begin();
+  m_ClassSetName = *arg++;
+  
+  // Create the new class set.
+  cmCableClassSet* classSet = new cmCableClassSet(m_ClassSetName.c_str());
+  
+  // Add all the regular entries.
+  for(; (arg != args.end()) && (*arg != "SOURCES_BEGIN"); ++arg)
+    {
+    classSet->ParseAndAddElement(arg->c_str(), m_Makefile);
+    }
+  
+  // Add any sources that are associated with all the members.
+  if(arg != args.end())
+    {
+    for(++arg; arg != args.end(); ++arg)
+      {
+      classSet->AddSource(arg->c_str());
+      }
+    }
+  
+  // Store the class set in the makefile.
+  m_Makefile->RegisterData(classSet);
+  
+  return true;
+}
+

+ 106 - 0
Source/cmCableClassSetCommand.h

@@ -0,0 +1,106 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+Copyright (c) 2001 Insight Consortium
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+ * The name of the Insight Consortium, nor the names of any consortium members,
+   nor of any contributors, may be used to endorse or promote products derived
+   from this software without specific prior written permission.
+
+  * Modified source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================*/
+#ifndef cmCableClassSetCommand_h
+#define cmCableClassSetCommand_h
+
+#include "cmStandardIncludes.h"
+#include "cmCommand.h"
+#include "cmCableClassSet.h"
+
+/** \class cmCableClassSetCommand
+ *
+ */
+class cmCableClassSetCommand : public cmCommand
+{
+public:
+  cmCableClassSetCommand() {}
+  virtual ~cmCableClassSetCommand() {}
+
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone()
+    {
+      return new cmCableClassSetCommand;
+    }
+
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool Invoke(std::vector<std::string>& args);
+  
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() { return "CABLE_CLASS_SET";}
+
+  /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() 
+    {
+    return "Define a set of classes for use in other CABLE commands.";
+    }
+  
+  /**
+   * More documentation.
+   */
+  virtual const char* GetFullDocumentation()
+    {
+    return
+      "CABLE_CLASS_SET(set_name class1 class2 ...)\n"
+      "Defines a set with the given name containing classes and their\n"
+      "associated header files.  The set can later be used by other CABLE\n"
+      "commands.";
+    }  
+
+  cmTypeMacro(cmCableClassSetCommand, cmCommand);
+private:
+  /**
+   * The name of the class set.
+   */
+  std::string m_ClassSetName;  
+};
+
+
+
+#endif

+ 307 - 0
Source/cmCableWrapTclCommand.cxx

@@ -0,0 +1,307 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+Copyright (c) 2001 Insight Consortium
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+ * The name of the Insight Consortium, nor the names of any consortium members,
+   nor of any contributors, may be used to endorse or promote products derived
+   from this software without specific prior written permission.
+
+  * Modified source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================*/
+#include "cmCableWrapTclCommand.h"
+#include "cmCacheManager.h"
+#include "cmTarget.h"
+#include "cmGeneratedFileStream.h"
+#include <strstream>
+
+cmCableWrapTclCommand::cmCableWrapTclCommand():
+  m_CableClassSet(NULL)
+{
+}
+
+cmCableWrapTclCommand::~cmCableWrapTclCommand()
+{
+  if(m_CableClassSet)
+    {
+    delete m_CableClassSet;
+    }
+}
+
+
+
+// cmCableWrapTclCommand
+bool cmCableWrapTclCommand::Invoke(std::vector<std::string>& args)
+{
+  if(args.size() < 2)
+    {
+    this->SetError("called with incorrect number of arguments");
+    return false;
+    }
+  
+  // Prepare to iterate through the arguments.
+  std::vector<std::string>::const_iterator arg = args.begin();
+  
+  // The first argument is the name of the target.
+  m_TargetName = *arg++;
+  
+  // Create the new class set.
+  m_CableClassSet = new cmCableClassSet(m_TargetName.c_str());
+  
+  // Add all the regular entries.
+  for(; (arg != args.end()) && (*arg != "SOURCES_BEGIN"); ++arg)
+    {
+    m_CableClassSet->ParseAndAddElement(arg->c_str(), m_Makefile);
+    }
+  
+  // Add any sources that are associated with all the members.
+  if(arg != args.end())
+    {
+    for(++arg; arg != args.end(); ++arg)
+      {
+      m_CableClassSet->AddSource(arg->c_str());
+      }
+    }  
+
+  this->GenerateCableFiles();
+  
+  // Add the source list to the target.
+  m_Makefile->GetTargets()[m_TargetName.c_str()].GetSourceLists().push_back(m_TargetName);
+  
+  return true;
+}
+
+
+/**
+ * Generate the files that CABLE will use to generate the wrappers.
+ */
+void cmCableWrapTclCommand::GenerateCableFiles() const
+{
+  // Setup the output directory.
+  std::string outDir = m_Makefile->GetCurrentOutputDirectory();
+  cmSystemTools::MakeDirectory((outDir+"/Tcl").c_str());
+
+  std::string packageConfigName = outDir+"/Tcl/"+m_TargetName+"_config.xml";
+  std::string packageTclName = outDir+"/Tcl/"+m_TargetName+"_tcl";
+  
+  // Generate the main package configuration file for CABLE.
+  cmGeneratedFileStream packageConfig(packageConfigName.c_str());
+  if(packageConfig)
+    {
+    packageConfig <<
+      "<CableConfiguration package=\"" << m_TargetName.c_str() << "\">\n"
+      "  <Groups>\n";
+    for(unsigned int i=0; i < m_CableClassSet->Size(); ++i)
+      {
+      packageConfig <<
+        "  " << m_TargetName.c_str() << "_" << i << "\n";
+      }
+    packageConfig <<
+      "  </Groups>\n"
+      "</CableConfiguration>\n";
+  
+    packageConfig.close();
+    }
+  else
+    {
+    cmSystemTools::Error("Error opening CABLE configuration file for writing: ",
+                         packageConfigName.c_str());
+    }
+
+  {
+  std::string command = "${CABLE}";
+  m_Makefile->ExpandVariablesInString(command);
+  std::vector<std::string> depends;
+  depends.push_back(command);
+  command = cmSystemTools::EscapeSpaces(command.c_str());
+  command += " "+packageConfigName+" -tcl "+packageTclName+".cxx";
+  
+  depends.push_back(packageConfigName);
+  
+  std::vector<std::string> outputs;
+  outputs.push_back(packageTclName+".cxx");
+  
+  m_Makefile->AddCustomCommand(packageConfigName.c_str(),
+                               command.c_str(),
+                               depends,
+                               outputs, m_TargetName.c_str());
+  }
+  
+  // Add the generated source to the package's source list.
+  cmSourceFile file;
+  file.SetName(packageTclName.c_str(), outDir.c_str(), "cxx", false);
+  // Set dependency hints.
+  file.GetDepends().push_back("wrapCalls.h");
+  m_Makefile->AddSource(file, m_TargetName.c_str());
+  
+  unsigned int index = 0;
+  for(cmCableClassSet::CableClassMap::const_iterator
+        c = m_CableClassSet->Begin(); c != m_CableClassSet->End(); ++c, ++index)
+    {
+    this->GenerateCableClassFiles(c->first.c_str(), c->second, index);
+    }
+  
+}
+
+
+void cmCableWrapTclCommand::GenerateCableClassFiles(const char* name,
+                                                    const cmCableClass& c,
+                                                    unsigned int index) const
+{
+  std::strstream indexStrStream;
+  indexStrStream << index << std::ends;
+  std::string indexStr = indexStrStream.str();
+  
+  std::string outDir = m_Makefile->GetCurrentOutputDirectory();  
+  
+  std::string className = name;
+  std::string groupName = m_TargetName+"_"+indexStr;
+  std::string classConfigName = outDir+"/Tcl/"+groupName+"_config_tcl.xml";
+  std::string classCxxName = outDir+"/Tcl/"+groupName+"_cxx_tcl.cxx";
+  std::string classXmlName = outDir+"/Tcl/"+groupName+"_cxx_tcl.xml";
+  std::string classTclName = outDir+"/Tcl/"+groupName+"_tcl";
+  
+  cmGeneratedFileStream classConfig(classConfigName.c_str());
+  if(classConfig)
+    {
+    classConfig <<
+      "<CableConfiguration source=\"" << classXmlName.c_str() << "\" "
+      "group=\"" << groupName.c_str() << "\">\n";
+    for(cmCableClass::Sources::const_iterator source = c.SourcesBegin();
+        source != c.SourcesEnd(); ++source)
+      {
+      classConfig <<
+        "  <Header name=\"" << source->c_str() << "\"/>\n";
+      }
+    classConfig <<
+      "  <WrapperSet>\n"
+      "  _wrap_::wrapper::Wrapper\n"
+      "  </WrapperSet>\n"
+      "</CableConfiguration>\n";
+  
+    classConfig.close();
+    }
+  else
+    {
+    cmSystemTools::Error("Error opening CABLE configuration file for writing: ",
+                         classConfigName.c_str());
+    }
+
+  cmGeneratedFileStream classCxx(classCxxName.c_str());
+  if(classCxx)
+    {
+    for(cmCableClass::Sources::const_iterator source = c.SourcesBegin();
+        source != c.SourcesEnd(); ++source)
+      {
+      classCxx <<
+        "#include \"" << source->c_str() << "\"\n";
+      }
+    classCxx <<
+      "\n"
+      "namespace _wrap_\n"
+      "{\n"
+      "\n"
+      "struct wrapper\n"
+      "{\n"
+      "  typedef ::" << className.c_str() << " Wrapper;\n"
+      "};\n"
+      "\n"
+      "template <typename T> void Eat(T) {}\n"
+      "\n"
+      "void InstantiateMemberDeclarations()\n"
+      "{\n"
+      "  Eat(sizeof(wrapper::Wrapper));\n"
+      "}\n"
+      "\n"
+      "}\n";
+    
+    classCxx.close();
+    }
+  else
+    {
+    cmSystemTools::Error("Error opening file for writing: ",
+                         classCxxName.c_str());
+    }
+  
+  {
+  std::string command = "${GCCXML}";
+  m_Makefile->ExpandVariablesInString(command);
+  // Only add the rule if GCC-XML is available.
+  if((command != "") && (command != "${GCCXML}"))
+    {
+    std::vector<std::string> depends;
+    depends.push_back(command);
+    command = cmSystemTools::EscapeSpaces(command.c_str());
+    command += " ${CMAKE_CXXFLAGS} ${INCLUDE_FLAGS} -fsyntax-only -fxml=" + classXmlName + " " + classCxxName;
+    
+    std::vector<std::string> outputs;
+    outputs.push_back(classXmlName);
+    
+    m_Makefile->AddCustomCommand(classCxxName.c_str(),
+                                 command.c_str(),
+                                 depends,
+                                 outputs, m_TargetName.c_str());
+    }
+  }
+
+  {
+  std::string command = "${CABLE}";
+  m_Makefile->ExpandVariablesInString(command);
+  std::vector<std::string> depends;
+  depends.push_back(command);
+  command = cmSystemTools::EscapeSpaces(command.c_str());
+  command += " "+classConfigName+" -tcl "+classTclName+".cxx";
+  
+  depends.push_back(classConfigName);
+  depends.push_back(classXmlName);
+  
+  std::vector<std::string> outputs;
+  outputs.push_back(classTclName+".cxx");
+  
+  m_Makefile->AddCustomCommand(classConfigName.c_str(),
+                               command.c_str(),
+                               depends,
+                               outputs, m_TargetName.c_str());
+  }
+
+  // Add the generated source to the package's source list.
+  cmSourceFile file;
+  file.SetName(classTclName.c_str(), outDir.c_str(), "cxx", false);
+  // Set dependency hints.
+  for(cmCableClass::Sources::const_iterator source = c.SourcesBegin();
+      source != c.SourcesEnd(); ++source)
+    {
+    file.GetDepends().push_back(*source);
+    }
+  file.GetDepends().push_back("wrapCalls.h");
+  m_Makefile->AddSource(file, m_TargetName.c_str());
+}

+ 121 - 0
Source/cmCableWrapTclCommand.h

@@ -0,0 +1,121 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+Copyright (c) 2001 Insight Consortium
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+ * The name of the Insight Consortium, nor the names of any consortium members,
+   nor of any contributors, may be used to endorse or promote products derived
+   from this software without specific prior written permission.
+
+  * Modified source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================*/
+#ifndef cmCableWrapTclCommand_h
+#define cmCableWrapTclCommand_h
+
+#include "cmStandardIncludes.h"
+#include "cmCommand.h"
+#include "cmCableClassSet.h"
+
+/** \class cmCableWrapTclCommand
+ * \brief Define a command that wraps a set of classes in Tcl.
+ */
+class cmCableWrapTclCommand : public cmCommand
+{
+public:
+  cmCableWrapTclCommand();
+  virtual ~cmCableWrapTclCommand();
+
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone()
+    {
+      return new cmCableWrapTclCommand;
+    }
+
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool Invoke(std::vector<std::string>& args);  
+  
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() { return "CABLE_WRAP_TCL";}
+
+  /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() 
+    {
+    return "Wrap a set of classes in Tcl.";
+    }
+  
+  /**
+   * More documentation.
+   */
+  virtual const char* GetFullDocumentation()
+    {
+    return
+      "CABLE_WRAP_TCL(target class1 class2 ...)\n"
+      "Wrap the given set of classes in Tcl using the CABLE tool.  The set\n"
+      "of source files produced for the given package name will be added to\n"
+      "a source list with the given name.";
+    }
+  
+  cmTypeMacro(cmCableWrapTclCommand, cmCommand);
+
+protected:
+  void GenerateCableFiles() const;
+  void GenerateCableClassFiles(const char*, const cmCableClass&, unsigned int) const;
+  
+private:
+  /**
+   * The name of the package of wrappers to produce.
+   */
+  std::string m_TargetName;
+  
+  /**
+   * The name of the source list into which the files needed for the package
+   * will be placed.
+   */
+  std::string m_SourceListName;
+  
+  /**
+   * The set of classes to be wrapped in the package.  This is also implicitly
+   * added to the makefile as another set.
+   */
+  cmCableClassSet* m_CableClassSet;
+};
+
+#endif

+ 4 - 0
Source/cmCommands.cxx

@@ -12,6 +12,7 @@
 #include "cmBuildCommand.cxx"
 #include "cmBuildNameCommand.cxx"
 #include "cmBuildSharedLibrariesCommand.cxx"
+#include "cmCableClassSetCommand.cxx"
 #include "cmCableCloseNamespaceCommand.cxx"
 #include "cmCableCommand.cxx"
 #include "cmCableData.cxx"
@@ -22,6 +23,7 @@
 #include "cmCablePackageCommand.cxx"
 #include "cmCablePackageEntryCommand.cxx"
 #include "cmCableSourceFilesCommand.cxx"
+#include "cmCableWrapTclCommand.cxx"
 #include "cmCableWrapCommand.cxx"
 #include "cmConfigureFileCommand.cxx"
 #include "cmConfigureFileNoAutoconf.cxx"
@@ -67,6 +69,7 @@ void GetPredefinedCommands(std::list<cmCommand*>& commands)
   commands.push_back(new cmBuildCommand);
   commands.push_back(new cmBuildNameCommand);
   commands.push_back(new cmBuildSharedLibrariesCommand);
+  commands.push_back(new cmCableClassSetCommand);
   commands.push_back(new cmCableCloseNamespaceCommand);
   commands.push_back(new cmCableDefineSetCommand);
   commands.push_back(new cmCableInstantiateCommand);
@@ -74,6 +77,7 @@ void GetPredefinedCommands(std::list<cmCommand*>& commands)
   commands.push_back(new cmCableOpenNamespaceCommand);
   commands.push_back(new cmCablePackageCommand);
   commands.push_back(new cmCableSourceFilesCommand);
+  commands.push_back(new cmCableWrapTclCommand);
   commands.push_back(new cmCableWrapCommand);
   commands.push_back(new cmConfigureFileCommand);
   commands.push_back(new cmConfigureFileNoAutoconf);