Browse Source

Huge cppparser and interrogate overhaul, bringing:
* Better support for typedefs
* Same code should compile for both 32-bit and 64-bit
* C++11 typed enum support
* Synthesize __setitem__ when operator [] returns reference
* Rewrite coerce system to have better performance
* Change semantics of __getattr__ and __setattr__ to match
Python's, add __getattribute__, __delattr__ and __delitem__
* Improve performance of slot functions a bit more
* Reduce memory overhead of type system
* Some support for wrapping arrays of numeric types
* C++11 character type support in cppparser
* Chars are handled as strings of length 1
* Template functions for CreatePyInstance that use runtime type map
* More functions from dtool as extension functions
* Code cleanup

rdb 11 years ago
parent
commit
6db5d0dc11
100 changed files with 3169 additions and 1564 deletions
  1. 115 93
      dtool/src/cppparser/cppBison.yxx
  2. 4 4
      dtool/src/cppparser/cppDeclaration.cxx
  3. 3 3
      dtool/src/cppparser/cppDeclaration.h
  4. 94 12
      dtool/src/cppparser/cppEnumType.cxx
  5. 6 0
      dtool/src/cppparser/cppEnumType.h
  6. 103 1
      dtool/src/cppparser/cppExpression.cxx
  7. 1 0
      dtool/src/cppparser/cppExpression.h
  8. 1 1
      dtool/src/cppparser/cppExtensionType.cxx
  9. 40 2
      dtool/src/cppparser/cppIdentifier.cxx
  10. 5 1
      dtool/src/cppparser/cppIdentifier.h
  11. 1 1
      dtool/src/cppparser/cppInstance.cxx
  12. 2 2
      dtool/src/cppparser/cppManifest.cxx
  13. 11 4
      dtool/src/cppparser/cppPreprocessor.cxx
  14. 1 0
      dtool/src/cppparser/cppPreprocessor.h
  15. 61 47
      dtool/src/cppparser/cppScope.cxx
  16. 3 3
      dtool/src/cppparser/cppScope.h
  17. 12 4
      dtool/src/cppparser/cppSimpleType.cxx
  18. 4 2
      dtool/src/cppparser/cppSimpleType.h
  19. 10 11
      dtool/src/cppparser/cppStructType.cxx
  20. 1 0
      dtool/src/cppparser/cppTemplateParameterList.cxx
  21. 3 2
      dtool/src/cppparser/cppTemplateScope.cxx
  22. 1 1
      dtool/src/cppparser/cppType.cxx
  23. 2 2
      dtool/src/cppparser/cppType.h
  24. 13 1
      dtool/src/cppparser/cppTypeProxy.cxx
  25. 1 1
      dtool/src/cppparser/cppTypeProxy.h
  26. 0 91
      dtool/src/cppparser/cppTypedef.cxx
  27. 0 42
      dtool/src/cppparser/cppTypedef.h
  28. 388 0
      dtool/src/cppparser/cppTypedefType.cxx
  29. 74 0
      dtool/src/cppparser/cppTypedefType.h
  30. 1 6
      dtool/src/cppparser/p3cppParser_composite1.cxx
  31. 9 1
      dtool/src/dtoolbase/atomicAdjust.h
  32. 4 25
      dtool/src/dtoolbase/typeHandle.cxx
  33. 1 10
      dtool/src/dtoolbase/typeHandle.h
  34. 5 0
      dtool/src/dtoolutil/Sources.pp
  35. 11 0
      dtool/src/dtoolutil/filename.I
  36. 1 61
      dtool/src/dtoolutil/filename.cxx
  37. 6 4
      dtool/src/dtoolutil/filename.h
  38. 7 39
      dtool/src/dtoolutil/globPattern.cxx
  39. 2 2
      dtool/src/dtoolutil/globPattern.h
  40. 0 0
      dtool/src/dtoolutil/lineStream.I
  41. 0 0
      dtool/src/dtoolutil/lineStream.cxx
  42. 2 2
      dtool/src/dtoolutil/lineStream.h
  43. 0 0
      dtool/src/dtoolutil/lineStreamBuf.I
  44. 0 0
      dtool/src/dtoolutil/lineStreamBuf.cxx
  45. 2 2
      dtool/src/dtoolutil/lineStreamBuf.h
  46. 2 0
      dtool/src/dtoolutil/p3dtoolutil_composite1.cxx
  47. 99 11
      dtool/src/interrogate/functionRemap.cxx
  48. 16 12
      dtool/src/interrogate/functionRemap.h
  49. 49 56
      dtool/src/interrogate/interfaceMaker.cxx
  50. 333 232
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  51. 70 39
      dtool/src/interrogate/interfaceMakerPythonNative.h
  52. 1 0
      dtool/src/interrogate/interrogate.cxx
  53. 1 1
      dtool/src/interrogate/interrogate.h
  54. 252 76
      dtool/src/interrogate/interrogateBuilder.cxx
  55. 5 0
      dtool/src/interrogate/interrogateBuilder.h
  56. 9 9
      dtool/src/interrogate/parse_file.cxx
  57. 557 122
      dtool/src/interrogate/typeManager.cxx
  58. 11 1
      dtool/src/interrogate/typeManager.h
  59. 1 6
      dtool/src/interrogatedb/dtool_super_base.cxx
  60. 30 0
      dtool/src/interrogatedb/interrogateType.I
  61. 11 0
      dtool/src/interrogatedb/interrogateType.cxx
  62. 7 0
      dtool/src/interrogatedb/interrogateType.h
  63. 6 0
      dtool/src/interrogatedb/interrogate_interface.cxx
  64. 1 0
      dtool/src/interrogatedb/interrogate_interface.h
  65. 51 215
      dtool/src/interrogatedb/py_panda.cxx
  66. 140 118
      dtool/src/interrogatedb/py_panda.h
  67. 2 2
      dtool/src/parser-inc/Python.h
  68. 1 1
      dtool/src/parser-inc/ssl.h
  69. 3 0
      dtool/src/parser-inc/string
  70. 4 0
      dtool/src/pystub/pystub.cxx
  71. 5 2
      makepanda/makepandacore.py
  72. 2 2
      panda/src/distort/nonlinearImager.cxx
  73. 1 0
      panda/src/egg/eggNurbsSurface.h
  74. 39 0
      panda/src/event/pythonTask.I
  75. 71 75
      panda/src/event/pythonTask.cxx
  76. 38 4
      panda/src/event/pythonTask.h
  77. 69 0
      panda/src/express/filename_ext.cxx
  78. 41 0
      panda/src/express/filename_ext.h
  79. 45 0
      panda/src/express/globPattern_ext.cxx
  80. 40 0
      panda/src/express/globPattern_ext.h
  81. 19 15
      panda/src/express/multifile.h
  82. 3 0
      panda/src/express/p3express_ext_composite.cxx
  83. 2 2
      panda/src/express/pointerToArray.I
  84. 38 0
      panda/src/express/typeHandle_ext.cxx
  85. 40 0
      panda/src/express/typeHandle_ext.h
  86. 2 6
      panda/src/framework/windowFramework.cxx
  87. 3 3
      panda/src/gobj/material.h
  88. 4 1
      panda/src/gobj/texture.h
  89. 3 0
      panda/src/linmath/aa_luse.h
  90. 11 6
      panda/src/linmath/compose_matrix_src.h
  91. 0 11
      panda/src/linmath/lmatrix3_ext_src.I
  92. 0 12
      panda/src/linmath/lmatrix3_ext_src.h
  93. 2 2
      panda/src/linmath/lmatrix3_src.I
  94. 6 1
      panda/src/linmath/lmatrix3_src.h
  95. 0 11
      panda/src/linmath/lmatrix4_ext_src.I
  96. 0 12
      panda/src/linmath/lmatrix4_ext_src.h
  97. 2 2
      panda/src/linmath/lmatrix4_src.I
  98. 10 1
      panda/src/linmath/lmatrix4_src.h
  99. 0 11
      panda/src/linmath/lvecBase2_ext_src.I
  100. 0 1
      panda/src/linmath/lvecBase2_ext_src.h

+ 115 - 93
dtool/src/cppparser/cppBison.yxx

@@ -1,6 +1,6 @@
 // Filename: cppBison.y
 // Created by:  drose (16Jan99)
-// 
+//
 ////////////////////////////////////////////////////////////////////
 
 %{
@@ -21,7 +21,7 @@
 #include "cppClassTemplateParameter.h"
 #include "cppTemplateParameterList.h"
 #include "cppInstanceIdentifier.h"
-#include "cppTypedef.h"
+#include "cppTypedefType.h"
 #include "cppTypeDeclaration.h"
 #include "cppVisibility.h"
 #include "cppIdentifier.h"
@@ -38,7 +38,7 @@ CPPScope *current_scope = NULL;
 CPPScope *global_scope = NULL;
 CPPPreprocessor *current_lexer = NULL;
 
-static CPPStructType *current_struct = NULL; 
+static CPPStructType *current_struct = NULL;
 static CPPEnumType *current_enum = NULL;
 static int current_storage_class = 0;
 static CPPType *current_type = NULL;
@@ -98,7 +98,7 @@ parse_cpp(CPPParser *cp) {
   current_scope = old_scope;
   global_scope = old_global_scope;
   current_lexer = old_lexer;
-    
+
 }
 
 CPPExpression *
@@ -140,7 +140,7 @@ parse_type(CPPPreprocessor *pp, CPPScope *new_current_scope,
   yyparse();
 
   CPPType *result = current_type;
-  
+
   current_scope = old_scope;
   global_scope = old_global_scope;
   current_lexer = old_lexer;
@@ -223,8 +223,8 @@ pop_struct() {
 %token UNARY_REF
 %token POINTSAT
 %token SCOPE
-%token PLUSPLUS 
-%token MINUSMINUS 
+%token PLUSPLUS
+%token MINUSMINUS
 %token TIMESEQUAL
 %token DIVIDEEQUAL
 %token MODEQUAL
@@ -241,15 +241,16 @@ pop_struct() {
 %token KW_BOOL
 %token KW_CATCH
 %token KW_CHAR
-%token KW_WCHAR_T
-%token KW_CLASS 
-%token KW_CONST 
+%token KW_CHAR16_T
+%token KW_CHAR32_T
+%token KW_CLASS
+%token KW_CONST
 %token KW_DELETE
 %token KW_DOUBLE
 %token KW_DYNAMIC_CAST
 %token KW_ELSE
-%token KW_END_PUBLISH 
-%token KW_ENUM 
+%token KW_END_PUBLISH
+%token KW_ENUM
 %token KW_EXTENSION
 %token KW_EXTERN
 %token KW_EXPLICIT
@@ -280,19 +281,20 @@ pop_struct() {
 %token KW_SIZEOF
 %token KW_STATIC
 %token KW_STATIC_CAST
-%token KW_STRUCT 
+%token KW_STRUCT
 %token KW_TEMPLATE
 %token KW_THROW
 %token KW_TRUE
 %token KW_TRY
-%token KW_TYPEDEF 
+%token KW_TYPEDEF
 %token KW_TYPENAME
-%token KW_UNION 
+%token KW_UNION
 %token KW_UNSIGNED
 %token KW_USING
 %token KW_VIRTUAL
 %token KW_VOID
 %token KW_VOLATILE
+%token KW_WCHAR_T
 %token KW_WHILE
 
 /* These special tokens are used to set the starting state of the
@@ -324,8 +326,7 @@ pop_struct() {
 %type <u.type> full_type
 %type <u.struct_type> anonymous_struct
 %type <u.struct_type> named_struct
-%type <u.enum_type> anonymous_enum
-%type <u.enum_type> named_enum
+%type <u.enum_type> enum
 %type <u.extension_enum> enum_keyword
 %type <u.extension_enum> struct_keyword
 %type <u.simple_type> simple_type
@@ -333,6 +334,7 @@ pop_struct() {
 %type <u.simple_type> simple_float_type
 %type <u.simple_type> simple_void_type
 %type <u.type> class_derivation_name
+%type <u.type> enum_element_type
 /*%type <u.type> typedefname*/
 %type <u.identifier> name
 %type <str> string
@@ -352,7 +354,7 @@ pop_struct() {
 
 /* Precedence rules. */
 
-%left IDENTIFIER TYPENAME_IDENTIFIER TYPEDEFNAME KW_ENUM ELLIPSIS KW_OPERATOR KW_TYPENAME KW_INT KW_SHORT KW_UNSIGNED KW_SIGNED KW_LONG KW_FLOAT KW_DOUBLE KW_CHAR KW_WCHAR_T KW_BOOL
+%left IDENTIFIER TYPENAME_IDENTIFIER TYPEDEFNAME KW_ENUM ELLIPSIS KW_OPERATOR KW_TYPENAME KW_INT KW_SHORT KW_UNSIGNED KW_SIGNED KW_LONG KW_FLOAT KW_DOUBLE KW_CHAR KW_WCHAR_T KW_CHAR16_T KW_CHAR32_T KW_BOOL
 
 %left '{' ',' ';'
 
@@ -417,7 +419,7 @@ constructor_init:
 extern_c:
         storage_class '{'
 {
-  push_storage_class((current_storage_class & ~CPPInstance::SC_c_binding) | 
+  push_storage_class((current_storage_class & ~CPPInstance::SC_c_binding) |
                      ($1 & CPPInstance::SC_c_binding));
 }
         cpp '}'
@@ -434,7 +436,7 @@ declaration:
         | using_declaration
         | friend_declaration
         | KW_TYPEDEF typedef_declaration
-        | KW_BEGIN_PUBLISH 
+        | KW_BEGIN_PUBLISH
 {
   if (publish_nest_level != 0) {
     yyerror("Unclosed __begin_publish", publish_loc);
@@ -447,7 +449,7 @@ declaration:
   publish_nest_level++;
   current_scope->set_current_vis(V_published);
 }
-        | KW_END_PUBLISH 
+        | KW_END_PUBLISH
 {
   if (publish_nest_level != 1) {
     yyerror("Unmatched __end_publish", @1);
@@ -716,7 +718,8 @@ typedef_declaration:
     if (inst != (CPPInstance *)NULL) {
       inst->_storage_class |= (current_storage_class | $1);
       current_scope->add_declaration(inst, global_scope, current_lexer, @2);
-      current_scope->add_declaration(new CPPTypedef(inst, current_scope == global_scope), global_scope, current_lexer, @2);
+      CPPTypedefType *typedef_type = new CPPTypedefType(inst->_type, inst->_ident, current_scope);
+      current_scope->add_declaration(typedef_type, global_scope, current_lexer, @2);
     }
   }
 }
@@ -725,19 +728,15 @@ typedef_declaration:
 typedef_instance_identifiers:
         instance_identifier maybe_initialize_or_function_body
 {
-  CPPInstance *inst = new CPPInstance(current_type, $1,
-                                      current_storage_class,
-                                      @1.file);
-  inst->set_initializer($2);
-  current_scope->add_declaration(new CPPTypedef(inst, current_scope == global_scope), global_scope, current_lexer, @1);
+  CPPType *target_type = current_type;
+  CPPTypedefType *typedef_type = new CPPTypedefType(target_type, $1, current_scope, @1.file);
+  current_scope->add_declaration(typedef_type, global_scope, current_lexer, @1);
 }
         | instance_identifier maybe_initialize ',' typedef_instance_identifiers
 {
-  CPPInstance *inst = new CPPInstance(current_type, $1,
-                                      current_storage_class,
-                                      @1.file);
-  inst->set_initializer($2);
-  current_scope->add_declaration(new CPPTypedef(inst, current_scope == global_scope), global_scope, current_lexer, @1);
+  CPPType *target_type = current_type;
+  CPPTypedefType *typedef_type = new CPPTypedefType(target_type, $1, current_scope, @1.file);
+  current_scope->add_declaration(typedef_type, global_scope, current_lexer, @1);
 }
         ;
 
@@ -745,27 +744,23 @@ typedef_const_instance_identifiers:
         instance_identifier maybe_initialize_or_function_body
 {
   $1->add_modifier(IIT_const);
-  CPPInstance *inst = new CPPInstance(current_type, $1,
-                                      current_storage_class,
-                                      @1.file);
-  inst->set_initializer($2);
-  current_scope->add_declaration(new CPPTypedef(inst, current_scope == global_scope), global_scope, current_lexer, @1);
+  CPPType *target_type = current_type;
+  CPPTypedefType *typedef_type = new CPPTypedefType(target_type, $1, current_scope, @1.file);
+  current_scope->add_declaration(typedef_type, global_scope, current_lexer, @1);
 }
         | instance_identifier maybe_initialize ',' typedef_const_instance_identifiers
 {
   $1->add_modifier(IIT_const);
-  CPPInstance *inst = new CPPInstance(current_type, $1,
-                                      current_storage_class,
-                                      @1.file);
-  inst->set_initializer($2);
-  current_scope->add_declaration(new CPPTypedef(inst, current_scope == global_scope), global_scope, current_lexer, @1);
+  CPPType *target_type = current_type;
+  CPPTypedefType *typedef_type = new CPPTypedefType(target_type, $1, current_scope, @1.file);
+  current_scope->add_declaration(typedef_type, global_scope, current_lexer, @1);
 }
         ;
 
 function_prototype:
 
 /* Functions with implicit return types, and constructors */
-        IDENTIFIER '(' 
+        IDENTIFIER '('
 {
   push_scope($1->get_scope(current_scope, global_scope));
 }
@@ -821,13 +816,13 @@ function_prototype:
   if ($2->is_scoped()) {
     yyerror("Invalid destructor name: ~" + $2->get_fully_scoped_name(), @2);
   } else {
-    CPPIdentifier *ident = 
+    CPPIdentifier *ident =
       new CPPIdentifier("~" + $2->get_simple_name(), @2.file);
     delete $2;
 
     CPPType *type;
     type = new CPPSimpleType(CPPSimpleType::T_void);
-    
+
     CPPInstanceIdentifier *ii = new CPPInstanceIdentifier(ident);
     ii->add_func_modifier($5, $7);
 
@@ -932,7 +927,7 @@ function_prototype:
    avoid shift/reduce conflicts. */
         | IDENTIFIER
 {
-  CPPDeclaration *decl = 
+  CPPDeclaration *decl =
     $1->find_symbol(current_scope, global_scope, current_lexer);
   if (decl != (CPPDeclaration *)NULL) {
     $$ = decl->as_instance();
@@ -1560,11 +1555,7 @@ type:
 {
   $$ = CPPType::new_type($1);
 }
-        | anonymous_enum
-{
-  $$ = CPPType::new_type($1);
-}
-        | named_enum
+        | enum
 {
   $$ = CPPType::new_type($1);
 }
@@ -1574,7 +1565,7 @@ type:
   if (type != NULL) {
     $$ = type;
   } else {
-    CPPExtensionType *et = 
+    CPPExtensionType *et =
       CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
       ->as_extension_type();
     CPPScope *scope = $2->get_scope(current_scope, global_scope);
@@ -1584,13 +1575,13 @@ type:
     $$ = et;
   }
 }
-        | enum_keyword name
+        | enum_keyword name ':' enum_element_type
 {
   CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
   if (type != NULL) {
     $$ = type;
   } else {
-    CPPExtensionType *et = 
+    CPPExtensionType *et =
       CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
       ->as_extension_type();
     CPPScope *scope = $2->get_scope(current_scope, global_scope);
@@ -1624,11 +1615,7 @@ type_decl:
 {
   $$ = new CPPTypeDeclaration(CPPType::new_type($1));
 }
-        | anonymous_enum
-{
-  $$ = CPPType::new_type($1);
-}
-        | named_enum
+        | enum
 {
   $$ = new CPPTypeDeclaration(CPPType::new_type($1));
 }
@@ -1638,7 +1625,7 @@ type_decl:
   if (type != NULL) {
     $$ = type;
   } else {
-    CPPExtensionType *et = 
+    CPPExtensionType *et =
       CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
       ->as_extension_type();
     CPPScope *scope = $2->get_scope(current_scope, global_scope);
@@ -1648,13 +1635,13 @@ type_decl:
     $$ = et;
   }
 }
-        | enum_keyword name
+        | enum_keyword name ':' enum_element_type
 {
   CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
   if (type != NULL) {
     $$ = type;
   } else {
-    CPPExtensionType *et = 
+    CPPExtensionType *et =
       CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
       ->as_extension_type();
     CPPScope *scope = $2->get_scope(current_scope, global_scope);
@@ -1686,7 +1673,7 @@ predefined_type:
   if (type != NULL) {
     $$ = type;
   } else {
-    CPPExtensionType *et = 
+    CPPExtensionType *et =
       CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
       ->as_extension_type();
     CPPScope *scope = $2->get_scope(current_scope, global_scope);
@@ -1702,7 +1689,7 @@ predefined_type:
   if (type != NULL) {
     $$ = type;
   } else {
-    CPPExtensionType *et = 
+    CPPExtensionType *et =
       CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
       ->as_extension_type();
     CPPScope *scope = $2->get_scope(current_scope, global_scope);
@@ -1733,9 +1720,9 @@ full_type:
 anonymous_struct:
         struct_keyword '{'
 {
-  CPPVisibility starting_vis = 
+  CPPVisibility starting_vis =
   ($1 == CPPExtensionType::T_class) ? V_private : V_public;
-  
+
   CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("anon"),
                                      starting_vis);
   CPPStructType *st = new CPPStructType($1, NULL, current_scope,
@@ -1757,7 +1744,7 @@ anonymous_struct:
 named_struct:
         struct_keyword name
 {
-  CPPVisibility starting_vis = 
+  CPPVisibility starting_vis =
   ($1 == CPPExtensionType::T_class) ? V_private : V_public;
 
   CPPScope *scope = $2->get_scope(current_scope, global_scope, current_lexer);
@@ -1771,7 +1758,7 @@ named_struct:
                                         new_scope, @1.file);
   new_scope->set_struct_type(st);
   current_scope->define_extension_type(st);
-  
+
   push_scope(new_scope);
   push_struct(st);
 }
@@ -1833,27 +1820,41 @@ base_specification:
 }
         ;
 
-anonymous_enum:
-        enum_keyword '{'
-{
-  current_enum = new CPPEnumType(NULL, current_scope, @1.file);
-}
-        enum_body '}'
+enum:
+        enum_decl '{' enum_body '}'
 {
   $$ = current_enum;
   current_enum = NULL;
 }
         ;
 
-named_enum:
-        enum_keyword name '{'
+enum_decl:
+        enum_keyword name ':' enum_element_type
+{
+  current_enum = new CPPEnumType($2, $4, current_scope, @1.file);
+}
+        | enum_keyword name
 {
   current_enum = new CPPEnumType($2, current_scope, @1.file);
 }
-        enum_body '}'
+        | enum_keyword ':' enum_element_type
 {
-  $$ = current_enum;
-  current_enum = NULL;
+  current_enum = new CPPEnumType(NULL, $3, current_scope, @1.file);
+}
+        | enum_keyword
+{
+  current_enum = new CPPEnumType(NULL, current_scope, @1.file);
+}
+        ;
+
+enum_element_type:
+        simple_int_type
+{
+  $$ = CPPType::new_type($1);
+}
+        | TYPENAME_IDENTIFIER
+{
+  $$ = $1->find_type(current_scope, global_scope, false, current_lexer);
 }
         ;
 
@@ -1916,7 +1917,7 @@ namespace_declaration:
   CPPScope *scope = $2->find_scope(current_scope, global_scope, current_lexer);
   if (scope == NULL) {
     // This must be a new namespace declaration.
-    CPPScope *parent_scope = 
+    CPPScope *parent_scope =
       $2->get_scope(current_scope, global_scope, current_lexer);
     if (parent_scope == NULL) {
       parent_scope = current_scope;
@@ -1969,6 +1970,14 @@ simple_int_type:
         | KW_WCHAR_T
 {
   $$ = new CPPSimpleType(CPPSimpleType::T_wchar_t);
+}
+        | KW_CHAR16_T
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_char16_t);
+}
+        | KW_CHAR32_T
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_char32_t);
 }
         | KW_SHORT
 {
@@ -2104,13 +2113,14 @@ element:
         | ELLIPSIS | OROR | ANDAND
         | EQCOMPARE | NECOMPARE | LECOMPARE | GECOMPARE
         | LSHIFT | RSHIFT | POINTSAT_STAR | DOT_STAR | POINTSAT
-        | SCOPE | PLUSPLUS | MINUSMINUS 
+        | SCOPE | PLUSPLUS | MINUSMINUS
         | TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL
         | OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL
-        | KW_BOOL | KW_CATCH | KW_CHAR | KW_WCHAR_T | KW_CLASS | KW_CONST
+        | KW_BOOL | KW_CATCH | KW_CHAR | KW_CHAR16_T | KW_CHAR32_T
+        | KW_WCHAR_T | KW_CLASS | KW_CONST
         | KW_DELETE | KW_DOUBLE | KW_DYNAMIC_CAST | KW_ELSE | KW_ENUM
         | KW_EXTERN | KW_EXPLICIT | KW_FALSE
-        | KW_FLOAT | KW_FRIEND | KW_FOR | KW_GOTO 
+        | KW_FLOAT | KW_FRIEND | KW_FOR | KW_GOTO
         | KW_IF | KW_INLINE | KW_INT
         | KW_LONG | KW_MUTABLE | KW_NEW | KW_PRIVATE | KW_PROTECTED
         | KW_PUBLIC | KW_PUBLISHED | KW_REGISTER | KW_RETURN
@@ -2329,65 +2339,77 @@ const_expr:
 }
         | KW_INT '(' optional_const_expr_comma ')'
 {
-  CPPType *type = 
+  CPPType *type =
     CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int));
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
 }
         | KW_CHAR '(' optional_const_expr_comma ')'
 {
-  CPPType *type = 
+  CPPType *type =
     CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char));
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
 }
         | KW_WCHAR_T '(' optional_const_expr_comma ')'
 {
-  CPPType *type = 
+  CPPType *type =
     CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_wchar_t));
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+        | KW_CHAR16_T '(' optional_const_expr_comma ')'
+{
+  CPPType *type =
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char16_t));
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+        | KW_CHAR32_T '(' optional_const_expr_comma ')'
+{
+  CPPType *type =
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char32_t));
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
 }
         | KW_BOOL '(' optional_const_expr_comma ')'
 {
-  CPPType *type = 
+  CPPType *type =
     CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool));
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
 }
         | KW_SHORT '(' optional_const_expr_comma ')'
 {
-  CPPType *type = 
+  CPPType *type =
     CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int,
                                         CPPSimpleType::F_short));
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
 }
         | KW_LONG '(' optional_const_expr_comma ')'
 {
-  CPPType *type = 
+  CPPType *type =
     CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int,
                                         CPPSimpleType::F_long));
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
 }
         | KW_UNSIGNED '(' optional_const_expr_comma ')'
 {
-  CPPType *type = 
+  CPPType *type =
     CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int,
                                         CPPSimpleType::F_unsigned));
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
 }
         | KW_SIGNED '(' optional_const_expr_comma ')'
 {
-  CPPType *type = 
+  CPPType *type =
     CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int,
                                         CPPSimpleType::F_signed));
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
 }
         | KW_FLOAT '(' optional_const_expr_comma ')'
 {
-  CPPType *type = 
+  CPPType *type =
     CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_float));
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
 }
         | KW_DOUBLE '(' optional_const_expr_comma ')'
 {
-  CPPType *type = 
+  CPPType *type =
     CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double));
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
 }

+ 4 - 4
dtool/src/cppparser/cppDeclaration.cxx

@@ -177,13 +177,13 @@ as_class_template_parameter() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CPPDeclaration::as_typedef
+//     Function: CPPDeclaration::as_typedef_type
 //       Access: Public, Virtual
 //  Description:
 ////////////////////////////////////////////////////////////////////
