Browse Source

add per-overload comments and make_seq synthetic functions to interrogatedb

David Rose 16 years ago
parent
commit
1872104e61

+ 12 - 0
dtool/Config.pp

@@ -925,6 +925,18 @@
 // compiled-in font).
 #define COMPILE_IN_DEFAULT_FONT 1
 
+// We use wxWidgets--the C++ library, not the Python library--for
+// building the application p3dcert, which is needed only when
+// building the plugin/runtime system.  This uses a wx-config program,
+// similar to freetype, above.
+#defer WX_CONFIG $[if $[not $[WINDOWS_PLATFORM]],wx-config]
+#defer HAVE_WX $[or $[libtest $[WX_LPATH],$[WX_LIBS]],$[bintest $[WX_CONFIG]]]
+
+#define WX_CFLAGS 
+#define WX_IPATH
+#define WX_LPATH 
+#define WX_LIBS 
+
 // Is Maya installed?  This matters only to programs in PANDATOOL.
 
 // Also, as of Maya 5.0 it seems the Maya library will not compile

+ 5 - 0
dtool/LocalSetup.pp

@@ -116,6 +116,11 @@
 #else
 #print - Did not find Freetype
 #endif
+#if $[HAVE_WX]
+#print + WxWidgets
+#else
+#print - Did not find WxWidgets
+#endif
 #if $[HAVE_GL]
 #print + OpenGL
 #elif $[HAVE_GLES2]

+ 17 - 0
dtool/Package.pp

@@ -308,6 +308,13 @@
 #set FREETYPE_LPATH $[unixfilename $[FREETYPE_LPATH]]
 #set FREETYPE_LIBS $[FREETYPE_LIBS]
 
+#set WX_CONFIG $[WX_CONFIG]
+#set HAVE_WX $[HAVE_WX]
+#set WX_CFLAGS $[WX_CFLAGS]
+#set WX_IPATH $[unixfilename $[WX_IPATH]]
+#set WX_LPATH $[unixfilename $[WX_LPATH]]
+#set WX_LIBS $[WX_LIBS]
+
 
 #set MAYA_LOCATION $[unixfilename $[MAYA_LOCATION]]
 #set HAVE_MAYA $[HAVE_MAYA]
@@ -346,6 +353,16 @@
   #define FREETYPE_LIBS $[patsubst -l%,%,$[filter -l%,$[libs]]]
 #endif
 
+#if $[and $[HAVE_WX],$[WX_CONFIG]]
+  #define cflags $[shell $[WX_CONFIG] --cflags]
+  #define libs $[shell $[WX_CONFIG] --libs adv,html,xml,core,base]
+
+  #define WX_CFLAGS $[filter-out -I%,$[cflags]]
+  #define WX_IPATH $[unique $[patsubst -I%,%,$[filter -I%,$[cflags]]]]
+  #define WX_LPATH $[unique $[patsubst -L%,%,$[filter -L%,$[libs]]]]
+  #define WX_LIBS $[patsubst -l%,%,$[filter -l%,$[libs]]]
+#endif
+
 #if $[HAVE_PHYSX]
   #define GENPYCODE_LIBS $[GENPYCODE_LIBS] libpandaphysx
 #endif

+ 8 - 0
dtool/pptempl/Global.pp

@@ -349,6 +349,14 @@
   #define freetype_framework $[FREETYPE_FRAMEWORK]
 #endif
 
+#if $[HAVE_WX]
+  #define wx_ipath $[wildcard $[WX_IPATH]]
+  #define wx_lpath $[wildcard $[WX_LPATH]]
+  #define wx_cflags $[WX_CFLAGS]
+  #define wx_libs $[WX_LIBS]
+  #define wx_framework $[WX_FRAMEWORK]
+#endif
+
 #if $[and $[HAVE_MAYA],$[MAYA_LOCATION]]
   #define maya_ipath $[MAYA_LOCATION]/include
   #define maya_lpath $[MAYA_LOCATION]/lib

+ 5 - 0
dtool/src/interrogate/functionRemap.cxx

@@ -263,6 +263,11 @@ make_wrapper_entry(FunctionIndex function_index) {
   iwrapper._name = _wrapper_name;
   iwrapper._unique_name = _unique_name;
 
+  if (_cppfunc->_leading_comment != (CPPCommentBlock *)NULL) {
+    iwrapper._comment = InterrogateBuilder::trim_blanks(_cppfunc->_leading_comment->_comment);
+  }
+
+
   if (output_function_names) {
     // If we're keeping the function names, record that the wrapper is
     // callable.

+ 3 - 0
dtool/src/interrogate/interfaceMaker.cxx

@@ -154,6 +154,9 @@ check_protocols() {
           string wrapper_name = "MakeSeq_" + clean_name + "_" + cpp_make_seq->_seq_name;
           MakeSeq *make_seq = new MakeSeq(wrapper_name, cpp_make_seq);
           _make_seqs.push_back(make_seq);
+
+          // Also add to the interrogate database.
+          builder.get_make_seq(cpp_make_seq, stype);
         }
       }
     }

+ 96 - 27
dtool/src/interrogate/interrogateBuilder.cxx

@@ -44,6 +44,7 @@
 #include "cppTypeDeclaration.h"
 #include "cppEnumType.h"
 #include "cppCommentBlock.h"
+#include "cppMakeSeq.h"
 #include "pnotify.h"
 
 #include <ctype.h>
