Преглед на файлове

ENH: Implemented automatic tag generation for CABIL_DEFINE_SET command. Added tag output to WriteConfiguration methods. Added CABIL_INSTANTIATE_CLASS command to generate explicit class template instantiation configuration output.

Brad King преди 25 години
родител
ревизия
711c652edb

+ 9 - 1
Source/cmCableCommand.h

@@ -21,7 +21,15 @@
 #include "cmCabilData.h"
 
 /** \class cmCabilCommand
- * \brief Superclass for all CABIL_ command classes.
+ * \brief Superclass for all cmCabil command classes.
+ *
+ * cmCabilCommand is the superclass for all CABIL-related commands.
+ * The C++ Automated Bindings for Interpreted Languages (CABIL,
+ * pronounced "sawbill") tool is configured using an XML input file.
+ * The input format is quite flexible, but XML is hard for humans to
+ * write by hand.  The CABIL commands in CMake are designed to simplify
+ * the interface with only a small loss in functionality.  These commands
+ * can be used to automatically generate CABIL configuration files.
  */
 class cmCabilCommand : public cmCommand
 {

+ 102 - 2
Source/cmCableDefineSetCommand.cxx

@@ -16,6 +16,8 @@
 #include "cmCabilDefineSetCommand.h"
 #include "cmCacheManager.h"
 
+#include "cmRegularExpression.h"
+
 
 // cmCabilDefineSetCommand
 bool cmCabilDefineSetCommand::Invoke(std::vector<std::string>& args)
@@ -34,7 +36,7 @@ bool cmCabilDefineSetCommand::Invoke(std::vector<std::string>& args)
   // The rest of the arguments are the elements to be placed in the set.
   for(; arg != args.end(); ++arg)
     {
-    m_Elements.push_back(*arg);
+    m_Elements.push_back(Element(this->GenerateTag(*arg), *arg));
     }
   
   return true;
@@ -46,11 +48,109 @@ bool cmCabilDefineSetCommand::Invoke(std::vector<std::string>& args)
  */
 void cmCabilDefineSetCommand::WriteConfiguration(std::ostream& os) const
 {
+  cmRegularExpression needCdataBlock("[&<>]");
+  
   os << "  <Set name=\"" << m_SetName.c_str() << "\">" << std::endl;
   for(Elements::const_iterator e = m_Elements.begin();
       e != m_Elements.end(); ++e)
     {
-    os << "    <Element>" << e->c_str() << "</Element>" << std::endl;
+    os << "    <Element";
+    // Only output the tag if it is not the empty string.
+    if(e->first.length() > 0)
+      {
+      os << " tag=\"" << e->first.c_str() << "\"";
+      }
+    os << ">";
+    if(needCdataBlock.find(e->second.c_str()))
+      {
+      os << "<![CDATA[" << e->second.c_str() << "]]>";
+      }
+    else
+      {
+      os << e->second.c_str();
+      }
+    os << "</Element>" << std::endl;
     }
   os << "  </Set>" << std::endl;
 }
+
+
+/**
+ * Given the string representing a set element, automatically generate
+ * the CABIL element tag for it.
+ *
+ * **This function determines how the output language of all
+ * CABIL-generated wrappers will look!**
+ */
+std::string
+cmCabilDefineSetCommand::GenerateTag(const std::string& element) const
+{
+  // Hold the regular expressions for matching against the element.
+  cmRegularExpression regex;
+  
+  // If the element's code begins in a $, it is referring to a set name.
+  // The set's elements have their own tags, so we don't need one.
+  regex.compile("^[ \t]*\\$");
+  if(regex.find(element))
+    { return ""; }
+  
+  // Test for simple integer
+  regex.compile("^[ \t]*([0-9]*)[ \t]*$");
+  if(regex.find(element))
+    {
+    std::string tag = "_";
+    tag.append(regex.match(1));
+    return tag;
+    }
+
+  // Test for basic integer type
+  regex.compile("^[ \t]*(unsigned[ ]|signed[ ])?[ \t]*(char|short|int|long|long[ ]long)[ \t]*$");
+  if(regex.find(element))
+    {
+    std::string tag = "_";
+    if(regex.match(1) == "unsigned ")
+      { tag.append("u"); }
+    if(regex.match(2) == "long long")
+      { tag.append("llong"); }
+    else
+      { tag.append(regex.match(2)); }
+    return tag;
+    }
+
+  // Test for basic floating-point type
+  regex.compile("^[ \t]*(long[ ])?[ \t]*(float|double)[ \t]*$");
+  if(regex.find(element))
+    {
+    std::string tag = "_";
+    if(regex.match(1) == "long ")
+      tag.append("l");
+    tag.append(regex.match(2));
+    return tag;
+    }
+
+  // Test for basic wide-character type
+  regex.compile("^[ \t]*(wchar_t)[ \t]*$");
+  if(regex.find(element))
+    {
+    return "_wchar";
+    }
+
+  // Test for plain type name (without template arguments).
+  regex.compile("^[ \t]*([A-Za-z_][A-Za-z0-9_]*)[ \t]*$");
+  if(regex.find(element))
+    {
+    // The tag is the same as the type.
+    return regex.match(1);
+    }
+  
+  // Test for template class instance.
+  regex.compile("^[ \t]*([A-Za-z_][A-Za-z0-9_]*)<.*[ \t]*$");
+  if(regex.find(element))
+    {
+    // The tag is the type without arguments (the arguments may have
+    // their own tags).
+    return regex.match(1);
+    }
+  
+  return "NO_AUTO_TAG";
+}

+ 10 - 2
Source/cmCableDefineSetCommand.h

@@ -69,14 +69,22 @@ public:
   virtual const char* GetFullDocumentation()
     {
     return
-      "CABIL_DEFINE_SET(name_of_set member1 member2 ...)";
+      "CABIL_DEFINE_SET(name_of_set member1 member2 ...)\n"
+      "Generates a Set definition in the CABIL configuration.  Tags are\n"
+      "automatically generated.  The sets are referenced in other CABIL\n"
+      "commands by a '$' immediately followed by the set name (ex. $SetName).";
     }
 
   virtual void WriteConfiguration(std::ostream&) const;
   
   cmTypeMacro(cmCabilDefineSetCommand, cmCabilCommand);
+  
+private:
+  std::string GenerateTag(const std::string&) const;
+
 private:  
-  typedef std::vector<std::string>  Elements;
+  typedef std::pair<std::string, std::string>  Element;
+  typedef std::vector<Element>  Elements;
   
   /**
    * The name of the set.

+ 47 - 0
Source/cmCableInstantiateClassCommand.cxx

@@ -0,0 +1,47 @@
+/*=========================================================================
+
+  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 "cmCabilInstantiateClassCommand.h"
+#include "cmCacheManager.h"
+
+#include "cmRegularExpression.h"
+
+
+/**
+ * Write the CABIL configuration code to define this InstantiationSet.
+ * This includes the "class" keyword to do class template instantiations.
+ */
+void cmCabilInstantiateClassCommand::WriteConfiguration(std::ostream& os) const
+{
+  cmRegularExpression needCdataBlock("[&<>]");
+  
+  os << std::endl
+     << "  <InstantiationSet>" << std::endl;
+  for(Elements::const_iterator e = m_Elements.begin();
+      e != m_Elements.end(); ++e)
+    {
+    os << "    <Element>class ";
+    if(needCdataBlock.find(e->c_str()))
+      {
+      os << "<![CDATA[" << e->c_str() << "]]>";
+      }
+    else
+      {
+      os << e->c_str();
+      }
+    os << "</Element>" << std::endl;
+    }
+  os << "  </InstantiationSet>" << std::endl;
+}

+ 75 - 0
Source/cmCableInstantiateClassCommand.h

@@ -0,0 +1,75 @@
+/*=========================================================================
+
+  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 cmCabilInstantiateClassCommand_h
+#define cmCabilInstantiateClassCommand_h
+
+#include "cmStandardIncludes.h"
+#include "cmCabilInstantiateCommand.h"
+
+/** \class cmCabilInstantiateClassCommand
+ * \brief Define a command that generates a rule for explicit template
+ * instantiations of classes.
+ *
+ * cmCabilInstantiateCommand is used to generate a rule in a CABIL
+ * configuration file to create explicit template instantiations of
+ * classes.
+ */
+class cmCabilInstantiateClassCommand : public cmCabilInstantiateCommand
+{
+public:
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone() 
+    {
+    return new cmCabilInstantiateClassCommand;
+    }
+
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() { return "CABIL_INSTANTIATE_CLASS";}
+
+  /**
+   * Succinct documentation.
+   */
+  virtual const char* GetTerseDocumentation() 
+    {
+    return "Define CABIL InstantiationSet of classes.";
+    }
+  
+  /**
+   * More documentation.
+   */
+  virtual const char* GetFullDocumentation()
+    {
+    return
+      "CABIL_INSTANTIATE_CLASS(cabil_config_file member1 member2 ...)\n"
+      "Generates an InstantiationSet in the CABIL configuration.  It is\n"
+      "assumed that all members of the set are explicit instantiations of\n"
+      "template classes (not functions, operators, etc).";
+    }
+
+  virtual void WriteConfiguration(std::ostream&) const;  
+
+  cmTypeMacro(cmCabilInstantiateClassCommand, cmCabilInstantiateCommand);
+protected:
+  typedef cmCabilInstantiateCommand::Elements  Elements;
+};
+
+
+
+#endif

+ 13 - 1
Source/cmCableInstantiateCommand.cxx

@@ -17,6 +17,7 @@
 #include "cmCacheManager.h"
 
 #include "cmCabilDefineSetCommand.h"
+#include "cmRegularExpression.h"
 
 // cmCabilInstantiateCommand
 bool cmCabilInstantiateCommand::Invoke(std::vector<std::string>& args)
@@ -97,12 +98,23 @@ void cmCabilInstantiateCommand::FinalPass()
  */
 void cmCabilInstantiateCommand::WriteConfiguration(std::ostream& os) const
 {
+  cmRegularExpression needCdataBlock("[&<>]");
+  
   os << std::endl
      << "  <InstantiationSet>" << std::endl;
   for(Elements::const_iterator e = m_Elements.begin();
       e != m_Elements.end(); ++e)
     {
-    os << "    <Element>" << e->c_str() << "</Element>" << std::endl;
+    os << "    <Element>";
+    if(needCdataBlock.find(e->c_str()))
+      {
+      os << "<![CDATA[" << e->c_str() << "]]>";
+      }
+    else
+      {
+      os << e->c_str();
+      }
+    os << "</Element>" << std::endl;
     }
   os << "  </InstantiationSet>" << std::endl;
 }

+ 6 - 3
Source/cmCableInstantiateCommand.h

@@ -65,7 +65,7 @@ public:
    */
   virtual const char* GetTerseDocumentation() 
     {
-    return "Define a rule for creating explicit template instantiations.";
+    return "Define CABIL InstantiationSet.";
     }
   
   /**
@@ -74,13 +74,16 @@ public:
   virtual const char* GetFullDocumentation()
     {
     return
-      "CABIL_INSTANTIATE(cabil_config_file member1 member2 ...)";
+      "CABIL_INSTANTIATE(cabil_config_file member1 member2 ...)\n"
+      "Generates an InstantiationSet in the CABIL configuration.  It is\n"
+      "assumed that all members of the set are explicit instantiations of\n"
+      "template non-classes (functions, operators, etc).";
     }
 
   virtual void WriteConfiguration(std::ostream&) const;  
 
   cmTypeMacro(cmCabilInstantiateCommand, cmCabilCommand);
-private:
+protected:
   typedef std::vector<std::string>  Elements;
   
   /**

+ 2 - 0
Source/cmCommands.cxx

@@ -28,6 +28,7 @@
 #include "cmCabilData.cxx"
 #include "cmCabilDefineSetCommand.cxx"
 #include "cmCabilInstantiateCommand.cxx"
+#include "cmCabilInstantiateClassCommand.cxx"
 #include "cmFindFileCommand.cxx"
 #include "cmWrapTclCommand.cxx"
 
@@ -56,6 +57,7 @@ void GetPredefinedCommands(std::list<cmCommand*>& commands)
   commands.push_back(new cmConfigureFileNoAutoconf);
   commands.push_back(new cmCabilDefineSetCommand);
   commands.push_back(new cmCabilInstantiateCommand);
+  commands.push_back(new cmCabilInstantiateClassCommand);
   commands.push_back(new cmFindFileCommand);
   commands.push_back(new cmWrapTclCommand);
 }