-CPPTypedef *CPPDeclaration::
-as_typedef() {
-  return (CPPTypedef *)NULL;
+CPPTypedefType *CPPDeclaration::
+as_typedef_type() {
+  return (CPPTypedefType *)NULL;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 3 - 3
dtool/src/cppparser/cppDeclaration.h

@@ -30,7 +30,7 @@ using namespace std;
 
 class CPPInstance;
 class CPPTemplateParameterList;
-class CPPTypedef;
+class CPPTypedefType;
 class CPPTypeDeclaration;
 class CPPExpression;
 class CPPType;
@@ -64,7 +64,6 @@ public:
   enum SubType {
     // Subtypes of CPPDeclaration
     ST_instance,
-    ST_typedef,
     ST_type_declaration,
     ST_expression,
     ST_type,
@@ -87,6 +86,7 @@ public:
     ST_class_template_parameter,
     ST_tbd,
     ST_type_proxy,
+    ST_typedef,
   };
 
   CPPDeclaration(const CPPFile &file);
@@ -120,7 +120,7 @@ public:
 
   virtual CPPInstance *as_instance();
   virtual CPPClassTemplateParameter *as_class_template_parameter();
-  virtual CPPTypedef *as_typedef();
+  virtual CPPTypedefType *as_typedef_type();
   virtual CPPTypeDeclaration *as_type_declaration();
   virtual CPPExpression *as_expression();
   virtual CPPType *as_type();

+ 94 - 12
dtool/src/cppparser/cppEnumType.cxx

@@ -13,7 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "cppEnumType.h"
-#include "cppTypedef.h"
+#include "cppTypedefType.h"
 #include "cppExpression.h"
 #include "cppSimpleType.h"
 #include "cppConstType.h"
@@ -24,12 +24,29 @@
 ////////////////////////////////////////////////////////////////////
 //     Function: CPPEnumType::Constructor
 //       Access: Public
-//  Description:
+//  Description: Creates an untyped, unscoped enum.
 ////////////////////////////////////////////////////////////////////
 CPPEnumType::
 CPPEnumType(CPPIdentifier *ident, CPPScope *current_scope,
             const CPPFile &file) :
   CPPExtensionType(T_enum, ident, current_scope, file),
+  _parent_scope(current_scope),
+  _element_type(NULL),
+  _last_value(NULL)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPEnumType::Constructor
+//       Access: Public
+//  Description: Creates a typed but unscoped enum.
+////////////////////////////////////////////////////////////////////
+CPPEnumType::
+CPPEnumType(CPPIdentifier *ident, CPPType *element_type,
+            CPPScope *current_scope, const CPPFile &file) :
+  CPPExtensionType(T_enum, ident, current_scope, file),
+  _parent_scope(current_scope),
+  _element_type(element_type),
   _last_value(NULL)
 {
 }
@@ -41,12 +58,24 @@ CPPEnumType(CPPIdentifier *ident, CPPScope *current_scope,
 ////////////////////////////////////////////////////////////////////
 CPPInstance *CPPEnumType::
 add_element(const string &name, CPPExpression *value) {
-  CPPType *type =
-    CPPType::new_type(new CPPConstType(new CPPSimpleType(
-      CPPSimpleType::T_int, CPPSimpleType::F_unsigned)));
-
   CPPIdentifier *ident = new CPPIdentifier(name);
-  CPPInstance *inst = new CPPInstance(type, ident);
+  ident->_native_scope = _parent_scope;
+  CPPInstance *inst;
+
+  static CPPType *default_element_type = NULL;
+  if (_element_type == NULL) {
+    // This enum is untyped.  Use a suitable default, ie. 'int'.
+    if (default_element_type == NULL) {
+      default_element_type =
+        CPPType::new_type(new CPPConstType(new CPPSimpleType(CPPSimpleType::T_int, 0)));
+    }
+
+    inst = new CPPInstance(default_element_type, ident);
+  } else {
+    // This enum has an explicit type, so use that.
+    inst = new CPPInstance(CPPType::new_type(new CPPConstType(_element_type)), ident);
+  }
+
   _elements.push_back(inst);
 
   if (value == (CPPExpression *)NULL) {
@@ -81,6 +110,39 @@ is_incomplete() const {
   return false;
 }
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPEnumType::is_fully_specified
+//       Access: Public, Virtual
+//  Description: Returns true if this declaration is an actual,
+//               factual declaration, or false if some part of the
+//               declaration depends on a template parameter which has
+//               not yet been instantiated.
+////////////////////////////////////////////////////////////////////
+bool CPPEnumType::
+is_fully_specified() const {
+  if (!CPPDeclaration::is_fully_specified()) {
+    return false;
+  }
+
+  if (_ident != NULL && !_ident->is_fully_specified()) {
+    return false;
+  }
+
+  if (_element_type != NULL && !_element_type->is_fully_specified()) {
+    return false;
+  }
+
+  Elements::const_iterator ei;
+  for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
+    if (!(*ei)->is_fully_specified()) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CPPEnumType::substitute_decl
 //       Access: Public, Virtual
@@ -100,7 +162,28 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
       _ident->substitute_decl(subst, current_scope, global_scope);
   }
 
-  if (rep->_ident == _ident) {
+  if (_element_type != NULL) {
+    rep->_element_type =
+      _element_type->substitute_decl(subst, current_scope, global_scope)
+      ->as_type();
+  }
+
+  bool any_changed = false;
+
+  for (int i = 0; i < _elements.size(); ++i) {
+    CPPInstance *elem_rep =
+      _elements[i]->substitute_decl(subst, current_scope, global_scope)
+      ->as_instance();
+
+    if (elem_rep != _elements[i]) {
+      _elements[i] = elem_rep;
+      any_changed = true;
+    }
+  }
+
+  if (rep->_ident == _ident &&
+      rep->_element_type == _element_type &&
+      !any_changed) {
     delete rep;
     rep = this;
   }
@@ -124,15 +207,14 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
     }
     out << _ident->get_local_name(scope);
 
-  } else if (!complete && !_typedefs.empty()) {
-    // If we have a typedef name, use it.
-    out << _typedefs.front()->get_local_name(scope);
-
   } else {
     out << _type;
     if (_ident != NULL) {
       out << " " << _ident->get_local_name(scope);
     }
+    if (_element_type != NULL) {
+      out << " : " << _element_type->get_local_name(scope);
+    }
 
     out << " {\n";
     Elements::const_iterator ei;

+ 6 - 0
dtool/src/cppparser/cppEnumType.h

@@ -34,12 +34,15 @@ class CPPEnumType : public CPPExtensionType {
 public:
   CPPEnumType(CPPIdentifier *ident, CPPScope *current_scope,
               const CPPFile &file);
+  CPPEnumType(CPPIdentifier *ident, CPPType *element_type,
+              CPPScope *current_scope, const CPPFile &file);
 
   CPPInstance *add_element(const string &name,
                            CPPExpression *value = (CPPExpression *)NULL);
 
   virtual bool is_incomplete() const;
 
+  virtual bool is_fully_specified() const;
   virtual CPPDeclaration *substitute_decl(SubstDecl &subst,
                                           CPPScope *current_scope,
                                           CPPScope *global_scope);
@@ -50,6 +53,9 @@ public:
 
   virtual CPPEnumType *as_enum_type();
 
+  CPPScope *_parent_scope;
+  CPPType *_element_type;
+
   typedef vector<CPPInstance *> Elements;
   Elements _elements;
   CPPExpression *_last_value;

+ 103 - 1
dtool/src/cppparser/cppExpression.cxx

@@ -226,7 +226,7 @@ CPPExpression(CPPIdentifier *ident, CPPScope *current_scope,
   CPPDeclaration(CPPFile())
 {
   CPPDeclaration *decl =
-    ident->find_symbol(current_scope, global_scope, error_sink);
+    ident->find_symbol(current_scope, global_scope);
 
   if (decl != NULL) {
     CPPInstance *inst = decl->as_instance();
@@ -245,6 +245,7 @@ CPPExpression(CPPIdentifier *ident, CPPScope *current_scope,
 
   _type = T_unknown_ident;
   _u._ident = ident;
+  _u._ident->_native_scope = current_scope;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -801,6 +802,66 @@ determine_type() const {
   return NULL;  // Compiler kludge; can't get here.
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CPPExpression::is_fully_specified
+//       Access: Public, Virtual
+//  Description: Returns true if this declaration is an actual,
+//               factual declaration, or false if some part of the
+//               declaration depends on a template parameter which has
+//               not yet been instantiated.
+////////////////////////////////////////////////////////////////////
+bool CPPExpression::
+is_fully_specified() const {
+  if (!CPPDeclaration::is_fully_specified()) {
+    return false;
+  }
+
+  switch (_type) {
+  case T_integer:
+  case T_real:
+  case T_string:
+    return false;
+
+  case T_variable:
+    return _u._variable->is_fully_specified();
+
+  case T_function:
+    return _u._fgroup->is_fully_specified();
+
+  case T_unknown_ident:
+    return _u._ident->is_fully_specified();
+
+  case T_typecast:
+  case T_construct:
+  case T_new:
+    return (_u._typecast._to->is_fully_specified() &&
+            _u._typecast._op1->is_fully_specified());
+
+  case T_default_construct:
+  case T_default_new:
+  case T_sizeof:
+    return _u._typecast._to->is_fully_specified();
+
+  case T_trinary_operation:
+    if (!_u._op._op3->is_fully_specified()) {
+      return false;
+    }
+    // Fall through
+
+  case T_binary_operation:
+    if (!_u._op._op2->is_fully_specified()) {
+      return false;
+    }
+    // Fall through
+
+  case T_unary_operation:
+    return _u._op._op1->is_fully_specified();
+
+  default:
+    return true;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CPPExpression::substitute_decl
 //       Access: Public, Virtual
@@ -827,6 +888,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
         // Replacing the variable reference with another variable reference.
         rep->_u._variable = decl->as_instance();
         any_changed = true;
+
       } else if (decl->as_expression()) {
         // Replacing the variable reference with an expression.
         delete rep;
@@ -836,6 +898,43 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
     }
     break;
 
+  case T_unknown_ident:
+    rep->_u._ident = _u._ident->substitute_decl(subst, current_scope, global_scope);
+    any_changed = any_changed || (rep->_u._ident != _u._ident);
+
+    // See if we can define it now.
+    decl = rep->_u._ident->find_symbol(current_scope, global_scope, subst);
+    if (decl != NULL) {
+      CPPInstance *inst = decl->as_instance();
+      if (inst != NULL) {
+        rep->_type = T_variable;
+        rep->_u._variable = inst;
+        any_changed = true;
+
+        decl = inst->substitute_decl(subst, current_scope, global_scope);
+        if (decl != inst) {
+          if (decl->as_instance()) {
+            // Replacing the variable reference with another variable reference.
+            rep->_u._variable = decl->as_instance();
+
+          } else if (decl->as_expression()) {
+            // Replacing the variable reference with an expression.
+            delete rep;
+            rep = decl->as_expression();
+          }
+        }
+        break;
+      }
+      CPPFunctionGroup *fgroup = decl->as_function_group();
+      if (fgroup != NULL) {
+        rep->_type = T_function;
+        rep->_u._fgroup = fgroup;
+        any_changed = true;
+      }
+    }
+
+    break;
+
   case T_typecast:
   case T_construct:
   case T_new:
@@ -909,6 +1008,9 @@ is_tbd() const {
 
     return true;
 
+  case T_unknown_ident:
+    return true;
+
   case T_typecast:
   case T_construct:
   case T_new:

+ 1 - 0
dtool/src/cppparser/cppExpression.h

@@ -78,6 +78,7 @@ public:
   CPPType *determine_type() const;
   bool is_tbd() const;
 
+  virtual bool is_fully_specified() const;
   virtual CPPDeclaration *substitute_decl(SubstDecl &subst,
                                           CPPScope *current_scope,
                                           CPPScope *global_scope);

+ 1 - 1
dtool/src/cppparser/cppExtensionType.cxx

@@ -14,7 +14,7 @@
 
 
 #include "cppExtensionType.h"
-#include "cppTypedef.h"
+#include "cppTypedefType.h"
 #include "cppIdentifier.h"
 #include "cppParser.h"
 #include "indent.h"

+ 40 - 2
dtool/src/cppparser/cppIdentifier.cxx

@@ -39,7 +39,7 @@ CPPIdentifier(const string &name, const CPPFile &file) : _file(file) {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 CPPIdentifier::
-CPPIdentifier(const CPPNameComponent &name) {
+CPPIdentifier(const CPPNameComponent &name, const CPPFile &file) : _file(file) {
   _names.push_back(name);
   _native_scope = (CPPScope *)NULL;
 }
@@ -382,6 +382,7 @@ find_type(CPPScope *current_scope, CPPScope *global_scope,
   if (scope == NULL) {
     return NULL;
   }
+
   CPPType *type = scope->find_type(get_simple_name(), subst, global_scope);
   if (type != NULL && _names.back().has_templ()) {
     // This is a template type.
@@ -398,7 +399,6 @@ find_type(CPPScope *current_scope, CPPScope *global_scope,
       assert(new_type != NULL);
       if (new_type == type) {
         type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
-        //      type = new_type;
       } else {
         type = new_type;
       }
@@ -424,12 +424,50 @@ find_symbol(CPPScope *current_scope, CPPScope *global_scope,
   if (scope == NULL) {
     return NULL;
   }
+
+  CPPDeclaration *sym;
+  if (!_names.back().has_templ()) {
+    sym = scope->find_symbol(get_simple_name());
+
+  } else {
+    sym = scope->find_template(get_simple_name());
+    if (sym != NULL) {
+      CPPType *type = sym->as_type();
+      if (type != NULL && type->is_incomplete()) {
+        // We can't instantiate an incomplete type.
+        sym = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
+      } else {
+        // Instantiate the symbol.
+        sym = sym->instantiate(_names.back().get_templ(), current_scope,
+                               global_scope, error_sink);
+      }
+    }
+  }
+
+  return sym;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPIdentifier::find_symbol
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+CPPDeclaration *CPPIdentifier::
+find_symbol(CPPScope *current_scope, CPPScope *global_scope,
+            CPPDeclaration::SubstDecl &subst,
+            CPPPreprocessor *error_sink) const {
+  CPPScope *scope = get_scope(current_scope, global_scope, subst, error_sink);
+  if (scope == NULL) {
+    return NULL;
+  }
+
   CPPDeclaration *sym;
   if (!_names.back().has_templ()) {
     sym = scope->find_symbol(get_simple_name());
 
   } else {
     sym = scope->find_template(get_simple_name());
+
     if (sym != NULL) {
       CPPType *type = sym->as_type();
       if (type != NULL && type->is_incomplete()) {

+ 5 - 1
dtool/src/cppparser/cppIdentifier.h

@@ -36,7 +36,7 @@ class CPPTemplateParameterList;
 class CPPIdentifier {
 public:
   CPPIdentifier(const string &name, const CPPFile &file = CPPFile());
-  CPPIdentifier(const CPPNameComponent &name);
+  CPPIdentifier(const CPPNameComponent &name, const CPPFile &file = CPPFile());
   void add_name(const string &name);
   void add_name(const CPPNameComponent &name);
 
@@ -69,6 +69,10 @@ public:
   CPPDeclaration *find_symbol(CPPScope *current_scope,
                               CPPScope *global_scope,
                               CPPPreprocessor *error_sink = NULL) const;
+  CPPDeclaration *find_symbol(CPPScope *current_scope,
+                              CPPScope *global_scope,
+                              CPPDeclaration::SubstDecl &subst,
+                              CPPPreprocessor *error_sink = NULL) const;
   CPPDeclaration *find_template(CPPScope *current_scope,
                                 CPPScope *global_scope,
                                 CPPPreprocessor *error_sink = NULL) const;

+ 1 - 1
dtool/src/cppparser/cppInstance.cxx

@@ -372,6 +372,7 @@ CPPDeclaration *CPPInstance::
 instantiate(const CPPTemplateParameterList *actual_params,
             CPPScope *current_scope, CPPScope *global_scope,
             CPPPreprocessor *error_sink) const {
+
   if (!is_template()) {
     if (error_sink != NULL) {
       error_sink->warning("Ignoring template parameters for instance " +
@@ -457,7 +458,6 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
   rep->_type = new_type->as_type();
 
   if (rep->_type == NULL) {
-    cerr << "Type " << *_type << " became " << *new_type << " which isn't a type\n";
     rep->_type = _type;
   }
 

+ 2 - 2
dtool/src/cppparser/cppManifest.cxx

@@ -47,8 +47,8 @@ ExpansionNode(const string &str, bool paste) :
 ////////////////////////////////////////////////////////////////////
 CPPManifest::
 CPPManifest(const string &args, const CPPFile &file) :
-  _file(file),
   _variadic_param(-1),
+  _file(file),
   _expr((CPPExpression *)NULL)
 {
   assert(!args.empty());
@@ -184,7 +184,7 @@ expand(const vector_string &args) const {
         // to a comma and no arguments are passed, the comma
         // is removed.  MSVC does this automatically.  Not sure
         // if we should allow MSVC behavior as well.
-        if (*result.rbegin() == ',') {
+        if (!result.empty() && *result.rbegin() == ',') {
           result.resize(result.size() - 1);
         }
       }

+ 11 - 4
dtool/src/cppparser/cppPreprocessor.cxx

@@ -200,6 +200,7 @@ CPPPreprocessor() {
 
   _warning_count = 0;
   _error_count = 0;
+  _error_abort = true;
 #ifdef CPP_VERBOSE_LEX
   _token_index = 0;
 #endif
@@ -404,8 +405,7 @@ get_next_token0() {
 
     int token_type = IDENTIFIER;
     CPPDeclaration *decl = ident->find_symbol(current_scope, global_scope);
-    if (decl != NULL &&
-        (decl->as_typedef() != NULL || decl->as_type() != NULL)) {
+    if (decl != NULL && decl->as_type() != NULL) {
       token_type = TYPENAME_IDENTIFIER;
     }
 
@@ -452,7 +452,7 @@ error(const string &message, int line, int col, CPPFile file) {
     // Don't report or log errors in the nested state.  These will be
     // reported when the nesting level collapses.
     return;
-  };
+  }
 
   if (_verbose >= 1) {
     if (line == 0) {
@@ -467,6 +467,11 @@ error(const string &message, int line, int col, CPPFile file) {
       << " near line " << line << ", column " << col << ":\n";
     indent(cerr, _files.size() * 2)
       << message << "\n";
+
+    if (_error_abort) {
+      cerr << "Aborting.\n";
+      abort();
+    }
   }
   _error_count++;
 }
@@ -2005,7 +2010,8 @@ check_keyword(const string &name) {
   if (name == "bool") return KW_BOOL;
   if (name == "catch") return KW_CATCH;
   if (name == "char") return KW_CHAR;
-  if (name == "wchar_t") return KW_WCHAR_T;
+  if (name == "char16_t") return KW_CHAR16_T;
+  if (name == "char32_t") return KW_CHAR32_T;
   if (name == "class") return KW_CLASS;
   if (name == "const") return KW_CONST;
   if (name == "delete") return KW_DELETE;
@@ -2056,6 +2062,7 @@ check_keyword(const string &name) {
   if (name == "virtual") return KW_VIRTUAL;
   if (name == "void") return KW_VOID;
   if (name == "volatile") return KW_VOLATILE;
+  if (name == "wchar_t") return KW_WCHAR_T;
   if (name == "while") return KW_WHILE;
 
   if (!cpp_longlong_keyword.empty() && name == cpp_longlong_keyword) {

+ 1 - 0
dtool/src/cppparser/cppPreprocessor.h

@@ -209,6 +209,7 @@ private:
 
   int _warning_count;
   int _error_count;
+  bool _error_abort;
 };
 
 #endif

+ 61 - 47
dtool/src/cppparser/cppScope.cxx

@@ -16,7 +16,7 @@
 #include "cppScope.h"
 #include "cppDeclaration.h"
 #include "cppNamespace.h"
-#include "cppTypedef.h"
+#include "cppTypedefType.h"
 #include "cppTypeDeclaration.h"
 #include "cppExtensionType.h"
 #include "cppInstance.h"
@@ -200,28 +200,28 @@ define_extension_type(CPPExtensionType *type) {
 
   case CPPExtensionType::T_union:
     _unions[name] = type;
+    break;
 
   case CPPExtensionType::T_enum:
     _enums[name] = type;
   }
 
   // Create an implicit typedef for the extension.
-  CPPIdentifier *ident = new CPPIdentifier(name);
-  CPPTypedef *td = new CPPTypedef(new CPPInstance(type, ident), false);
-  pair<Typedefs::iterator, bool> result =
-    _typedefs.insert(Typedefs::value_type(name, td));
+  //CPPTypedefType *td = new CPPTypedefType(type, name);
+  pair<Types::iterator, bool> result =
+    _types.insert(Types::value_type(name, type));
 
   if (!result.second) {
     // There's already a typedef for this extension.  This one
     // overrides if it has template parameters and the other one
     // doesn't.
-    CPPType *other_type = (*result.first).second->_type;
+    CPPType *other_type = (*result.first).second;
     if (type->is_template() && !other_type->is_template()) {
-      (*result.first).second = td;
+      (*result.first).second = type;
 
       // Or if the other one is a forward reference.
     } else if (other_type->get_subtype() == CPPDeclaration::ST_extension) {
-      (*result.first).second = td;
+      (*result.first).second = type;
     }
   }
 
@@ -391,11 +391,13 @@ instantiate(const CPPTemplateParameterList *actual_params,
       CPPDeclaration *decl = (*pi);
       CPPClassTemplateParameter *ctp = decl->as_class_template_parameter();
       if (ctp != NULL) {
-        CPPInstance *inst = new CPPInstance(ctp, ctp->_ident);
-        CPPTypedef *td = new CPPTypedef(inst, true);
-        scope->_typedefs.insert(Typedefs::value_type
-                                (ctp->_ident->get_local_name(),
-                                 td));
+        //CPPTypedefType *td = new CPPTypedefType(ctp, ctp->_ident);
+        //scope->_typedefs.insert(Typedefs::value_type
+        //                        (ctp->_ident->get_local_name(),
+        //                         td));
+        scope->_types.insert(Types::value_type
+                             (ctp->_ident->get_local_name(),
+                              ctp));
       }
     }
   }
@@ -465,10 +467,10 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
 ////////////////////////////////////////////////////////////////////
 CPPType *CPPScope::
 find_type(const string &name, bool recurse) const {
-  Typedefs::const_iterator ti;
-  ti = _typedefs.find(name);
-  if (ti != _typedefs.end()) {
-    return (*ti).second->_type;
+  Types::const_iterator ti;
+  ti = _types.find(name);
+  if (ti != _types.end()) {
+    return ti->second;
   }
 
   Using::const_iterator ui;
@@ -509,11 +511,11 @@ find_type(const string &name, bool recurse) const {
 CPPType *CPPScope::
 find_type(const string &name, CPPDeclaration::SubstDecl &subst,
           CPPScope *global_scope, bool recurse) const {
-  Typedefs::const_iterator ti;
-  ti = _typedefs.find(name);
-  if (ti != _typedefs.end()) {
+  Types::const_iterator ti;
+  ti = _types.find(name);
+  if (ti != _types.end()) {
     CPPScope *current_scope = (CPPScope *)this;
-    return (*ti).second->_type->substitute_decl
+    return (*ti).second->substitute_decl
       (subst, current_scope, global_scope)->as_type();
   }
 
@@ -562,10 +564,14 @@ find_scope(const string &name, bool recurse) const {
 
   CPPType *type = (CPPType *)NULL;
 
-  Typedefs::const_iterator ti;
-  ti = _typedefs.find(name);
-  if (ti != _typedefs.end()) {
-    type = (*ti).second->_type;
+  Types::const_iterator ti;
+  ti = _types.find(name);
+  if (ti != _types.end()) {
+    type = (*ti).second;
+    // Resolve if this is a typedef.
+    while (type->as_typedef_type() != (CPPTypedefType *)NULL) {
+      type = type->as_typedef_type()->_type;
+    }
 
   } else if (_struct_type != NULL) {
     CPPStructType::Derivation::const_iterator di;
@@ -613,10 +619,17 @@ find_scope(const string &name, CPPDeclaration::SubstDecl &subst,
   if (type == NULL) {
     return NULL;
   }
+
+  // Resolve this if it is a typedef.
+  while (type->get_subtype() == CPPDeclaration::ST_typedef) {
+    type = type->as_typedef_type()->_type;
+  }
+
   CPPStructType *st = type->as_struct_type();
   if (st == NULL) {
     return NULL;
   }
+
   return st->_scope;
 }
 
@@ -631,10 +644,10 @@ find_symbol(const string &name, bool recurse) const {
     return _struct_type;
   }
 
-  Typedefs::const_iterator ti;
-  ti = _typedefs.find(name);
-  if (ti != _typedefs.end()) {
-    return (*ti).second->_type;
+  Types::const_iterator ti;
+  ti = _types.find(name);
+  if (ti != _types.end()) {
+    return (*ti).second;
   }
 
   Variables::const_iterator vi;
@@ -816,8 +829,7 @@ write(ostream &out, int indent_level, CPPScope *scope) const {
     }
     bool complete = false;
 
-    if (cd->as_typedef() != NULL || cd->as_type() != NULL ||
-        cd->as_namespace() != NULL) {
+    if (cd->as_type() != NULL || cd->as_namespace() != NULL) {
       complete = true;
     }
 
@@ -880,7 +892,7 @@ copy_substitute_decl(CPPScope *to_scope, CPPDeclaration::SubstDecl &subst,
     }
     to_scope->_struct_type =
       new CPPStructType(_struct_type->_type,
-                        new CPPIdentifier(to_scope->_name),
+                        new CPPIdentifier(to_scope->_name, _struct_type->_file),
                         native_scope, to_scope, _struct_type->_file);
     to_scope->_struct_type->_incomplete = false;
 
@@ -985,11 +997,11 @@ copy_substitute_decl(CPPScope *to_scope, CPPDeclaration::SubstDecl &subst,
     }
   }
 
-  Typedefs::const_iterator ti;
-  for (ti = _typedefs.begin(); ti != _typedefs.end(); ++ti) {
-    CPPTypedef *td =
-      (*ti).second->substitute_decl(subst, to_scope, global_scope)->as_typedef();
-    to_scope->_typedefs.insert(Typedefs::value_type((*ti).first, td));
+  Types::const_iterator ti;
+  for (ti = _types.begin(); ti != _types.end(); ++ti) {
+    CPPType *td =
+      (*ti).second->substitute_decl(subst, to_scope, global_scope)->as_type();
+    to_scope->_types.insert(Types::value_type((*ti).first, td));
     if (td != (*ti).second) {
       anything_changed = true;
     }
@@ -1004,6 +1016,15 @@ copy_substitute_decl(CPPScope *to_scope, CPPDeclaration::SubstDecl &subst,
     }
   }
 
+  for (vi = _enum_values.begin(); vi != _enum_values.end(); ++vi) {
+    CPPInstance *inst =
+      (*vi).second->substitute_decl(subst, to_scope, global_scope)->as_instance();
+    to_scope->_enum_values.insert(Variables::value_type((*vi).first, inst));
+    if (inst != (*vi).second) {
+      anything_changed = true;
+    }
+  }
+
   Templates::const_iterator tmi;
   for (tmi = _templates.begin(); tmi != _templates.end(); ++tmi) {
     CPPDeclaration *decl =
@@ -1027,24 +1048,17 @@ copy_substitute_decl(CPPScope *to_scope, CPPDeclaration::SubstDecl &subst,
 ////////////////////////////////////////////////////////////////////
 void CPPScope::
 handle_declaration(CPPDeclaration *decl, CPPScope *global_scope) {
-  CPPTypedef *def = decl->as_typedef();
+  CPPTypedefType *def = decl->as_typedef_type();
   if (def != NULL) {
     string name = def->get_simple_name();
-    _typedefs[name] = def;
+
+    _types[name] = def;
 
     CPPExtensionType *et = def->_type->as_extension_type();
     if (et != NULL) {
       define_extension_type(et);
     }
 
-    if (!name.empty() && def->get_scope(this, global_scope) == this) {
-      // Don't add a new template definition if we already had one
-      // by the same name in another scope.
-
-      if (find_template(name) == NULL) {
-        _templates.insert(Templates::value_type(name, def));
-      }
-    }
     return;
   }
 

+ 3 - 3
dtool/src/cppparser/cppScope.h

@@ -34,7 +34,7 @@ class CPPExtensionType;
 class CPPStructType;
 class CPPNamespace;
 class CPPUsing;
-class CPPTypedef;
+class CPPTypedefType;
 class CPPInstance;
 class CPPFunctionGroup;
 class CPPTemplateScope;
@@ -128,8 +128,8 @@ public:
   typedef map<string, CPPNamespace *> Namespaces;
   Namespaces _namespaces;
 
-  typedef map<string, CPPTypedef *> Typedefs;
-  Typedefs _typedefs;
+  typedef map<string, CPPType *> Types;
+  Types _types;
   typedef map<string, CPPInstance *> Variables;
   Variables _variables;
   Variables _enum_values;

+ 12 - 4
dtool/src/cppparser/cppSimpleType.cxx

@@ -99,6 +99,10 @@ output(ostream &out, int, CPPScope *, bool) const {
   }
 
   switch (_type) {
+  case T_unknown:
+    out << "unknown";
+    break;
+
   case T_bool:
     out << "bool";
     break;
@@ -111,6 +115,14 @@ output(ostream &out, int, CPPScope *, bool) const {
     out << "wchar_t";
     break;
 
+  case T_char16_t:
+    out << "char16_t";
+    break;
+
+  case T_char32_t:
+    out << "char32_t";
+    break;
+
   case T_int:
     out << "int";
     break;
@@ -127,10 +139,6 @@ output(ostream &out, int, CPPScope *, bool) const {
     out << "void";
     break;
 
-  case T_unknown:
-    out << "unknown";
-    break;
-
   case T_parameter:
     out << "parameter";
     break;

+ 4 - 2
dtool/src/cppparser/cppSimpleType.h

@@ -26,14 +26,16 @@
 class CPPSimpleType : public CPPType {
 public:
   enum Type {
+    T_unknown,
     T_bool,
     T_char,
-    T_wchar_t,  // Not strictly a builtin type, but we pretend.
+    T_wchar_t,
+    T_char16_t,
+    T_char32_t,
     T_int,
     T_float,
     T_double,
     T_void,
-    T_unknown,
 
     // T_parameter is a special type which is assigned to expressions
     // that are discovered where a formal parameter was expected.

+ 10 - 11
dtool/src/cppparser/cppStructType.cxx

@@ -14,7 +14,7 @@
 
 
 #include "cppStructType.h"
-#include "cppTypedef.h"
+#include "cppTypedefType.h"
 #include "cppScope.h"
 #include "cppTypeProxy.h"
 #include "cppTemplateScope.h"
@@ -91,6 +91,13 @@ operator = (const CPPStructType &copy) {
 void CPPStructType::
 append_derivation(CPPType *base, CPPVisibility vis, bool is_virtual) {
   if (base != NULL) {
+    // Unwrap any typedefs, since we can't inherit from a typedef.
+    CPPTypedefType *def = base->as_typedef_type();
+    while (def != NULL) {
+      base = def->_type;
+      def = base->as_typedef_type();
+    }
+
     Base b;
     b._base = base;
     b._vis = vis;
@@ -110,7 +117,6 @@ get_scope() const {
   return _scope;
 }
 
-
 ////////////////////////////////////////////////////////////////////
 //     Function: CPPStructType::is_abstract
 //       Access: Public
@@ -246,7 +252,7 @@ instantiate(const CPPTemplateParameterList *actual_params,
     // don't yet know what its associated struct type will be.
 
     // Postpone the evaluation of this type.
-    CPPIdentifier *ident = new CPPIdentifier(get_fully_scoped_name());
+    CPPIdentifier *ident = new CPPIdentifier(get_fully_scoped_name(), _file);
 
     return CPPType::new_type(new CPPTBDType(ident));
   }
@@ -318,7 +324,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
             rep->_template_scope = (CPPTemplateScope *)NULL;
             CPPNameComponent nc(get_simple_name());
             nc.set_templ(pscope->_name.get_templ());
-            rep->_ident = new CPPIdentifier(nc);
+            rep->_ident = new CPPIdentifier(nc, _file);
           }
         }
       }
@@ -356,7 +362,6 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
   assert(rep != NULL);
   if (rep != this) {
     _instantiations.insert(rep);
-    //    cerr << "Subst for " << *this << " is " << *rep << "\n";
   }
   return rep;
 }
@@ -377,15 +382,9 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
 
     if (is_template()) {
       CPPTemplateScope *tscope = get_template_scope();
-      out << "< ";
       tscope->_parameters.output(out, scope);
-      out << " >";
     }
 
-  } else if (!complete && !_typedefs.empty()) {
-    // If we have a typedef name, use it.
-    out << _typedefs.front()->get_local_name(scope);
-
   } else {
     if (is_template()) {
       get_template_scope()->_parameters.write_formal(out, scope);

+ 1 - 0
dtool/src/cppparser/cppTemplateParameterList.cxx

@@ -52,6 +52,7 @@ void CPPTemplateParameterList::
 build_subst_decl(const CPPTemplateParameterList &formal_params,
                  CPPDeclaration::SubstDecl &subst,
                  CPPScope *current_scope, CPPScope *global_scope) const {
+
   Parameters::const_iterator pfi, pai;
   for (pfi = formal_params._parameters.begin(), pai = _parameters.begin();
        pfi != formal_params._parameters.end() && pai != _parameters.end();

+ 3 - 2
dtool/src/cppparser/cppTemplateScope.cxx

@@ -17,7 +17,7 @@
 #include "cppExtensionType.h"
 #include "cppClassTemplateParameter.h"
 #include "cppIdentifier.h"
-#include "cppTypedef.h"
+#include "cppTypedefType.h"
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CPPTemplateScope::Constructor
@@ -105,8 +105,9 @@ add_template_parameter(CPPDeclaration *param) {
   if (cl != NULL) {
     // Create an implicit typedef for this class parameter.
     string name = cl->_ident->get_local_name();
-    _typedefs[name] = new CPPTypedef(new CPPInstance(cl, cl->_ident), false);
+    _types[name] = cl;
   }
+
   CPPInstance *inst = param->as_instance();
   if (inst != NULL) {
     // Register the variable for this value parameter.

+ 1 - 1
dtool/src/cppparser/cppType.cxx

@@ -14,7 +14,7 @@
 
 
 #include "cppType.h"
-#include "cppTypedef.h"
+#include "cppTypedefType.h"
 #include <algorithm>
 
 CPPType::Types CPPType::_types;

+ 2 - 2
dtool/src/cppparser/cppType.h

@@ -22,7 +22,7 @@
 #include <set>
 
 class CPPType;
-class CPPTypedef;
+class CPPTypedefType;
 class CPPTypeDeclaration;
 
 
@@ -39,7 +39,7 @@ public:
 ////////////////////////////////////////////////////////////////////
 class CPPType : public CPPDeclaration {
 public:
-  typedef vector<CPPTypedef *> Typedefs;
+  typedef vector<CPPTypedefType *> Typedefs;
   Typedefs _typedefs;
 
   CPPType(const CPPFile &file);

+ 13 - 1
dtool/src/cppparser/cppTypeProxy.cxx

@@ -357,6 +357,19 @@ as_tbd_type() {
   return _actual_type->as_tbd_type();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypeProxy::as_typedef_type
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+CPPTypedefType *CPPTypeProxy::
+as_typedef_type() {
+  if (_actual_type == (CPPType *)NULL) {
+    return (CPPTypedefType *)NULL;
+  }
+  return _actual_type->as_typedef_type();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CPPTypeProxy::as_type_proxy
 //       Access: Public, Virtual
@@ -366,4 +379,3 @@ CPPTypeProxy *CPPTypeProxy::
 as_type_proxy() {
   return this;
 }
-

+ 1 - 1
dtool/src/cppparser/cppTypeProxy.h

@@ -19,7 +19,6 @@
 
 #include "cppType.h"
 
-
 ///////////////////////////////////////////////////////////////////
 //       Class : CPPTypeProxy
 // Description : This is a special kind of type that is a placeholder
@@ -66,6 +65,7 @@ public:
   virtual CPPStructType *as_struct_type();
   virtual CPPEnumType *as_enum_type();
   virtual CPPTBDType *as_tbd_type();
+  virtual CPPTypedefType *as_typedef_type();
   virtual CPPTypeProxy *as_type_proxy();
 
   CPPType *_actual_type;

+ 0 - 91
dtool/src/cppparser/cppTypedef.cxx

@@ -1,91 +0,0 @@
-// Filename: cppTypedef.cxx
-// Created by:  drose (19Oct99)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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 "cppTypedef.h"
-
-////////////////////////////////////////////////////////////////////
-//     Function: CPPTypedef::Constructor
-//       Access: Public
-//  Description: Constructs a new CPPTypedef object based on the
-//               indicated CPPInstance object.  The CPPInstance is
-//               deallocated.
-//
-//               If global is true, the typedef is defined at the
-//               global scope, and hence it's worth telling the type
-//               itself about.  Otherwise, it's just a locally-scoped
-//               typedef.
-////////////////////////////////////////////////////////////////////
-CPPTypedef::
-CPPTypedef(CPPInstance *inst, bool global) : CPPInstance(*inst)
-{
-  // Actually, we'll avoid deleting this for now.  It causes problems
-  // for some reason to be determined later.
-  //  delete inst;
-
-  assert(_type != NULL);
-  if (global) {
-    _type->_typedefs.push_back(this);
-    CPPType::record_alt_name_for(_type, inst->get_local_name());
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CPPTypedef::substitute_decl
-//       Access: Public, Virtual
-//  Description:
-////////////////////////////////////////////////////////////////////
-CPPDeclaration *CPPTypedef::
-substitute_decl(CPPDeclaration::SubstDecl &subst,
-                CPPScope *current_scope, CPPScope *global_scope) {
-  CPPDeclaration *decl =
-    CPPInstance::substitute_decl(subst, current_scope, global_scope);
-  assert(decl != NULL);
-  if (decl->as_typedef()) {
-    return decl;
-  }
-  assert(decl->as_instance() != NULL);
-  return new CPPTypedef(new CPPInstance(*decl->as_instance()), false);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CPPTypedef::output
-//       Access: Public, Virtual
-//  Description:
-////////////////////////////////////////////////////////////////////
-void CPPTypedef::
-output(ostream &out, int indent_level, CPPScope *scope, bool) const {
-  out << "typedef ";
-  CPPInstance::output(out, indent_level, scope, false);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CPPTypedef::get_subtype
-//       Access: Public, Virtual
-//  Description:
-////////////////////////////////////////////////////////////////////
-CPPDeclaration::SubType CPPTypedef::
-get_subtype() const {
-  return ST_typedef;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CPPTypedef::as_typedef
-//       Access: Public, Virtual
-//  Description:
-////////////////////////////////////////////////////////////////////
-CPPTypedef *CPPTypedef::
-as_typedef() {
-  return this;
-}

+ 0 - 42
dtool/src/cppparser/cppTypedef.h

@@ -1,42 +0,0 @@
-// Filename: cppTypedef.h
-// Created by:  drose (19Oct99)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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 CPPTYPEDEF_H
-#define CPPTYPEDEF_H
-
-#include "dtoolbase.h"
-
-#include "cppInstance.h"
-
-///////////////////////////////////////////////////////////////////
-//       Class : CPPTypedef
-// Description :
-////////////////////////////////////////////////////////////////////
-class CPPTypedef : public CPPInstance {
-public:
-  CPPTypedef(CPPInstance *instance, bool global);
-
-  virtual CPPDeclaration *substitute_decl(SubstDecl &subst,
-                                          CPPScope *current_scope,
-                                          CPPScope *global_scope);
-
-  virtual void output(ostream &out, int indent_level, CPPScope *scope,
-                      bool complete) const;
-  virtual SubType get_subtype() const;
-
-  virtual CPPTypedef *as_typedef();
-};
-
-#endif
-

+ 388 - 0
dtool/src/cppparser/cppTypedefType.cxx

@@ -0,0 +1,388 @@
+// Filename: cppTypedefType.cxx
+// Created by:  rdb (01Aug14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "cppTypedefType.h"
+#include "cppIdentifier.h"
+#include "cppInstanceIdentifier.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+CPPTypedefType::
+CPPTypedefType(CPPType *type, const string &name, CPPScope *current_scope) :
+  CPPType(CPPFile()),
+  _type(type),
+  _ident(new CPPIdentifier(name))
+{
+  if (_ident != NULL) {
+    _ident->_native_scope = current_scope;
+  }
+
+  _subst_decl_recursive_protect = false;
+
+  //assert(_type != NULL);
+  //if (global) {
+  //  _type->_typedefs.push_back(this);
+  //  CPPType::record_alt_name_for(_type, inst->get_local_name());
+  //}
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+CPPTypedefType::
+CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope) :
+  CPPType(CPPFile()),
+  _type(type),
+  _ident(ident)
+{
+  if (_ident != NULL) {
+    _ident->_native_scope = current_scope;
+  }
+  _subst_decl_recursive_protect = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::Constructor
+//       Access: Public
+//  Description: Constructs a new CPPTypedefType object that defines a
+//               typedef to the indicated type according to the type
+//               and the InstanceIdentifier.  The InstanceIdentifier
+//               pointer is deallocated.
+////////////////////////////////////////////////////////////////////
+CPPTypedefType::
+CPPTypedefType(CPPType *type, CPPInstanceIdentifier *ii,
+               CPPScope *current_scope, const CPPFile &file) :
+  CPPType(file)
+{
+  _type = ii->unroll_type(type);
+  _ident = ii->_ident;
+  ii->_ident = NULL;
+  delete ii;
+
+  if (_ident != NULL) {
+    _ident->_native_scope = current_scope;
+  }
+
+  _subst_decl_recursive_protect = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::is_scoped
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool CPPTypedefType::
+is_scoped() const {
+  if (_ident == NULL) {
+    return false;
+  } else {
+    return _ident->is_scoped();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::get_scope
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+CPPScope *CPPTypedefType::
+get_scope(CPPScope *current_scope, CPPScope *global_scope,
+          CPPPreprocessor *error_sink) const {
+  if (_ident == NULL) {
+    return current_scope;
+  } else {
+    return _ident->get_scope(current_scope, global_scope, error_sink);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::get_simple_name
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+string CPPTypedefType::
+get_simple_name() const {
+  if (_ident == NULL) {
+    return "";
+  }
+  return _ident->get_simple_name();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::get_local_name
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+string CPPTypedefType::
+get_local_name(CPPScope *scope) const {
+  if (_ident == NULL) {
+    return "";
+  }
+  return _ident->get_local_name(scope);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::get_fully_scoped_name
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+string CPPTypedefType::
+get_fully_scoped_name() const {
+  if (_ident == NULL) {
+    return "";
+  }
+  return _ident->get_fully_scoped_name();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::is_incomplete
+//       Access: Public, Virtual
+//  Description: Returns true if the type has not yet been fully
+//               specified, false if it has.
+////////////////////////////////////////////////////////////////////
+bool CPPTypedefType::
+is_incomplete() const {
+  return false;
+  //return _type->is_incomplete();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::is_tbd
+//       Access: Public, Virtual
+//  Description: Returns true if the type, or any nested type within
+//               the type, is a CPPTBDType and thus isn't fully
+//               determined right now.  In this case, calling
+//               resolve_type() may or may not resolve the type.
+////////////////////////////////////////////////////////////////////
+bool CPPTypedefType::
+is_tbd() const {
+  if (_ident != NULL && _ident->is_tbd()) {
+    return true;
+  }
+  return _type->is_tbd();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::is_fully_specified
+//       Access: Public, Virtual
+//  Description: Returns true if this declaration is an actual,
+//               factual declaration, or false if some part of the
+//               declaration depends on a template parameter which has
+//               not yet been instantiated.
+////////////////////////////////////////////////////////////////////
+bool CPPTypedefType::
+is_fully_specified() const {
+  if (_ident != NULL && !_ident->is_fully_specified()) {
+    return false;
+  }
+  return CPPDeclaration::is_fully_specified() &&
+    _type->is_fully_specified();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::substitute_decl
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+CPPDeclaration *CPPTypedefType::
+substitute_decl(CPPDeclaration::SubstDecl &subst,
+                CPPScope *current_scope, CPPScope *global_scope) {
+
+  return _type->substitute_decl(subst, current_scope, global_scope);
+
+  // Bah, this doesn't seem to work, and I can't figure out why.
+  // Well, for now, let's just substitute it with the type we're
+  // pointing to.  This is not a huge deal for now, until we find
+  // that we need to preserve these typedefs.
+
+  /*
+  CPPDeclaration *top =
+    CPPType::substitute_decl(subst, current_scope, global_scope);
+  if (top != this) {
+    return top;
+  }
+
+  if (_subst_decl_recursive_protect) {
+    // We're already executing this block; we'll have to return a
+    // proxy to the type which we'll define later.
+    CPPTypeProxy *proxy = new CPPTypeProxy;
+    _proxies.push_back(proxy);
+    assert(proxy != NULL);
+    return proxy;
+  }
+  _subst_decl_recursive_protect = true;
+
+  CPPTypedefType *rep = new CPPTypedefType(*this);
+  CPPDeclaration *new_type =
+    _type->substitute_decl(subst, current_scope, global_scope);
+  rep->_type = new_type->as_type();
+
+  if (rep->_type == NULL) {
+    rep->_type = _type;
+  }
+
+  if (_ident != NULL) {
+    rep->_ident =
+      _ident->substitute_decl(subst, current_scope, global_scope);
+  }
+
+  if (rep->_type == _type && rep->_ident == _ident) {
+    delete rep;
+    rep = this;
+  }
+
+  rep = CPPType::new_type(rep)->as_typedef_type();
+  subst.insert(SubstDecl::value_type(this, rep));
+
+  _subst_decl_recursive_protect = false;
+  // Now fill in all the proxies we created for our recursive
+  // references.
+  Proxies::iterator pi;
+  for (pi = _proxies.begin(); pi != _proxies.end(); ++pi) {
+    (*pi)->_actual_type = rep;
+  }
+
+  return rep; */
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPFunctionType::resolve_type
+//       Access: Public, Virtual
+//  Description: If this CPPType object is a forward reference or
+//               other nonspecified reference to a type that might now
+//               be known a real type, returns the real type.
+//               Otherwise returns the type itself.
+////////////////////////////////////////////////////////////////////
+CPPType *CPPTypedefType::
+resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
+  CPPType *ptype = _type->resolve_type(current_scope, global_scope);
+
+  if (ptype != _type) {
+    CPPTypedefType *rep = new CPPTypedefType(*this);
+    rep->_type = ptype;
+    return CPPType::new_type(rep);
+  }
+
+  return this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::is_equivalent_type
+//       Access: Public, Virtual
+//  Description: This is a little more forgiving than is_equal(): it
+//               returns true if the types appear to be referring to
+//               the same thing, even if they may have different
+//               pointers or somewhat different definitions.  It's
+//               useful for parameter matching, etc.
+////////////////////////////////////////////////////////////////////
+bool CPPTypedefType::
+is_equivalent(const CPPType &other) const {
+  CPPType *ot = (CPPType *)&other;
+
+  // Unwrap all the typedefs to get to where it is pointing.
+  while (ot->get_subtype() == ST_typedef) {
+    ot = ot->as_typedef_type()->_type;
+  }
+
+  // Compare the unwrapped type to what we are pointing to.
+  // If we are pointing to a typedef ourselves, then this will
+  // automatically recurse.
+  return _type->is_equivalent(*ot);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::output
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+void CPPTypedefType::
+output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
+  string name;
+  if (_ident != NULL) {
+    name = _ident->get_local_name(scope);
+  }
+
+  if (complete) {
+    out << "typedef ";
+    _type->output_instance(out, indent_level, scope, false, "", name);
+  } else {
+    out << name;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::get_subtype
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+CPPDeclaration::SubType CPPTypedefType::
+get_subtype() const {
+  return ST_typedef;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::as_typedef_type
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+CPPTypedefType *CPPTypedefType::
+as_typedef_type() {
+  return this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::is_equal
+//       Access: Protected, Virtual
+//  Description: Called by CPPDeclaration() to determine whether this type is
+//               equivalent to another type of the same type.
+////////////////////////////////////////////////////////////////////
+bool CPPTypedefType::
+is_equal(const CPPDeclaration *other) const {
+  const CPPTypedefType *ot = ((CPPDeclaration *)other)->as_typedef_type();
+  assert(ot != NULL);
+
+  return (_type == ot->_type) && (*_ident == *ot->_ident);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPTypedefType::is_less
+//       Access: Protected, Virtual
+//  Description: Called by CPPDeclaration() to determine whether this type
+//               should be ordered before another type of the same
+//               type, in an arbitrary but fixed ordering.
+////////////////////////////////////////////////////////////////////
+bool CPPTypedefType::
+is_less(const CPPDeclaration *other) const {
+  return CPPDeclaration::is_less(other);
+
+  // The below code causes a crash for unknown reasons.
+  /*
+  const CPPTypedefType *ot = ((CPPDeclaration *)other)->as_typedef_type();
+  assert(ot != NULL);
+
+  if (_type != ot->_type) {
+    return _type < ot->_type;
+  }
+
+  if (*_ident != *ot->_ident) {
+    return *_ident < *ot->_ident;
+  }
+
+  return false; */
+}

+ 74 - 0
dtool/src/cppparser/cppTypedefType.h

@@ -0,0 +1,74 @@
+// Filename: cppTypedefType.h
+// Created by:  rdb (01Aug14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 CPPTYPEDEFTYPE_H
+#define CPPTYPEDEFTYPE_H
+
+#include "dtoolbase.h"
+#include "cppType.h"
+
+class CPPIdentifier;
+
+///////////////////////////////////////////////////////////////////
+//       Class : CPPTypedefType
+// Description :
+////////////////////////////////////////////////////////////////////
+class CPPTypedefType : public CPPType {
+public:
+  CPPTypedefType(CPPType *type, const string &name, CPPScope *current_scope);
+  CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope);
+  CPPTypedefType(CPPType *type, CPPInstanceIdentifier *ii,
+                 CPPScope *current_scope, const CPPFile &file);
+
+  bool is_scoped() const;
+  CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope,
+                      CPPPreprocessor *error_sink = NULL) const;
+
+  virtual string get_simple_name() const;
+  virtual string get_local_name(CPPScope *scope = NULL) const;
+  virtual string get_fully_scoped_name() const;
+
+  virtual bool is_incomplete() const;
+  virtual bool is_tbd() const;
+
+  virtual bool is_fully_specified() const;
+
+  virtual CPPDeclaration *substitute_decl(SubstDecl &subst,
+                                          CPPScope *current_scope,
+                                          CPPScope *global_scope);
+
+  virtual CPPType *resolve_type(CPPScope *current_scope,
+                                CPPScope *global_scope);
+
+  virtual bool is_equivalent(const CPPType &other) const;
+
+  virtual void output(ostream &out, int indent_level, CPPScope *scope,
+                      bool complete) const;
+  virtual SubType get_subtype() const;
+
+  virtual CPPTypedefType *as_typedef_type();
+
+  CPPType *_type;
+  CPPIdentifier *_ident;
+
+protected:
+  virtual bool is_equal(const CPPDeclaration *other) const;
+  virtual bool is_less(const CPPDeclaration *other) const;
+
+  bool _subst_decl_recursive_protect;
+  typedef vector<CPPTypeProxy *> Proxies;
+  Proxies _proxies;
+};
+
+#endif

+ 1 - 6
dtool/src/cppparser/p3cppParser_composite1.cxx

@@ -18,13 +18,8 @@
 #include "cppTypeDeclaration.cxx"
 #include "cppTypeParser.cxx"
 #include "cppTypeProxy.cxx"
+#include "cppTypedefType.cxx"
 #include "cppSimpleType.cxx"
 #include "cppTBDType.cxx"
-#include "cppTypedef.cxx"
 #include "cppUsing.cxx"
 #include "cppVisibility.cxx"
-
-
-
-
-

+ 9 - 1
dtool/src/dtoolbase/atomicAdjust.h

@@ -18,7 +18,15 @@
 #include "dtoolbase.h"
 #include "selectThreadImpl.h"
 
-#if defined(THREAD_DUMMY_IMPL)||defined(THREAD_SIMPLE_IMPL)
+#if defined(CPPPARSER)
+
+struct AtomicAdjust {
+  typedef long Integer;
+  typedef void *UnalignedPointer;
+  typedef UnalignedPointer Pointer;
+};
+
+#elif defined(THREAD_DUMMY_IMPL) || defined(THREAD_SIMPLE_IMPL)
 
 #include "atomicAdjustDummyImpl.h"
 typedef AtomicAdjustDummyImpl AtomicAdjust;

+ 4 - 25
dtool/src/dtoolbase/typeHandle.cxx

@@ -16,33 +16,9 @@
 #include "typeRegistryNode.h"
 #include "atomicAdjust.h"
 
-#ifdef HAVE_PYTHON
-#include "Python.h"
-#endif
-
 // This is initialized to zero by static initialization.
 TypeHandle TypeHandle::_none;
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: TypeHandle::make
-//       Access: Published
-//  Description: This special method allows coercion to a TypeHandle
-//               from a Python class object or instance.  It simply
-//               attempts to call classobj.get_class_type(), and
-//               returns that value (or raises an exception if that
-//               method doesn't work).
-//
-//               This method allows a Python class object to be used
-//               anywhere a TypeHandle is expected by the C++
-//               interface.
-////////////////////////////////////////////////////////////////////
-PyObject *TypeHandle::
-make(PyObject *classobj) {
-  return PyObject_CallMethod(classobj, (char *)"get_class_type", (char *)"");
-}
-#endif  // HAVE_PYTHON
-
 #ifdef DO_MEMORY_USAGE
 ////////////////////////////////////////////////////////////////////
 //     Function: TypeHandle::get_memory_usage
@@ -80,7 +56,10 @@ inc_memory_usage(MemoryClass memory_class, int size) {
     assert(rnode != (TypeRegistryNode *)NULL);
     AtomicAdjust::add(rnode->_memory_usage[memory_class], (AtomicAdjust::Integer)size);
     //cerr << *this << ".inc(" << memory_class << ", " << size << ") -> " << rnode->_memory_usage[memory_class] << "\n";
-    assert(rnode->_memory_usage[memory_class] >= 0);
+    if (rnode->_memory_usage[memory_class] < 0) {
+      cerr << "Memory usage overflow for type " << *this << ".\n";
+      abort();
+    }
   }
 }
 #endif  // DO_MEMORY_USAGE

+ 1 - 10
dtool/src/dtoolbase/typeHandle.h

@@ -65,13 +65,6 @@
 
 class TypedObject;
 
-#ifdef HAVE_PYTHON
-#ifndef PyObject_HEAD
-struct _object;
-typedef _object PyObject;
-#endif
-#endif
-
 ////////////////////////////////////////////////////////////////////
 //       Class : TypeHandle
 // Description : TypeHandle is the identifier used to differentiate
@@ -105,9 +98,7 @@ PUBLISHED:
   INLINE TypeHandle();
   INLINE TypeHandle(const TypeHandle &copy);
 
-#ifdef HAVE_PYTHON
-  static PyObject *make(PyObject *classobj);
-#endif  // HAVE_PYTHON
+  EXTENSION(static TypeHandle make(PyTypeObject *classobj));
 
   INLINE bool operator == (const TypeHandle &other) const;
   INLINE bool operator != (const TypeHandle &other) const;

+ 5 - 0
dtool/src/dtoolutil/Sources.pp

@@ -17,6 +17,8 @@
     filename.h \
     $[if $[IS_OSX],filename_assist.mm filename_assist.h,] \
     globPattern.I globPattern.h \
+    lineStream.I lineStream.h \
+    lineStreamBuf.I lineStreamBuf.h \
     load_dso.h \
     pandaFileStream.h pandaFileStream.I \
     pandaFileStreamBuf.h \
@@ -38,6 +40,7 @@
     dSearchPath.cxx \
     executionEnvironment.cxx filename.cxx \
     globPattern.cxx \
+    lineStream.cxx lineStreamBuf.cxx \
     load_dso.cxx  \
     pandaFileStream.cxx pandaFileStreamBuf.cxx \
     pandaSystem.cxx \
@@ -58,6 +61,8 @@
     executionEnvironment.I executionEnvironment.h filename.I \
     filename.h \
     globPattern.I globPattern.h \
+    lineStream.I lineStream.h \
+    lineStreamBuf.I lineStreamBuf.h \
     load_dso.h \
     pandaFileStream.h pandaFileStream.I \
     pandaFileStreamBuf.h \

+ 11 - 0
dtool/src/dtoolutil/filename.I

@@ -306,6 +306,17 @@ operator + (const string &other) const {
   return a;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Filename::operator /
+//       Access: Published
+//  Description: Returns a new Filename that is composed of the
+//               other filename added to the end of this filename,
+//               with an intervening slash added if necessary.
+////////////////////////////////////////////////////////////////////
+INLINE Filename Filename::
+operator / (const Filename &other) const {
+  return Filename(*this, other);
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: Filename::get_fullpath

+ 1 - 61
dtool/src/dtoolutil/filename.cxx

@@ -308,30 +308,6 @@ Filename(const Filename &dirname, const Filename &basename) {
   }
 }
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: Filename::__reduce__
-//       Access: Published
-//  Description: This special Python method is implement to provide
-//               support for the pickle module.
-////////////////////////////////////////////////////////////////////
-PyObject *Filename::
-__reduce__(PyObject *self) const {
-  // We should return at least a 2-tuple, (Class, (args)): the
-  // necessary class object whose constructor we should call
-  // (e.g. this), and the arguments necessary to reconstruct this
-  // object.
-  PyObject *this_class = PyObject_Type(self);
-  if (this_class == NULL) {
-    return NULL;
-  }
-
-  PyObject *result = Py_BuildValue("(O(s))", this_class, c_str());
-  Py_DECREF(this_class);
-  return result;
-}
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: Filename::from_os_specific
 //       Access: Published, Static
@@ -2005,49 +1981,13 @@ scan_directory(vector_string &contents) const {
   globfree(&globbuf);
 
   return true;
-  
+
 #else
   // Don't know how to scan directories!
   return false;
 #endif
 }
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: Filename::scan_directory
-//       Access: Published
-//  Description: This variant on scan_directory returns a Python list
-//               of strings on success, or None on failure.
-////////////////////////////////////////////////////////////////////
-PyObject *Filename::
-scan_directory() const {
-  vector_string contents;
-  if (!scan_directory(contents)) {
-    PyObject *result = Py_None;
-    Py_INCREF(result);
-    return result;
-  }
-
-  PyObject *result = PyList_New(contents.size());
-  for (size_t i = 0; i < contents.size(); ++i) {
-    const string &filename = contents[i];
-#if PY_MAJOR_VERSION >= 3
-    // This function expects UTF-8.
-    PyObject *str = PyUnicode_FromStringAndSize(filename.data(), filename.size());
-#else
-    PyObject *str = PyString_FromStringAndSize(filename.data(), filename.size());
-#endif
-#ifdef Py_LIMITED_API
-    PyList_SetItem(result, i, str);
-#else
-    PyList_SET_ITEM(result, i, str);
-#endif
-  }
-
-  return result;
-}
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: Filename::open_read
 //       Access: Published

+ 6 - 4
dtool/src/dtoolutil/filename.h

@@ -69,7 +69,7 @@ PUBLISHED:
   INLINE ~Filename();
 
 #ifdef HAVE_PYTHON
-  PyObject *__reduce__(PyObject *self) const;
+  EXTENSION(PyObject *__reduce__(PyObject *self) const);
 #endif
 
   // Static constructors to explicitly create a filename that refers
@@ -116,6 +116,8 @@ PUBLISHED:
   INLINE void operator += (const string &other);
   INLINE Filename operator + (const string &other) const;
 
+  INLINE Filename operator / (const Filename &other) const;
+
   // Or, you can use any of these.
   INLINE string get_fullpath() const;
   INLINE wstring get_fullpath_w() const;
@@ -190,11 +192,11 @@ PUBLISHED:
                         const string &default_extension = string());
   bool make_relative_to(Filename directory, bool allow_backups = true);
   int find_on_searchpath(const DSearchPath &searchpath);
-  
+
   bool scan_directory(vector_string &contents) const;
 #ifdef HAVE_PYTHON
-  PyObject *scan_directory() const;
-#endif 
+  EXTENSION(PyObject *scan_directory() const);
+#endif
 
   bool open_read(ifstream &stream) const;
   bool open_write(ofstream &stream, bool truncate = true) const;

+ 7 - 39
dtool/src/dtoolutil/globPattern.cxx

@@ -113,44 +113,12 @@ match_files(vector_string &results, const Filename &cwd) const {
     pattern = source.substr(0, slash);
     suffix = source.substr(slash + 1);
   }
-  
+
   GlobPattern glob(pattern);
   glob.set_case_sensitive(_case_sensitive);
   return glob.r_match_files(prefix, suffix, results, cwd);
 }
 
-#ifdef HAVE_PYTHON
-////////////////////////////////////////////////////////////////////
-//     Function: GlobPattern::match_files
-//       Access: Published
-//  Description: This variant on match_files returns a Python list
-//               of strings.
-////////////////////////////////////////////////////////////////////
-PyObject *GlobPattern::
-match_files(const Filename &cwd) const {
-  vector_string contents;
-  match_files(contents, cwd);
-
-  PyObject *result = PyList_New(contents.size());
-  for (size_t i = 0; i < contents.size(); ++i) {
-    const string &filename = contents[i];
-#if PY_MAJOR_VERSION >= 3
-    // This function expects UTF-8.
-    PyObject *str = PyUnicode_FromStringAndSize(filename.data(), filename.size());
-#else
-    PyObject *str = PyString_FromStringAndSize(filename.data(), filename.size());
-#endif
-#ifdef Py_LIMITED_API
-    PyList_SetItem(result, i, str);
-#else
-    PyList_SET_ITEM(result, i, str);
-#endif
-  }
-
-  return result;
-}
-#endif  // HAVE_PYTHON
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GlobPattern::r_match_files
 //       Access: Private
@@ -195,21 +163,21 @@ r_match_files(const Filename &prefix, const string &suffix,
     return next_glob.r_match_files(Filename(prefix, _pattern),
                                    next_suffix, results, cwd);
 
-  } 
+  }
 
   // If there *are* special glob characters, we must attempt to
   // match the pattern against the files in this directory.
-  
+
   vector_string dir_files;
   if (!parent_dir.scan_directory(dir_files)) {
     // Not a directory, or unable to read directory; stop here.
     return 0;
   }
-  
+
   // Now go through each file in the directory looking for one that
   // matches the pattern.
   int num_matched = 0;
-  
+
   vector_string::const_iterator fi;
   for (fi = dir_files.begin(); fi != dir_files.end(); ++fi) {
     const string &local_file = (*fi);
@@ -218,7 +186,7 @@ r_match_files(const Filename &prefix, const string &suffix,
         // We have a match; continue.
         if (suffix.empty()) {
           results.push_back(Filename(prefix, local_file));
-          num_matched++; 
+          num_matched++;
         } else {
           num_matched += next_glob.r_match_files(Filename(prefix, local_file),
                                                  next_suffix, results, cwd);
@@ -226,7 +194,7 @@ r_match_files(const Filename &prefix, const string &suffix,
       }
     }
   }
-  
+
   return num_matched;
 }
 

+ 2 - 2
dtool/src/dtoolutil/globPattern.h

@@ -61,8 +61,8 @@ PUBLISHED:
   string get_const_prefix() const;
   int match_files(vector_string &results, const Filename &cwd = Filename()) const;
 #ifdef HAVE_PYTHON
-  PyObject *match_files(const Filename &cwd = Filename()) const;
-#endif 
+  EXTENSION(PyObject *match_files(const Filename &cwd = Filename()) const);
+#endif
 
 private:
   bool matches_substr(string::const_iterator pi,

+ 0 - 0
panda/src/putil/lineStream.I → dtool/src/dtoolutil/lineStream.I


+ 0 - 0
panda/src/putil/lineStream.cxx → dtool/src/dtoolutil/lineStream.cxx


+ 2 - 2
panda/src/putil/lineStream.h → dtool/src/dtoolutil/lineStream.h

@@ -15,7 +15,7 @@
 #ifndef LINESTREAM_H
 #define LINESTREAM_H
 
-#include "pandabase.h"
+#include "dtoolbase.h"
 
 #include "lineStreamBuf.h"
 
@@ -33,7 +33,7 @@
 //               More text can still be written to it and continuously
 //               extracted.
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_PUTIL LineStream : public ostream {
+class EXPCL_DTOOL LineStream : public ostream {
 PUBLISHED:
   INLINE LineStream();
 

+ 0 - 0
panda/src/putil/lineStreamBuf.I → dtool/src/dtoolutil/lineStreamBuf.I


+ 0 - 0
panda/src/putil/lineStreamBuf.cxx → dtool/src/dtoolutil/lineStreamBuf.cxx


+ 2 - 2
panda/src/putil/lineStreamBuf.h → dtool/src/dtoolutil/lineStreamBuf.h

@@ -15,7 +15,7 @@
 #ifndef LINESTREAMBUF_H
 #define LINESTREAMBUF_H
 
-#include "pandabase.h"
+#include "dtoolbase.h"
 
 #include <string>
 
@@ -26,7 +26,7 @@
 //               continuously extracted as a sequence of lines of
 //               text.
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_PUTIL LineStreamBuf : public streambuf {
+class EXPCL_DTOOL LineStreamBuf : public streambuf {
 public:
   LineStreamBuf();
   virtual ~LineStreamBuf();

+ 2 - 0
dtool/src/dtoolutil/p3dtoolutil_composite1.cxx

@@ -4,6 +4,8 @@
 #include "executionEnvironment.cxx"
 #include "filename.cxx"
 #include "globPattern.cxx"
+#include "lineStream.cxx"
+#include "lineStreamBuf.cxx"
 #include "load_dso.cxx"
 #include "pandaSystem.cxx"
 

+ 99 - 11
dtool/src/interrogate/functionRemap.cxx

@@ -275,7 +275,6 @@ make_wrapper_entry(FunctionIndex function_index) {
     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.
@@ -413,14 +412,26 @@ get_call_str(const string &container, const vector_string &pexprs) const {
       separator = ", ";
     }
 
-    for (int pn = _first_true_parameter;
-         pn < (int)_parameters.size();
-         ++pn) {
+    int pn = _first_true_parameter;
+    int num_parameters = _parameters.size();
+
+    if (_type == T_item_assignment_operator) {
+      // The last parameter is the value to set.
+      --num_parameters;
+    }
+
+    for (pn = _first_true_parameter;
+         pn < num_parameters; ++pn) {
       call << separator;
       _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
       separator = ", ";
     }
     call << ")";
+
+    if (_type == T_item_assignment_operator) {
+      call << " = ";
+      _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
+    }
   }
 
   return call.str();
@@ -484,6 +495,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
   }
 
   string fname = _cppfunc->get_simple_name();
+  CPPType *rtype = _ftype->_return_type->resolve_type(&parser, _cppscope);
 
   if (_cpptype != (CPPType *)NULL &&
       ((_cppfunc->_storage_class & CPPInstance::SC_static) == 0) &&
@@ -520,13 +532,22 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
         fname == "operator <<=" ||
         fname == "operator >>=") {
       _type = T_assignment_method;
+
+    } else if (fname == "operator []" && !_const_method && rtype != NULL) {
+       // Check if this is an item-assignment operator.
+      CPPReferenceType *reftype = rtype->as_reference_type();
+      if (reftype != NULL && reftype->_pointing_at->as_const_type() == NULL) {
+        // It returns a mutable reference.
+        _type = T_item_assignment_operator;
+      }
     }
   }
 
   const CPPParameterList::Parameters &params =
     _ftype->_parameters->_parameters;
   for (int i = 0; i < (int)params.size() - _num_default_parameters; i++) {
-    CPPType *type = params[i]->_type->resolve_type(&parser, _cppscope);
+    //CPPType *type = params[i]->_type->resolve_type(&parser, _cppscope);
+    CPPType *type = params[i]->_type;
     Parameter param;
     param._has_name = true;
     param._name = params[i]->get_simple_name();
@@ -588,9 +609,39 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
       }
     }
 
+  } else if (_type == T_item_assignment_operator) {
+    // An item-assignment method isn't really a thing in C++, but it is
+    // in scripting languages, so we use this to denote item-access operators
+    // that return a non-const reference.
+
+    if (_cpptype == (CPPType *)NULL) {
+      nout << "Method " << *_cppfunc << " has no struct type\n";
+      return false;
+    } else {
+      // Synthesize a const reference parameter for the assignment.
+      CPPType *bare_type = TypeManager::unwrap_reference(rtype);
+      CPPType *const_type = CPPType::new_type(new CPPConstType(bare_type));
+      CPPType *ref_type = CPPType::new_type(new CPPReferenceType(const_type));
+
+      Parameter param;
+      param._has_name = true;
+      param._name = "assign_val";
+      param._remap = interface_maker->remap_parameter(_cpptype, ref_type);
+
+      if (param._remap == NULL || !param._remap->is_valid()) {
+        nout << "Invalid remap for assignment type of method " << *_cppfunc << "\n";
+        return false;
+      }
+      _parameters.push_back(param);
+
+      // Pretend we don't return anything at all.
+      CPPType *void_type = TypeManager::get_void_type();
+      _return_type = interface_maker->remap_parameter(_cpptype, void_type);
+      _void_return = true;
+    }
+
   } else {
     // The normal case.
-    CPPType *rtype = _ftype->_return_type->resolve_type(&parser, _cppscope);
     _return_type = interface_maker->remap_parameter(_cpptype, rtype);
     if (_return_type != (ParameterRemap *)NULL) {
       _void_return = TypeManager::is_void(rtype);
@@ -639,7 +690,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
   }
 
   if (_has_this || _type == T_constructor) {
-    if (_parameters.size() > first_param && _parameters[first_param]._name == "self" &&
+    if ((int)_parameters.size() > first_param && _parameters[first_param]._name == "self" &&
         TypeManager::is_pointer_to_PyObject(_parameters[first_param]._remap->get_orig_type())) {
       // Here's a special case.  If the first parameter of a nonstatic
       // method is a PyObject * called "self", then we will
@@ -650,9 +701,9 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
     }
   }
 
-  if (_parameters.size() == first_param) {
+  if ((int)_parameters.size() == first_param) {
     _args_type = InterfaceMaker::AT_no_args;
-  } else if (_parameters.size() == first_param + 1) {
+  } else if ((int)_parameters.size() == first_param + 1) {
     _args_type = InterfaceMaker::AT_single_arg;
   } else {
     _args_type = InterfaceMaker::AT_varargs;
@@ -669,8 +720,8 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
       }
 
     } else if (fname == "__setitem__") {
-      _flags |= F_setitem;
       if (_has_this && _parameters.size() > 2) {
+        _flags |= F_setitem;
         if (TypeManager::is_integer(_parameters[1]._remap->get_new_type())) {
           // Its first parameter is an int parameter, presumably an index.
           _flags |= F_setitem_int;
@@ -678,6 +729,16 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
         }
       }
 
+    } else if (fname == "__delitem__") {
+      if (_has_this && _parameters.size() == 2) {
+        _flags |= F_delitem;
+        if (TypeManager::is_integer(_parameters[1]._remap->get_new_type())) {
+          // Its first parameter is an int parameter, presumably an index.
+          _flags |= F_delitem_int;
+          _args_type = InterfaceMaker::AT_single_arg;
+        }
+      }
+
     } else if (fname == "size" || fname == "__len__") {
       if ((int)_parameters.size() == first_param &&
           TypeManager::is_integer(_return_type->get_new_type())) {
@@ -722,11 +783,20 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
         _flags |= F_compare_to;
       }
 
+    } else if (fname == "make") {
+      if (!_has_this && _parameters.size() >= 1 &&
+          TypeManager::is_pointer(_return_type->get_new_type())) {
+        // We can use this for coercion.
+        _flags |= F_coerce_constructor;
+      }
+
     } else if (fname == "operator ()" || fname == "__call__") {
       // Call operators always take keyword arguments.
       _args_type = InterfaceMaker::AT_keyword_args;
 
-    } else if (fname == "__setattr__" || fname == "__getattr__") {
+    } else if (fname == "__setattr__"
+            || fname == "__getattr__"
+            || fname == "__delattr__") {
       // Just to prevent these from getting keyword arguments.
 
     } else {
@@ -737,6 +807,19 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
       }
     }
 
+  } else if (_type == T_item_assignment_operator) {
+    // The concept of "item assignment operator" doesn't really exist in C++,
+    // but it does in scripting languages, and this allows us to wrap cases
+    // where the C++ getitem returns an assignable reference.
+    _flags |= F_setitem;
+    if (_has_this && _parameters.size() > 2) {
+      if (TypeManager::is_integer(_parameters[1]._remap->get_new_type())) {
+        // Its first parameter is an int parameter, presumably an index.
+        _flags |= F_setitem_int;
+      }
+    }
+    _args_type = InterfaceMaker::AT_varargs;
+
   } else if (_type == T_constructor) {
     if (!_has_this && _parameters.size() == 1 &&
         TypeManager::unwrap(_parameters[0]._remap->get_orig_type()) ==
@@ -745,7 +828,12 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
       // "this" type, this is a copy constructor.
       _flags |= F_copy_constructor;
 
+    } else if (!_has_this && _parameters.size() > 0 &&
+               (_cppfunc->_storage_class & CPPInstance::SC_explicit) == 0) {
+      // A non-explicit non-copy constructor might be eligible for coercion.
+      _flags |= F_coerce_constructor;
     }
+
     // Constructors always take varargs and keyword args.
     _args_type = InterfaceMaker::AT_keyword_args;
   }

+ 16 - 12
dtool/src/interrogate/functionRemap.h

@@ -76,21 +76,25 @@ public:
     T_typecast,
     T_getter,
     T_setter,
+    T_item_assignment_operator,
   };
 
   enum Flags {
-    F_getitem          = 0x0001,
-    F_getitem_int      = 0x0002,
-    F_size             = 0x0004,
-    F_setitem          = 0x0008,
-    F_setitem_int      = 0x0010,
-    F_make_copy        = 0x0020,
-    F_copy_constructor = 0x0040,
-    F_explicit_self    = 0x0080,
-    F_iter             = 0x0100,
-    F_getbuffer        = 0x0200,
-    F_releasebuffer    = 0x0400,
-    F_compare_to       = 0x0800,
+    F_getitem            = 0x0001,
+    F_getitem_int        = 0x0002,
+    F_size               = 0x0004,
+    F_setitem            = 0x0008,
+    F_setitem_int        = 0x0010,
+    F_delitem            = 0x0020,
+    F_delitem_int        = 0x0040,
+    F_make_copy          = 0x0080,
+    F_copy_constructor   = 0x0100,
+    F_explicit_self      = 0x0200,
+    F_iter               = 0x0400,
+    F_getbuffer          = 0x0800,
+    F_releasebuffer      = 0x1000,
+    F_compare_to         = 0x2000,
+    F_coerce_constructor = 0x4000,
   };
 
   typedef vector<Parameter> Parameters;

+ 49 - 56
dtool/src/interrogate/interfaceMaker.cxx

@@ -41,7 +41,7 @@
 #include "pnotify.h"
 
 InterrogateType dummy_type;
- 
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterfaceMaker::Function::Constructor
 //       Access: Public
@@ -59,7 +59,7 @@ Function(const string &name,
   _flags = 0;
   _args_type = AT_unknown;
 }
- 
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterfaceMaker::Function::Destructor
 //       Access: Public
@@ -72,7 +72,7 @@ InterfaceMaker::Function::
     delete (*ri);
   }
 }
- 
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterfaceMaker::MakeSeq::Constructor
 //       Access: Public
@@ -143,7 +143,7 @@ check_protocols() {
     flags |= func->_flags;
   }
 
-  if ((flags & (FunctionRemap::F_getitem_int | FunctionRemap::F_size)) == 
+  if ((flags & (FunctionRemap::F_getitem_int | FunctionRemap::F_size)) ==
       (FunctionRemap::F_getitem_int | FunctionRemap::F_size)) {
     // If we have both a getitem that receives an int, and a size,
     // then we implement the sequence protocol: you can iterate
@@ -169,8 +169,6 @@ check_protocols() {
     _protocol_types |= PT_iter;
   }
 
-  InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
-
   // Now are there any make_seq requests within this class?
   if (_itype._cpptype != NULL) {
     CPPStructType *stype = _itype._cpptype->as_struct_type();
@@ -269,18 +267,8 @@ generate_wrappers() {
   // traversal.
   int ti = 0;
   while (ti < idb->get_num_all_types()) {
-    TypeIndex type_index = idb->get_all_type(ti);
+    TypeIndex type_index = idb->get_all_type(ti++);
     record_object(type_index);
-
-    if (interrogate_type_is_enum(ti)) {
-      int enum_count = interrogate_type_number_of_enum_values(ti);
-      for (int xx = 0; xx < enum_count; ++xx) {
-//        printf("   PyModule_AddIntConstant(module,\"%s\",%d)\n",interrogate_type_enum_value_name(ti,xx),interrogate_type_enum_value(ti,xx));
-      }
-    }
-
-    ++ti;
-//    printf(" New Type %d\n",ti);
   }
 
   int num_global_elements = idb->get_num_global_elements();
@@ -321,7 +309,7 @@ generate_wrappers() {
       FunctionIndex func_index = ielement.get_setter();
       record_function(dummy_type, func_index);
     }
-  }    
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -396,7 +384,7 @@ remap_parameter(CPPType *struct_type, CPPType *param_type) {
     // convert basic_string<char>'s to atomic strings.
 
     if (struct_type == (CPPType *)NULL ||
-        !(TypeManager::is_basic_string_char(struct_type) || 
+        !(TypeManager::is_basic_string_char(struct_type) ||
           TypeManager::is_basic_string_wchar(struct_type))) {
       if (TypeManager::is_basic_string_char(param_type)) {
         return new ParameterRemapBasicStringToString(param_type);
@@ -454,7 +442,10 @@ remap_parameter(CPPType *struct_type, CPPType *param_type) {
   } else if (TypeManager::is_const_ref_to_simple(param_type)) {
     return new ParameterRemapReferenceToConcrete(param_type);
 
-  } else if (TypeManager::is_pointer(param_type) || TypeManager::is_simple(param_type)) {
+  } else if (TypeManager::is_pointer(param_type) ||
+             TypeManager::is_void(param_type) ||
+             TypeManager::is_simple(param_type) ||
+             TypeManager::is_simple_array(param_type)) {
     return new ParameterRemapUnchanged(param_type);
 
   } else {
@@ -550,21 +541,19 @@ FunctionRemap *InterfaceMaker::
 make_function_remap(const InterrogateType &itype,
                     const InterrogateFunction &ifunc,
                     CPPInstance *cppfunc, int num_default_parameters) {
-  FunctionRemap *remap = 
+  FunctionRemap *remap =
     new FunctionRemap(itype, ifunc, cppfunc, num_default_parameters, this);
-  if (remap->_is_valid) 
-  {
-    if (separate_overloading()) 
-    {
+  if (remap->_is_valid) {
+    if (separate_overloading()) {
       hash_function_signature(remap);
       remap->_unique_name =
         get_unique_prefix() + _def->library_hash_name + remap->_hash;
-      remap->_wrapper_name = 
+      remap->_wrapper_name =
         get_wrapper_prefix() + _def->library_hash_name + remap->_hash;
       remap->_reported_name = remap->_wrapper_name;
-      if (true_wrapper_names) 
-      {
-        remap->_reported_name = 
+
+      if (true_wrapper_names) {
+        remap->_reported_name =
           InterrogateBuilder::clean_identifier(remap->_cppfunc->get_local_name(&parser));
       }
     }
@@ -589,7 +578,7 @@ make_function_remap(const InterrogateType &itype,
 //               an overloaded function) need not define a name here.
 ////////////////////////////////////////////////////////////////////
 string InterfaceMaker::
-get_wrapper_name(const InterrogateType &itype, 
+get_wrapper_name(const InterrogateType &itype,
                  const InterrogateFunction &ifunc,
                  FunctionIndex func_index) {
   string func_name = ifunc.get_scoped_name();
@@ -677,12 +666,13 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) {
       // parameters.  This will happen only if separate_overloading(),
       // tested above, returned true; otherwise, max_default_parameters
       // will be 0 and the loop will only be traversed once.
-      for (int num_default_parameters = 0; 
+      for (int num_default_parameters = 0;
            num_default_parameters <= max_default_parameters;
            num_default_parameters++) {
-        FunctionRemap *remap = 
+        FunctionRemap *remap =
           make_function_remap(itype, ifunc, cppfunc, num_default_parameters);
         if (remap != (FunctionRemap *)NULL) {
+
           func->_remaps.push_back(remap);
 
           // If *any* of the variants of this function has a "this"
@@ -741,7 +731,8 @@ record_object(TypeIndex type_index) {
   }
 
   InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
-  const InterrogateType &itype = idb->get_type(type_index);    
+  const InterrogateType &itype = idb->get_type(type_index);
+  assert(&itype != NULL);
 
   Object *object = new Object(itype);
   bool inserted = _objects.insert(Objects::value_type(type_index, object)).second;
@@ -754,29 +745,26 @@ record_object(TypeIndex type_index) {
     function = record_function(itype, itype.get_constructor(ci));
     object->_constructors.push_back(function);
   }
-  
+
   int num_methods = itype.number_of_methods();
   int mi;
   for (mi = 0; mi < num_methods; mi++) {
     function = record_function(itype, itype.get_method(mi));
     object->_methods.push_back(function);
   }
-  
+
   int num_casts = itype.number_of_casts();
   for (mi = 0; mi < num_casts; mi++) {
     function = record_function(itype, itype.get_cast(mi));
     object->_methods.push_back(function);
   }
-  
+
   int num_derivations = itype.number_of_derivations();
-  for (int di = 0; di < num_derivations; di++) 
-  {
-    if (itype.derivation_has_upcast(di)) 
-    {
+  for (int di = 0; di < num_derivations; di++) {
+    if (itype.derivation_has_upcast(di)) {
       record_function(itype, itype.derivation_get_upcast(di));
     }
-    if (itype.derivation_has_downcast(di)) 
-    {
+    if (itype.derivation_has_downcast(di)) {
       // Downcasts are methods of the base class, not the child class.
       TypeIndex base_type_index = itype.get_derivation(di);
       const InterrogateType &base_type = idb->get_type(base_type_index);
@@ -785,27 +773,23 @@ record_object(TypeIndex type_index) {
   }
 
   int num_elements = itype.number_of_elements();
-  for (int ei = 0; ei < num_elements; ei++)
-  {
+  for (int ei = 0; ei < num_elements; ei++) {
     ElementIndex element_index = itype.get_element(ei);
     const InterrogateElement &ielement = idb->get_element(element_index);
-    if (ielement.has_getter()) 
-    {
+    if (ielement.has_getter()) {
       FunctionIndex func_index = ielement.get_getter();
       record_function(itype, func_index);
     }
-    if (ielement.has_setter()) 
-    {
+    if (ielement.has_setter()) {
       FunctionIndex func_index = ielement.get_setter();
       record_function(itype, func_index);
     }
-  }    
+  }
 
   object->check_protocols();
 
   int num_nested = itype.number_of_nested_types();
-  for (int ni = 0; ni < num_nested; ni++) 
-  {
+  for (int ni = 0; ni < num_nested; ni++) {
     TypeIndex nested_index = itype.get_nested_type(ni);
     record_object(nested_index);
   }
@@ -885,7 +869,7 @@ delete_return_value(ostream &out, int indent_level,
 //               the indicated variable name.
 ////////////////////////////////////////////////////////////////////
 void InterfaceMaker::
-output_ref(ostream &out, int indent_level, FunctionRemap *remap, 
+output_ref(ostream &out, int indent_level, FunctionRemap *remap,
            const string &varname) const {
   if (remap->_type == FunctionRemap::T_constructor ||
       remap->_type == FunctionRemap::T_typecast) {
@@ -915,7 +899,7 @@ output_ref(ostream &out, int indent_level, FunctionRemap *remap,
 //               the indicated variable name.
 ////////////////////////////////////////////////////////////////////
 void InterfaceMaker::
-output_unref(ostream &out, int indent_level, FunctionRemap *remap, 
+output_unref(ostream &out, int indent_level, FunctionRemap *remap,
              const string &varname) const {
   if (remap->_type == FunctionRemap::T_constructor ||
       remap->_type == FunctionRemap::T_typecast) {
@@ -931,8 +915,17 @@ output_unref(ostream &out, int indent_level, FunctionRemap *remap,
     indent(out, indent_level)
       << "if (" << varname << " != ("
       << remap->_return_type->get_new_type()->get_local_name(&parser) << ")NULL) {\n";
-    indent(out, indent_level + 2)
-      << "unref_delete(" << varname << ");\n";
+
+    if (TypeManager::is_pointer_to_base(remap->_return_type->get_temporary_type())) {
+      // We're sure the reference count won't reach zero since we have it
+      // stored in a PointerTo, so call the unref() method directly.
+      indent(out, indent_level + 2)
+        << varname << "->unref();\n";
+    } else {
+      indent(out, indent_level + 2)
+        << "unref_delete(" << varname << ");\n";
+    }
+
     indent(out, indent_level)
       << "}\n";
   }
@@ -967,7 +960,7 @@ hash_function_signature(FunctionRemap *remap) {
     nout << "Internal error!  Function signature "
          << remap->_function_signature << " repeated!\n";
     remap->_hash = hash;
-    abort(); 
+    abort();
     return;
   }
 

File diff suppressed because it is too large
+ 333 - 232
dtool/src/interrogate/interfaceMakerPythonNative.cxx


+ 70 - 39
dtool/src/interrogate/interfaceMakerPythonNative.h

@@ -31,32 +31,32 @@ class InterfaceMakerPythonNative : public InterfaceMakerPython {
 public:
   InterfaceMakerPythonNative(InterrogateModuleDef *def);
   virtual ~InterfaceMakerPythonNative();
-  
-  
+
+
   virtual void write_prototypes(ostream &out, ostream *out_h);
   void write_prototypes_class(ostream &out, ostream *out_h, Object *obj) ;
   void write_prototypes_class_external(ostream &out, Object *obj);
-  
+
   virtual void write_functions(ostream &out);
-  
+
   virtual void write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def);
   virtual void write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def);
-  
-  void write_module_class(ostream &out, Object *cls); 
-  virtual void write_sub_module(ostream &out, Object *obj); 
-  
+
+  void write_module_class(ostream &out, Object *cls);
+  virtual void write_sub_module(ostream &out, Object *obj);
+
   virtual bool synthesize_this_parameter();
-  
+
   virtual Object *record_object(TypeIndex type_index);
-  
+
 protected:
   virtual string get_wrapper_prefix();
   virtual string get_unique_prefix();
-  virtual void record_function_wrapper(InterrogateFunction &ifunc, 
+  virtual void record_function_wrapper(InterrogateFunction &ifunc,
                                        FunctionWrapperIndex wrapper_index);
-  
+
   virtual void generate_wrappers();
-  
+
 private:
   // This enum defines the various prototypes that must be generated
   // for the specialty functions that Python requires, especially for
@@ -65,7 +65,7 @@ private:
     WT_none,
     WT_no_params,
     WT_one_param,
-    WT_numeric_operator,
+    WT_binary_operator,
     WT_setattr,
     WT_getattr,
     WT_sequence_getitem,
@@ -76,8 +76,33 @@ private:
     WT_getbuffer,
     WT_releasebuffer,
     WT_iter_next,
-    WT_one_or_two_params,
     WT_ternary_operator,
+    WT_inplace_binary_operator,
+    WT_inplace_ternary_operator,
+  };
+
+  // This enum is passed to the wrapper generation functions to indicate
+  // what sort of values the wrapper function is expected to return.
+  enum ReturnFlags {
+    // -1 on failure, 0 on success.
+    RF_int  = 0x100,
+
+    // Returns the actual return value as PyObject*.
+    RF_pyobject = 0x010,
+
+    // Returns a reference to self.
+    RF_self = 0x020,
+
+    // Assign to the coerced argument, in the case of a coercion constructor.
+    RF_coerced = 0x040,
+
+    // These indicate what should be returned on error.
+    RF_err_notimplemented = 0x002,
+    RF_err_null = 0x004,
+    RF_err_false = 0x008,
+
+    // Decref temporary args object before returning.
+    RF_decref_args = 0x200,
   };
 
   class SlottedFunctionDef {
@@ -85,37 +110,41 @@ private:
     string _answer_location;
     WrapperType _wrapper_type;
     int _min_version;
+    Function *_func;
+    set<FunctionRemap*> _remaps;
   };
 
-  static bool get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def);
+  static bool get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap, SlottedFunctionDef &def);
 
   void write_prototype_for_name(ostream &out, Function *func, const std::string &name);
   void write_prototype_for(ostream &out, Function *func);
   void write_function_for_top(ostream &out, Object *obj, Function *func);
-  void write_function_for_name(ostream &out, Object *obj, Function *func,
-                               const std::string &name,
-                               bool coercion_allowed, bool &coercion_attempted,
-                               ArgsType args_type, bool return_int, bool write_comment);
-
-  void write_function_forset(ostream &out, Object *obj, Function *func,
-                             std::set<FunctionRemap*> &remaps, string &expected_params,
-                             int indent_level, bool inplace,
-                             bool coercion_allowed, bool &coercion_attempted,
-                             ArgsType args_type, bool return_int,
+
+  void write_function_for_name(ostream &out, Object *obj,
+                               const Function::Remaps &remaps,
+                               const std::string &name, string &expected_params,
+                               bool coercion_allowed,
+                               ArgsType args_type, int return_flags);
+  void write_coerce_constructor(ostream &out, Object *obj, bool is_const);
+
+  void write_function_forset(ostream &out,
+                             const std::set<FunctionRemap*> &remaps,
+                             string &expected_params, int indent_level,
+                             bool coercion_allowed, bool report_errors,
+                             ArgsType args_type, int return_flags,
+                             bool check_exceptions = true,
                              const string &first_expr = string());
 
-  void write_function_instance(ostream &out, Object *obj, Function *func,
-                               FunctionRemap *remap, string &expected_params,
-                               int indent_level, bool is_inplace,
-                               bool coercion_allowed, bool &coercion_attempted,
-                               ArgsType args_type, bool return_int,
+  void write_function_instance(ostream &out, FunctionRemap *remap,
+                               string &expected_params, int indent_level,
+                               bool coercion_allowed, bool report_errors,
+                               ArgsType args_type, int return_flags,
+                               bool check_exceptions = true,
                                const string &first_pexpr = string());
 
+  void error_return(ostream &out, int indent_level, int return_flags);
   void pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
-                         const std::string &return_expr, bool in_place);
-  void pack_python_value(ostream &out, int indent_level, FunctionRemap *remap,
-                         ParameterRemap *return_type, const std::string &return_expr,
-                         const std::string &assign_expr, bool in_place);
+                         const std::string &return_expr);
 
   void write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
                       MakeSeq *make_seq);
@@ -126,7 +155,9 @@ private:
 
 public:
   bool is_remap_legal(FunctionRemap *remap);
-  bool is_function_legal( Function *func);
+  int has_coerce_constructor(CPPStructType *type);
+  bool is_remap_coercion_possible(FunctionRemap *remap);
+  bool is_function_legal(Function *func);
   bool is_cpp_type_legal(CPPType *ctype);
   bool isExportThisRun(CPPType *ctype);
   bool isExportThisRun(Function *func);
@@ -145,7 +176,7 @@ public:
   void get_valid_child_classes(std::map<std::string, CastDetails> &answer, CPPStructType *inclass, const std::string &upcast_seed = "", bool can_downcast = true);
   bool DoesInheritFromIsClass(const CPPStructType * inclass, const std::string &name);
   bool IsPandaTypedObject(CPPStructType * inclass) { return DoesInheritFromIsClass(inclass,"TypedObject"); };
-  void write_python_instance(ostream &out, int indent_level, const std::string &return_expr, const std::string &assign_expr, std::string &owns_memory_flag, const std::string &class_name, CPPType *ctype, bool inplace, const std::string &const_flag);
+  void write_python_instance(ostream &out, int indent_level, const std::string &return_expr, bool owns_memory, const std::string &class_name, CPPType *ctype, bool is_const);
   string HasAGetKeyFunction(const InterrogateType &itype_class);
   bool HasAGetClassTypeFunction(const InterrogateType &itype_class);
   int NeedsAStrFunction(const InterrogateType &itype_class);
@@ -153,9 +184,9 @@ public:
   bool NeedsARichCompareFunction(const InterrogateType &itype_class);
 
   void output_quoted(ostream &out, int indent_level, const std::string &str);
-  
+
   // stash the forward declarations for this compile pass..
-  std::set<std::string>     _external_imports;    
+  std::set<CPPType *> _external_imports;
 };
 
 #endif

+ 1 - 0
dtool/src/interrogate/interrogate.cxx

@@ -46,6 +46,7 @@ bool save_unique_names = false;
 bool no_database = false;
 bool generate_spam = false;
 bool left_inheritance_requires_upcast = true;
+bool mangle_names = true;
 CPPVisibility min_vis = V_published;
 string library_name;
 string module_name;

+ 1 - 1
dtool/src/interrogate/interrogate.h

@@ -43,9 +43,9 @@ extern bool save_unique_names;
 extern bool no_database;
 extern bool generate_spam;
 extern bool left_inheritance_requires_upcast;
+extern bool mangle_names;
 extern CPPVisibility min_vis;
 extern string library_name;
 extern string module_name;
 
 #endif
-

+ 252 - 76
dtool/src/interrogate/interrogateBuilder.cxx

@@ -40,7 +40,7 @@
 #include "cppExtensionType.h"
 #include "cppStructType.h"
 #include "cppExpression.h"
-#include "cppTypedef.h"
+#include "cppTypedefType.h"
 #include "cppTypeDeclaration.h"
 #include "cppEnumType.h"
 #include "cppCommentBlock.h"
@@ -270,7 +270,8 @@ build() {
       }
 
     } else if ((*di)->get_subtype() == CPPDeclaration::ST_typedef) {
-      CPPTypedef *tdef = (*di)->as_typedef();
+      CPPTypedefType *tdef = (*di)->as_typedef_type();
+
       if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct) {
         // A typedef counts as a declaration.  This lets us pick up
         // most template instantiations.
@@ -279,13 +280,16 @@ build() {
         scan_struct_type(struct_type);
       }
 
+      scan_typedef_type(tdef);
+
     } else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) {
       CPPType *type = (*di)->as_type_declaration()->_type;
+
       type->_vis = (*di)->_vis;
 
-      if (type->get_subtype() == CPPDeclaration::ST_struct)
-      {
-        CPPStructType *struct_type =type->as_type()->resolve_type(&parser, &parser)->as_struct_type();
+      if (type->get_subtype() == CPPDeclaration::ST_struct) {
+        CPPStructType *struct_type =
+          type->as_type()->resolve_type(&parser, &parser)->as_struct_type();
         scan_struct_type(struct_type);
 
       } else if (type->get_subtype() == CPPDeclaration::ST_enum) {
@@ -313,7 +317,8 @@ build() {
 //  Description: Generates all the code necessary to the indicated
 //               output stream.
 ////////////////////////////////////////////////////////////////////
-void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, InterrogateModuleDef *def) {
+void InterrogateBuilder::
+write_code(ostream &out_code,ostream * out_include, InterrogateModuleDef *def) {
   typedef vector<InterfaceMaker *> InterfaceMakers;
   InterfaceMakers makers;
 
@@ -378,9 +383,10 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
     }
     declaration_bodies << "#include \"py_panda.h\"\n";
     declaration_bodies << "#include \"extension.h\"\n";
+    declaration_bodies << "#include \"dcast.h\"\n";
   }
   declaration_bodies << "\n";
-  
+
   IncludeFiles::const_iterator ifi;
   for (ifi = _include_files.begin();
        ifi != _include_files.end();
@@ -397,7 +403,6 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
   }
   declaration_bodies << "\n";
 
-
   for (mi = makers.begin(); mi != makers.end(); ++mi) {
     (*mi)->write_includes(declaration_bodies);
   }
@@ -411,8 +416,6 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
 
   declaration_bodies << "\n";
 
-
-
   // And now the prototypes.
   for (mi = makers.begin(); mi != makers.end(); ++mi) {
     (*mi)->write_prototypes(declaration_bodies,out_include);
@@ -422,21 +425,19 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
 //  if(out_include != NULL)
 //    (*out_include) << declaration_bodies.str();
 //  else
-    out_code << declaration_bodies.str();
+  out_code << declaration_bodies.str();
 
-  
   // Followed by the function bodies.
   out_code << function_bodies.str() << "\n";
 
-    for (mi = makers.begin(); mi != makers.end(); ++mi) {
-      (*mi)->write_module_support(out_code,out_include,def);
-    }
-
+  for (mi = makers.begin(); mi != makers.end(); ++mi) {
+    (*mi)->write_module_support(out_code, out_include, def);
+  }
 
   if (output_module_specific) {
     // Output whatever stuff we should output if this were a module.
     for (mi = makers.begin(); mi != makers.end(); ++mi) {
-      (*mi)->write_module(out_code,out_include, def);
+      (*mi)->write_module(out_code, out_include, def);
     }
   }
 
@@ -445,7 +446,7 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
   for (mi = makers.begin(); mi != makers.end(); ++mi) {
     (*mi)->get_function_remaps(remaps);
   }
-  
+
   // Make sure all of the function wrappers appear first in the set of
   // indices, and that they occupy consecutive index numbers, so we
   // can build a simple array of function pointers by index.
@@ -488,7 +489,6 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
     out_code << "};\n\n";
   }
 
-
   if (save_unique_names) {
     // Write out the table of unique names, in no particular order.
     out_code << "static InterrogateUniqueNameDef _in_unique_names["
@@ -502,9 +502,6 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
     out_code << "};\n\n";
   }
 
-//if(1==2)
-{
-
   if (!no_database) {
     // Now build the module definition structure to add ourselves to
     // the global interrogate database.
@@ -528,7 +525,7 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
           << "  0,  /* num_unique_names */\n";
     }
 
-    if (output_function_pointers) { 
+    if (output_function_pointers) {
       out_code << "  _in_fptrs,\n"
           << "  " << num_wrappers << ",  /* num_fptrs */\n";
     } else {
@@ -549,7 +546,6 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
         << "}\n\n";
   }
 }
-}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateBuilder::make_module_def
@@ -871,6 +867,15 @@ in_ignoreinvolved(CPPType *type) const {
       return false;
     }
 
+  case CPPDeclaration::ST_typedef:
+    {
+      if (in_ignoreinvolved(type->get_simple_name())) {
+        return true;
+      }
+      CPPTypedefType *tdef = type->as_typedef_type();
+      return in_ignoreinvolved(tdef->_type);
+    }
+
   default:
     return in_ignoreinvolved(type->get_simple_name());
   }
@@ -1129,7 +1134,7 @@ scan_function(CPPInstance *function) {
   }
 
   get_function(function, "",
-               (CPPStructType *)NULL, scope, 
+               (CPPStructType *)NULL, scope,
                InterrogateFunction::F_global);
 }
 
@@ -1165,8 +1170,7 @@ scan_struct_type(CPPStructType *type) {
 
   // Check if any of the members are exported.  If none of them are,
   // and the type itself is not marked for export, then never mind.
-  if (type->_vis > min_vis) 
-  {
+  if (type->_vis > min_vis) {
     CPPScope *scope = type->_scope;
 
     bool any_exported = false;
@@ -1176,6 +1180,7 @@ scan_struct_type(CPPStructType *type) {
          ++di) {
       if ((*di)->_vis <= min_vis) {
         any_exported = true;
+        break;
       }
     }
 
@@ -1225,6 +1230,93 @@ scan_enum_type(CPPEnumType *type) {
   get_type(type, true);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateBuilder::scan_typedef_type
+//       Access: Private
+//  Description: Adds the indicated typedef type to the database, if
+//               warranted.
+////////////////////////////////////////////////////////////////////
+void InterrogateBuilder::
+scan_typedef_type(CPPTypedefType *type) {
+  if (type == (CPPTypedefType *)NULL) {
+    return;
+  }
+
+  // A typedef cannot be a template declaration.
+  assert(!type->is_template());
+
+  if (type->_file.is_c_file()) {
+    // This type declaration appears in a .C file.  We can only export
+    // types defined in a .h file.
+    return;
+  }
+
+  if (type->_file._source != CPPFile::S_local ||
+      in_ignorefile(type->_file._filename_as_referenced)) {
+    // The type is defined in some other package or in an
+    // ignorable file.
+    return;
+  }
+
+  // Do we require explicitly placing BEGIN_PUBLISH/END_PUBLISH
+  // blocks around typedefs for them to be exported?  My thinking is
+  // that we shoudn't, for now, since we don't require it for structs
+  // either (we only require it to have published methods).
+  //if (type->_vis > min_vis) {
+  //  // The wrapped type is not marked to be exported.
+  //  return;
+  //}
+
+  // Find out what this typedef points to.
+  CPPType *wrapped_type = type->_type;
+  bool forced = in_forcetype(wrapped_type->get_local_name(&parser));
+
+  while (wrapped_type->get_subtype() == CPPDeclaration::ST_typedef) {
+    wrapped_type = wrapped_type->as_typedef_type()->_type;
+    forced = forced || in_forcetype(wrapped_type->get_local_name(&parser));
+  }
+
+  CPPStructType *struct_type = wrapped_type->as_struct_type();
+  if (struct_type == (CPPStructType *)NULL) {
+    // We only export typedefs to structs, for now.
+    return;
+  }
+
+  // Always export typedefs pointing to forced types.
+  if (!forced) {
+    if (wrapped_type->_file._source != CPPFile::S_local ||
+        in_ignorefile(wrapped_type->_file._filename_as_referenced)) {
+      // The wrapped type is defined in some other package or
+      // in an ignorable file.
+      return;
+    }
+
+    // Check if any of the wrapped type's members are published.
+    // If none of them are, and the wrapped type itself is not
+    // marked for export, then never mind.
+    if (struct_type->_vis > min_vis) {
+      CPPScope *scope = struct_type->_scope;
+
+      bool any_exported = false;
+      CPPScope::Declarations::const_iterator di;
+      for (di = scope->_declarations.begin();
+           di != scope->_declarations.end() && !any_exported;
+           ++di) {
+        if ((*di)->_vis <= min_vis) {
+          any_exported = true;
+          break;
+        }
+      }
+
+      if (!any_exported) {
+        return;
+      }
+    }
+  }
+
+  get_type(type, true);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateBuilder::scan_manifest
 //       Access: Private
@@ -1667,6 +1759,11 @@ get_function(CPPInstance *function, string description,
     return 0;
   }
 
+  TypeIndex class_index = 0;
+  if (struct_type != (CPPStructType *)NULL) {
+    class_index = get_type(struct_type, false);
+  }
+
   string function_name = TypeManager::get_function_name(function);
   string function_signature = TypeManager::get_function_signature(function);
 
@@ -1682,18 +1779,17 @@ get_function(CPPInstance *function, string description,
     _functions_by_name.find(function_name);
   if (tni != _functions_by_name.end()) {
     FunctionIndex index = (*tni).second;
+
     // It's already here, so update the flags.
     InterrogateFunction &ifunction =
       InterrogateDatabase::get_ptr()->update_function(index);
 
-    // Not 100% sure why, but there's a case where this happens,
-    // in a case where a typedef shadowed an actual type. ~rdb
     nassertr(&ifunction != NULL, 0);
 
     ifunction._flags |= flags;
 
     // Also, make sure this particular signature is defined.
-    pair<InterrogateFunction::Instances::iterator, bool> result = 
+    pair<InterrogateFunction::Instances::iterator, bool> result =
       ifunction._instances->insert(InterrogateFunction::Instances::value_type(function_signature, function));
 
     InterrogateFunction::Instances::iterator ii = result.first;
@@ -1748,7 +1844,7 @@ get_function(CPPInstance *function, string description,
   if (struct_type != (CPPStructType *)NULL) {
     // The function is a method.
     ifunction->_flags |= InterrogateFunction::F_method;
-    ifunction->_class = get_type(struct_type, false);
+    ifunction->_class = class_index;
   }
 
   if (ftype->_flags & CPPFunctionType::F_unary_op) {
@@ -1958,7 +2054,7 @@ get_type(CPPType *type, bool global) {
   if (true_name.empty()) {
     // Whoops, it's an anonymous type.  That's okay, because we'll
     // usually only encounter them once anyway, so let's go ahead and
-    // define it without checking in _types_by_name.
+    // define it without checking _types_by_name first.
 
   } else {
     TypesByName::const_iterator tni = _types_by_name.find(true_name);
@@ -2028,29 +2124,39 @@ get_type(CPPType *type, bool global) {
     }
   }
 
-  CPPExtensionType *ext_type = type->as_extension_type();
-  if (ext_type != (CPPExtensionType *)NULL) {
-    // If it's an extension type of some kind, it might be scoped.
+  CPPScope *scope = NULL;
+  // If it's an extension type or typedef, it might be scoped.
+  if (CPPTypedefType *td_type = type->as_typedef_type()) {
+    scope = td_type->_ident->get_scope(&parser, &parser);
+
+  } else if (CPPExtensionType *ext_type = type->as_extension_type()) {
     if (ext_type->_ident != (CPPIdentifier *)NULL) {
-      CPPScope *scope = ext_type->_ident->get_scope(&parser, &parser);
-      while (scope->as_template_scope() != (CPPTemplateScope *)NULL)
-      {
-        assert(scope->get_parent_scope() != scope);
-        scope = scope->get_parent_scope();
-        assert(scope != (CPPScope *)NULL);
-      }
-      itype._cppscope = scope;
+      scope = ext_type->_ident->get_scope(&parser, &parser);
 
-      if (scope != &parser) {
-        // We're scoped!
-        itype._scoped_name =
-          descope(scope->get_local_name(&parser) + "::" + itype._name);
-        CPPStructType *struct_type = scope->get_struct_type();
+    } else if (CPPEnumType *enum_type = ext_type->as_enum_type()) {
+      // Special case for anonymous enums.
+      scope = enum_type->_parent_scope;
+    }
 
-        if (struct_type != (CPPStructType *)NULL) {
-          itype._flags |= InterrogateType::F_nested;
-          itype._outer_class = get_type(struct_type, false);
-        }
+  }
+
+  if (scope != (CPPScope *)NULL) {
+    while (scope->as_template_scope() != (CPPTemplateScope *)NULL) {
+      assert(scope->get_parent_scope() != scope);
+      scope = scope->get_parent_scope();
+      assert(scope != (CPPScope *)NULL);
+    }
+    itype._cppscope = scope;
+
+    if (scope != &parser) {
+      // We're scoped!
+      itype._scoped_name =
+        descope(scope->get_local_name(&parser) + "::" + itype._name);
+      CPPStructType *struct_type = scope->get_struct_type();
+
+      if (struct_type != (CPPStructType *)NULL) {
+        itype._flags |= InterrogateType::F_nested;
+        itype._outer_class = get_type(struct_type, false);
       }
     }
   }
@@ -2076,8 +2182,15 @@ get_type(CPPType *type, bool global) {
     } else if (type->as_extension_type() != (CPPExtensionType *)NULL) {
       define_extension_type(itype, type->as_extension_type());
 
+    } else if (type->as_typedef_type() != (CPPTypedefType *)NULL) {
+      define_typedef_type(itype, type->as_typedef_type());
+
+    } else if (type->as_array_type() != (CPPArrayType *)NULL) {
+      define_array_type(itype, type->as_array_type());
+
     } else {
-      //      nout << "Attempt to define invalid type " << true_name << "\n";
+      nout << "Attempt to define invalid type " << *type
+           << " (subtype " << type->get_subtype() << ")\n";
 
       // Remove the type from the database.
       InterrogateDatabase::get_ptr()->remove_type(index);
@@ -2113,6 +2226,16 @@ define_atomic_type(InterrogateType &itype, CPPSimpleType *cpptype) {
     itype._atomic_token = AT_int;
     break;
 
+  case CPPSimpleType::T_char16_t:
+    itype._flags |= InterrogateType::F_unsigned;
+    itype._atomic_token = AT_int;
+    break;
+
+  case CPPSimpleType::T_char32_t:
+    itype._flags |= InterrogateType::F_unsigned;
+    itype._atomic_token = AT_int;
+    break;
+
   case CPPSimpleType::T_int:
     if ((cpptype->_flags & CPPSimpleType::F_longlong) != 0) {
       itype._atomic_token = AT_longlong;
@@ -2134,7 +2257,8 @@ define_atomic_type(InterrogateType &itype, CPPSimpleType *cpptype) {
     break;
 
   default:
-    nout << "Invalid CPPSimpleType: " << (int)cpptype->_type << "\n";
+    nout << "Type \"" << *cpptype << "\" has invalid CPPSimpleType: "
+         << (int)cpptype->_type << "\n";
     itype._atomic_token = AT_not_atomic;
   }
 
@@ -2249,23 +2373,25 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
 
   // A struct type should always be global.
   itype._flags |= InterrogateType::F_global;
-  
+
   CPPScope *scope = cpptype->_scope;
-  
+
   CPPStructType::Derivation::const_iterator bi;
   for (bi = cpptype->_derivation.begin();
        bi != cpptype->_derivation.end();
        ++bi) {
-    const CPPStructType::Base &base = (*bi);
-    if (base._vis <= V_public) 
-    {
 
+    const CPPStructType::Base &base = (*bi);
+    if (base._vis <= V_public) {
       CPPType *base_type = TypeManager::resolve_type(base._base, scope);
       TypeIndex base_index = get_type(base_type, true);
 
-      
       if (base_index == 0) {
-        nout << *cpptype << " reports a derivation from an invalid type.\n";
+        if (base_type != NULL) {
+          nout << *cpptype << " reports a derivation from invalid type " << *base_type << ".\n";
+        } else {
+          nout << *cpptype << " reports a derivation from an invalid type.\n";
+        }
 
       } else {
         InterrogateType::Derivation d;
@@ -2273,7 +2399,7 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
         d._base = base_index;
         d._upcast = 0;
         d._downcast = 0;
-        
+
         // Do we need to synthesize upcast and downcast functions?
         bool generate_casts = false;
 
@@ -2281,12 +2407,12 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
         if (base._is_virtual) {
           // We do in the presence of virtual inheritance.
           generate_casts = true;
-          
+
         } else if (bi != cpptype->_derivation.begin()) {
           // Or if we're not talking about the leftmost fork of multiple
           // inheritance.
           generate_casts = true;
-          
+
         } else if (cpptype->_derivation.size() != 1 &&
                    left_inheritance_requires_upcast) {
           // Or even if we are the leftmost fork of multiple
@@ -2302,13 +2428,11 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
           // pointer, while the parent class won't).
           generate_casts = true;
         }
-        
-        if (generate_casts) {
-        
 
+        if (generate_casts) {
           d._upcast = get_cast_function(base_type, cpptype, "upcast");
           d._flags |= InterrogateType::DF_upcast;
-          
+
           if (base._is_virtual) {
             // If this is a virtual inheritance, we can't write a
             // downcast.
@@ -2355,8 +2479,9 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
           CPPExtensionType *nested_type = type->as_extension_type();
           assert(nested_type != (CPPExtensionType *)NULL);
 
-          // Only try to export named types.
-          if (nested_type->_ident != (CPPIdentifier *)NULL) {
+          // For now, we don't allow anonymous structs.
+          if (nested_type->_ident != (CPPIdentifier *)NULL ||
+              nested_type->as_enum_type() != (CPPEnumType *)NULL) {
             TypeIndex nested_index = get_type(nested_type, false);
             itype._nested_types.push_back(nested_index);
           }
@@ -2366,11 +2491,31 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
       CPPType *type = (*di)->as_enum_type();
 
       // An anonymous enum type.
-      if ((*di)->_vis <= min_vis) {
+      if (type->_vis <= min_vis) {
         TypeIndex nested_index = get_type(type, false);
         itype._nested_types.push_back(nested_index);
       }
 
+    } else if ((*di)->get_subtype() == CPPDeclaration::ST_typedef) {
+      CPPTypedefType *type = (*di)->as_typedef_type();
+
+      // A nested typedef.  Unwrap it to find out what it's pointing to.
+      CPPType *wrapped_type = type->_type;
+
+      while (wrapped_type->get_subtype() == CPPDeclaration::ST_typedef) {
+        wrapped_type = wrapped_type->as_typedef_type()->_type;
+      }
+
+      CPPStructType *struct_type = wrapped_type->as_struct_type();
+      if (struct_type != (CPPStructType *)NULL) {
+        // We only export typedefs to structs, for now.
+
+        if (type->_vis <= min_vis) {
+          TypeIndex nested_index = get_type(type, false);
+          itype._nested_types.push_back(nested_index);
+        }
+      }
+
     } else if ((*di)->get_subtype() == CPPDeclaration::ST_make_property) {
       ElementIndex element_index = get_make_property((*di)->as_make_property(), cpptype);
       itype._elements.push_back(element_index);
@@ -2467,7 +2612,7 @@ update_function_comment(CPPInstance *function, CPPScope *scope) {
     ifunction._comment += comment;
 
     // Also update the particular wrapper comment.
-    InterrogateFunction::Instances::iterator ii = 
+    InterrogateFunction::Instances::iterator ii =
       ifunction._instances->find(function_signature);
     if (ii != ifunction._instances->end()) {
       if ((*ii).second->_leading_comment == NULL ||
@@ -2489,8 +2634,7 @@ void InterrogateBuilder::
 define_method(CPPFunctionGroup *fgroup, InterrogateType &itype,
               CPPStructType *struct_type, CPPScope *scope) {
   CPPFunctionGroup::Instances::const_iterator fi;
-  for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) 
-  {
+  for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
     CPPInstance *function = (*fi);
     define_method(function, itype, struct_type, scope);
   }
@@ -2626,7 +2770,7 @@ void InterrogateBuilder::
 define_enum_type(InterrogateType &itype, CPPEnumType *cpptype) {
   itype._flags |= InterrogateType::F_enum;
 
-  CPPScope *scope = &parser;
+  CPPScope *scope = cpptype->_parent_scope;
   if (cpptype->_ident != (CPPIdentifier *)NULL) {
     scope = cpptype->_ident->get_scope(&parser, &parser);
   }
@@ -2667,7 +2811,15 @@ define_enum_type(InterrogateType &itype, CPPEnumType *cpptype) {
 
     if (element->_initializer != (CPPExpression *)NULL) {
       CPPExpression::Result result = element->_initializer->evaluate();
-      next_value = result.as_integer();
+
+      if (result._type == CPPExpression::RT_error) {
+        nout << "enum value ";
+        element->output(nout, 0, &parser, true);
+        nout << " has invalid definition!\n";
+        return;
+      } else {
+        next_value = result.as_integer();
+      }
     }
     evalue._value = next_value;
     itype._enum_values.push_back(evalue);
@@ -2676,6 +2828,30 @@ define_enum_type(InterrogateType &itype, CPPEnumType *cpptype) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateBuilder::define_typedef_type
+//       Access: Private
+//  Description: Builds up a definition for the indicated typedef.
+////////////////////////////////////////////////////////////////////
+void InterrogateBuilder::
+define_typedef_type(InterrogateType &itype, CPPTypedefType *cpptype) {
+  itype._flags |= InterrogateType::F_typedef;
+  itype._wrapped_type = get_type(cpptype->_type, false);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateBuilder::define_array_type
+//       Access: Private
+//  Description: Builds up a definition for the indicated wrapped type.
+////////////////////////////////////////////////////////////////////
+void InterrogateBuilder::
+define_array_type(InterrogateType &itype, CPPArrayType *cpptype) {
+  itype._flags |= InterrogateType::F_array;
+  itype._wrapped_type = get_type(cpptype->_element_type, false);
+
+  itype._array_size = cpptype->_bounds->evaluate().as_integer();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateBuilder::define_extension_type
 //       Access: Private

+ 5 - 0
dtool/src/interrogate/interrogateBuilder.h

@@ -33,6 +33,8 @@ class CPPConstType;
 class CPPExtensionType;
 class CPPStructType;
 class CPPEnumType;
+class CPPTypedefType;
+class CPPArrayType;
 class CPPFunctionType;
 class CPPScope;
 class CPPIdentifier;
@@ -92,6 +94,7 @@ public:
   void scan_function(CPPInstance *function);
   void scan_struct_type(CPPStructType *type);
   void scan_enum_type(CPPEnumType *type);
+  void scan_typedef_type(CPPTypedefType *type);
   void scan_manifest(CPPManifest *manifest);
   ElementIndex scan_element(CPPInstance *element, CPPStructType *struct_type,
                             CPPScope *scope);
@@ -128,6 +131,8 @@ public:
   void define_method(CPPInstance *function, InterrogateType &itype,
                      CPPStructType *struct_type, CPPScope *scope);
   void define_enum_type(InterrogateType &itype, CPPEnumType *cpptype);
+  void define_typedef_type(InterrogateType &itype, CPPTypedefType *cpptype);
+  void define_array_type(InterrogateType &itype, CPPArrayType *cpptype);
   void define_extension_type(InterrogateType &itype,
                              CPPExtensionType *cpptype);
 

+ 9 - 9
dtool/src/interrogate/parse_file.cxx

@@ -16,7 +16,7 @@
 #include "cppManifest.h"
 #include "cppStructType.h"
 #include "cppFunctionGroup.h"
-#include "cppTypedef.h"
+#include "cppTypedefType.h"
 #include "cppExpressionParser.h"
 #include "cppExpression.h"
 #include "cppType.h"
@@ -166,7 +166,7 @@ show_data_members(const string &str) {
 }
 
 void
-show_typedefs(const string &str) {
+show_nested_types(const string &str) {
   CPPType *type = parser.parse_type(str);
   if (type == NULL) {
     cerr << "Invalid type: " << str << "\n";
@@ -182,12 +182,12 @@ show_typedefs(const string &str) {
   CPPScope *scope = stype->get_scope();
   assert(scope != (CPPScope *)NULL);
 
-  cerr << "Typedefs in " << *stype << ":\n";
+  cerr << "Nested types in " << *stype << ":\n";
 
-  CPPScope::Typedefs::const_iterator ti;
-  for (ti = scope->_typedefs.begin(); ti != scope->_typedefs.end(); ++ti) {
-    CPPTypedef *td = (*ti).second;
-    cerr << "  " << *td << "\n";
+  CPPScope::Types::const_iterator ti;
+  for (ti = scope->_types.begin(); ti != scope->_types.end(); ++ti) {
+    CPPType *tp = (*ti).second;
+    cerr << "  " << *tp << "\n";
   }
 }
 
@@ -286,8 +286,8 @@ main(int argc, char **argv) {
             show_methods(remainder);
           } else if (first_word == "members") {
             show_data_members(remainder);
-          } else if (first_word == "typedefs") {
-            show_typedefs(remainder);
+          } else if (first_word == "types") {
+            show_nested_types(remainder);
           } else {
             show_type_or_expression(str);
           }

File diff suppressed because it is too large
+ 557 - 122
dtool/src/interrogate/typeManager.cxx


+ 11 - 1
dtool/src/interrogate/typeManager.h

@@ -50,6 +50,7 @@ public:
   static bool is_ref_to_anything(CPPType *type);
   static bool is_const_ref_to_anything(CPPType *type);
   static bool is_const_pointer_to_anything(CPPType *type);
+  static bool is_const_pointer_or_ref(CPPType *type);
   static bool is_non_const_pointer_or_ref(CPPType *type);
   static bool is_pointer(CPPType *type);
   static bool is_const(CPPType *type);
@@ -61,9 +62,15 @@ public:
   static bool is_const_simple(CPPType *type);
   static bool is_const_ref_to_simple(CPPType *type);
   static bool is_ref_to_simple(CPPType *type);
+  static bool is_simple_array(CPPType *type);
+  static bool is_pointer_to_simple(CPPType *type);
   static bool is_pointable(CPPType *type);
   static bool is_char(CPPType *type);
+  static bool is_unsigned_char(CPPType *type);
   static bool is_char_pointer(CPPType *type);
+  static bool is_const_char_pointer(CPPType *type);
+  static bool is_unsigned_char_pointer(CPPType *type);
+  static bool is_const_unsigned_char_pointer(CPPType *type);
   static bool is_basic_string_char(CPPType *type);
   static bool is_const_basic_string_char(CPPType *type);
   static bool is_const_ref_to_basic_string_char(CPPType *type);
@@ -80,6 +87,7 @@ public:
   static bool is_bool(CPPType *type);
   static bool is_integer(CPPType *type);
   static bool is_unsigned_integer(CPPType *type);
+  static bool is_size(CPPType *type);
   static bool is_short(CPPType *type);
   static bool is_unsigned_short(CPPType *type);
   static bool is_longlong(CPPType *type);
@@ -94,6 +102,8 @@ public:
   static bool is_const_ref_to_pointer_to_base(CPPType *type);
   static bool is_pointer_to_PyObject(CPPType *type);
   static bool is_PyObject(CPPType *type);
+  static bool is_pointer_to_PyTypeObject(CPPType *type);
+  static bool is_PyTypeObject(CPPType *type);
   static bool is_pointer_to_PyStringObject(CPPType *type);
   static bool is_PyStringObject(CPPType *type);
   static bool is_pointer_to_PyUnicodeObject(CPPType *type);
@@ -134,7 +144,7 @@ public:
 
 
   static bool IsExported(CPPType *type);
-  static bool IsLocal(CPPType *type);
+  static bool is_local(CPPType *type);
 
 };
 

+ 1 - 6
dtool/src/interrogatedb/dtool_super_base.cxx

@@ -38,7 +38,7 @@ static Py_hash_t DTool_HashKey_Methods_DTOOL_SUPER_BASE(PyObject *self) {
   return (Py_hash_t) local_this;
 };
 
-inline void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module) {
+EXPCL_DTOOLCONFIG void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module) {
   static bool initdone = false;
   if (!initdone) {
 
@@ -83,9 +83,4 @@ int Dtool_Init_DTOOL_SUPER_BASE(PyObject *self, PyObject *args, PyObject *kwds)
   return -1;
 }
 
-int Dtool_InitNoCoerce_DTOOL_SUPER_BASE(PyObject *self, PyObject *args) {
-  PyErr_SetString(PyExc_TypeError, "cannot init super base");
-  return -1;
-}
-
 #endif  // HAVE_PYTHON

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

@@ -207,6 +207,16 @@ is_const() const {
   return (_flags & F_const) != 0;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateType::is_typedef
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool InterrogateType::
+is_typedef() const {
+  return (_flags & F_typedef) != 0;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateType::get_wrapped_type
 //       Access: Public
@@ -217,6 +227,26 @@ get_wrapped_type() const {
   return _wrapped_type;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateType::is_array
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool InterrogateType::
+is_array() const {
+  return (_flags & F_array) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: InterrogateType::get_array_size
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE int InterrogateType::
+get_array_size() const {
+  return _array_size;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: InterrogateType::is_enum
 //       Access: Public

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

@@ -32,6 +32,7 @@ InterrogateType(InterrogateModuleDef *def) :
   _outer_class = 0;
   _atomic_token = AT_not_atomic;
   _wrapped_type = 0;
+  _array_size = 1;
   _destructor = 0;
 
   _cpptype = (CPPType *)NULL;
@@ -111,6 +112,7 @@ operator = (const InterrogateType &copy) {
   _outer_class = copy._outer_class;
   _atomic_token = copy._atomic_token;
   _wrapped_type = copy._wrapped_type;
+  _array_size = copy._array_size;
   _constructors = copy._constructors;
   _destructor = copy._destructor;
   _elements = copy._elements;
@@ -165,6 +167,11 @@ output(ostream &out) const {
   out << _outer_class << " "
       << (int)_atomic_token << " "
       << _wrapped_type << " ";
+
+  if (is_array()) {
+    out << _array_size << " ";
+  }
+
   idf_output_vector(out, _constructors);
   out << _destructor << " ";
   idf_output_vector(out, _elements);
@@ -197,6 +204,10 @@ input(istream &in) {
   _atomic_token = (AtomicToken)token;
   in >> _wrapped_type;
 
+  if (is_array()) {
+    in >> _array_size;
+  }
+
   idf_input_vector(in, _constructors);
   in >> _destructor;
 

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

@@ -60,8 +60,12 @@ public:
   INLINE bool is_wrapped() const;
   INLINE bool is_pointer() const;
   INLINE bool is_const() const;
+  INLINE bool is_typedef() const;
   INLINE TypeIndex get_wrapped_type() const;
 
+  INLINE bool is_array() const;
+  INLINE int get_array_size() const;
+
   INLINE bool is_enum() const;
   INLINE int number_of_enum_values() const;
   INLINE const string &get_enum_value_name(int n) const;
@@ -132,6 +136,8 @@ private:
     F_nested               = 0x040000,
     F_enum                 = 0x080000,
     F_unpublished          = 0x100000,
+    F_typedef              = 0x200000,
+    F_array                = 0x400000,
   };
 
 public:
@@ -143,6 +149,7 @@ public:
   TypeIndex _outer_class;
   AtomicToken _atomic_token;
   TypeIndex _wrapped_type;
+  int _array_size;
 
   typedef vector<FunctionIndex> Functions;
   Functions _constructors;

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

@@ -613,6 +613,12 @@ interrogate_type_is_const(TypeIndex type) {
   return InterrogateDatabase::get_ptr()->get_type(type).is_const();
 }
 
+bool
+interrogate_type_is_typedef(TypeIndex type) {
+  //cerr << "interrogate_type_is_typedef(" << type << ")\n";
+  return InterrogateDatabase::get_ptr()->get_type(type).is_typedef();
+}
+
 TypeIndex
 interrogate_type_wrapped_type(TypeIndex type) {
   //cerr << "interrogate_type_wrapped_type(" << type << ")\n";

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

@@ -447,6 +447,7 @@ EXPCL_DTOOLCONFIG bool interrogate_type_is_short(TypeIndex type);
 EXPCL_DTOOLCONFIG bool interrogate_type_is_wrapped(TypeIndex type);
 EXPCL_DTOOLCONFIG bool interrogate_type_is_pointer(TypeIndex type);
 EXPCL_DTOOLCONFIG bool interrogate_type_is_const(TypeIndex type);
+EXPCL_DTOOLCONFIG bool interrogate_type_is_typedef(TypeIndex type);
 EXPCL_DTOOLCONFIG TypeIndex interrogate_type_wrapped_type(TypeIndex type);
 
 // If interrogate_type_is_enum() returns true, this is an enumerated

+ 51 - 215
dtool/src/interrogatedb/py_panda.cxx

@@ -18,7 +18,7 @@
 #ifdef HAVE_PYTHON
 
 PyMemberDef standard_type_members[] = {
-  {(char *)"this", T_ULONG, offsetof(Dtool_PyInstDef,_ptr_to_object),READONLY, (char *)"C++ 'this' pointer, if any"},
+  {(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"},
 //  {(char *)"this_ownership", T_INT, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"},
 //  {(char *)"this_const", T_INT, offsetof(Dtool_PyInstDef, _is_const), READONLY, (char *)"C++ 'this' const flag"},
 //  {(char *)"this_signature", T_INT, offsetof(Dtool_PyInstDef, _signature), READONLY, (char *)"A type check signature"},
@@ -31,6 +31,9 @@ PyMemberDef standard_type_members[] = {
 ////////////////////////////////////////////////////////////////////////
 bool DtoolCanThisBeAPandaInstance(PyObject *self) {
   // simple sanity check for the class type..size.. will stop basic foobars..
+  // It is arguably better to use something like this:
+  // PyType_IsSubtype(Py_TYPE(self), &Dtool_DTOOL_SUPER_BASE._PyType)
+  // ...but probably not as fast.
   if (Py_TYPE(self)->tp_basicsize >= (int)sizeof(Dtool_PyInstDef)) {
     Dtool_PyInstDef *pyself = (Dtool_PyInstDef *) self;
     if (pyself->_signature == PY_PANDA_SIGNATURE) {
@@ -55,104 +58,6 @@ void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *c
   }
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: attempt_coercion
-//  Description: A helper function for DTOOL_Call_GetPointerThisClass,
-//               below.  This attempts to coerce the given object to
-//               the indicated Panda object, by creating a temporary
-//               instance of the required Panda object.  If
-//               successful, returns the "this" pointer of the
-//               temporary object; otherwise, returns NULL.
-////////////////////////////////////////////////////////////////////
-static void *
-attempt_coercion(PyObject *self, Dtool_PyTypedObject *classdef,
-                 PyObject **coerced) {
-  // The supplied parameter is not the required type.
-  if (coerced != NULL) {
-    // Attempt coercion: try to create a temporary instance of the
-    // required class using the supplied parameter.
-    // Because we want to use the special InitNoCoerce constructor
-    // here instead of the regular constructor (we don't want to risk
-    // recursive coercion on the nested type we're creating), we have
-    // to call the constructor with a few more steps.
-    PyObject *obj = NULL;
-    if (classdef->_PyType.tp_new != NULL) {
-      obj = classdef->_PyType.tp_new(&classdef->_PyType, self, NULL);
-      assert(obj != NULL);
-
-      if (PyTuple_Check(self)) {
-        // A tuple was passed, which we assume are the constructor arguments.
-        if (classdef->_Dtool_InitNoCoerce(obj, self) != 0) {
-          Py_DECREF(obj);
-          obj = NULL;
-        }
-      } else {
-        // We need to pack the value into an args tuple.
-        PyObject *args = PyTuple_Pack(1, self);
-        if (classdef->_Dtool_InitNoCoerce(obj, args) != 0) {
-          Py_DECREF(obj);
-          obj = NULL;
-        }
-        Py_DECREF(args);
-      }
-    }
-    if (obj == NULL) {
-      // That didn't work; try to call a static "make" method instead.
-      // Presently, we don't bother filtering this for coercion,
-      // because none of our classes suffer from a recursion danger
-      // here.  Maybe one day we will need to also construct a
-      // makeNoCoerce wrapper?
-      PyObject *make = PyObject_GetAttrString((PyObject *)classdef, "make");
-      if (make != NULL) {
-        PyErr_Clear();
-        if (PyTuple_Check(self)) {
-          obj = PyObject_CallObject(make, self);
-        } else {
-          obj = PyObject_CallFunctionObjArgs(make, self, NULL);
-        }
-        Py_DECREF(make);
-      }
-    }
-    if (obj != NULL) {
-      // Well, whaddaya know?  The supplied parameter(s) suited
-      // the object's constructor.  Now we have a temporary object
-      // that we can pass to the function.
-      Dtool_PyTypedObject *my_type = ((Dtool_PyInstDef *)obj)->_My_Type;
-      void *result = my_type->_Dtool_UpcastInterface(obj, classdef);
-      if (result != NULL) {
-        // Successfully coerced.  Store the newly-allocated
-        // pointer, so the caller can release the coerced object
-        // at his leisure.  We store it in a list, so that other
-        // parameters can accumulate there too.
-        if ((*coerced) == NULL) {
-          (*coerced) = PyList_New(0);
-        }
-        PyList_Append(*coerced, obj);
-        Py_DECREF(obj);
-        return result;
-      }
-      // Some problem getting the C++ pointer from our created
-      // temporary object.  Weird.
-      Py_DECREF(obj);
-    }
-
-    // Clear the error returned by the coercion constructor.  It's not
-    // the error message we want to report.
-    PyErr_Clear();
-  }
-  return NULL;
-}
-
-// Temporary function to preserve backward compatibility.
-void *
-DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
-                               int param, const string &function_name, bool const_ok,
-                               PyObject **coerced) {
-  return DTOOL_Call_GetPointerThisClass(self, classdef,
-                                        param, function_name, const_ok,
-                                        coerced, true);
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DTOOL_Call_GetPointerThisClass
 //  Description: Extracts the C++ pointer for an object, given its
@@ -176,18 +81,6 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
 //               declared non-const, and can therefore be called with
 //               only a non-const "this" pointer.
 //
-//               If coerced is non-NULL, parameter coercion will be
-//               attempted.  This means the supplied parameter may not
-//               exactly match the required type, but will satisfy the
-//               require type's constructor; and we will create
-//               temporary object(s) of the required type instead.  In
-//               this case, coerced is a pointer to a PyList that will
-//               be filled with these temporary objects.  If coerced
-//               is a pointer to a NULL PyObject, a new PyList will be
-//               created on the first successful coercion.  If coerced
-//               itself is NULL, parameter coercion will not be
-//               attempted.
-//
 //               The return value is the C++ pointer that was
 //               extracted, or NULL if there was a problem (in which
 //               case the Python exception state will have been set).
@@ -195,103 +88,42 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
 void *
 DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
                                int param, const string &function_name, bool const_ok,
-                               PyObject **coerced, bool report_errors) {
-  if (PyErr_Occurred()) {
+                               bool report_errors) {
+  //if (PyErr_Occurred()) {
+  //  return NULL;
+  //}
+  if (self == NULL) {
+    if (report_errors) {
+      PyErr_SetString(PyExc_TypeError, "self is NULL");
+    }
     return NULL;
   }
-  if (self != NULL) {
-    if (DtoolCanThisBeAPandaInstance(self)) {
-      Dtool_PyTypedObject *my_type = ((Dtool_PyInstDef *)self)->_My_Type;
-      void *result = my_type->_Dtool_UpcastInterface(self, classdef);
-      if (result != NULL) {
-        if (const_ok || !((Dtool_PyInstDef *)self)->_is_const) {
-          return result;
-        }
 
-        if (report_errors) {
-          ostringstream str;
-          str << function_name << "() argument " << param << " may not be const";
-          string msg = str.str();
-          PyErr_SetString(PyExc_TypeError, msg.c_str());
-        }
-
-      } else {
-        if (report_errors) {
-          ostringstream str;
-          str << function_name << "() argument " << param << " must be ";
-
-          PyObject *fname = PyObject_GetAttrString((PyObject *)classdef, "__name__");
-          if (fname != (PyObject *)NULL) {
-#if PY_MAJOR_VERSION >= 3
-            str << PyUnicode_AsUTF8(fname);
-#else
-            str << PyString_AsString(fname);
-#endif
-            Py_DECREF(fname);
-          } else {
-            str << classdef->_name;
-          }
-
-          PyObject *tname = PyObject_GetAttrString((PyObject *)Py_TYPE(self), "__name__");
-          if (tname != (PyObject *)NULL) {
-#if PY_MAJOR_VERSION >= 3
-            str << ", not " << PyUnicode_AsUTF8(tname);
-#else
-            str << ", not " << PyString_AsString(tname);
-#endif
-            Py_DECREF(tname);
-          } else {
-            str << ", not " << my_type->_name;
-          }
-
-          string msg = str.str();
-          PyErr_SetString(PyExc_TypeError, msg.c_str());
-        }
-      }
+  if (DtoolCanThisBeAPandaInstance(self)) {
+    void *result = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, classdef);
 
-    } else {
-      // The parameter was not a Panda type.  Can we coerce it to the
-      // appropriate type, by creating a temporary object?
-      void *result = attempt_coercion(self, classdef, coerced);
-      if (result != NULL) {
+    if (result != NULL) {
+      if (const_ok || !((Dtool_PyInstDef *)self)->_is_const) {
         return result;
       }
 
-      // Coercion failed.
       if (report_errors) {
-        ostringstream str;
-        str << function_name << "() argument " << param << " must be ";
+        PyErr_Format(PyExc_TypeError,
+                     "%s() argument %d may not be const",
+                     function_name.c_str(), param);
+      }
 
-        PyObject *fname = PyObject_GetAttrString((PyObject *)classdef, "__name__");
-        if (fname != (PyObject *)NULL) {
-#if PY_MAJOR_VERSION >= 3
-          str << PyUnicode_AsUTF8(fname);
-#else
-          str << PyString_AsString(fname);
-#endif
-          Py_DECREF(fname);
-        } else {
-          str << classdef->_name;
-        }
+      return NULL;
+    }
+  }
 
-        PyObject *tname = PyObject_GetAttrString((PyObject *)Py_TYPE(self), "__name__");
-        if (tname != (PyObject *)NULL) {
-#if PY_MAJOR_VERSION >= 3
-          str << ", not " << PyUnicode_AsUTF8(tname);
-#else
-          str << ", not " << PyString_AsString(tname);
-#endif
-          Py_DECREF(tname);
-        }
+  if (report_errors) {
+    PyTypeObject *tp = Py_TYPE(self);
 
-        string msg = str.str();
-        PyErr_SetString(PyExc_TypeError, msg.c_str());
-      }
-    }
-  } else {
-    if (report_errors) {
-      PyErr_SetString(PyExc_TypeError, "self is NULL");
-    }
+    PyErr_Format(PyExc_TypeError,
+                 "%s() argument %d must be %s, not %s",
+                 function_name.c_str(), param,
+                 classdef->_PyType.tp_name, tp->tp_name);
   }
 
   return NULL;
@@ -314,7 +146,7 @@ void *DTOOL_Call_GetPointerThis(PyObject *self) {
 // this function relies on the behavior of typed objects in the panda system.
 //
 ////////////////////////////////////////////////////////////////////////
-PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject & known_class_type, bool memory_rules, bool is_const, int RunTimeType) {
+PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &known_class_type, bool memory_rules, bool is_const, int type_index) {
   if (local_this_in == NULL) {
     // Let's not be stupid..
     PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this'");
@@ -324,11 +156,11 @@ PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &
   /////////////////////////////////////////////////////
   // IF the class is possibly a run time typed object
   /////////////////////////////////////////////////////
-  if (RunTimeType > 0) {
+  if (type_index > 0) {
     /////////////////////////////////////////////////////
     // get best fit class...
     /////////////////////////////////////////////////////
-    Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(RunTimeType);
+    Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(type_index);
     if (target_class != NULL) {
       /////////////////////////////////////////////////////
       // cast to the type...
@@ -343,7 +175,7 @@ PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &
           self->_ptr_to_object = new_local_this;
           self->_memory_rules = memory_rules;
           self->_is_const = is_const;
-          self->_signature = PY_PANDA_SIGNATURE;
+          //self->_signature = PY_PANDA_SIGNATURE;
           self->_My_Type = target_class;
           return (PyObject *)self;
         }
@@ -360,7 +192,7 @@ PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &
     self->_ptr_to_object = local_this_in;
     self->_memory_rules = memory_rules;
     self->_is_const = is_const;
-    self->_signature = PY_PANDA_SIGNATURE;
+    //self->_signature = PY_PANDA_SIGNATURE;
     self->_My_Type = &known_class_type;
   }
   return (PyObject *)self;
@@ -425,7 +257,7 @@ void
 RegisterRuntimeClass(Dtool_PyTypedObject *otype, int class_id) {
   if (class_id == 0) {
     interrogatedb_cat.warning()
-      << "Class " << otype->_name
+      << "Class " << otype->_PyType.tp_name
       << " has a zero TypeHandle value; check that init_type() is called.\n";
 
   } else if (class_id > 0) {
@@ -436,13 +268,14 @@ RegisterRuntimeClass(Dtool_PyTypedObject *otype, int class_id) {
       // There was already an entry in the dictionary for class_id.
       Dtool_PyTypedObject *other_type = (*result.first).second;
       interrogatedb_cat.warning()
-        << "Classes " << otype->_name << " and " << other_type->_name
+        << "Classes " << otype->_PyType.tp_name
+        << " and " << other_type->_PyType.tp_name
         << " share the same TypeHandle value (" << class_id
         << "); check class definitions.\n";
 
     } else {
       GetRunTimeTypeList().insert(class_id);
-      otype->_Dtool_IsRunTimeCapable = true;
+      otype->_type = TypeRegistry::ptr()->find_type_by_id(class_id);
     }
   }
 }
@@ -523,18 +356,24 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
 PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args) {
   PyObject *from_in = NULL;
   PyObject *to_in = NULL;
-  if (PyArg_ParseTuple(args, "OO", &to_in, &from_in)) {
+  if (PyArg_UnpackTuple(args, "Dtool_BorrowThisReference", 2, 2, &to_in, &from_in)) {
 
     if (DtoolCanThisBeAPandaInstance(from_in) && DtoolCanThisBeAPandaInstance(to_in)) {
-      Dtool_PyInstDef * from = (Dtool_PyInstDef *) from_in;
-      Dtool_PyInstDef * to = (Dtool_PyInstDef *) to_in;
+      Dtool_PyInstDef *from = (Dtool_PyInstDef *) from_in;
+      Dtool_PyInstDef *to = (Dtool_PyInstDef *) to_in;
+
+      //if (PyObject_TypeCheck(to_in, Py_TYPE(from_in))) {
       if (from->_My_Type == to->_My_Type) {
         to->_memory_rules = false;
         to->_is_const = from->_is_const;
         to->_ptr_to_object = from->_ptr_to_object;
-        return Py_BuildValue("");
+
+        Py_INCREF(Py_None);
+        return Py_None;
       }
-      PyErr_SetString(PyExc_TypeError, "Must Be Same Type??");
+
+      PyErr_Format(PyExc_TypeError, "types %s and %s do not match",
+                   Py_TYPE(from)->tp_name, Py_TYPE(to)->tp_name);
     } else {
       PyErr_SetString(PyExc_TypeError, "One of these does not appear to be DTOOL Instance ??");
     }
@@ -772,18 +611,15 @@ PyObject *map_deepcopy_to_copy(PyObject *self, PyObject *args) {
 //               either a regular integer or a long integer, according
 //               to whether the indicated value will fit.
 ////////////////////////////////////////////////////////////////////
+#if PY_MAJOR_VERSION < 3
 EXPCL_DTOOLCONFIG PyObject *
 PyLongOrInt_FromUnsignedLong(unsigned long value) {
-#if PY_MAJOR_VERSION >= 3
-  // Python 3 only has longs.
-  return PyLong_FromUnsignedLong(value);
-#else
   if ((long)value < 0) {
     return PyLong_FromUnsignedLong(value);
   } else {
     return PyInt_FromLong((long)value);
   }
-#endif
 }
+#endif
 
 #endif  // HAVE_PYTHON

+ 140 - 118
dtool/src/interrogatedb/py_panda.h

@@ -13,12 +13,12 @@
 ////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////
 //  Too do list ..
-//      We need a better dispatcher for the functions..  The behavior today is 
-//          try one till it works or you run out of possibilities..  This is anything but optimal 
-//          for performance and is treading on thin ice for function python or c++ will 
+//      We need a better dispatcher for the functions..  The behavior today is
+//          try one till it works or you run out of possibilities..  This is anything but optimal
+//          for performance and is treading on thin ice for function python or c++ will
 //          course there types to other types.
 //
-//      The linking step will produce allot of warnings 
+//      The linking step will produce allot of warnings
 //                      warning LNK4049: locally defined symbol..
 //
 //  Get a second coder to review this file and the generated  code ..
@@ -40,6 +40,8 @@
 
 #endif
 
+#include "pnotify.h"
+
 #if defined(HAVE_PYTHON) && !defined(CPPPARSER)
 
 #ifdef _POSIX_C_SOURCE
@@ -102,21 +104,29 @@ inline PyObject* doPy_RETURN_FALSE()
 #define Py_TPFLAGS_CHECKTYPES 0
 #endif
 
-#if PY_MAJOR_VERSION < 3
-// For more portably defining hash functions.
-typedef long Py_hash_t;
-#endif
-
 #if PY_MAJOR_VERSION >= 3
+// For writing code that will compile in both versions.
 #define nb_nonzero nb_bool
 #define nb_divide nb_true_divide
 #define nb_inplace_divide nb_inplace_true_divide
+
+#define PyLongOrInt_FromSize_t PyLong_FromSize_t
+#define PyLongOrInt_FromLong PyLong_FromLong
+#define PyLongOrInt_FromUnsignedLong PyLong_FromUnsignedLong
+#define PyInt_Check PyLong_Check
+#define PyInt_AsLong PyLong_Aslong
+#define PyInt_AS_LONG PyLong_AS_LONG
+#else
+// PyInt_FromSize_t automatically picks the right type.
+#define PyLongOrInt_FromSize_t PyInt_FromSize_t
+#define PyLongOrInt_FromLong PyInt_FromLong
+
+// For more portably defining hash functions.
+typedef long Py_hash_t;
 #endif
 
 using namespace std;
 
-#define PY_PANDA_SMALLER_FOOTPRINT 1
-
 ///////////////////////////////////////////////////////////////////////////////////
 // this is tempory .. untill this is glued better into the panda build system
 ///////////////////////////////////////////////////////////////////////////////////
@@ -138,43 +148,28 @@ EXPCL_DTOOLCONFIG RunTimeTypeDictionary &GetRunTimeDictionary();
 EXPCL_DTOOLCONFIG RunTimeTypeList &GetRunTimeTypeList();
 
 //////////////////////////////////////////////////////////
-// used to stamp dtool instance.. 
+// used to stamp dtool instance..
 #define PY_PANDA_SIGNATURE 0xbeaf
-typedef void * ( * ConvertFunctionType  )(PyObject *,Dtool_PyTypedObject * );
-typedef void * ( * ConvertFunctionType1  )(void *, Dtool_PyTypedObject *);
-typedef void   ( *FreeFunction  )(PyObject *);
-typedef void   ( *PyModuleClassInit)(PyObject *module);
-typedef int    ( *InitNoCoerce)(PyObject *self, PyObject *args);
+typedef void *(*UpcastFunction)(PyObject *,Dtool_PyTypedObject *);
+typedef void *(*DowncastFunction)(void *, Dtool_PyTypedObject *);
 
 //inline          Dtool_PyTypedObject *  Dtool_RuntimeTypeDtoolType(int type);
-inline void     Dtool_Deallocate_General(PyObject * self);
+//inline void     Dtool_Deallocate_General(PyObject * self);
 //inline int      DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2);
 //
 ////////////////////////////////////////////////////////////////////////
 // THIS IS THE INSTANCE CONTAINER FOR ALL panda py objects....
 ////////////////////////////////////////////////////////////////////////
-#ifdef  PY_PANDA_SMALLER_FOOTPRINT
 // this should save   8 bytes per object ....
 struct Dtool_PyInstDef {
   PyObject_HEAD
   void *_ptr_to_object;
   struct Dtool_PyTypedObject *_My_Type;
-  unsigned short _signature ; 
+  unsigned short _signature;
   int _memory_rules : 1;   // true if we own the pointer and should delete it or unref it
   int _is_const     : 1;       // true if this is a "const" pointer.
 };
 
-#else
-struct Dtool_PyInstDef {
-  PyObject_HEAD
-  void *_ptr_to_object;
-  int _memory_rules;   // true if we own the pointer and should delete it or unref it
-  int _is_const;       // true if this is a "const" pointer.
-  unsigned long _signature;
-  struct Dtool_PyTypedObject *_My_Type;
-};
-#endif
-
 ////////////////////////////////////////////////////////////////////////
 // A Offset Dictionary Defining How to read the Above Object..
 ////////////////////////////////////////////////////////////////////////
@@ -188,13 +183,11 @@ struct Dtool_PyTypedObject {
   PyTypeObject _PyType;
 
   // My Class Level Features..
-  const char *_name;                             // cpp name for the object
-  bool _Dtool_IsRunTimeCapable;                  // derived from TypedObject
-  ConvertFunctionType _Dtool_UpcastInterface;    // The Upcast Function By Slot
-  ConvertFunctionType1 _Dtool_DowncastInterface; // The Downcast Function By Slot
-  FreeFunction _Dtool_FreeInstance;
-  PyModuleClassInit _Dtool_ClassInit;            // The module init function pointer
-  InitNoCoerce _Dtool_InitNoCoerce;              // A variant of the constructor that does not attempt to perform coercion of its arguments.
+  UpcastFunction _Dtool_UpcastInterface;    // The Upcast Function By Slot
+  DowncastFunction _Dtool_DowncastInterface; // The Downcast Function By Slot
+
+  // May be TypeHandle::none() to indicate a non-TypedObject class.
+  TypeHandle _type;
 
   // some convenience functions..
   inline PyTypeObject &As_PyTypeObject() { return _PyType; };
@@ -212,7 +205,7 @@ struct Dtool_PyTypedObject {
         #MODULE_NAME "." #PUBLIC_NAME,       /*type name with module */ \
         sizeof(Dtool_PyInstDef),                /* tp_basicsize */      \
         0,                                      /* tp_itemsize */       \
-        &Dtool_Deallocate_General,              /* tp_dealloc */        \
+        &Dtool_FreeInstance_##CLASS_NAME,       /* tp_dealloc */        \
         0,                                      /* tp_print */          \
         0,                                      /* tp_getattr */        \
         0,                                      /* tp_setattr */        \
@@ -248,13 +241,9 @@ struct Dtool_PyTypedObject {
         Dtool_new_##CLASS_NAME,                 /* tp_new */            \
         PyObject_Del,                           /* tp_free */           \
       },                                                                \
-      #CLASS_NAME,                                                      \
-      false,                                                            \
       Dtool_UpcastInterface_##CLASS_NAME,                               \
       Dtool_DowncastInterface_##CLASS_NAME,                             \
-      Dtool_FreeInstance_##CLASS_NAME,                                  \
-      Dtool_PyModuleClassInit_##CLASS_NAME,                             \
-      Dtool_InitNoCoerce_##CLASS_NAME                                   \
+      TypeHandle::none(),                                               \
     };
 
 #define Define_Dtool_Class(MODULE_NAME, CLASS_NAME, PUBLIC_NAME)        \
@@ -265,67 +254,62 @@ struct Dtool_PyTypedObject {
   Define_Dtool_PyTypedObject(MODULE_NAME, CLASS_NAME, PUBLIC_NAME)
 
 ////////////////////////////////////////////////////////////////////////
-// The Fast Deallocator.. for Our instances..
-////////////////////////////////////////////////////////////////////////
-inline void Dtool_Deallocate_General(PyObject * self) {
-  ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_FreeInstance(self);
-  Py_TYPE(self)->tp_free(self);
-}
-
-////////////////////////////////////////////////////////////////////////
-//  More Macro(s) to Implement class functions.. Usually used if C++ needs type information 
+//  More Macro(s) to Implement class functions.. Usually used if C++ needs type information
 ////////////////////////////////////////////////////////////////////////
 #define Define_Dtool_new(CLASS_NAME,CNAME)\
-PyObject *Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds)\
-{\
-    PyObject *self = type->tp_alloc(type, 0);\
-    ((Dtool_PyInstDef *)self)->_signature = PY_PANDA_SIGNATURE;\
-    ((Dtool_PyInstDef *)self)->_ptr_to_object = NULL;\
-    ((Dtool_PyInstDef *)self)->_memory_rules = false;\
-    ((Dtool_PyInstDef *)self)->_is_const = false;\
-    ((Dtool_PyInstDef *)self)->_My_Type = &Dtool_##CLASS_NAME;\
-    return self;\
+PyObject *Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds) {\
+  (void) args; (void) kwds;\
+  PyObject *self = type->tp_alloc(type, 0);\
+  ((Dtool_PyInstDef *)self)->_signature = PY_PANDA_SIGNATURE;\
+  ((Dtool_PyInstDef *)self)->_My_Type = &Dtool_##CLASS_NAME;\
+  return self;\
 }
 
+// The following used to be in the above macro, but it doesn't seem to
+// be necessary as tp_alloc memsets the object to 0.
+  //((Dtool_PyInstDef *)self)->_ptr_to_object = NULL;\
+  //((Dtool_PyInstDef *)self)->_memory_rules = false;\
+  //((Dtool_PyInstDef *)self)->_is_const = false;\
+
 ////////////////////////////////////////////////////////////////////////
 /// Delete functions..
 ////////////////////////////////////////////////////////////////////////
 #ifdef NDEBUG
 #define Define_Dtool_FreeInstance_Private(CLASS_NAME,CNAME)\
-static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self)\
-{\
+static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
+  Py_TYPE(self)->tp_free(self);\
 }
 #else // NDEBUG
 #define Define_Dtool_FreeInstance_Private(CLASS_NAME,CNAME)\
-static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self)\
-{\
-    if(((Dtool_PyInstDef *)self)->_ptr_to_object != NULL)\
-        if(((Dtool_PyInstDef *)self)->_memory_rules)\
-        {\
-          cerr << "Detected leak for " << #CLASS_NAME \
-               << " which interrogate cannot delete.\n"; \
-        }\
+static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
+  if (((Dtool_PyInstDef *)self)->_ptr_to_object != NULL) {\
+    if (((Dtool_PyInstDef *)self)->_memory_rules) {\
+      cerr << "Detected leak for " << #CLASS_NAME \
+           << " which interrogate cannot delete.\n"; \
+    }\
+  }\
+  Py_TYPE(self)->tp_free(self);\
 }
 #endif  // NDEBUG
 
 #define Define_Dtool_FreeInstance(CLASS_NAME,CNAME)\
-static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self)\
-{\
-    if(((Dtool_PyInstDef *)self)->_ptr_to_object != NULL)\
-        if(((Dtool_PyInstDef *)self)->_memory_rules)\
-        {\
-            delete ((CNAME *)((Dtool_PyInstDef *)self)->_ptr_to_object);\
-        }\
+static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
+  if (((Dtool_PyInstDef *)self)->_ptr_to_object != NULL) {\
+    if (((Dtool_PyInstDef *)self)->_memory_rules) {\
+      delete ((CNAME *)((Dtool_PyInstDef *)self)->_ptr_to_object);\
+    }\
+  }\
+  Py_TYPE(self)->tp_free(self);\
 }
 
 #define Define_Dtool_FreeInstanceRef(CLASS_NAME,CNAME)\
-static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self)\
-{\
-    if(((Dtool_PyInstDef *)self)->_ptr_to_object != NULL)\
-        if(((Dtool_PyInstDef *)self)->_memory_rules)\
-        {\
-            unref_delete((CNAME *)((Dtool_PyInstDef *)self)->_ptr_to_object);\
-        }\
+static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
+  if (((Dtool_PyInstDef *)self)->_ptr_to_object != NULL) {\
+    if (((Dtool_PyInstDef *)self)->_memory_rules) {\
+      unref_delete((CNAME *)((Dtool_PyInstDef *)self)->_ptr_to_object);\
+    }\
+  }\
+  Py_TYPE(self)->tp_free(self);\
 }
 
 ////////////////////////////////////////////////////////////////////////
@@ -333,38 +317,88 @@ static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self)\
 ////////////////////////////////////////////////////////////////////////
 EXPCL_DTOOLCONFIG bool DtoolCanThisBeAPandaInstance(PyObject *self);
 
+///////////////////////////////////////////////////////////////////////////////
+//  ** HACK ** allert..
+//
+//      Need to keep a runtime type dictionary ... that is forward declared of typed object.
+//        We rely on the fact that typed objects are uniquly defined by an integer.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+EXPCL_DTOOLCONFIG void RegisterRuntimeClass(Dtool_PyTypedObject *otype, int class_id);
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+EXPCL_DTOOLCONFIG Dtool_PyTypedObject *Dtool_RuntimeTypeDtoolType(int type);
+
 ////////////////////////////////////////////////////////////////////////
 //  Function : DTOOL_Call_ExtractThisPointerForType
 //
-//  These are the wrappers that allow for down and upcast from type .. 
+//  These are the wrappers that allow for down and upcast from type ..
 //      needed by the Dtool py interface.. Be very careful if you muck
 //      with these as the generated code depends on how this is set
 //      up..
 ////////////////////////////////////////////////////////////////////////
 EXPCL_DTOOLCONFIG void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject * classdef, void ** answer);
 
-EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced, bool report_errors);
-
-EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced);
+EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, bool report_errors);
 
 EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThis(PyObject *self);
 
+template<class T> INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into) {
+  if (DtoolCanThisBeAPandaInstance(self)) {
+    Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+    if (target_class != NULL) {
+      into = (T*) ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, target_class);
+      return (into != NULL);
+    }
+  }
+  into = NULL;
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////////
 //  Function : DTool_CreatePyInstanceTyped
 //
-// this function relies on the behavior of typed objects in the panda system. 
+// this function relies on the behavior of typed objects in the panda system.
 //
 ////////////////////////////////////////////////////////////////////////
 EXPCL_DTOOLCONFIG PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &known_class_type, bool memory_rules, bool is_const, int RunTimeType);
 
 ////////////////////////////////////////////////////////////////////////
-// DTool_CreatePyInstance .. wrapper function to finalize the existance of a general 
+// DTool_CreatePyInstance .. wrapper function to finalize the existance of a general
 //    dtool py instance..
 ////////////////////////////////////////////////////////////////////////
 EXPCL_DTOOLCONFIG PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_classdef, bool memory_rules, bool is_const);
 
+// These template methods allow use when the Dtool_PyTypedObject is not known.
+// They require a get_class_type() to be defined for the class.
+template<class T> INLINE PyObject *DTool_CreatePyInstance(const T *obj, bool memory_rules) {
+  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  nassertr(known_class != NULL, NULL);
+  return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, true);
+}
+
+template<class T> INLINE PyObject *DTool_CreatePyInstance(T *obj, bool memory_rules) {
+  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  nassertr(known_class != NULL, NULL);
+  return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, false);
+}
+
+template<class T> INLINE PyObject *DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules) {
+  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  nassertr(known_class != NULL, NULL);
+  return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, true, obj->get_type().get_index());
+}
+
+template<class T> INLINE PyObject *DTool_CreatePyInstanceTyped(T *obj, bool memory_rules) {
+  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  nassertr(known_class != NULL, NULL);
+  return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, false, obj->get_type().get_index());
+}
+
 ///////////////////////////////////////////////////////////////////////////////
-//  Macro(s) class definition .. Used to allocate storage and 
+//  Macro(s) class definition .. Used to allocate storage and
 //     init some values for a Dtool Py Type object.
 /////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
@@ -374,11 +408,9 @@ EXPCL_DTOOLCONFIG PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTyp
 extern EXPORT_THIS   Dtool_PyTypedObject Dtool_##CLASS_NAME;\
 extern struct        PyMethodDef Dtool_Methods_##CLASS_NAME[];\
 int         Dtool_Init_##CLASS_NAME(PyObject *self, PyObject *args, PyObject *kwds);\
-int         Dtool_InitNoCoerce_##CLASS_NAME(PyObject *self, PyObject *args);\
 PyObject *  Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds);\
 void  *     Dtool_UpcastInterface_##CLASS_NAME(PyObject *self, Dtool_PyTypedObject *requested_type);\
-void  *     Dtool_DowncastInterface_##CLASS_NAME(void *self, Dtool_PyTypedObject *requested_type);\
-void        Dtool_PyModuleClassInit_##CLASS_NAME(PyObject *module);
+void  *     Dtool_DowncastInterface_##CLASS_NAME(void *self, Dtool_PyTypedObject *requested_type);
 
 ///////////////////////////////////////////////////////////////////////////////
 #define Define_Module_Class(MODULE_NAME,CLASS_NAME,CNAME,PUBLIC_NAME)\
@@ -415,7 +447,7 @@ Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME)
 EXPCL_DTOOLCONFIG int DTool_PyInit_Finalize(PyObject *self, void *This, Dtool_PyTypedObject *type, bool memory_rules, bool is_const);
 
 ///////////////////////////////////////////////////////////////////////////////
-/// A heler function to glu methed definition together .. that can not be done at 
+/// A heler function to glu methed definition together .. that can not be done at
 // code generation time becouse of multiple generation passes in interigate..
 //
 ///////////////////////////////////////////////////////////////////////////////
@@ -424,22 +456,8 @@ typedef std::map<std::string, PyMethodDef *> MethodDefmap;
 EXPCL_DTOOLCONFIG void Dtool_Accum_MethDefs(PyMethodDef in[], MethodDefmap &themap);
 
 ///////////////////////////////////////////////////////////////////////////////
-//  ** HACK ** allert..
-//
-//      Need to keep a runtime type dictionary ... that is forward declared of typed object.
-//        We rely on the fact that typed objects are uniquly defined by an integer.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-EXPCL_DTOOLCONFIG void RegisterRuntimeClass(Dtool_PyTypedObject * otype, int class_id);
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-EXPCL_DTOOLCONFIG Dtool_PyTypedObject *Dtool_RuntimeTypeDtoolType(int type);
-
-///////////////////////////////////////////////////////////////////////////////
-//// We need a way to runtime merge compile units into a python "Module" .. this is done with the 
-/// fallowing structors and code.. along with the support of interigate_module 
+//// We need a way to runtime merge compile units into a python "Module" .. this is done with the
+/// fallowing structors and code.. along with the support of interigate_module
 ///////////////////////////////////////////////////////////////////////////////
 struct LibraryDef {
   typedef void (*ConstantFunction)(PyObject *);
@@ -456,7 +474,7 @@ EXPCL_DTOOLCONFIG PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const c
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
-///  HACK.... Be carefull 
+///  HACK.... Be carefull
 //
 //  Dtool_BorrowThisReference
 //      This function can be used to grab the "THIS" pointer from an object and use it
@@ -476,7 +494,7 @@ EXPCL_DTOOLCONFIG long  DTool_HashKey(PyObject * inst)
 {
     long   outcome = (long)inst;
     PyObject * func = PyObject_GetAttrString(inst, "__hash__");
-    if (func == NULL) 
+    if (func == NULL)
     {
         if(DtoolCanThisBeAPandaInstance(inst))
             if(((Dtool_PyInstDef *)inst)->_ptr_to_object != NULL)
@@ -488,13 +506,13 @@ EXPCL_DTOOLCONFIG long  DTool_HashKey(PyObject * inst)
         Py_DECREF(func);
         if (res == NULL)
             return -1;
-        if (PyInt_Check(res)) 
+        if (PyInt_Check(res))
         {
             outcome = PyInt_AsLong(res);
             if (outcome == -1)
                 outcome = -2;
         }
-        else 
+        else
         {
             PyErr_SetString(PyExc_TypeError,
                 "__hash__() should return an int");
@@ -531,11 +549,15 @@ copy_from_copy_constructor(PyObject *self);
 EXPCL_DTOOLCONFIG PyObject *
 map_deepcopy_to_copy(PyObject *self, PyObject *args);
 
+#if PY_MAJOR_VERSION < 3
+// In the Python 3 case, it is defined as a macro, at the beginning of this file.
 EXPCL_DTOOLCONFIG PyObject *
 PyLongOrInt_FromUnsignedLong(unsigned long value);
+#endif
 
 EXPCL_DTOOLCONFIG extern struct Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE;
+EXPCL_DTOOLCONFIG extern void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module);
 
 #endif  // HAVE_PYTHON && !CPPPARSER
 
-#endif // PY_PANDA_H_ 
+#endif // PY_PANDA_H_

+ 2 - 2
dtool/src/parser-inc/Python.h

@@ -26,8 +26,8 @@ typedef _object PyObject;
 struct _typeobject;
 typedef _typeobject PyTypeObject;
 
-struct PyStringObject;
-struct PyUnicodeObject;
+typedef struct {} PyStringObject;
+typedef struct {} PyUnicodeObject;
 
 class PyThreadState;
 typedef int Py_ssize_t;

+ 1 - 1
dtool/src/parser-inc/ssl.h

@@ -10,6 +10,6 @@ struct X509;
 struct X509_STORE;
 struct X509_NAME;
 struct SSL;
-#define STACK_OF(num) STACK
+#define STACK_OF(type) struct stack_st_##type
 
 #endif

+ 3 - 0
dtool/src/parser-inc/string

@@ -25,6 +25,9 @@
 template<class ctype>
 class basic_string {
 public:
+  typedef typename size_t size_type;
+  static const size_t npos = (size_t)-1;
+
   basic_string();
   basic_string(const basic_string &copy);
   void operator = (const basic_string &copy);

+ 4 - 0
dtool/src/pystub/pystub.cxx

@@ -79,6 +79,7 @@ extern "C" {
   EXPCL_PYSTUB int PyLong_AsUnsignedLongLong(...);
   EXPCL_PYSTUB int PyLong_FromLong(...);
   EXPCL_PYSTUB int PyLong_FromLongLong(...);
+  EXPCL_PYSTUB int PyLong_FromSize_t(...);
   EXPCL_PYSTUB int PyLong_FromUnsignedLong(...);
   EXPCL_PYSTUB int PyLong_FromUnsignedLongLong(...);
   EXPCL_PYSTUB int PyLong_Type(...);
@@ -153,6 +154,7 @@ extern "C" {
   EXPCL_PYSTUB int PyUnicode_AsUTF8(...);
   EXPCL_PYSTUB int PyUnicode_AsUTF8AndSize(...);
   EXPCL_PYSTUB int PyUnicode_AsWideChar(...);
+  EXPCL_PYSTUB int PyUnicode_AsWideCharString(...);
   EXPCL_PYSTUB int PyUnicode_FromString(...);
   EXPCL_PYSTUB int PyUnicode_FromStringAndSize(...);
   EXPCL_PYSTUB int PyUnicode_FromWideChar(...);
@@ -263,6 +265,7 @@ int PyLong_AsUnsignedLong(...) { return 0; }
 int PyLong_AsUnsignedLongLong(...) { return 0; }
 int PyLong_FromLong(...) { return 0; }
 int PyLong_FromLongLong(...) { return 0; }
+int PyLong_FromSize_t(...) { return 0; }
 int PyLong_FromUnsignedLong(...) { return 0; }
 int PyLong_FromUnsignedLongLong(...) { return 0; }
 int PyLong_Type(...) { return 0; }
@@ -337,6 +340,7 @@ int PyUnicodeUCS4_GetSize(...) { return 0; }
 int PyUnicode_AsUTF8(...) { return 0; }
 int PyUnicode_AsUTF8AndSize(...) { return 0; }
 int PyUnicode_AsWideChar(...) { return 0; }
+int PyUnicode_AsWideCharString(...) { return 0; }
 int PyUnicode_FromString(...) { return 0; }
 int PyUnicode_FromStringAndSize(...) { return 0; }
 int PyUnicode_FromWideChar(...) { return 0; }

+ 5 - 2
makepanda/makepandacore.py

@@ -2416,13 +2416,16 @@ def CopyPythonTree(dstdir, srcdir, lib2to3_fixers=[]):
             for fixer in lib2to3_fixers:
                 lib2to3_args += ['-f', fixer]
 
+    exclude_files = set(VCS_FILES)
+    exclude_files.add('panda3d.py')
+
     refactor = []
     for entry in os.listdir(srcdir):
         srcpth = os.path.join(srcdir, entry)
         dstpth = os.path.join(dstdir, entry)
-        if (os.path.isfile(srcpth)):
+        if os.path.isfile(srcpth):
             base, ext = os.path.splitext(entry)
-            if entry not in VCS_FILES and ext not in SUFFIX_INC + ['.pyc', '.pyo']:
+            if entry not in exclude_files and ext not in SUFFIX_INC + ['.pyc', '.pyo']:
                 if (NeedsBuild([dstpth], [srcpth])):
                     WriteBinaryFile(dstpth, ReadBinaryFile(srcpth))
 

+ 2 - 2
panda/src/distort/nonlinearImager.cxx

@@ -183,7 +183,7 @@ get_num_screens() const {
 ////////////////////////////////////////////////////////////////////
 NodePath NonlinearImager::
 get_screen(int index) const {
-  nassertr(index >= 0 && index < (int)_screens.size(), (ProjectionScreen *)NULL);
+  nassertr(index >= 0 && index < (int)_screens.size(), NodePath());
   return _screens[index]._screen;
 }
 
@@ -215,7 +215,7 @@ get_buffer(int index) const {
 void NonlinearImager::
 set_texture_size(int index, int width, int height) {
   nassertv(index >= 0 && index < (int)_screens.size());
-  
+
   Screen &screen = _screens[index];
 
   screen._tex_width = width;

+ 1 - 0
panda/src/egg/eggNurbsSurface.h

@@ -77,6 +77,7 @@ PUBLISHED:
 
   virtual void write(ostream &out, int indent_level) const;
 
+public:
   Curves _curves_on_surface;
   Trims _trims;
 

+ 39 - 0
panda/src/event/pythonTask.I

@@ -12,3 +12,42 @@
 //
 ////////////////////////////////////////////////////////////////////
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: PythonTask::set_delay
+//       Access: Public
+//  Description: If None is passed, calls clear_delay, otherwise
+//               sets the delay time.  See AsyncTask::set_delay()
+//               and AsyncTask::clear_delay().
+////////////////////////////////////////////////////////////////////
+INLINE void PythonTask::
+set_delay(PyObject *delay) {
+  if (delay == Py_None) {
+    AsyncTask::clear_delay();
+    return;
+  }
+
+  PyObject *value = PyNumber_Float(delay);
+  if (value == NULL) {
+    return;
+  }
+
+  AsyncTask::set_delay(PyFloat_AS_DOUBLE(value));
+  Py_DECREF(value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PythonTask::get_delay
+//       Access: Public
+//  Description: Returns the delay time if set, None otherwise.
+//               See AsyncTask::has_delay() and AsyncTask::get_delay().
+////////////////////////////////////////////////////////////////////
+INLINE PyObject *PythonTask::
+get_delay() const {
+  if (AsyncTask::has_delay()) {
+    return PyFloat_FromDouble(AsyncTask::get_delay());
+  } else {
+    Py_INCREF(Py_None);
+    return Py_None;
+  }
+}

+ 71 - 75
panda/src/event/pythonTask.cxx

@@ -17,7 +17,7 @@
 #include "config_event.h"
 
 #ifdef HAVE_PYTHON
-#include "py_panda.h"  
+#include "py_panda.h" 
 
 TypeHandle PythonTask::_type_handle;
 
@@ -46,7 +46,7 @@ PythonTask(PyObject *function, const string &name) :
   set_upon_death(Py_None);
   set_owner(Py_None);
 
-  _dict = PyDict_New();
+  __dict__ = PyDict_New();
 
 #ifndef SIMPLE_THREADS
   // Ensure that the Python threading system is initialized and ready
@@ -71,7 +71,7 @@ PythonTask::
 ~PythonTask() {
   Py_DECREF(_function);
   Py_DECREF(_args);
-  Py_DECREF(_dict);
+  Py_DECREF(__dict__);
   Py_XDECREF(_generator);
   Py_XDECREF(_owner);
   Py_XDECREF(_upon_death);
@@ -118,7 +118,7 @@ void PythonTask::
 set_args(PyObject *args, bool append_task) {
   Py_XDECREF(_args);
   _args = NULL;
-    
+
   if (args == Py_None) {
     // None means no arguments; create an empty tuple.
     _args = PyTuple_New(0);
@@ -249,53 +249,36 @@ get_owner() {
 //               arbitrary data to the Task object.
 ////////////////////////////////////////////////////////////////////
 int PythonTask::
-__setattr__(const string &attr_name, PyObject *v) {
+__setattr__(PyObject *self, PyObject *attr, PyObject *v) {
+  if (PyObject_GenericSetAttr(self, attr, v) == 0) {
+    return 0;
+  }
+
+  if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+    return -1;
+  }
+
+  PyErr_Clear();
+
   if (task_cat.is_debug()) {
     PyObject *str = PyObject_Repr(v);
-    task_cat.debug() 
-      << *this << ": task." << attr_name << " = "
+    task_cat.debug()
+      << *this << ": task."
 #if PY_MAJOR_VERSION >= 3
+      << PyUnicode_AsUTF8(attr) << " = "
       << PyUnicode_AsUTF8(str) << "\n";
 #else
-      << PyString_AsString(str) << "\n"; 
+      << PyString_AsString(attr) << " = "
+      << PyString_AsString(str) << "\n";
 #endif
     Py_DECREF(str);
   }
 
-  if (attr_name == "delayTime") {
-    if (v == Py_None) {
-      clear_delay();
-    } else {
-      double delay = PyFloat_AsDouble(v);
-      if (!PyErr_Occurred()) {
-        set_delay(delay);
-      }
-    }
-
-  } else if (attr_name == "name") {
-#if PY_MAJOR_VERSION >= 3
-    char *name = PyUnicode_AsUTF8(v);
-#else
-    char *name = PyString_AsString(v);
-#endif
-    if (name != (char *)NULL) {
-      set_name(name);
-    }
-
-  } else if (attr_name == "id" || attr_name == "time" || 
-             attr_name == "frame" || attr_name == "wakeTime") {
-    nassert_raise("Cannot set constant value");
-    return true;
-
-  } else {
-    return PyDict_SetItemString(_dict, attr_name.c_str(), v);
-  }
-
-  return 0;
+  return PyDict_SetItem(__dict__, attr, v);
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: PythonTask::__setattr__
+//     Function: PythonTask::__delattr__
 //       Access: Published
 //  Description: Maps from an expression like "del task.attr_name".
 //               This is customized here so we can support some
@@ -304,8 +287,32 @@ __setattr__(const string &attr_name, PyObject *v) {
 //               arbitrary data to the Task object.
 ////////////////////////////////////////////////////////////////////
 int PythonTask::
-__setattr__(const string &attr_name) {
-  return PyDict_DelItemString(_dict, attr_name.c_str());
+__delattr__(PyObject *self, PyObject *attr) {
+  if (PyObject_GenericSetAttr(self, attr, NULL) == 0) {
+    return 0;
+  }
+
+  if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+    return -1;
+  }
+
+  PyErr_Clear();
+
+  if (PyDict_DelItem(__dict__, attr) == -1) {
+    // PyDict_DelItem does not raise an exception.
+#if PY_MAJOR_VERSION < 3
+    PyErr_Format(PyExc_AttributeError,
+                 "'PythonTask' object has no attribute '%.400s'",
+                 PyString_AS_STRING(attr));
+#else
+    PyErr_Format(PyExc_AttributeError,
+                 "'PythonTask' object has no attribute '%U'",
+                 attr);
+#endif
+    return -1;
+  }
+
+  return 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -318,43 +325,32 @@ __setattr__(const string &attr_name) {
 //               arbitrary data to the Task object.
 ////////////////////////////////////////////////////////////////////
 PyObject *PythonTask::
-__getattr__(const string &attr_name) const {
-  if (attr_name == "time") {
-    return PyFloat_FromDouble(get_elapsed_time());
-
-  } else if (attr_name == "name") {
-#if PY_MAJOR_VERSION >= 3
-    return PyUnicode_FromString(get_name().c_str());
-#else
-    return PyString_FromString(get_name().c_str());
-#endif
-
-  } else if (attr_name == "wakeTime") {
-    return PyFloat_FromDouble(get_wake_time());
-
-  } else if (attr_name == "delayTime") {
-    if (!has_delay()) {
-      Py_RETURN_NONE;
-    }
-    return PyFloat_FromDouble(get_delay());
-
-  } else if (attr_name == "frame") {
-#if PY_MAJOR_VERSION >= 3
-    return PyLong_FromLong(get_elapsed_frames());
-#else
-    return PyInt_FromLong(get_elapsed_frames());
-#endif
-
-  } else if (attr_name == "id") {
-#if PY_MAJOR_VERSION >= 3
-    return PyLong_FromLong(_task_id);
+__getattr__(PyObject *attr) const {
+  // Note that with the new Interrogate behavior, this method
+  // behaves more like the Python __getattr__ rather than being
+  // directly assigned to the tp_getattro slot (a la __getattribute__).
+  // So, we won't get here when the attribute has already been found
+  // via other methods.
+
+  PyObject *item = PyDict_GetItem(__dict__, attr);
+
+  if (item == NULL) {
+    // PyDict_GetItem does not raise an exception.
+#if PY_MAJOR_VERSION < 3
+    PyErr_Format(PyExc_AttributeError,
+                 "'PythonTask' object has no attribute '%.400s'",
+                 PyString_AS_STRING(attr));
 #else
-    return PyInt_FromLong(_task_id);
+    PyErr_Format(PyExc_AttributeError,
+                 "'PythonTask' object has no attribute '%U'",
+                 attr);
 #endif
-
-  } else {
-    return PyMapping_GetItemString(_dict, (char *)attr_name.c_str());
+    return NULL;
   }
+
+  // PyDict_GetItem returns a borrowed reference.
+  Py_INCREF(item);
+  return item;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 38 - 4
panda/src/event/pythonTask.h

@@ -43,9 +43,44 @@ PUBLISHED:
   void set_owner(PyObject *owner);
   PyObject *get_owner();
 
-  int __setattr__(const string &attr_name, PyObject *v);
-  int __setattr__(const string &attr_name);
-  PyObject *__getattr__(const string &attr_name) const;
+  int __setattr__(PyObject *self, PyObject *attr, PyObject *v);
+  int __delattr__(PyObject *self, PyObject *attr);
+  PyObject *__getattr__(PyObject *attr) const;
+
+  INLINE void set_delay(PyObject *delay);
+  INLINE PyObject *get_delay() const;
+
+PUBLISHED:
+  // The name of this task.
+  MAKE_PROPERTY(name, get_name, set_name);
+
+  // The amount of seconds that have elapsed since the task was
+  // started, according to the task manager's clock.
+  MAKE_PROPERTY(time, get_elapsed_time);
+
+  // If this task has been added to an AsyncTaskManager with a delay
+  // in effect, this contains the time at which the task is expected
+  // to awaken.  It has no meaning of the task has not yet been added
+  // to a queue, or if there was no delay in effect at the time the
+  // task was added.
+  //
+  // If the task's status is not S_sleeping, this contains 0.0.
+  MAKE_PROPERTY(wake_time, get_wake_time);
+
+  // The delay value that has been set on this task, if any, or None.
+  MAKE_PROPERTY(delay_time, get_delay, set_delay);
+
+  // The number of frames that have elapsed since the task was
+  // started, according to the task manager's clock.
+  MAKE_PROPERTY(frame, get_elapsed_frames);
+
+  // This is a number guaranteed to be unique for each different
+  // AsyncTask object in the universe.
+  MAKE_PROPERTY(id, get_task_id);
+
+  // This is a special variable to hold the instance dictionary in
+  // which custom variables may be stored.
+  PyObject *__dict__;
 
 protected:
   virtual bool is_runnable();
@@ -67,7 +102,6 @@ private:
   PyObject *_upon_death;
   PyObject *_owner;
   bool _registered_to_owner;
-  PyObject *_dict;
 
   PyObject *_generator;
 

+ 69 - 0
panda/src/express/filename_ext.cxx

@@ -0,0 +1,69 @@
+// Filename: filename_ext.cxx
+// Created by:  rdb (17Sep14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "filename_ext.h"
+
+#ifdef HAVE_PYTHON
+////////////////////////////////////////////////////////////////////
+//     Function: Extension<Filename>::__reduce__
+//       Access: Published
+//  Description: This special Python method is implement to provide
+//               support for the pickle module.
+////////////////////////////////////////////////////////////////////
+PyObject *Extension<Filename>::
+__reduce__(PyObject *self) const {
+  // We should return at least a 2-tuple, (Class, (args)): the
+  // necessary class object whose constructor we should call
+  // (e.g. this), and the arguments necessary to reconstruct this
+  // object.
+  PyTypeObject *this_class = Py_TYPE(self);
+  if (this_class == NULL) {
+    return NULL;
+  }
+
+  PyObject *result = Py_BuildValue("(O(s))", this_class, _this->c_str());
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Extension<Filename>::scan_directory
+//       Access: Published
+//  Description: This variant on scan_directory returns a Python list
+//               of strings on success, or None on failure.
+////////////////////////////////////////////////////////////////////
+PyObject *Extension<Filename>::
+scan_directory() const {
+  vector_string contents;
+  if (!_this->scan_directory(contents)) {
+    Py_INCREF(Py_None);
+    return Py_None;
+  }
+
+  PyObject *result = PyList_New(contents.size());
+  for (size_t i = 0; i < contents.size(); ++i) {
+    const string &filename = contents[i];
+#if PY_MAJOR_VERSION >= 3
+    // This function expects UTF-8.
+    PyObject *str = PyUnicode_FromStringAndSize(filename.data(), filename.size());
+#else
+    PyObject *str = PyString_FromStringAndSize(filename.data(), filename.size());
+#endif
+    PyList_SET_ITEM(result, i, str);
+  }
+
+  return result;
+}
+#endif  // HAVE_PYTHON
+
+

+ 41 - 0
panda/src/express/filename_ext.h

@@ -0,0 +1,41 @@
+// Filename: filename_ext.h
+// Created by:  rdb (17Sep14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 FILENAME_EXT_H
+#define FILENAME_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "extension.h"
+#include "filename.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<Filename>
+// Description : This class defines the extension methods for
+//               Filename, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<Filename> : public ExtensionBase<Filename> {
+public:
+  PyObject *__reduce__(PyObject *self) const;
+  PyObject *scan_directory() const;
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // FILENAME_EXT_H

+ 45 - 0
panda/src/express/globPattern_ext.cxx

@@ -0,0 +1,45 @@
+// Filename: globPattern_ext.cxx
+// Created by:  rdb (17Sep14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "globPattern_ext.h"
+
+#ifdef HAVE_PYTHON
+
+////////////////////////////////////////////////////////////////////
+//     Function: Extension<GlobPattern>::match_files
+//       Access: Published
+//  Description: This variant on match_files returns a Python list
+//               of strings.
+////////////////////////////////////////////////////////////////////
+PyObject *Extension<GlobPattern>::
+match_files(const Filename &cwd) const {
+  vector_string contents;
+  _this->match_files(contents, cwd);
+
+  PyObject *result = PyList_New(contents.size());
+  for (size_t i = 0; i < contents.size(); ++i) {
+    const string &filename = contents[i];
+#if PY_MAJOR_VERSION >= 3
+    // This function expects UTF-8.
+    PyObject *str = PyUnicode_FromStringAndSize(filename.data(), filename.size());
+#else
+    PyObject *str = PyString_FromStringAndSize(filename.data(), filename.size());
+#endif
+    PyList_SET_ITEM(result, i, str);
+  }
+
+  return result;
+}
+
+#endif  // HAVE_PYTHON

+ 40 - 0
panda/src/express/globPattern_ext.h

@@ -0,0 +1,40 @@
+// Filename: globPattern_ext.h
+// Created by:  rdb (17Sep14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 GLOBPATTERN_EXT_H
+#define GLOBPATTERN_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "extension.h"
+#include "globPattern.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<GlobPattern>
+// Description : This class defines the extension methods for
+//               GlobPattern, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<GlobPattern> : public ExtensionBase<GlobPattern> {
+public:
+  PyObject *match_files(const Filename &cwd = Filename()) const;
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // GLOBPATTERN_EXT_H

+ 19 - 15
panda/src/express/multifile.h

@@ -84,27 +84,14 @@ PUBLISHED:
                         int compression_level);
 
 #ifdef HAVE_OPENSSL
-  class CertRecord {
-  public:
-    INLINE CertRecord(X509 *cert);
-    INLINE CertRecord(const CertRecord &copy);
-    INLINE ~CertRecord();
-    INLINE void operator = (const CertRecord &other);
-    X509 *_cert;
-  };
-  typedef pvector<CertRecord> CertChain;
-
-  bool add_signature(const Filename &certificate, 
+  bool add_signature(const Filename &certificate,
                      const Filename &chain,
                      const Filename &pkey,
                      const string &password = "");
-  bool add_signature(const Filename &composite, 
+  bool add_signature(const Filename &composite,
                      const string &password = "");
-  bool add_signature(X509 *certificate, STACK_OF(X509) *chain, EVP_PKEY *pkey);
-  bool add_signature(const CertChain &chain, EVP_PKEY *pkey);
 
   int get_num_signatures() const;
-  const CertChain &get_signature(int n) const;
   string get_signature_subject_name(int n) const;
   string get_signature_friendly_name(int n) const;
   string get_signature_public_key(int n) const;
@@ -152,6 +139,23 @@ PUBLISHED:
   INLINE const string &get_header_prefix() const;
 
 public:
+#ifdef HAVE_OPENSSL
+  class CertRecord {
+  public:
+    INLINE CertRecord(X509 *cert);
+    INLINE CertRecord(const CertRecord &copy);
+    INLINE ~CertRecord();
+    INLINE void operator = (const CertRecord &other);
+    X509 *_cert;
+  };
+  typedef pvector<CertRecord> CertChain;
+
+  bool add_signature(X509 *certificate, STACK_OF(X509) *chain, EVP_PKEY *pkey);
+  bool add_signature(const CertChain &chain, EVP_PKEY *pkey);
+
+  const CertChain &get_signature(int n) const;
+#endif  // HAVE_OPENSSL
+
   bool read_subfile(int index, string &result);
   bool read_subfile(int index, pvector<unsigned char> &result);
 

+ 3 - 0
panda/src/express/p3express_ext_composite.cxx

@@ -1,4 +1,7 @@
+#include "filename_ext.cxx"
+#include "globPattern_ext.cxx"
 #include "memoryUsagePointers_ext.cxx"
 #include "ramfile_ext.cxx"
 #include "streamReader_ext.cxx"
+#include "typeHandle_ext.cxx"
 #include "virtualFileSystem_ext.cxx"

+ 2 - 2
panda/src/express/pointerToArray.I

@@ -163,7 +163,7 @@ PointerToArray(PyObject *self, PyObject *source) :
       PyErr_SetString(PyExc_ValueError, str.c_str());
       return;
     }
-      
+
     int num_elements = size / sizeof(Element);
     insert(begin(), num_elements, Element());
 
@@ -185,7 +185,7 @@ PointerToArray(PyObject *self, PyObject *source) :
     if (item == NULL) {
       return;
     }
-    PyObject *result = PyObject_CallMethod(self, (char *)"pushBack", (char *)"O", item);
+    PyObject *result = PyObject_CallMethod(self, (char *)"push_back", (char *)"O", item);
     Py_DECREF(item);
     if (result == NULL) {
       // Unable to add item--probably it wasn't of the appropriate type.

+ 38 - 0
panda/src/express/typeHandle_ext.cxx

@@ -0,0 +1,38 @@
+// Filename: typeHandle_ext.cxx
+// Created by:  rdb (17Sep14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "typeHandle_ext.h"
+
+#ifdef HAVE_PYTHON
+
+////////////////////////////////////////////////////////////////////
+//     Function: TypeHandle::make
+//       Access: Published, Static
+//  Description: Constructs a TypeHandle from a Python class object.
+//               Useful for automatic coercion, to allow a class
+//               object to be passed wherever a TypeHandle is
+//               expected.
+////////////////////////////////////////////////////////////////////
+TypeHandle Extension<TypeHandle>::
+make(PyTypeObject *tp) {
+  if (!PyType_IsSubtype(tp, &Dtool_DTOOL_SUPER_BASE._PyType)) {
+    PyErr_SetString(PyExc_TypeError, "a Panda type is required");
+    return TypeHandle::none();
+  }
+
+  Dtool_PyTypedObject *dtool_tp = (Dtool_PyTypedObject *) tp;
+  return dtool_tp->_type;
+}
+
+#endif

+ 40 - 0
panda/src/express/typeHandle_ext.h

@@ -0,0 +1,40 @@
+// Filename: typeHandle_ext.h
+// Created by:  rdb (17Sep14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 TYPEHANDLE_EXT_H
+#define TYPEHANDLE_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "extension.h"
+#include "typeHandle.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<TypeHandle>
+// Description : This class defines the extension methods for
+//               TypeHandle, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<TypeHandle> : public ExtensionBase<TypeHandle> {
+public:
+  static TypeHandle make(PyTypeObject *tp);
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // TYPEHANDLE_EXT_H

+ 2 - 6
panda/src/framework/windowFramework.cxx

@@ -79,8 +79,6 @@ WindowFramework::
 WindowFramework(PandaFramework *panda_framework) :
   _panda_framework(panda_framework)
 {
-  _alight = (AmbientLight *)NULL;
-  _dlight = (DirectionalLight *)NULL;
   _got_keyboard = false;
   _got_trackball = false;
   _got_lights = false;
@@ -106,8 +104,6 @@ WindowFramework(const WindowFramework &copy, DisplayRegion *display_region) :
   _window(copy._window),
   _display_region_3d(display_region)
 {
-  _alight = (AmbientLight *)NULL;
-  _dlight = (DirectionalLight *)NULL;
   _got_keyboard = false;
   _got_trackball = false;
   _got_lights = false;
@@ -205,8 +201,8 @@ close_window() {
   _render_2d.remove_node();
   _mouse.remove_node();
 
-  _alight = (AmbientLight *)NULL;
-  _dlight = (DirectionalLight *)NULL;
+  _alight.clear();
+  _dlight.clear();
   _got_keyboard = false;
   _got_trackball = false;
   _got_lights = false;

+ 3 - 3
panda/src/gobj/material.h

@@ -33,13 +33,13 @@ class FactoryParams;
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_GOBJ Material : public TypedWritableReferenceCount, public Namable {
 PUBLISHED:
-  INLINE Material(const string &name = "");
+  INLINE explicit Material(const string &name = "");
   INLINE Material(const Material &copy);
   void operator = (const Material &copy);
   INLINE ~Material();
 
   INLINE static Material *get_default();
-  
+
   INLINE bool has_ambient() const;
   INLINE const LColor &get_ambient() const;
   void set_ambient(const LColor &color);
@@ -88,7 +88,7 @@ private:
   PN_stdfloat _shininess;
 
   static PT(Material) _default;
-  
+
   enum Flags {
     F_ambient     = 0x001,
     F_diffuse     = 0x002,

+ 4 - 1
panda/src/gobj/texture.h

@@ -40,6 +40,7 @@
 #include "cycleDataStageWriter.h"
 #include "pipelineCycler.h"
 #include "samplerState.h"
+#include "pnmImage.h"
 
 class PNMImage;
 class PfmFile;
@@ -208,10 +209,12 @@ PUBLISHED:
   };
 
 PUBLISHED:
-  Texture(const string &name = string());
+  explicit Texture(const string &name = string());
+
 protected:
   Texture(const Texture &copy);
   void operator = (const Texture &copy);
+
 PUBLISHED:
   virtual ~Texture();
 

+ 3 - 0
panda/src/linmath/aa_luse.h

@@ -45,6 +45,7 @@
 
 #define LCAST(numeric_type, object) lcast_to((numeric_type *)0, object)
 
+BEGIN_PUBLISH
 
 // Now we define some handy typedefs for these classes.
 typedef LPoint3f LVertexf;
@@ -185,4 +186,6 @@ typedef LQuaterniond Quat;
 
 #endif  // STDFLOAT_DOUBLE
 
+END_PUBLISH
+
 #endif

+ 11 - 6
panda/src/linmath/compose_matrix_src.h

@@ -30,7 +30,7 @@ compose_matrix(FLOATNAME(LMatrix4) &mat,
                CoordinateSystem cs = CS_default);
 
 INLINE_LINMATH void
-compose_matrix(FLOATNAME(LMatrix4) &mat, 
+compose_matrix(FLOATNAME(LMatrix4) &mat,
                const FLOATTYPE components[num_matrix_components],
                CoordinateSystem cs = CS_default);
 
@@ -50,7 +50,8 @@ decompose_matrix(const FLOATNAME(LMatrix4) &mat,
                  CoordinateSystem cs = CS_default);
 
 INLINE_LINMATH bool
-decompose_matrix(const FLOATNAME(LMatrix4) &mat, FLOATTYPE components[num_matrix_components],
+decompose_matrix(const FLOATNAME(LMatrix4) &mat,
+                 FLOATTYPE components[num_matrix_components],
                  CoordinateSystem CS = CS_default);
 
 
@@ -106,7 +107,8 @@ compose_matrix_old_hpr(FLOATNAME(LMatrix4) &mat,
                        CoordinateSystem cs = CS_default);
 
 INLINE_LINMATH void
-compose_matrix_old_hpr(FLOATNAME(LMatrix4) &mat, const FLOATTYPE components[num_matrix_components],
+compose_matrix_old_hpr(FLOATNAME(LMatrix4) &mat,
+                       const FLOATTYPE components[num_matrix_components],
                        CoordinateSystem cs = CS_default);
 
 EXPCL_PANDA_LINMATH bool
@@ -125,7 +127,8 @@ decompose_matrix_old_hpr(const FLOATNAME(LMatrix4) &mat,
                          CoordinateSystem cs = CS_default);
 
 INLINE_LINMATH bool
-decompose_matrix_old_hpr(const FLOATNAME(LMatrix4) &mat, FLOATTYPE components[num_matrix_components],
+decompose_matrix_old_hpr(const FLOATNAME(LMatrix4) &mat,
+                         FLOATTYPE components[num_matrix_components],
                          CoordinateSystem CS = CS_default);
 
 
@@ -145,7 +148,8 @@ compose_matrix_new_hpr(FLOATNAME(LMatrix4) &mat,
                        CoordinateSystem cs = CS_default);
 
 INLINE_LINMATH void
-compose_matrix_new_hpr(FLOATNAME(LMatrix4) &mat, const FLOATTYPE components[num_matrix_components],
+compose_matrix_new_hpr(FLOATNAME(LMatrix4) &mat,
+                       const FLOATTYPE components[num_matrix_components],
                        CoordinateSystem cs = CS_default);
 
 EXPCL_PANDA_LINMATH bool
@@ -164,7 +168,8 @@ decompose_matrix_new_hpr(const FLOATNAME(LMatrix4) &mat,
                          CoordinateSystem cs = CS_default);
 
 INLINE_LINMATH bool
-decompose_matrix_new_hpr(const FLOATNAME(LMatrix4) &mat, FLOATTYPE components[num_matrix_components],
+decompose_matrix_new_hpr(const FLOATNAME(LMatrix4) &mat,
+                         FLOATTYPE components[num_matrix_components],
                          CoordinateSystem CS = CS_default);
 
 

+ 0 - 11
panda/src/linmath/lmatrix3_ext_src.I

@@ -13,17 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: LMatrix3::Row::__setitem__
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH void Extension<FLOATNAME(LMatrix3)::Row>::
-__setitem__(int i, FLOATTYPE v) {
-  nassertv(i >= 0 && i < 3);
-  _this->_row[i] = v;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LMatrix3::__reduce__
 //       Access: Published

+ 0 - 12
panda/src/linmath/lmatrix3_ext_src.h

@@ -13,18 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 
-////////////////////////////////////////////////////////////////////
-//       Class : Extension<LMatrix3::Row>
-// Description : This class defines the extension methods for
-//               LMatrix3::Row, which are called instead of
-//               any C++ methods with the same prototype.
-////////////////////////////////////////////////////////////////////
-template<>
-class Extension<FLOATNAME(LMatrix3)::Row> : public ExtensionBase<FLOATNAME(LMatrix3)::Row> {
-public:
-  INLINE_LINMATH void __setitem__(int i, FLOATTYPE v);
-};
-
 ////////////////////////////////////////////////////////////////////
 //       Class : Extension<LMatrix3>
 // Description : This class defines the extension methods for

+ 2 - 2
panda/src/linmath/lmatrix3_src.I

@@ -448,7 +448,7 @@ begin() {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LMatrix3)::iterator FLOATNAME(LMatrix3)::
 end() {
-  return begin() + get_num_components();
+  return begin() + num_components;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -470,7 +470,7 @@ begin() const {
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(LMatrix3)::const_iterator FLOATNAME(LMatrix3)::
 end() const {
-  return begin() + get_num_components();
+  return begin() + num_components;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 6 - 1
panda/src/linmath/lmatrix3_src.h

@@ -24,10 +24,16 @@ class FLOATNAME(LMatrix4);
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_LINMATH FLOATNAME(LMatrix3) {
 public:
+  typedef FLOATTYPE numeric_type;
   typedef const FLOATTYPE *iterator;
   typedef const FLOATTYPE *const_iterator;
 
 PUBLISHED:
+  enum {
+    num_components = 9,
+    is_int = 0
+  };
+
   // These helper classes are used to support two-level operator [].
   class Row {
   private:
@@ -35,7 +41,6 @@ PUBLISHED:
   PUBLISHED:
     INLINE_LINMATH FLOATTYPE operator [](int i) const;
     INLINE_LINMATH FLOATTYPE &operator [](int i);
-    EXTENSION(INLINE_LINMATH void __setitem__(int i, FLOATTYPE v));
     INLINE_LINMATH static int size();
   public:
     FLOATTYPE *_row;

+ 0 - 11
panda/src/linmath/lmatrix4_ext_src.I

@@ -13,17 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: LMatrix4::Row::__setitem__
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH void Extension<FLOATNAME(LMatrix4)::Row>::
-__setitem__(int i, FLOATTYPE v) {
-  nassertv(i >= 0 && i < 4);
-  _this->_row[i] = v;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LMatrix4::__reduce__
 //       Access: Published

+ 0 - 12
panda/src/linmath/lmatrix4_ext_src.h

@@ -13,18 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 
-////////////////////////////////////////////////////////////////////
-//       Class : Extension<LMatrix4::Row>
-// Description : This class defines the extension methods for
-//               LMatrix4::Row, which are called instead of
-//               any C++ methods with the same prototype.
-////////////////////////////////////////////////////////////////////
-template<>
-class Extension<FLOATNAME(LMatrix4)::Row> : public ExtensionBase<FLOATNAME(LMatrix4)::Row> {
-public:
-  INLINE_LINMATH void __setitem__(int i, FLOATTYPE v);
-};
-
 ////////////////////////////////////////////////////////////////////
 //       Class : Extension<LMatrix4>
 // Description : This class defines the extension methods for

+ 2 - 2
panda/src/linmath/lmatrix4_src.I

@@ -166,7 +166,7 @@ INLINE_LINMATH FLOATNAME(LMatrix4) &FLOATNAME(LMatrix4)::
 operator = (const FLOATNAME(UnalignedLMatrix4) &copy) {
   TAU_PROFILE("void LMatrix4::operator = (const UnalignedLMatrix4 &)", " ", TAU_USER);
 
-  memcpy(&_m(0, 0), copy.get_data(), sizeof(FLOATTYPE) * get_num_components());
+  memcpy(&_m(0, 0), copy.get_data(), sizeof(FLOATTYPE) * num_components);
   return *this;
 }
 
@@ -1836,7 +1836,7 @@ FLOATNAME(UnalignedLMatrix4)(const FLOATNAME(UnalignedLMatrix4) &copy) : _m(copy
 ////////////////////////////////////////////////////////////////////
 INLINE_LINMATH FLOATNAME(UnalignedLMatrix4) &FLOATNAME(UnalignedLMatrix4)::
 operator = (const FLOATNAME(LMatrix4) &copy) {
-  memcpy(&_m(0, 0), copy.get_data(), sizeof(FLOATTYPE) * get_num_components());
+  memcpy(&_m(0, 0), copy.get_data(), sizeof(FLOATTYPE) * num_components);
   return *this;
 }
 

+ 10 - 1
panda/src/linmath/lmatrix4_src.h

@@ -20,10 +20,16 @@ class FLOATNAME(UnalignedLMatrix4);
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_LINMATH ALIGN_LINMATH FLOATNAME(LMatrix4) {
 public:
+  typedef FLOATTYPE numeric_type;
   typedef const FLOATTYPE *iterator;
   typedef const FLOATTYPE *const_iterator;
 
 PUBLISHED:
+  enum {
+    num_components = 16,
+    is_int = 0
+  };
+
   // These helper classes are used to support two-level operator [].
   class Row {
   private:
@@ -31,7 +37,6 @@ PUBLISHED:
   PUBLISHED:
     INLINE_LINMATH FLOATTYPE operator [](int i) const;
     INLINE_LINMATH FLOATTYPE &operator [](int i);
-    EXTENSION(INLINE_LINMATH void __setitem__(int i, FLOATTYPE v));
     INLINE_LINMATH static int size();
   public:
     FLOATTYPE *_row;
@@ -319,6 +324,10 @@ private:
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_LINMATH FLOATNAME(UnalignedLMatrix4) {
 PUBLISHED:
+  enum {
+    num_components = 16
+  };
+
   INLINE_LINMATH FLOATNAME(UnalignedLMatrix4)();
   INLINE_LINMATH FLOATNAME(UnalignedLMatrix4)(const FLOATNAME(LMatrix4) &copy);
   INLINE_LINMATH FLOATNAME(UnalignedLMatrix4)(const FLOATNAME(UnalignedLMatrix4) &copy);

+ 0 - 11
panda/src/linmath/lvecBase2_ext_src.I

@@ -35,17 +35,6 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4);
 #define PY_AS_FLOATTYPE PyFloat_AsDouble
 #endif
 
-////////////////////////////////////////////////////////////////////
-//     Function: LVecBase2::__setitem__
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE_LINMATH void Extension<FLOATNAME(LVecBase2)>::
-__setitem__(int i, FLOATTYPE v) {
-  nassertv(i >= 0 && i < 2);
-  _this->_v(i) = v;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase2::python_repr
 //       Access: Published

+ 0 - 1
panda/src/linmath/lvecBase2_ext_src.h

@@ -25,7 +25,6 @@ public:
   INLINE_LINMATH PyObject *__reduce__(PyObject *self) const;
   INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const;
   INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign);
-  INLINE_LINMATH void __setitem__(int i, FLOATTYPE v);
   INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const;
 
   INLINE_LINMATH FLOATNAME(LVecBase2) __pow__(FLOATTYPE exponent) const;

Some files were not shown because too many files changed in this diff