@@ -257,24 +258,17 @@ build() {
   for (di = parser._declarations.begin();
        di != parser._declarations.end();
        ++di) {
-    if ((*di)->get_subtype() == CPPDeclaration::ST_instance) 
-    {
+    if ((*di)->get_subtype() == CPPDeclaration::ST_instance) {
       CPPInstance *inst = (*di)->as_instance();
-      if (inst->_type->get_subtype() == CPPDeclaration::ST_function) 
-      {
+      if (inst->_type->get_subtype() == CPPDeclaration::ST_function) {
         // Here's a function declaration.
         scan_function(inst);
-
-      }
-      else 
-      {
+      } else {
         // Here's a data element declaration.
         scan_element(inst, (CPPStructType *)NULL, &parser);
       }
 
-    }
-    else if ((*di)->get_subtype() == CPPDeclaration::ST_typedef) 
-    {
+    } else if ((*di)->get_subtype() == CPPDeclaration::ST_typedef) {
       CPPTypedef *tdef = (*di)->as_typedef();
       if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct) {
         // A typedef counts as a declaration.  This lets us pick up
@@ -1081,7 +1075,7 @@ scan_function(CPPInstance *function) {
       // declaration for the method (since it's appearing
       // out-of-scope).  We don't need to define a new method for it,
       // but we'd like to update the comment, if we have a comment.
-      update_method_comment(function, scope->get_struct_type(), scope);
+      update_function_comment(function, scope);
       return;
     }
   }
@@ -1094,6 +1088,11 @@ scan_function(CPPInstance *function) {
   if (function->_file.is_c_file()) {
     // This function declaration appears in a .C file.  We can only
     // export functions whose prototypes appear in an .h file.
+
+    string function_name = TypeManager::get_function_name(function);
+
+    // Still, we can update the comment, at least.
+    update_function_comment(function, scope);
     return;
   }
 
@@ -1680,17 +1679,36 @@ get_function(CPPInstance *function, string description,
 
     ifunction._flags |= flags;
 
-    // And/or the comment.
+    // Also, make sure this particular signature is defined.
+    pair<InterrogateFunction::Instances::iterator, bool> result = 
+      ifunction._instances->insert(InterrogateFunction::Instances::value_type(function_signature, function));
+
+    InterrogateFunction::Instances::iterator ii = result.first;
+    bool inserted = result.second;
+
+    if (inserted) {
+      // If we just added the new signature, append the prototype.
+      ostringstream prototype;
+      function->output(prototype, 0, &parser, false);
+      prototype << ";";
+      ifunction._prototype += "\n" + prototype.str();
+    }
+
+    // Also set the comment.
     if (function->_leading_comment != (CPPCommentBlock *)NULL) {
       string comment = trim_blanks(function->_leading_comment->_comment);
       if (!ifunction._comment.empty()) {
         ifunction._comment += "\n\n";
       }
       ifunction._comment += comment;
-    }
 
-    // Also, make sure this particular signature is defined.
-    ifunction._instances->insert(InterrogateFunction::Instances::value_type(function_signature, function));
+      // And update the particular wrapper comment.
+      if ((*ii).second->_leading_comment == NULL ||
+          function->_leading_comment->_comment.length() >
+          (*ii).second->_leading_comment->_comment.length()) {
+        (*ii).second->_leading_comment = function->_leading_comment;
+      }
+    }
 
     return index;
   }
@@ -1739,6 +1757,44 @@ get_function(CPPInstance *function, string description,
   return index;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateBuilder::get_make_seq
+//       Access: Private
+//  Description: Adds the indicated make_seq to the database, if it is
+//               not already present.  In either case, returns the
+//               MakeSeq of the make_seq within the database.
+////////////////////////////////////////////////////////////////////
+MakeSeqIndex InterrogateBuilder::
+get_make_seq(CPPMakeSeq *make_seq, CPPStructType *struct_type) {
+  string make_seq_name = struct_type->get_local_name(&parser) + "::MakeSeq_" + make_seq->_seq_name;
+
+  // First, check to see if it's already there.
+  MakeSeqsByName::const_iterator tni =
+    _make_seqs_by_name.find(make_seq_name);
+  if (tni != _make_seqs_by_name.end()) {
+    MakeSeqIndex index = (*tni).second;
+    return index;
+  }
+
+  InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
+  // It isn't here, so we'll have to define it.
+  MakeSeqIndex index = idb->get_next_index();
+  _make_seqs_by_name[make_seq_name] = index;
+
+  InterrogateMakeSeq imake_seq;
+  imake_seq._class = get_type(struct_type, false);
+  imake_seq._seq_name = make_seq->_seq_name;
+  imake_seq._num_name = make_seq->_num_name;
+  imake_seq._element_name = make_seq->_element_name;
+
+  idb->add_make_seq(index, imake_seq);
+
+  InterrogateType &itype = idb->update_type(imake_seq._class);
+  itype._make_seqs.push_back(index);
+
+  return index;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateBuilder::get_atomic_string_type
 //       Access: Private
@@ -2228,18 +2284,17 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: InterrogateBuilder::update_method_comment
+//     Function: InterrogateBuilder::update_function_comment
 //       Access: Private
-//  Description: Updates the method definition in the database to
+//  Description: Updates the function definition in the database to
 //               include whatever comment is associated with this
 //               declaration.  This is called when we encounted a
-//               method definition outside of the class; the only new
-//               information this might include for us is the method
-//               comment.
+//               method definition outside of the class or function
+//               definition in a C++ file; the only new information
+//               this might include for us is the comment.
 ////////////////////////////////////////////////////////////////////
 void InterrogateBuilder::
-update_method_comment(CPPInstance *function, CPPStructType *struct_type,
-                      CPPScope *scope) {
+update_function_comment(CPPInstance *function, CPPScope *scope) {
   if (function->_leading_comment == (CPPCommentBlock *)NULL) {
     // No comment anyway.  Forget it.
     return;
@@ -2256,6 +2311,14 @@ update_method_comment(CPPInstance *function, CPPStructType *struct_type,
   function->_type = ftype;
 
   string function_name = TypeManager::get_function_name(function);
+  string function_signature = TypeManager::get_function_signature(function);
+
+  if (ftype->_flags & CPPFunctionType::F_unary_op) {
+    // This is a unary operator function.  Name it differently so we
+    // don't consider it an overloaded version of a similarly-named
+    // binary operator.
+    function_name += "unary";
+  }
 
   // Now look it up.
   FunctionsByName::const_iterator tni =
@@ -2273,11 +2336,17 @@ update_method_comment(CPPInstance *function, CPPStructType *struct_type,
       ifunction._comment += "\n\n";
     }
     ifunction._comment += comment;
-    /*
-    if (comment.length() > ifunction._comment.length()) {
-      ifunction._comment = comment;
+
+    // Also update the particular wrapper comment.
+    InterrogateFunction::Instances::iterator ii = 
+      ifunction._instances->find(function_signature);
+    if (ii != ifunction._instances->end()) {
+      if ((*ii).second->_leading_comment == NULL ||
+          function->_leading_comment->_comment.length() >
+          (*ii).second->_leading_comment->_comment.length()) {
+        (*ii).second->_leading_comment = function->_leading_comment;
+      }
     }
-    */
   }
 }
 

+ 7 - 3
dtool/src/interrogate/interrogateBuilder.h

@@ -38,6 +38,7 @@ class CPPScope;
 class CPPIdentifier;
 class CPPNameComponent;
 class CPPManifest;
+class CPPMakeSeq;
 class InterrogateType;
 class InterrogateFunction;
 class FunctionRemap;
@@ -107,16 +108,17 @@ public:
                CPPStructType *struct_type, CPPScope *scope,
                int flags, const string &expression = string());
 
+  MakeSeqIndex
+  get_make_seq(CPPMakeSeq *make_seq, CPPStructType *struct_type);
+
   TypeIndex get_atomic_string_type();
-//  TypeIndex get_type(CPPType *type, bool global);
 
   void define_atomic_type(InterrogateType &itype, CPPSimpleType *cpptype);
   void define_wrapped_type(InterrogateType &itype, CPPPointerType *cpptype);
   void define_wrapped_type(InterrogateType &itype, CPPConstType *cpptype);
   void define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
                           TypeIndex type_index, bool forced);
-  void update_method_comment(CPPInstance *function, CPPStructType *struct_type,
-                             CPPScope *scope);
+  void update_function_comment(CPPInstance *function, CPPScope *scope);
   void define_method(CPPFunctionGroup *fgroup, InterrogateType &itype,
                      CPPStructType *struct_type, CPPScope *scope);
   void define_method(CPPInstance *function, InterrogateType &itype,
@@ -129,9 +131,11 @@ public:
 
   typedef map<string, TypeIndex> TypesByName;
   typedef map<string, FunctionIndex> FunctionsByName;
+  typedef map<string, MakeSeqIndex> MakeSeqsByName;
 
   TypesByName _types_by_name;
   FunctionsByName _functions_by_name;
+  MakeSeqsByName _make_seqs_by_name;
 
   typedef map<string, char> IncludeFiles;
   IncludeFiles _include_files;

+ 7 - 3
dtool/src/interrogatedb/Sources.pp

@@ -11,8 +11,10 @@
     interrogateDatabase.h interrogateElement.I  \
     interrogateElement.h interrogateFunction.I  \
     interrogateFunction.h interrogateFunctionWrapper.I  \
-    interrogateFunctionWrapper.h interrogateManifest.I  \
-    interrogateManifest.h interrogateType.I interrogateType.h  \
+    interrogateFunctionWrapper.h \
+    interrogateMakeSeq.I interrogateMakeSeq.h \
+    interrogateManifest.I interrogateManifest.h \
+    interrogateType.I interrogateType.h  \
     interrogate_datafile.I interrogate_datafile.h  \
     interrogate_interface.h interrogate_request.h \
     py_panda.h \
@@ -24,7 +26,9 @@
     indexRemapper.cxx  \
     interrogateComponent.cxx interrogateDatabase.cxx  \
     interrogateElement.cxx interrogateFunction.cxx  \
-    interrogateFunctionWrapper.cxx interrogateManifest.cxx  \
+    interrogateFunctionWrapper.cxx \
+    interrogateMakeSeq.cxx  \
+    interrogateManifest.cxx  \
     interrogateType.cxx interrogate_datafile.cxx  \
     interrogate_interface.cxx interrogate_request.cxx  \
     py_panda.cxx \

+ 92 - 0
dtool/src/interrogatedb/interrogateDatabase.cxx

@@ -379,6 +379,25 @@ get_element(ElementIndex element) {
   return (*ei).second;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateDatabase::get_make_seq
+//       Access: Public
+//  Description: Returns the make_seq associated with the given
+//               MakeSeqIndex, if there is one.
+////////////////////////////////////////////////////////////////////
+const InterrogateMakeSeq &InterrogateDatabase::
+get_make_seq(MakeSeqIndex make_seq) {
+  static InterrogateMakeSeq bogus_make_seq;
+
+  check_latest();
+  MakeSeqMap::const_iterator si;
+  si = _make_seq_map.find(make_seq);
+  if (si == _make_seq_map.end()) {
+    return bogus_make_seq;
+  }
+  return (*si).second;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateDatabase::remove_type
 //       Access: Public
@@ -608,6 +627,19 @@ add_element(ElementIndex index, const InterrogateElement &element) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateDatabase::add_make_seq
+//       Access: Public
+//  Description: Adds the indicated make_seq to the database at
+//               the given index number.
+////////////////////////////////////////////////////////////////////
+void InterrogateDatabase::
+add_make_seq(MakeSeqIndex index, const InterrogateMakeSeq &make_seq) {
+  bool inserted =
+    _make_seq_map.insert(MakeSeqMap::value_type(index, make_seq)).second;
+  assert(inserted);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateDatabase::update_type
 //       Access: Public
@@ -669,6 +701,18 @@ update_element(ElementIndex element) {
   return _element_map[element];
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateDatabase::update_make_seq
+//       Access: Public
+//  Description: Returns a non-const reference to the indicated
+//               make_seq, allowing the user to update it.
+////////////////////////////////////////////////////////////////////
+InterrogateMakeSeq &InterrogateDatabase::
+update_make_seq(MakeSeqIndex make_seq) {
+  check_latest();
+  return _make_seq_map[make_seq];
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateDatabase::remap_indices
 //       Access: Public
@@ -743,6 +787,14 @@ remap_indices(int first_index, IndexRemapper &remap) {
     first_index++;
   }
 
+  MakeSeqMap new_make_seq_map;
+  MakeSeqMap::iterator si;
+  for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) {
+    remap.add_mapping((*si).first, first_index);
+    new_make_seq_map[first_index] = (*si).second;
+    first_index++;
+  }
+
   _next_index = first_index;
 
   _wrapper_map.swap(new_wrapper_map);
@@ -750,6 +802,7 @@ remap_indices(int first_index, IndexRemapper &remap) {
   _type_map.swap(new_type_map);
   _manifest_map.swap(new_manifest_map);
   _element_map.swap(new_element_map);
+  _make_seq_map.swap(new_make_seq_map);
 
   // Then, go back through and update all of the internal references.
   for (wi = _wrapper_map.begin(); wi != _wrapper_map.end(); ++wi) {
@@ -767,6 +820,9 @@ remap_indices(int first_index, IndexRemapper &remap) {
   for (ei = _element_map.begin(); ei != _element_map.end(); ++ei) {
     (*ei).second.remap_indices(remap);
   }
+  for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) {
+    (*si).second.remap_indices(remap);
+  }
   GlobalFunctions::iterator gfi;
   for (gfi = _global_functions.begin(); gfi != _global_functions.end(); ++gfi) {
     (*gfi) = remap.map_from(*gfi);
@@ -842,6 +898,12 @@ write(ostream &out, InterrogateModuleDef *def) const {
   for (ei = _element_map.begin(); ei != _element_map.end(); ++ei) {
     out << (*ei).first << " " << (*ei).second << "\n";
   }
+
+  out << _make_seq_map.size() << "\n";
+  MakeSeqMap::const_iterator si;
+  for (si = _make_seq_map.begin(); si != _make_seq_map.end(); ++si) {
+    out << (*si).first << " " << (*si).second << "\n";
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1078,6 +1140,26 @@ read_new(istream &in, InterrogateModuleDef *def) {
     }
   }
 
+  { // MakeSeqs.
+    int num_make_seqs;
+    in >> num_make_seqs;
+    if (in.fail()) {
+      return false;
+    }
+
+    while (num_make_seqs > 0) {
+      MakeSeqIndex index;
+      InterrogateMakeSeq make_seq(def);
+      in >> index >> make_seq;
+      if (in.fail()) {
+        return false;
+      }
+
+      add_make_seq(index, make_seq);
+      num_make_seqs--;
+    }
+  }
+
   return true;
 }
 
@@ -1192,6 +1274,16 @@ merge_from(const InterrogateDatabase &other) {
     update_element(other_element_index).remap_indices(remap);
   }
 
+  MakeSeqMap::const_iterator si;
+  for (si = other._make_seq_map.begin();
+       si != other._make_seq_map.end();
+       ++si) {
+    MakeSeqIndex other_make_seq_index = (*si).first;
+    const InterrogateMakeSeq &other_make_seq = (*si).second;
+    add_make_seq(other_make_seq_index, other_make_seq);
+    update_make_seq(other_make_seq_index).remap_indices(remap);
+  }
+
   _lookups_fresh = 0;
 }
 

+ 7 - 0
dtool/src/interrogatedb/interrogateDatabase.h

@@ -23,6 +23,7 @@
 #include "interrogateFunctionWrapper.h"
 #include "interrogateManifest.h"
 #include "interrogateElement.h"
+#include "interrogateMakeSeq.h"
 #include "interrogate_request.h"
 
 #include <map>
@@ -64,6 +65,7 @@ public:
   const InterrogateFunctionWrapper &get_wrapper(FunctionWrapperIndex wrapper);
   const InterrogateManifest &get_manifest(ManifestIndex manifest);
   const InterrogateElement &get_element(ElementIndex element);
+  const InterrogateMakeSeq &get_make_seq(MakeSeqIndex element);
 
   INLINE TypeIndex lookup_type_by_name(const string &name);
   INLINE TypeIndex lookup_type_by_scoped_name(const string &name);
@@ -94,12 +96,14 @@ public:
                    const InterrogateFunctionWrapper &wrapper);
   void add_manifest(ManifestIndex index, const InterrogateManifest &manifest);
   void add_element(ElementIndex index, const InterrogateElement &element);
+  void add_make_seq(MakeSeqIndex index, const InterrogateMakeSeq &make_seq);
 
   InterrogateType &update_type(TypeIndex type);
   InterrogateFunction &update_function(FunctionIndex function);
   InterrogateFunctionWrapper &update_wrapper(FunctionWrapperIndex wrapper);
   InterrogateManifest &update_manifest(ManifestIndex manifest);
   InterrogateElement &update_element(ElementIndex element);
+  InterrogateMakeSeq &update_make_seq(MakeSeqIndex make_seq);
 
   int remap_indices(int first_index);
   int remap_indices(int first_index, IndexRemapper &remap);
@@ -134,6 +138,9 @@ private:
   typedef map<ElementIndex, InterrogateElement> ElementMap;
   ElementMap _element_map;
 
+  typedef map<MakeSeqIndex, InterrogateMakeSeq> MakeSeqMap;
+  MakeSeqMap _make_seq_map;
+
   typedef vector<TypeIndex> GlobalTypes;
   GlobalTypes _global_types;
   GlobalTypes _all_types;

+ 21 - 0
dtool/src/interrogatedb/interrogateFunctionWrapper.I

@@ -51,6 +51,7 @@ operator = (const InterrogateFunctionWrapper &copy) {
   _return_type = copy._return_type;
   _return_value_destructor = copy._return_value_destructor;
   _unique_name = copy._unique_name;
+  _comment = copy._comment;
   _parameters = copy._parameters;
 }
 
@@ -188,6 +189,26 @@ get_unique_name() const {
   return _unique_name;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateFunctionWrapper::has_comment
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool InterrogateFunctionWrapper::
+has_comment() const {
+  return !_comment.empty();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateFunctionWrapper::get_comment
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const string &InterrogateFunctionWrapper::
+get_comment() const {
+  return _comment;
+}
+
 INLINE ostream &
 operator << (ostream &out, const InterrogateFunctionWrapper &wrapper) {
   wrapper.output(out);

+ 2 - 0
dtool/src/interrogatedb/interrogateFunctionWrapper.cxx

@@ -54,6 +54,7 @@ output(ostream &out) const {
       << _return_type << " "
       << _return_value_destructor << " ";
   idf_output_string(out, _unique_name);
+  idf_output_string(out, _comment);
   idf_output_vector(out, _parameters);
 }
 
@@ -71,6 +72,7 @@ input(istream &in) {
      >> _return_type
      >> _return_value_destructor;
   idf_input_string(in, _unique_name);
+  idf_input_string(in, _comment);
   idf_input_vector(in, _parameters);
 }
 

+ 4 - 0
dtool/src/interrogatedb/interrogateFunctionWrapper.h

@@ -50,6 +50,9 @@ public:
 
   INLINE const string &get_unique_name() const;
 
+  INLINE bool has_comment() const;
+  INLINE const string &get_comment() const;
+
   void output(ostream &out) const;
   void input(istream &in);
 
@@ -72,6 +75,7 @@ private:
   TypeIndex _return_type;
   FunctionIndex _return_value_destructor;
   string _unique_name;
+  string _comment;
 
 public:
   // This nested class must be declared public just so we can declare

+ 104 - 0
dtool/src/interrogatedb/interrogateMakeSeq.I

@@ -0,0 +1,104 @@
+// Filename: interrogateMakeSeq.I
+// Created by:  drose (15Sep09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+
+
+////////////////////////////////////////////////////////////////////
+//     MakeSeq: InterrogateMakeSeq::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE InterrogateMakeSeq::
+InterrogateMakeSeq(InterrogateModuleDef *def) :
+  InterrogateComponent(def)
+{
+  _class = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     MakeSeq: InterrogateMakeSeq::Copy Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE InterrogateMakeSeq::
+InterrogateMakeSeq(const InterrogateMakeSeq &copy) {
+  (*this) = copy;
+}
+
+////////////////////////////////////////////////////////////////////
+//     MakeSeq: InterrogateMakeSeq::Copy Assignment Operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void InterrogateMakeSeq::
+operator = (const InterrogateMakeSeq &copy) {
+  InterrogateComponent::operator = (copy);
+  _class = copy._class;
+  _seq_name = copy._seq_name;
+  _num_name = copy._num_name;
+  _element_name = copy._element_name;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateMakeSeq::get_class
+//       Access: Public
+//  Description: Return the class that owns the make_seq.
+////////////////////////////////////////////////////////////////////
+INLINE TypeIndex InterrogateMakeSeq::
+get_class() const {
+  return _class;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateMakeSeq::get_seq_name
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const string &InterrogateMakeSeq::
+get_seq_name() const {
+  return _seq_name;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateMakeSeq::get_num_name
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const string &InterrogateMakeSeq::
+get_num_name() const {
+  return _num_name;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateMakeSeq::get_element_name
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE const string &InterrogateMakeSeq::
+get_element_name() const {
+  return _element_name;
+}
+
+
+INLINE ostream &
+operator << (ostream &out, const InterrogateMakeSeq &make_seq) {
+  make_seq.output(out);
+  return out;
+}
+
+INLINE istream &
+operator >> (istream &in, InterrogateMakeSeq &make_seq) {
+  make_seq.input(in);
+  return in;
+}

+ 58 - 0
dtool/src/interrogatedb/interrogateMakeSeq.cxx

@@ -0,0 +1,58 @@
+// Filename: interrogateMakeSeq.cxx
+// Created by:  drose (15Sep09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "interrogateMakeSeq.h"
+#include "indexRemapper.h"
+#include "interrogate_datafile.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateMakeSeq::output
+//       Access: Public
+//  Description: Formats the InterrogateMakeSeq data for output to a data
+//               file.
+////////////////////////////////////////////////////////////////////
+void InterrogateMakeSeq::
+output(ostream &out) const {
+  InterrogateComponent::output(out);
+  out << _class << " ";
+  idf_output_string(out, _seq_name);
+  idf_output_string(out, _num_name);
+  idf_output_string(out, _element_name);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateMakeSeq::input
+//       Access: Public
+//  Description: Reads the data file as previously formatted by
+//               output().
+////////////////////////////////////////////////////////////////////
+void InterrogateMakeSeq::
+input(istream &in) {
+  InterrogateComponent::input(in);
+  in >> _class;
+  idf_input_string(in, _seq_name);
+  idf_input_string(in, _num_name);
+  idf_input_string(in, _element_name);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateMakeSeq::remap_indices
+//       Access: Public
+//  Description: Remaps all internal index numbers according to the
+//               indicated map.  This called from
+//               InterrogateDatabase::remap_indices().
+////////////////////////////////////////////////////////////////////
+void InterrogateMakeSeq::
+remap_indices(const IndexRemapper &remap) {
+}

+ 59 - 0
dtool/src/interrogatedb/interrogateMakeSeq.h

@@ -0,0 +1,59 @@
+// Filename: interrogateMakeSeq.h
+// Created by:  drose (15Sep09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef INTERROGATEMAKESEQ_H
+#define INTERROGATEMAKESEQ_H
+
+#include "dtoolbase.h"
+
+#include "interrogateComponent.h"
+
+class IndexRemapper;
+
+////////////////////////////////////////////////////////////////////
+//       Class : InterrogateMakeSeq
+// Description : Represents a synthetic method created via the
+//               MAKE_SEQ() macro.
+////////////////////////////////////////////////////////////////////
+class EXPCL_DTOOLCONFIG InterrogateMakeSeq : public InterrogateComponent {
+public:
+  INLINE InterrogateMakeSeq(InterrogateModuleDef *def = NULL);
+  INLINE InterrogateMakeSeq(const InterrogateMakeSeq &copy);
+  INLINE void operator = (const InterrogateMakeSeq &copy);
+
+  INLINE TypeIndex get_class() const;
+  INLINE const string &get_seq_name() const;
+  INLINE const string &get_num_name() const;
+  INLINE const string &get_element_name() const;
+
+  void output(ostream &out) const;
+  void input(istream &in);
+
+  void remap_indices(const IndexRemapper &remap);
+
+private:
+  TypeIndex _class;
+  string _seq_name;
+  string _num_name;
+  string _element_name;
+
+  friend class InterrogateBuilder;
+};
+
+INLINE ostream &operator << (ostream &out, const InterrogateMakeSeq &make_seq);
+INLINE istream &operator >> (istream &in, InterrogateMakeSeq &make_seq);
+
+#include "interrogateMakeSeq.I"
+
+#endif

+ 24 - 0
dtool/src/interrogatedb/interrogateType.I

@@ -431,6 +431,30 @@ get_method(int n) const {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateType::number_of_make_seqs
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE int InterrogateType::
+number_of_make_seqs() const {
+  return _make_seqs.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateType::get_make_seq
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE MakeSeqIndex InterrogateType::
+get_make_seq(int n) const {
+  if (n >= 0 && n < (int)_make_seqs.size()) {
+    return _make_seqs[n];
+  } else {
+    return 0;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateType::number_of_casts
 //       Access: Public

+ 8 - 0
dtool/src/interrogatedb/interrogateType.cxx

@@ -114,6 +114,7 @@ operator = (const InterrogateType &copy) {
   _destructor = copy._destructor;
   _elements = copy._elements;
   _methods = copy._methods;
+  _make_seqs = copy._make_seqs;
   _casts = copy._casts;
   _derivations = copy._derivations;
   _enum_values = copy._enum_values;
@@ -167,6 +168,7 @@ output(ostream &out) const {
   out << _destructor << " ";
   idf_output_vector(out, _elements);
   idf_output_vector(out, _methods);
+  idf_output_vector(out, _make_seqs);
   idf_output_vector(out, _casts);
   idf_output_vector(out, _derivations);
   idf_output_vector(out, _enum_values);
@@ -199,6 +201,7 @@ input(istream &in) {
 
   idf_input_vector(in, _elements);
   idf_input_vector(in, _methods);
+  idf_input_vector(in, _make_seqs);
   idf_input_vector(in, _casts);
   idf_input_vector(in, _derivations);
   idf_input_vector(in, _enum_values);
@@ -236,6 +239,11 @@ remap_indices(const IndexRemapper &remap) {
     (*fi) = remap.map_from(*fi);
   }
 
+  MakeSeqs::iterator si;
+  for (si = _make_seqs.begin(); si != _make_seqs.end(); ++si) {
+    (*si) = remap.map_from(*si);
+  }
+
   Derivations::iterator di;
   for (di = _derivations.begin(); di != _derivations.end(); ++di) {
     (*di)._base = remap.map_from((*di)._base);

+ 5 - 0
dtool/src/interrogatedb/interrogateType.h

@@ -83,6 +83,8 @@ public:
   INLINE ElementIndex get_element(int n) const;
   INLINE int number_of_methods() const;
   INLINE FunctionIndex get_method(int n) const;
+  INLINE int number_of_make_seqs() const;
+  INLINE MakeSeqIndex get_make_seq(int n) const;
 
   INLINE int number_of_casts() const;
   INLINE FunctionIndex get_cast(int n) const;
@@ -150,6 +152,9 @@ public:
   Functions _methods;
   Functions _casts;
 
+  typedef vector<MakeSeqIndex> MakeSeqs;
+  MakeSeqs _make_seqs;
+
   enum DerivationFlags {
     DF_upcast               = 0x01,
     DF_downcast             = 0x02,

+ 54 - 0
dtool/src/interrogatedb/interrogate_interface.cxx

@@ -310,6 +310,18 @@ interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper) {
   return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_callable_by_name();
 }
 
+bool
+interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper) {
+  //cerr << "interrogate_wrapper_has_comment(" << wrapper << ")\n";
+  return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).has_comment();
+}
+
+const char *
+interrogate_wrapper_comment(FunctionWrapperIndex wrapper) {
+  //cerr << "interrogate_wrapper_comment(" << wrapper << ")\n";
+  return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).get_comment().c_str();
+}
+
 bool
 interrogate_wrapper_has_return_value(FunctionWrapperIndex wrapper) {
   //cerr << "interrogate_wrapper_has_return_value(" << wrapper << ")\n";
@@ -390,6 +402,36 @@ interrogate_get_wrapper_by_unique_name(const char *unique_name) {
   return InterrogateDatabase::get_ptr()->get_wrapper_by_unique_name(unique_name);
 }
 
+TypeIndex 
+interrogate_make_seq_class(MakeSeqIndex make_seq) {
+  //cerr << "interrogate_make_seq_class(" << make_seq << ")\n";
+  return InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_class();
+}
+
+const char *
+interrogate_make_seq_seq_name(MakeSeqIndex make_seq) {
+  //cerr << "interrogate_make_seq_seq_name(" << make_seq << ")\n";
+  static string result;
+  result = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_seq_name();
+  return result.c_str();
+}
+
+const char *
+interrogate_make_seq_num_name(MakeSeqIndex make_seq) {
+  //cerr << "interrogate_make_seq_num_name(" << make_seq << ")\n";
+  static string result;
+  result = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_num_name();
+  return result.c_str();
+}
+
+const char *
+interrogate_make_seq_element_name(MakeSeqIndex make_seq) {
+  //cerr << "interrogate_make_seq_element_name(" << make_seq << ")\n";
+  static string result;
+  result = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_element_name();
+  return result.c_str();
+}
+
 int
 interrogate_number_of_global_types() {
   //cerr << "interrogate_number_of_global_types()\n";
@@ -679,6 +721,18 @@ interrogate_type_get_method(TypeIndex type, int n) {
   return InterrogateDatabase::get_ptr()->get_type(type).get_method(n);
 }
 
+int
+interrogate_type_number_of_make_seqs(TypeIndex type) {
+  //cerr << "interrogate_type_number_of_make_seqs(" << type << ")\n";
+  return InterrogateDatabase::get_ptr()->get_type(type).number_of_make_seqs();
+}
+
+MakeSeqIndex
+interrogate_type_get_make_seq(TypeIndex type, int n) {
+  //cerr << "interrogate_type_get_make_seq(" << type << ", " << n << ")\n";
+  return InterrogateDatabase::get_ptr()->get_type(type).get_make_seq(n);
+}
+
 int
 interrogate_type_number_of_casts(TypeIndex type) {
   //cerr << "interrogate_type_number_of_casts(" << type << ")\n";

+ 33 - 0
dtool/src/interrogatedb/interrogate_interface.h

@@ -61,6 +61,7 @@ typedef int ElementIndex;
 typedef int TypeIndex;
 typedef int FunctionIndex;
 typedef int FunctionWrapperIndex;
+typedef int MakeSeqIndex;
 
 // Atomic types are those that are built in to C.  This enumerated
 // value is returned by interrogate_type_atomic_token() when a type is
@@ -276,6 +277,12 @@ EXPCL_DTOOLCONFIG const char *interrogate_wrapper_name(FunctionWrapperIndex wrap
 // wrapper function callable directly by its name.
 EXPCL_DTOOLCONFIG bool interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper);
 
+// This returns the C++ comment written for the function wrapper,
+// usually from the .cpp file.  There may be a different comment for
+// each overload of a given function.
+EXPCL_DTOOLCONFIG bool interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper);
+EXPCL_DTOOLCONFIG const char *interrogate_wrapper_comment(FunctionWrapperIndex wrapper);
+
 // Every function wrapper has zero or more parameters and may or may
 // not have a return value.  Each parameter has a type and may or may
 // not have a name.  For member functions, the first parameter may be
@@ -342,6 +349,28 @@ EXPCL_DTOOLCONFIG const char *interrogate_wrapper_unique_name(FunctionWrapperInd
 // interrogate database.
 EXPCL_DTOOLCONFIG FunctionWrapperIndex interrogate_get_wrapper_by_unique_name(const char *unique_name);
 
+//////////////////////////////////////////////////////////////////////////
+//
+// MakeSeqs
+//
+//////////////////////////////////////////////////////////////////////////
+
+// These are special synthesized methods that iterate through a list.
+// They are generated in C++ code via the MAKE_SEQ macro.  The normal
+// pattern is that a pair of actual C++ methods like get_num_things()
+// and get_thing(n) are used to synthesize a new method called
+// get_things().
+
+// The class of which the make_seq is a method.
+EXPCL_DTOOLCONFIG TypeIndex interrogate_make_seq_class(MakeSeqIndex make_seq);
+
+// The name of the syntheized method, e.g. "get_things"
+EXPCL_DTOOLCONFIG const char *interrogate_make_seq_seq_name(MakeSeqIndex make_seq);
+// The name of the real method that returns the length, e.g. "get_num_things"
+EXPCL_DTOOLCONFIG const char *interrogate_make_seq_num_name(MakeSeqIndex make_seq);
+// The name of the real method that returns the nth element, e.g. "get_thing"
+EXPCL_DTOOLCONFIG const char *interrogate_make_seq_element_name(MakeSeqIndex make_seq);
+
 
 //////////////////////////////////////////////////////////////////////////
 //
@@ -480,6 +509,10 @@ EXPCL_DTOOLCONFIG ElementIndex interrogate_type_get_element(TypeIndex type, int
 EXPCL_DTOOLCONFIG int interrogate_type_number_of_methods(TypeIndex type);
 EXPCL_DTOOLCONFIG FunctionIndex interrogate_type_get_method(TypeIndex type, int n);
 
+// This is the set of MAKE_SEQ wrappers in the struct or class.
+EXPCL_DTOOLCONFIG int interrogate_type_number_of_make_seqs(TypeIndex type);
+EXPCL_DTOOLCONFIG MakeSeqIndex interrogate_type_get_make_seq(TypeIndex type, int n);
+
 // A C++ class may also define a number of explicit cast operators,
 // which define how to convert an object of this type to an object of
 // some other type (the type can be inferred by the return type of the

+ 2 - 8
dtool/src/interrogatedb/interrogatedb_composite1.cxx

@@ -1,14 +1,8 @@
-#include "vector_int.cxx"
-#include "dtool_super_base.cxx"
 #include "config_interrogatedb.cxx"
+#include "dtool_super_base.cxx"
 #include "indexRemapper.cxx"
 #include "interrogateComponent.cxx"
+#include "interrogateDatabase.cxx"
 #include "interrogateElement.cxx"
 #include "interrogateFunction.cxx"
 #include "interrogateFunctionWrapper.cxx"
-#include "interrogate_datafile.cxx"
-#include "interrogate_interface.cxx"
-#include "interrogateDatabase.cxx"
-#include "interrogateManifest.cxx"
-
-

+ 5 - 0
dtool/src/interrogatedb/interrogatedb_composite2.cxx

@@ -1,6 +1,11 @@
+#include "interrogateMakeSeq.cxx"
+#include "interrogateManifest.cxx"
 #include "interrogateType.cxx"
+#include "interrogate_datafile.cxx"
+#include "interrogate_interface.cxx"
 #include "interrogate_request.cxx"
 #include "py_panda.cxx"
+#include "vector_int.cxx"
 
 
 

+ 54 - 1
dtool/src/test_interrogate/test_interrogate.cxx

@@ -40,6 +40,29 @@ indent(ostream &out, int indent_level) {
   return out;
 }
 
+// Indents one or more lines of text, breaking the text up at newline
+// characters.
+static ostream &
+hanging_indent(ostream &out, const string &text, int first_indent_level, 
+               int next_indent_level = -1) {
+  if (next_indent_level < 0) {
+    next_indent_level = first_indent_level;
+  }
+
+  size_t start = 0;
+  size_t newline = text.find('\n');
+  int indent_level = first_indent_level;
+  while (newline != string::npos) {
+    indent(out, indent_level)
+      << text.substr(start, newline - start) << "\n";
+    start = newline + 1;
+    newline = text.find('\n', start);
+    indent_level = next_indent_level;
+  }
+  indent(out, indent_level)
+    << text.substr(start) << "\n";
+}
+
 void
 show_type(int type, bool verbose = false) {
   cout << interrogate_type_name(type) << " ";
@@ -96,6 +119,11 @@ describe_wrapper(int wrapper, int indent_level) {
     cout << "\n";
   }
 
+  if (interrogate_wrapper_has_comment(wrapper)) {
+    string comment = interrogate_wrapper_comment(wrapper);
+    hanging_indent(cout, comment, indent_level + 2);
+  }
+      
 
   if (interrogate_wrapper_caller_manages_return_value(wrapper)) {
     indent(cout, indent_level + 2)
@@ -133,7 +161,9 @@ describe_function(int function, int indent_level) {
     << " (" << function << ")\n";
 
   indent(cout, indent_level + 2)
-    << "In C: " << interrogate_function_prototype(function) << "\n";
+    << "In C: ";
+  hanging_indent(cout, interrogate_function_prototype(function),
+                 0, indent_level + 2 + 6);
 
   if (interrogate_function_is_method(function)) {
     indent(cout, indent_level + 2)
@@ -176,7 +206,16 @@ describe_function(int function, int indent_level) {
     describe_wrapper(interrogate_function_python_wrapper(function, w),
                      indent_level + 4);
   }
+}
 
+void
+describe_make_seq(int make_seq, int indent_level) {
+  indent(cout, indent_level)
+    << "MakeSeq " << interrogate_make_seq_seq_name(make_seq)
+    << " (" << make_seq << "): " 
+    << interrogate_make_seq_num_name(make_seq)
+    << ", " << interrogate_make_seq_element_name(make_seq)
+    << "\n";
 }
 
 void
@@ -248,6 +287,12 @@ describe_type(int type, int indent_level) {
   indent(cout, indent_level) << "Type ";
   show_type(type, true);
   cout << "\n";
+
+  if (interrogate_type_has_comment(type)) {
+    string comment = interrogate_type_comment(type);
+    hanging_indent(cout, comment, indent_level + 2);
+  }
+      
   if (interrogate_type_is_nested(type)) {
     indent(cout, indent_level + 2)
       << "Nested within ";
@@ -353,6 +398,14 @@ describe_type(int type, int indent_level) {
       describe_function(interrogate_type_get_method(type, i), 6);
     }
   }
+  int num_make_seqs = interrogate_type_number_of_make_seqs(type);
+  if (num_make_seqs > 0) {
+    indent(cout, indent_level + 2)
+      << num_make_seqs << " make_seqs:\n";
+    for (int i = 0; i < num_make_seqs; i++) {
+      describe_make_seq(interrogate_type_get_make_seq(type, i), 6);
+    }
+  }
   int num_elements = interrogate_type_number_of_elements(type);
   if (num_elements > 0) {
     indent(cout, indent_level + 2)