Browse Source

Interrogate enum class support (maps to Python 3.4 enums), sanify wrapper code

rdb 9 years ago
parent
commit
fb78fe6e2a

File diff suppressed because it is too large
+ 289 - 581
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 139 - 156
dtool/src/cppparser/cppBison.h.prebuilt

@@ -1,19 +1,19 @@
-/* A Bison parser, made by GNU Bison 2.7.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
 /* Bison interface for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-   
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
@@ -26,13 +26,13 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
 #ifndef YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
 # define YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
-/* Enabling traces.  */
+/* Debug traces.  */
 #ifndef YYDEBUG
 # define YYDEBUG 0
 #endif
@@ -40,134 +40,133 @@
 extern int cppyydebug;
 #endif
 
-/* Tokens.  */
+/* Token type.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     REAL = 258,
-     INTEGER = 259,
-     CHAR_TOK = 260,
-     SIMPLE_STRING = 261,
-     SIMPLE_IDENTIFIER = 262,
-     STRING_LITERAL = 263,
-     CUSTOM_LITERAL = 264,
-     IDENTIFIER = 265,
-     TYPENAME_IDENTIFIER = 266,
-     SCOPING = 267,
-     TYPEDEFNAME = 268,
-     ELLIPSIS = 269,
-     OROR = 270,
-     ANDAND = 271,
-     EQCOMPARE = 272,
-     NECOMPARE = 273,
-     LECOMPARE = 274,
-     GECOMPARE = 275,
-     LSHIFT = 276,
-     RSHIFT = 277,
-     POINTSAT_STAR = 278,
-     DOT_STAR = 279,
-     UNARY = 280,
-     UNARY_NOT = 281,
-     UNARY_NEGATE = 282,
-     UNARY_MINUS = 283,
-     UNARY_PLUS = 284,
-     UNARY_STAR = 285,
-     UNARY_REF = 286,
-     POINTSAT = 287,
-     SCOPE = 288,
-     PLUSPLUS = 289,
-     MINUSMINUS = 290,
-     TIMESEQUAL = 291,
-     DIVIDEEQUAL = 292,
-     MODEQUAL = 293,
-     PLUSEQUAL = 294,
-     MINUSEQUAL = 295,
-     OREQUAL = 296,
-     ANDEQUAL = 297,
-     XOREQUAL = 298,
-     LSHIFTEQUAL = 299,
-     RSHIFTEQUAL = 300,
-     KW_ALIGNAS = 301,
-     KW_ALIGNOF = 302,
-     KW_AUTO = 303,
-     KW_BEGIN_PUBLISH = 304,
-     KW_BLOCKING = 305,
-     KW_BOOL = 306,
-     KW_CATCH = 307,
-     KW_CHAR = 308,
-     KW_CHAR16_T = 309,
-     KW_CHAR32_T = 310,
-     KW_CLASS = 311,
-     KW_CONST = 312,
-     KW_CONSTEXPR = 313,
-     KW_CONST_CAST = 314,
-     KW_DECLTYPE = 315,
-     KW_DEFAULT = 316,
-     KW_DELETE = 317,
-     KW_DOUBLE = 318,
-     KW_DYNAMIC_CAST = 319,
-     KW_ELSE = 320,
-     KW_END_PUBLISH = 321,
-     KW_ENUM = 322,
-     KW_EXTENSION = 323,
-     KW_EXTERN = 324,
-     KW_EXPLICIT = 325,
-     KW_PUBLISHED = 326,
-     KW_FALSE = 327,
-     KW_FINAL = 328,
-     KW_FLOAT = 329,
-     KW_FRIEND = 330,
-     KW_FOR = 331,
-     KW_GOTO = 332,
-     KW_IF = 333,
-     KW_INLINE = 334,
-     KW_INT = 335,
-     KW_LONG = 336,
-     KW_MAKE_PROPERTY = 337,
-     KW_MAKE_PROPERTY2 = 338,
-     KW_MAKE_SEQ = 339,
-     KW_MUTABLE = 340,
-     KW_NAMESPACE = 341,
-     KW_NEW = 342,
-     KW_NOEXCEPT = 343,
-     KW_NULLPTR = 344,
-     KW_OPERATOR = 345,
-     KW_OVERRIDE = 346,
-     KW_PRIVATE = 347,
-     KW_PROTECTED = 348,
-     KW_PUBLIC = 349,
-     KW_REGISTER = 350,
-     KW_REINTERPRET_CAST = 351,
-     KW_RETURN = 352,
-     KW_SHORT = 353,
-     KW_SIGNED = 354,
-     KW_SIZEOF = 355,
-     KW_STATIC = 356,
-     KW_STATIC_ASSERT = 357,
-     KW_STATIC_CAST = 358,
-     KW_STRUCT = 359,
-     KW_TEMPLATE = 360,
-     KW_THREAD_LOCAL = 361,
-     KW_THROW = 362,
-     KW_TRUE = 363,
-     KW_TRY = 364,
-     KW_TYPEDEF = 365,
-     KW_TYPEID = 366,
-     KW_TYPENAME = 367,
-     KW_UNION = 368,
-     KW_UNSIGNED = 369,
-     KW_USING = 370,
-     KW_VIRTUAL = 371,
-     KW_VOID = 372,
-     KW_VOLATILE = 373,
-     KW_WCHAR_T = 374,
-     KW_WHILE = 375,
-     START_CPP = 376,
-     START_CONST_EXPR = 377,
-     START_TYPE = 378
-   };
+  enum yytokentype
+  {
+    REAL = 258,
+    INTEGER = 259,
+    CHAR_TOK = 260,
+    SIMPLE_STRING = 261,
+    SIMPLE_IDENTIFIER = 262,
+    STRING_LITERAL = 263,
+    CUSTOM_LITERAL = 264,
+    IDENTIFIER = 265,
+    TYPENAME_IDENTIFIER = 266,
+    SCOPING = 267,
+    TYPEDEFNAME = 268,
+    ELLIPSIS = 269,
+    OROR = 270,
+    ANDAND = 271,
+    EQCOMPARE = 272,
+    NECOMPARE = 273,
+    LECOMPARE = 274,
+    GECOMPARE = 275,
+    LSHIFT = 276,
+    RSHIFT = 277,
+    POINTSAT_STAR = 278,
+    DOT_STAR = 279,
+    UNARY = 280,
+    UNARY_NOT = 281,
+    UNARY_NEGATE = 282,
+    UNARY_MINUS = 283,
+    UNARY_PLUS = 284,
+    UNARY_STAR = 285,
+    UNARY_REF = 286,
+    POINTSAT = 287,
+    SCOPE = 288,
+    PLUSPLUS = 289,
+    MINUSMINUS = 290,
+    TIMESEQUAL = 291,
+    DIVIDEEQUAL = 292,
+    MODEQUAL = 293,
+    PLUSEQUAL = 294,
+    MINUSEQUAL = 295,
+    OREQUAL = 296,
+    ANDEQUAL = 297,
+    XOREQUAL = 298,
+    LSHIFTEQUAL = 299,
+    RSHIFTEQUAL = 300,
+    KW_ALIGNAS = 301,
+    KW_ALIGNOF = 302,
+    KW_AUTO = 303,
+    KW_BEGIN_PUBLISH = 304,
+    KW_BLOCKING = 305,
+    KW_BOOL = 306,
+    KW_CATCH = 307,
+    KW_CHAR = 308,
+    KW_CHAR16_T = 309,
+    KW_CHAR32_T = 310,
+    KW_CLASS = 311,
+    KW_CONST = 312,
+    KW_CONSTEXPR = 313,
+    KW_CONST_CAST = 314,
+    KW_DECLTYPE = 315,
+    KW_DEFAULT = 316,
+    KW_DELETE = 317,
+    KW_DOUBLE = 318,
+    KW_DYNAMIC_CAST = 319,
+    KW_ELSE = 320,
+    KW_END_PUBLISH = 321,
+    KW_ENUM = 322,
+    KW_EXTENSION = 323,
+    KW_EXTERN = 324,
+    KW_EXPLICIT = 325,
+    KW_PUBLISHED = 326,
+    KW_FALSE = 327,
+    KW_FINAL = 328,
+    KW_FLOAT = 329,
+    KW_FRIEND = 330,
+    KW_FOR = 331,
+    KW_GOTO = 332,
+    KW_IF = 333,
+    KW_INLINE = 334,
+    KW_INT = 335,
+    KW_LONG = 336,
+    KW_MAKE_PROPERTY = 337,
+    KW_MAKE_PROPERTY2 = 338,
+    KW_MAKE_SEQ = 339,
+    KW_MUTABLE = 340,
+    KW_NAMESPACE = 341,
+    KW_NEW = 342,
+    KW_NOEXCEPT = 343,
+    KW_NULLPTR = 344,
+    KW_OPERATOR = 345,
+    KW_OVERRIDE = 346,
+    KW_PRIVATE = 347,
+    KW_PROTECTED = 348,
+    KW_PUBLIC = 349,
+    KW_REGISTER = 350,
+    KW_REINTERPRET_CAST = 351,
+    KW_RETURN = 352,
+    KW_SHORT = 353,
+    KW_SIGNED = 354,
+    KW_SIZEOF = 355,
+    KW_STATIC = 356,
+    KW_STATIC_ASSERT = 357,
+    KW_STATIC_CAST = 358,
+    KW_STRUCT = 359,
+    KW_TEMPLATE = 360,
+    KW_THREAD_LOCAL = 361,
+    KW_THROW = 362,
+    KW_TRUE = 363,
+    KW_TRY = 364,
+    KW_TYPEDEF = 365,
+    KW_TYPEID = 366,
+    KW_TYPENAME = 367,
+    KW_UNION = 368,
+    KW_UNSIGNED = 369,
+    KW_USING = 370,
+    KW_VIRTUAL = 371,
+    KW_VOID = 372,
+    KW_VOLATILE = 373,
+    KW_WCHAR_T = 374,
+    KW_WHILE = 375,
+    START_CPP = 376,
+    START_CONST_EXPR = 377,
+    START_TYPE = 378
+  };
 #endif
 /* Tokens.  */
 #define REAL 258
@@ -292,40 +291,24 @@ extern int cppyydebug;
 #define START_CONST_EXPR 377
 #define START_TYPE 378
 
+/* Value type.  */
 
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
+/* Location type.  */
 #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE
+typedef struct YYLTYPE YYLTYPE;
+struct YYLTYPE
 {
   int first_line;
   int first_column;
   int last_line;
   int last_column;
-} YYLTYPE;
-# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+};
 # define YYLTYPE_IS_DECLARED 1
 # define YYLTYPE_IS_TRIVIAL 1
 #endif
 
 
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int cppyyparse (void *YYPARSE_PARAM);
-#else
-int cppyyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
+
 int cppyyparse (void);
-#else
-int cppyyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
 
 #endif /* !YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED  */

+ 40 - 16
dtool/src/cppparser/cppBison.yxx

@@ -2349,21 +2349,23 @@ enum:
         ;
 
 enum_decl:
-        enum_keyword name_no_final ':' enum_element_type
+        enum_keyword ':' enum_element_type
 {
-  current_enum = new CPPEnumType($2, $4, current_scope, @1.file);
+  current_enum = new CPPEnumType($1, NULL, $3, current_scope, NULL, @1.file);
 }
-        | enum_keyword name_no_final
+        | enum_keyword
 {
-  current_enum = new CPPEnumType($2, current_scope, @1.file);
+  current_enum = new CPPEnumType($1, NULL, current_scope, NULL, @1.file);
 }
-        | enum_keyword ':' enum_element_type
+        | enum_keyword name_no_final ':' enum_element_type
 {
-  current_enum = new CPPEnumType(NULL, $3, current_scope, @1.file);
+  CPPScope *new_scope = new CPPScope(current_scope, $2->_names.back(), V_public);
+  current_enum = new CPPEnumType($1, $2, $4, current_scope, new_scope, @1.file);
 }
-        | enum_keyword
+        | enum_keyword name_no_final
 {
-  current_enum = new CPPEnumType(NULL, current_scope, @1.file);
+  CPPScope *new_scope = new CPPScope(current_scope, $2->_names.back(), V_public);
+  current_enum = new CPPEnumType($1, $2, current_scope, new_scope, @1.file);
 }
         ;
 
@@ -2383,14 +2385,12 @@ enum_body_trailing_comma:
         | enum_body_trailing_comma name ','
 {
   assert(current_enum != NULL);
-  CPPInstance *inst = current_enum->add_element($2->get_simple_name());
-  current_scope->add_enum_value(inst, current_lexer, @2);
+  current_enum->add_element($2->get_simple_name(), NULL, current_lexer, @2);
 }
         | enum_body_trailing_comma name '=' const_expr ','
 {
   assert(current_enum != NULL);
-  CPPInstance *inst = current_enum->add_element($2->get_simple_name(), $4);
-  current_scope->add_enum_value(inst, current_lexer, @2);
+  current_enum->add_element($2->get_simple_name(), $4, current_lexer, @2);
 };
 
 enum_body:
@@ -2398,14 +2398,12 @@ enum_body:
         | enum_body_trailing_comma name
 {
   assert(current_enum != NULL);
-  CPPInstance *inst = current_enum->add_element($2->get_simple_name());
-  current_scope->add_enum_value(inst, current_lexer, @2);
+  current_enum->add_element($2->get_simple_name(), NULL, current_lexer, @2);
 }
         | enum_body_trailing_comma name '=' const_expr
 {
   assert(current_enum != NULL);
-  CPPInstance *inst = current_enum->add_element($2->get_simple_name(), $4);
-  current_scope->add_enum_value(inst, current_lexer, @2);
+  current_enum->add_element($2->get_simple_name(), $4, current_lexer, @2);
 }
         ;
 
@@ -2413,6 +2411,14 @@ enum_keyword:
         KW_ENUM
 {
   $$ = CPPExtensionType::T_enum;
+}
+        | KW_ENUM KW_CLASS
+{
+  $$ = CPPExtensionType::T_enum_class;
+}
+        | KW_ENUM KW_STRUCT
+{
+  $$ = CPPExtensionType::T_enum_struct;
 }
         ;
 
@@ -3495,6 +3501,24 @@ name:
         | KW_OVERRIDE
 {
   $$ = new CPPIdentifier("override", @1);
+}
+        | KW_SIGNED
+{
+  // This is not a keyword in Python, so it is useful to be able to use this
+  // in MAKE_PROPERTY definitions, etc.
+  $$ = new CPPIdentifier("signed", @1);
+}
+        | KW_FLOAT
+{
+  $$ = new CPPIdentifier("float", @1);
+}
+        | KW_PUBLIC
+{
+  $$ = new CPPIdentifier("public", @1);
+}
+        | KW_PRIVATE
+{
+  $$ = new CPPIdentifier("private", @1);
 }
         ;
 

+ 66 - 13
dtool/src/cppparser/cppEnumType.cxx

@@ -22,42 +22,53 @@
 #include "indent.h"
 
 /**
- * Creates an untyped, unscoped enum.
+ * Creates an untyped enum.
  */
 CPPEnumType::
-CPPEnumType(CPPIdentifier *ident, CPPScope *current_scope,
-            const CPPFile &file) :
-  CPPExtensionType(T_enum, ident, current_scope, file),
-  _parent_scope(current_scope),
+CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
+            CPPScope *scope, const CPPFile &file) :
+  CPPExtensionType(type, ident, current_scope, file),
+  _scope(scope),
   _element_type(NULL),
   _last_value(NULL)
 {
+  _parent_scope = (type == T_enum) ? current_scope : scope;
+
   if (ident != NULL) {
     ident->_native_scope = current_scope;
   }
 }
 
 /**
- * Creates a typed but unscoped enum.
+ * Creates a typed 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),
+CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type,
+            CPPScope *current_scope, CPPScope *scope, const CPPFile &file) :
+  CPPExtensionType(type, ident, current_scope, file),
+  _scope(scope),
   _element_type(element_type),
   _last_value(NULL)
 {
+  _parent_scope = (type == T_enum) ? current_scope : scope;
   if (ident != NULL) {
     ident->_native_scope = current_scope;
   }
 }
 
+/**
+ * Returns true if this is a scoped enum.
+ */
+bool CPPEnumType::
+is_scoped() const {
+  return (_type != T_enum);
+}
+
 /**
  * Returns the integral type used to store enum values.
  */
 CPPType *CPPEnumType::
-get_element_type() {
+get_underlying_type() {
   if (_element_type == NULL) {
     // This enum is untyped.  Use a suitable default, ie.  'int'. In the
     // future, we might want to check whether it fits in an int.
@@ -78,11 +89,18 @@ get_element_type() {
  *
  */
 CPPInstance *CPPEnumType::
-add_element(const string &name, CPPExpression *value) {
+add_element(const string &name, CPPExpression *value, CPPPreprocessor *preprocessor, const cppyyltype &pos) {
   CPPIdentifier *ident = new CPPIdentifier(name);
   ident->_native_scope = _parent_scope;
 
-  CPPInstance *inst = new CPPInstance(get_element_type(), ident);
+  CPPInstance *inst;
+  if (_type == T_enum) {
+    // Weakly typed enum.
+    inst = new CPPInstance(get_underlying_type(), ident);
+  } else {
+    // C++11-style strongly typed enum.
+    inst = new CPPInstance(this, ident);
+  }
   inst->_storage_class |= CPPInstance::SC_constexpr;
   _elements.push_back(inst);
 
@@ -104,6 +122,41 @@ add_element(const string &name, CPPExpression *value) {
   }
   inst->_initializer = value;
   _last_value = value;
+
+  if (preprocessor != (CPPPreprocessor *)NULL) {
+    // Same-line comment?
+    CPPCommentBlock *comment =
+      preprocessor->get_comment_on(pos.first_line, pos.file);
+
+    if (comment == (CPPCommentBlock *)NULL) {
+      // Nope.  Check for a comment before this line.
+      comment =
+        preprocessor->get_comment_before(pos.first_line, pos.file);
+
+      if (comment != NULL) {
+        // This is a bit of a hack, but it prevents us from picking up a same-
+        // line comment from the previous line.
+        if (comment->_line_number != pos.first_line - 1 ||
+            comment->_col_number <= pos.first_column) {
+
+          inst->_leading_comment = comment;
+        }
+      }
+    } else {
+      inst->_leading_comment = comment;
+    }
+  }
+
+  // Add the value to the enum scope (as per C++11), assuming it's not anonymous.
+  if (_scope != NULL) {
+    _scope->add_enum_value(inst);
+  }
+
+  // Now add it to the containing scope as well if it's not an "enum class".
+  if (!is_scoped() && _parent_scope != NULL) {
+    _parent_scope->add_enum_value(inst);
+  }
+
   return inst;
 }
 

+ 9 - 7
dtool/src/cppparser/cppEnumType.h

@@ -30,15 +30,16 @@ class CPPScope;
  */
 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);
+  CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
+              CPPScope *scope, const CPPFile &file);
+  CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type,
+              CPPScope *current_scope, CPPScope *scope, const CPPFile &file);
 
-  CPPType *get_element_type();
+  bool is_scoped() const;
+  CPPType *get_underlying_type();
 
-  CPPInstance *add_element(const string &name,
-                           CPPExpression *value = (CPPExpression *)NULL);
+  CPPInstance *add_element(const string &name, CPPExpression *value,
+                           CPPPreprocessor *preprocessor, const cppyyltype &pos);
 
   virtual bool is_incomplete() const;
 
@@ -54,6 +55,7 @@ public:
   virtual CPPEnumType *as_enum_type();
 
   CPPScope *_parent_scope;
+  CPPScope *_scope;
   CPPType *_element_type;
 
   typedef vector<CPPInstance *> Elements;

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

@@ -949,7 +949,7 @@ determine_type() const {
 
         case CPPDeclaration::ST_enum:
           // Convert into integral type.
-          return t1->as_enum_type()->get_element_type();
+          return t1->as_enum_type()->get_underlying_type();
 
         case CPPDeclaration::ST_simple:
           {

+ 6 - 0
dtool/src/cppparser/cppExtensionType.cxx

@@ -229,6 +229,12 @@ operator << (ostream &out, CPPExtensionType::Type type) {
   case CPPExtensionType::T_union:
     return out << "union";
 
+  case CPPExtensionType::T_enum_class:
+    return out << "enum class";
+
+  case CPPExtensionType::T_enum_struct:
+    return out << "enum struct";
+
   default:
     return out << "***invalid extension type***";
   }

+ 2 - 0
dtool/src/cppparser/cppExtensionType.h

@@ -34,6 +34,8 @@ public:
     T_class,
     T_struct,
     T_union,
+    T_enum_class,
+    T_enum_struct,
   };
 
   CPPExtensionType(Type type, CPPIdentifier *ident, CPPScope *current_scope,

+ 16 - 29
dtool/src/cppparser/cppScope.cxx

@@ -124,34 +124,9 @@ add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
  *
  */
 void CPPScope::
-add_enum_value(CPPInstance *inst, CPPPreprocessor *preprocessor,
-               const cppyyltype &pos) {
+add_enum_value(CPPInstance *inst) {
   inst->_vis = _current_vis;
 
-  if (inst->_leading_comment == (CPPCommentBlock *)NULL) {
-    // Same-line comment?
-    CPPCommentBlock *comment =
-      preprocessor->get_comment_on(pos.first_line, pos.file);
-
-    if (comment == (CPPCommentBlock *)NULL) {
-      // Nope.  Check for a comment before this line.
-      comment =
-        preprocessor->get_comment_before(pos.first_line, pos.file);
-
-      if (comment != NULL) {
-        // This is a bit of a hack, but it prevents us from picking up a same-
-        // line comment from the previous line.
-        if (comment->_line_number != pos.first_line - 1 ||
-            comment->_col_number <= pos.first_column) {
-
-          inst->_leading_comment = comment;
-        }
-      }
-    } else {
-      inst->_leading_comment = comment;
-    }
-  }
-
   string name = inst->get_simple_name();
   if (!name.empty()) {
     _enum_values[name] = inst;
@@ -183,6 +158,8 @@ define_extension_type(CPPExtensionType *type, CPPPreprocessor *error_sink) {
     break;
 
   case CPPExtensionType::T_enum:
+  case CPPExtensionType::T_enum_struct:
+  case CPPExtensionType::T_enum_class:
     _enums[name] = type;
     break;
   }
@@ -606,6 +583,11 @@ find_scope(const string &name, bool recurse) const {
     if (st != NULL) {
       return st->_scope;
     }
+
+    CPPEnumType *et = type->as_enum_type();
+    if (et != NULL) {
+      return et->_scope;
+    }
   }
 
   Using::const_iterator ui;
@@ -645,11 +627,16 @@ find_scope(const string &name, CPPDeclaration::SubstDecl &subst,
   }
 
   CPPStructType *st = type->as_struct_type();
-  if (st == NULL) {
-    return NULL;
+  if (st != NULL) {
+    return st->_scope;
   }
 
-  return st->_scope;
+  CPPEnumType *et = type->as_enum_type();
+  if (et != NULL) {
+    return et->_scope;
+  }
+
+  return NULL;
 }
 
 /**

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

@@ -61,9 +61,7 @@ public:
   virtual void add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
                                CPPPreprocessor *preprocessor,
                                const cppyyltype &pos);
-  virtual void add_enum_value(CPPInstance *inst,
-                              CPPPreprocessor *preprocessor,
-                              const cppyyltype &pos);
+  virtual void add_enum_value(CPPInstance *inst);
   virtual void define_extension_type(CPPExtensionType *type,
                                      CPPPreprocessor *error_sink = NULL);
   virtual void define_namespace(CPPNamespace *scope);

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

@@ -43,11 +43,10 @@ add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
  *
  */
 void CPPTemplateScope::
-add_enum_value(CPPInstance *inst, CPPPreprocessor *preprocessor,
-               const cppyyltype &pos) {
+add_enum_value(CPPInstance *inst) {
   inst->_template_scope = this;
   assert(_parent_scope != NULL);
-  _parent_scope->add_enum_value(inst, preprocessor, pos);
+  _parent_scope->add_enum_value(inst);
 }
 
 /**

+ 1 - 3
dtool/src/cppparser/cppTemplateScope.h

@@ -33,9 +33,7 @@ public:
   virtual void add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
                                CPPPreprocessor *preprocessor,
                                const cppyyltype &pos);
-  virtual void add_enum_value(CPPInstance *inst,
-                              CPPPreprocessor *preprocessor,
-                              const cppyyltype &pos);
+  virtual void add_enum_value(CPPInstance *inst);
   virtual void define_extension_type(CPPExtensionType *type,
                                      CPPPreprocessor *error_sink = NULL);
   virtual void define_namespace(CPPNamespace *scope);

+ 111 - 228
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -764,10 +764,6 @@ write_prototypes(ostream &out_code, ostream *out_h) {
     *out_h << "#include \"py_panda.h\"\n\n";
   }
 
-  out_code << "//********************************************************************\n";
-  out_code << "//*** prototypes for .. Global\n";
-  out_code << "//********************************************************************\n";
-
   /*
   for (fi = _functions.begin(); fi != _functions.end(); ++fi)
   {
@@ -792,9 +788,9 @@ write_prototypes(ostream &out_code, ostream *out_h) {
     }
   }
 
-  out_code << "//********************************************************************\n";
-  out_code << "//*** prototypes for .. External Objects\n";
-  out_code << "//********************************************************************\n";
+  out_code << "/**\n";
+  out_code << " * Extern declarations for imported classes\n";
+  out_code << " */\n";
 
   for (std::set<CPPType *>::iterator ii = _external_imports.begin(); ii != _external_imports.end(); ii++) {
     CPPType *type = (*ii);
@@ -897,9 +893,9 @@ write_prototypes_class_external(ostream &out, Object *obj) {
   std::string preferred_name =  obj->_itype.get_name();
 
 
-  out << "//********************************************************************\n";
-  out << "//*** prototypes for external.. " << class_name << "\n";
-  out << "//********************************************************************\n";
+  out << "/**\n";
+  out << " * Forward declaration of class " << class_name << "\n";
+  out << " */\n";
 
   // This typedef is necessary for class templates since we can't pass a comma
   // to a macro function.
@@ -915,9 +911,9 @@ write_prototypes_class(ostream &out_code, ostream *out_h, Object *obj) {
   std::string ClassName = make_safe_name(obj->_itype.get_scoped_name());
   Functions::iterator fi;
 
-  out_code << "//********************************************************************\n";
-  out_code << "//*** prototypes for .. " << ClassName << "\n";
-  out_code << "//********************************************************************\n";
+  out_code << "/**\n";
+  out_code << " * Forward declarations for top-level class " << ClassName << "\n";
+  out_code << " */\n";
 
   /*
   for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) {
@@ -943,9 +939,9 @@ write_prototypes_class(ostream &out_code, ostream *out_h, Object *obj) {
  */
 void InterfaceMakerPythonNative::
 write_functions(ostream &out) {
-  out << "//********************************************************************\n";
-  out << "//*** Functions for .. Global\n" ;
-  out << "//********************************************************************\n";
+  out << "/**\n";
+  out << " * Python wrappers for global functions\n" ;
+  out << " */\n";
   FunctionsByIndex::iterator fi;
   for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
     Function *func = (*fi).second;
@@ -994,9 +990,9 @@ write_class_details(ostream &out, Object *obj) {
   std::string ClassName = make_safe_name(obj->_itype.get_scoped_name());
   std::string cClassName = obj->_itype.get_true_name();
 
-  out << "//********************************************************************\n";
-  out << "//*** Functions for .. " << cClassName << "\n" ;
-  out << "//********************************************************************\n";
+  out << "/**\n";
+  out << " * Python wrappers for functions of class " << cClassName << "\n" ;
+  out << " */\n";
 
   // First write out all the wrapper functions for the methods.
   for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) {
@@ -1183,7 +1179,6 @@ write_sub_module(ostream &out, Object *obj) {
   // Object * obj = _objects[_embeded_index] ;
   string class_name = make_safe_name(obj->_itype.get_scoped_name());
   string class_ptr;
-  out << "  // Module init upcall for " << obj->_itype.get_scoped_name() << "\n";
 
   if (!obj->_itype.is_typedef()) {
     out << "  // " << *(obj->_itype._cpptype) << "\n";
@@ -1242,9 +1237,9 @@ write_sub_module(ostream &out, Object *obj) {
  */
 void InterfaceMakerPythonNative::
 write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
-  out << "//********************************************************************\n";
-  out << "//*** Module Object Linker ..\n";
-  out << "//********************************************************************\n";
+  out << "/**\n";
+  out << " * Module Object Linker ..\n";
+  out << " */\n";
 
   Objects::iterator oi;
 
@@ -1305,14 +1300,41 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
     if (object->_itype.is_enum() && !object->_itype.is_nested() &&
         isExportThisRun(object->_itype._cpptype)) {
       int enum_count = object->_itype.number_of_enum_values();
-      for (int xx = 0; xx < enum_count; xx++) {
-        string name1 = classNameFromCppName(object->_itype.get_enum_value_name(xx), false);
-        string name2 = classNameFromCppName(object->_itype.get_enum_value_name(xx), true);
-        string enum_value = "::" + object->_itype.get_enum_value_name(xx);
-        out << "  PyModule_AddIntConstant(module, \"" << name1 << "\", " << enum_value << ");\n";
-        if (name1 != name2) {
-          // Also write the mangled name, for historical purposes.
-          out << "  PyModule_AddIntConstant(module, \"" << name2 << "\", " << enum_value << ");\n";
+
+      if (object->_itype.is_scoped_enum()) {
+        // Convert as Python 3.4 enum.
+        CPPType *underlying_type = TypeManager::unwrap_const(object->_itype._cpptype->as_enum_type()->get_underlying_type());
+        string cast_to = underlying_type->get_local_name(&parser);
+        out << "#if PY_VERSION_HEX >= 0x03040000\n\n";
+        out << "  // enum class " << object->_itype.get_scoped_name() << "\n";
+        out << "  {\n";
+        out << "    PyObject *members = PyTuple_New(" << enum_count << ");\n";
+        out << "    PyObject *member;\n";
+        for (int xx = 0; xx < enum_count; xx++) {
+          out << "    member = PyTuple_New(2);\n"
+                 "    PyTuple_SET_ITEM(member, 0, PyUnicode_FromString(\""
+              << object->_itype.get_enum_value_name(xx) << "\"));\n"
+                 "    PyTuple_SET_ITEM(member, 1, Dtool_WrapValue(("
+              << cast_to << ")" << object->_itype.get_scoped_name() << "::"
+              << object->_itype.get_enum_value_name(xx) << "));\n"
+                 "    PyTuple_SET_ITEM(members, " << xx << ", member);\n";
+        }
+        out << "    PyModule_AddObject(module, \"" << object->_itype.get_name()
+            << "\", Dtool_EnumType_Create(\"" << object->_itype.get_name()
+            << "\", members, \"" << _def->module_name << "\"));\n";
+        out << "  }\n";
+        out << "#endif\n";
+      } else {
+        out << "  // enum " << object->_itype.get_scoped_name() << "\n";
+        for (int xx = 0; xx < enum_count; xx++) {
+          string name1 = classNameFromCppName(object->_itype.get_enum_value_name(xx), false);
+          string name2 = classNameFromCppName(object->_itype.get_enum_value_name(xx), true);
+          string enum_value = "::" + object->_itype.get_enum_value_name(xx);
+          out << "  PyModule_AddObject(module, \"" << name1 << "\", Dtool_WrapValue(" << enum_value << "));\n";
+          if (name1 != name2) {
+            // Also write the mangled name, for historical purposes.
+            out << "  PyModule_AddObject(module, \"" << name2 << "\", Dtool_WrapValue(" << enum_value << "));\n";
+          }
         }
       }
     }
@@ -1360,13 +1382,6 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
       }
     }
   }
-  out << "//********************************************************************\n";
-  out << "//*** Module Init Upcall ..  Externally Defined Class\n";
-  out << "//********************************************************************\n";
-
-// for (std::set< std::string >::iterator ii = _external_imports.begin(); ii
-// != _external_imports.end(); ii++) out << "Dtool_" <<*ii <<
-// "._Dtool_ClassInit(NULL);\n";
 
   out << "}\n\n";
 
@@ -1435,9 +1450,9 @@ write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
   InterfaceMakerPython::write_module(out, out_h, def);
   Objects::iterator oi;
 
-  out << "//********************************************************************\n";
-  out << "//*** Py Init Code For .. GlobalScope\n" ;
-  out << "//********************************************************************\n";
+  out << "/**\n";
+  out << " * Module initialization functions for Python module \"" << def->module_name << "\"\n";
+  out << " */\n";
 
   out << "#if PY_MAJOR_VERSION >= 3\n"
       << "static struct PyModuleDef python_native_module = {\n"
@@ -1452,14 +1467,16 @@ write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
       << "#ifdef _WIN32\n"
       << "extern \"C\" __declspec(dllexport) PyObject *PyInit_" << def->module_name << "();\n"
       << "#elif __GNUC__ >= 4\n"
-      << "extern \"C\" __attribute__((visibility(\"default\"))) PyInit_" << def->module_name << "();\n"
+      << "extern \"C\" __attribute__((visibility(\"default\"))) PyObject *PyInit_" << def->module_name << "();\n"
       << "#else\n"
       << "extern \"C\" PyObject *PyInit_" << def->module_name << "();\n"
       << "#endif\n"
       << "\n"
       << "PyObject *PyInit_" << def->module_name << "() {\n"
       << "  LibraryDef *refs[] = {&" << def->library_name << "_moddef, NULL};\n"
-      << "  return Dtool_PyModuleInitHelper(refs, &python_native_module);\n"
+      << "  PyObject *module = Dtool_PyModuleInitHelper(refs, &python_native_module);\n"
+      << "  Dtool_" << def->library_name << "_BuildInstants(module);\n"
+      << "  return module;\n"
       << "}\n"
       << "\n"
       << "#else  // Python 2 case\n"
@@ -1467,14 +1484,15 @@ write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
       << "#ifdef _WIN32\n"
       << "extern \"C\" __declspec(dllexport) void init" << def->module_name << "();\n"
       << "#elif __GNUC__ >= 4\n"
-      << "extern \"C\" __attribute__((visibility(\"default\"))) init" << def->module_name << "();\n"
+      << "extern \"C\" __attribute__((visibility(\"default\"))) void init" << def->module_name << "();\n"
       << "#else\n"
       << "extern \"C\" void init" << def->module_name << "();\n"
       << "#endif\n"
       << "\n"
       << "void init" << def->module_name << "() {\n"
       << "  LibraryDef *refs[] = {&" << def->library_name << "_moddef, NULL};\n"
-      << "  Dtool_PyModuleInitHelper(refs, \"" << def->module_name << "\");\n"
+      << "  PyObject *module = Dtool_PyModuleInitHelper(refs, \"" << def->module_name << "\");\n"
+      << "  Dtool_" << def->library_name << "_BuildInstants(module);\n"
       << "}\n"
       << "\n"
       << "#endif\n"
@@ -1520,9 +1538,9 @@ write_module_class(ostream &out, Object *obj) {
   }
 
   Functions::iterator fi;
-  out << "//********************************************************************\n";
-  out << "//*** Py Init Code For .. " << ClassName << " | " << export_class_name << "\n" ;
-  out << "//********************************************************************\n";
+  out << "/**\n";
+  out << " * Python method tables for " << ClassName << " (" << export_class_name << ")\n" ;
+  out << " */\n";
   out << "static PyMethodDef Dtool_Methods_" << ClassName << "[] = {\n";
 
   SlottedFunctions slots;
@@ -2449,11 +2467,7 @@ write_module_class(ostream &out, Object *obj) {
             << classNameFromCppName(ClassName, false) << "\");\n";
       }
       out << "  std::string ss = os.str();\n";
-      out << "#if PY_MAJOR_VERSION >= 3\n";
-      out << "  return PyUnicode_FromStringAndSize(ss.data(), ss.length());\n";
-      out << "#else\n";
-      out << "  return PyString_FromStringAndSize(ss.data(), ss.length());\n";
-      out << "#endif\n";
+      out << "  return Dtool_WrapValue(ss);\n";
       out << "}\n\n";
       has_local_repr = true;
     }
@@ -2479,11 +2493,7 @@ write_module_class(ostream &out, Object *obj) {
         out << "  local_this->write(os);\n";
       }
       out << "  std::string ss = os.str();\n";
-      out << "#if PY_MAJOR_VERSION >= 3\n";
-      out << "  return PyUnicode_FromStringAndSize(ss.data(), ss.length());\n";
-      out << "#else\n";
-      out << "  return PyString_FromStringAndSize(ss.data(), ss.length());\n";
-      out << "#endif\n";
+      out << "  return Dtool_WrapValue(ss);\n";
       out << "}\n\n";
       has_local_str = true;
     }
@@ -3037,7 +3047,7 @@ write_module_class(ostream &out, Object *obj) {
     } else if (nested_obj->_itype.is_typedef()) {
       ++num_dict_items;
 
-    } else if (nested_obj->_itype.is_enum()) {
+    } else if (nested_obj->_itype.is_enum() && !nested_obj->_itype.is_scoped_enum()) {
       CPPEnumType *enum_type = nested_obj->_itype._cpptype->as_enum_type();
       num_dict_items += 2 * enum_type->_elements.size();
     }
@@ -3095,8 +3105,33 @@ write_module_class(ostream &out, Object *obj) {
       // No need to support mangled names for nested typedefs; we only added
       // support recently.
 
+    } else if (nested_obj->_itype.is_scoped_enum()) {
+      // Convert enum class as Python 3.4 enum.
+      int enum_count = nested_obj->_itype.number_of_enum_values();
+      CPPType *underlying_type = TypeManager::unwrap_const(nested_obj->_itype._cpptype->as_enum_type()->get_underlying_type());
+      string cast_to = underlying_type->get_local_name(&parser);
+      out << "#if PY_VERSION_HEX >= 0x03040000\n\n";
+      out << "    // enum class " << nested_obj->_itype.get_scoped_name() << ";\n";
+      out << "    {\n";
+      out << "      PyObject *members = PyTuple_New(" << enum_count << ");\n";
+      out << "      PyObject *member;\n";
+      for (int xx = 0; xx < enum_count; xx++) {
+        out << "      member = PyTuple_New(2);\n"
+               "      PyTuple_SET_ITEM(member, 0, PyUnicode_FromString(\""
+            << nested_obj->_itype.get_enum_value_name(xx) << "\"));\n"
+               "      PyTuple_SET_ITEM(member, 1, Dtool_WrapValue(("
+            << cast_to << ")" << nested_obj->_itype.get_scoped_name() << "::"
+            << nested_obj->_itype.get_enum_value_name(xx) << "));\n"
+               "      PyTuple_SET_ITEM(members, " << xx << ", member);\n";
+      }
+      out << "      PyDict_SetItemString(dict, \"" << nested_obj->_itype.get_name()
+          << "\", Dtool_EnumType_Create(\"" << nested_obj->_itype.get_name()
+          << "\", members, \"" << _def->module_name << "\"));\n";
+      out << "    }\n";
+      out << "#endif\n";
+
     } else if (nested_obj->_itype.is_enum()) {
-      out << "    // Enum  " << nested_obj->_itype.get_scoped_name() << ";\n";
+      out << "    // enum " << nested_obj->_itype.get_scoped_name() << ";\n";
       CPPEnumType *enum_type = nested_obj->_itype._cpptype->as_enum_type();
       CPPEnumType::Elements::const_iterator ei;
       for (ei = enum_type->_elements.begin(); ei != enum_type->_elements.end(); ++ei) {
@@ -3111,9 +3146,9 @@ write_module_class(ostream &out, Object *obj) {
           name2 = name1;
         }
         string enum_value = obj->_itype.get_scoped_name() + "::" + (*ei)->get_simple_name();
-        out << "    PyDict_SetItemString(dict, \"" << name1 << "\", PyLongOrInt_FromLong(" << enum_value << "));\n";
+        out << "    PyDict_SetItemString(dict, \"" << name1 << "\", Dtool_WrapValue(" << enum_value << "));\n";
         if (name1 != name2) {
-          out << "    PyDict_SetItemString(dict, \"" << name2 << "\", PyLongOrInt_FromLong(" << enum_value << "));\n";
+          out << "    PyDict_SetItemString(dict, \"" << name2 << "\", Dtool_WrapValue(" << enum_value << "));\n";
         }
       }
     }
@@ -3340,7 +3375,7 @@ write_function_for_name(ostream &out, Object *obj,
   int max_required_args = 0;
   bool all_nonconst = true;
 
-  out << "/******************************************************************\n" << " * Python type method wrapper for\n";
+  out << "/**\n * Python function wrapper for:\n";
   for (ri = remaps.begin(); ri != remaps.end(); ++ri) {
     remap = (*ri);
     if (is_remap_legal(remap)) {
@@ -3369,7 +3404,7 @@ write_function_for_name(ostream &out, Object *obj,
     }
   }
 
-  out << " *******************************************************************/\n";
+  out << " */\n";
 
   out << function_name << " {\n";
 
@@ -6033,164 +6068,16 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
   CPPType *orig_type = return_type->get_orig_type();
   CPPType *type = return_type->get_new_type();
 
-  if (return_type->new_type_is_atomic_string()) {
-    if (TypeManager::is_char_pointer(orig_type)) {
-      indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
-      indent(out, indent_level) << "  Py_INCREF(Py_None);\n";
-      indent(out, indent_level) << "  return Py_None;\n";
-      indent(out, indent_level) << "} else {\n";
-
-      out << "#if PY_MAJOR_VERSION >= 3\n";
-      indent(out, indent_level) << "  return "
-        << "PyUnicode_FromString(" << return_expr << ");\n";
-      out << "#else\n";
-      indent(out, indent_level) << "  return "
-        << "PyString_FromString(" << return_expr << ");\n";
-      out << "#endif\n";
-
-      indent(out, indent_level) << "}\n";
-
-    } else if (TypeManager::is_wchar_pointer(orig_type)) {
-      indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
-      indent(out, indent_level) << "  Py_INCREF(Py_None);\n";
-      indent(out, indent_level) << "  return Py_None;\n";
-      indent(out, indent_level) << "} else {\n";
-      indent(out, indent_level+2)
-        << "return PyUnicode_FromWideChar("
-        << return_expr << ", wcslen(" << return_expr << "));\n";
-      indent(out, indent_level) << "}\n";
-
-    } else if (TypeManager::is_wstring(orig_type)) {
-      indent(out, indent_level)
-        << "return PyUnicode_FromWideChar("
-        << return_expr << ".data(), (int) " << return_expr << ".length());\n";
-
-    } else if (TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) {
-      indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
-      indent(out, indent_level) << "  Py_INCREF(Py_None);\n";
-      indent(out, indent_level) << "  return Py_None;\n";
-      indent(out, indent_level) << "} else {\n";
-
-      indent(out, indent_level) << "  return "
-        << "PyUnicode_FromWideChar("
-        << return_expr << "->data(), (int) " << return_expr << "->length());\n";
-
-      indent(out, indent_level) << "}\n";
-
-    } else if (TypeManager::is_const_ptr_to_basic_string_char(orig_type)) {
-      indent(out, indent_level) << "if (" << return_expr<< " == NULL) {\n";
-      indent(out, indent_level) << "  Py_INCREF(Py_None);\n";
-      indent(out, indent_level) << "  return Py_None;\n";
-      indent(out, indent_level) << "} else {\n";
-
-      out << "#if PY_MAJOR_VERSION >= 3\n";
-      indent(out, indent_level) << "  return "
-        << "PyUnicode_FromStringAndSize("
-        << return_expr << "->data(), (Py_ssize_t)" << return_expr << "->length());\n";
-      out << "#else\n";
-      indent(out, indent_level) << "  return "
-        << "PyString_FromStringAndSize("
-        << return_expr << "->data(), (Py_ssize_t)" << return_expr << "->length());\n";
-      out << "#endif\n";
-
-      indent(out, indent_level) << "}\n";
-
-    } else {
-      out << "#if PY_MAJOR_VERSION >= 3\n";
-      indent(out, indent_level)
-        << "return PyUnicode_FromStringAndSize("
-        << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n";
-      out << "#else\n";
-      indent(out, indent_level)
-        << "return PyString_FromStringAndSize("
-        << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n";
-      out << "#endif\n";
-    }
-
-  } else if (TypeManager::is_bool(type)) {
-    indent(out, indent_level)
-      << "return PyBool_FromLong(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_ssize(type)) {
-    indent(out, indent_level)
-      << "return PyLongOrInt_FromSsize_t(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_size(type)) {
+  if (return_type->new_type_is_atomic_string() ||
+      TypeManager::is_simple(type) ||
+      TypeManager::is_char_pointer(type) ||
+      TypeManager::is_wchar_pointer(type) ||
+      TypeManager::is_pointer_to_PyObject(type) ||
+      TypeManager::is_pointer_to_Py_buffer(type)) {
+    // Most types are now handled by the many overloads of Dtool_WrapValue,
+    // defined in py_panda.h.
     indent(out, indent_level)
-      << "return PyLongOrInt_FromSize_t(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_char(type)) {
-    out << "#if PY_MAJOR_VERSION >= 3\n";
-    indent(out, indent_level)
-      << "return PyUnicode_FromStringAndSize(&" << return_expr << ", 1);\n";
-    out << "#else\n";
-    indent(out, indent_level)
-      << "return PyString_FromStringAndSize(&" << return_expr << ", 1);\n";
-    out << "#endif\n";
-
-  } else if (TypeManager::is_wchar(type)) {
-    indent(out, indent_level)
-      << "return PyUnicode_FromWideChar(&" << return_expr << ", 1);\n";
-
-  } else if (TypeManager::is_unsigned_longlong(type)) {
-    indent(out, indent_level)
-      << "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_longlong(type)) {
-    indent(out, indent_level)
-      << "return PyLong_FromLongLong(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_unsigned_integer(type)){
-    indent(out, indent_level)
-      << "return PyLongOrInt_FromUnsignedLong(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_integer(type)) {
-    indent(out, indent_level)
-      << "return PyLongOrInt_FromLong(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_float(type)) {
-    indent(out, indent_level)
-      << "return PyFloat_FromDouble(" << return_expr << ");\n";
-
-  } else if (TypeManager::is_char_pointer(type)) {
-    indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
-    indent(out, indent_level) << "  Py_INCREF(Py_None);\n";
-    indent(out, indent_level) << "  return Py_None;\n";
-    indent(out, indent_level) << "} else {\n";
-
-    out << "#if PY_MAJOR_VERSION >= 3\n";
-    indent(out, indent_level) << "  return "
-      << "PyUnicode_FromString(" << return_expr << ");\n";
-    out << "#else\n";
-    indent(out, indent_level) << "  return "
-      << "PyString_FromString(" << return_expr << ");\n";
-    out << "#endif\n";
-
-    indent(out, indent_level) << "}\n";
-
-  } else if (TypeManager::is_wchar_pointer(type)) {
-    indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
-    indent(out, indent_level) << "  Py_INCREF(Py_None);\n";
-    indent(out, indent_level) << "  return Py_None;\n";
-    indent(out, indent_level) << "} else {\n";
-    indent(out, indent_level) << "  return "
-      << "PyUnicode_FromWideChar("
-      << return_expr << ", wcslen(" << return_expr << "));\n";
-
-    indent(out, indent_level) << "}\n";
-
-  } else if (TypeManager::is_pointer_to_PyObject(type)) {
-    indent(out, indent_level)
-      << "return " << return_expr << ";\n";
-
-  } else if (TypeManager::is_pointer_to_Py_buffer(type)) {
-    indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
-    indent(out, indent_level) << "  Py_INCREF(Py_None);\n";
-    indent(out, indent_level) << "  return Py_None;\n";
-    indent(out, indent_level) << "} else {\n";
-    indent(out, indent_level) << "  return "
-      << "PyMemoryView_FromBuffer(" << return_expr << ");\n";
-    indent(out, indent_level) << "}\n";
+      << "return Dtool_WrapValue(" << return_expr << ");\n";
 
   } else if (TypeManager::is_pointer(type)) {
     bool is_const = TypeManager::is_const_pointer_to_anything(type);
@@ -6234,13 +6121,13 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
 
     } else {
       indent(out, indent_level) << "Should Never Reach This InterfaceMakerPythonNative::pack_python_value";
-          // << "return PyLongOrInt_FromLong((int) " << return_expr << ");\n";
+          // << "return Dtool_Integer((int) " << return_expr << ");\n";
     }
 
   } else {
     // Return None.
     indent(out, indent_level)
-      << "return Py_BuildValue(\"\");\n";
+      << "return Py_BuildValue(\"\"); // Don't know how to wrap type.\n";
   }
 }
 
@@ -6288,11 +6175,7 @@ write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
     "  PyObject *tuple = PyTuple_New(count);\n"
     "\n"
     "  for (Py_ssize_t i = 0; i < count; ++i) {\n"
-    "#if PY_MAJOR_VERSION >= 3\n"
-    "    PyObject *index = PyLong_FromSsize_t(i);\n"
-    "#else\n"
-    "    PyObject *index = PyInt_FromSsize_t(i);\n"
-    "#endif\n";
+    "    PyObject *index = Dtool_WrapValue(i);\n";
 
   switch (elem_getter->_args_type) {
   case AT_keyword_args:

+ 6 - 0
dtool/src/interrogate/interrogateBuilder.cxx

@@ -2838,6 +2838,10 @@ define_enum_type(InterrogateType &itype, CPPEnumType *cpptype) {
     return;
   }
 
+  if (cpptype->is_scoped()) {
+    itype._flags |= InterrogateType::F_scoped_enum;
+  }
+
   int next_value = 0;
 
   CPPEnumType::Elements::const_iterator ei;
@@ -2919,6 +2923,8 @@ define_extension_type(InterrogateType &itype, CPPExtensionType *cpptype) {
   // But we can at least indicate which of the various extension types it is.
   switch (cpptype->_type) {
   case CPPExtensionType::T_enum:
+  case CPPExtensionType::T_enum_class:
+  case CPPExtensionType::T_enum_struct:
     itype._flags |= InterrogateType::F_enum;
     break;
 

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

@@ -205,6 +205,14 @@ is_enum() const {
   return (_flags & F_enum) != 0;
 }
 
+/**
+ * Returns true if enum values are only available under a scope.
+ */
+INLINE bool InterrogateType::
+is_scoped_enum() const {
+  return (_flags & F_scoped_enum) != 0;
+}
+
 /**
  *
  */

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

@@ -65,6 +65,7 @@ public:
   INLINE int get_array_size() const;
 
   INLINE bool is_enum() const;
+  INLINE bool is_scoped_enum() const;
   INLINE int number_of_enum_values() const;
   INLINE const string &get_enum_value_name(int n) const;
   INLINE const string &get_enum_value_scoped_name(int n) const;
@@ -136,6 +137,7 @@ private:
     F_unpublished          = 0x100000,
     F_typedef              = 0x200000,
     F_array                = 0x400000,
+    F_scoped_enum          = 0x800000,
   };
 
 public:

+ 203 - 0
dtool/src/interrogatedb/py_panda.I

@@ -0,0 +1,203 @@
+/**
+ * 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."
+ *
+ * @file py_panda.I
+ * @author rdb
+ * @date 2016-06-06
+ */
+
+/**
+ * Template function that can be used to extract any TypedObject pointer from
+ * a wrapped Python object.
+ */
+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;
+}
+
+/**
+ * These functions wrap a pointer for a class that defines get_type_handle().
+ */
+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());
+}
+
+/**
+ * The following functions wrap an arbitrary C++ value into a PyObject.
+ */
+ALWAYS_INLINE PyObject *Dtool_WrapValue(int value) {
+#if PY_MAJOR_VERSION >= 3
+  return PyLong_FromLong((long)value);
+#else
+  return PyInt_FromLong((long)value);
+#endif
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned int value) {
+#if PY_MAJOR_VERSION >= 3 && SIZEOF_INT < SIZEOF_LONG
+  return PyLong_FromLong((long)value);
+#elif PY_MAJOR_VERSION >= 3
+  return PyLong_FromUnsignedLong((unsigned long)value);
+#elif SIZEOF_INT < SIZEOF_LONG
+  return PyInt_FromLong((long)value);
+#else
+  return (value > LONG_MAX)
+    ? PyLong_FromUnsignedLong((unsigned long)value)
+    : PyInt_FromLong((long)value);
+#endif
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(long value) {
+#if PY_MAJOR_VERSION >= 3
+  return PyLong_FromLong(value);
+#else
+  return PyInt_FromLong(value);
+#endif
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long value) {
+#if PY_MAJOR_VERSION >= 3
+  return PyLong_FromUnsignedLong(value);
+#else
+  return (value > LONG_MAX)
+    ? PyLong_FromUnsignedLong(value)
+    : PyInt_FromLong((long)value);
+#endif
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(long long value) {
+  return PyLong_FromLongLong(value);
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long long value) {
+  return PyLong_FromUnsignedLongLong(value);
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(bool value) {
+  PyObject *result = (value ? Py_True : Py_False);
+  Py_INCREF(result);
+  return result;
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(double value) {
+  return PyFloat_FromDouble(value);
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const char *value) {
+  if (value == (const char *)NULL) {
+    Py_INCREF(Py_None);
+    return Py_None;
+  } else {
+#if PY_MAJOR_VERSION >= 3
+    return PyUnicode_FromString(value);
+#else
+    return PyString_FromString(value);
+#endif
+  }
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const wchar_t *value) {
+  if (value == (const wchar_t *)NULL) {
+    Py_INCREF(Py_None);
+    return Py_None;
+  } else {
+    return PyUnicode_FromWideChar(value, (Py_ssize_t)wcslen(value));
+  }
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string &value) {
+#if PY_MAJOR_VERSION >= 3
+  return PyUnicode_FromStringAndSize(value.data(), (Py_ssize_t)value.length());
+#else
+  return PyString_FromStringAndSize(value.data(), (Py_ssize_t)value.length());
+#endif
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring &value) {
+  return PyUnicode_FromWideChar(value.data(), (Py_ssize_t)value.length());
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string *value) {
+  if (value == (const std::string *)NULL) {
+    Py_INCREF(Py_None);
+    return Py_None;
+  } else {
+#if PY_MAJOR_VERSION >= 3
+    return PyUnicode_FromStringAndSize(value->data(), (Py_ssize_t)value->length());
+#else
+    return PyString_FromStringAndSize(value->data(), (Py_ssize_t)value->length());
+#endif
+  }
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring *value) {
+  if (value == (const std::wstring *)NULL) {
+    Py_INCREF(Py_None);
+    return Py_None;
+  } else {
+    return PyUnicode_FromWideChar(value->data(), (Py_ssize_t)value->length());
+  }
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(char value) {
+#if PY_MAJOR_VERSION >= 3
+  return PyUnicode_FromStringAndSize(&value, 1);
+#else
+  return PyString_FromStringAndSize(&value, 1);
+#endif
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(wchar_t value) {
+  return PyUnicode_FromWideChar(&value, 1);
+}
+
+ALWAYS_INLINE PyObject *Dtool_WrapValue(PyObject *value) {
+  return value;
+}
+
+#if PY_MAJOR_VERSION >= 0x02060000
+ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value) {
+  if (value == (Py_buffer *)NULL) {
+    return value;
+  } else {
+    return PyMemoryView_FromBuffer(value);
+  }
+}
+#endif

+ 27 - 15
dtool/src/interrogatedb/py_panda.cxx

@@ -335,6 +335,33 @@ PyObject *_Dtool_Return(PyObject *value) {
   return value;
 }
 
+/**
+ * Creates a Python 3.4-style enum type.  Steals reference to 'names'.
+ */
+PyObject *Dtool_EnumType_Create(const char *name, PyObject *names, const char *module) {
+  static PyObject *enum_class = NULL;
+  static PyObject *enum_meta = NULL;
+  static PyObject *enum_create = NULL;
+  if (enum_meta == NULL) {
+    PyObject *enum_module = PyImport_ImportModule("enum");
+    nassertr_always(enum_module != NULL, NULL);
+
+    enum_class = PyObject_GetAttrString(enum_module, "Enum");
+    enum_meta = PyObject_GetAttrString(enum_module, "EnumMeta");
+    enum_create = PyObject_GetAttrString(enum_meta, "_create_");
+    nassertr(enum_meta != NULL, NULL);
+  }
+
+  PyObject *result = PyObject_CallFunction(enum_create, (char *)"OsN", enum_class, name, names);
+  nassertr(result != NULL, NULL);
+  if (module != NULL) {
+    PyObject *modstr = PyUnicode_FromString(module);
+    PyObject_SetAttrString(result, "__module__", modstr);
+    Py_DECREF(modstr);
+  }
+  return result;
+}
+
 /**
 
  */
@@ -833,19 +860,4 @@ PyObject *map_deepcopy_to_copy(PyObject *self, PyObject *args) {
   return PyObject_CallMethod(self, (char *)"__copy__", (char *)"()");
 }
 
-/**
- * Similar to PyLong_FromUnsignedLong(), but returns either a regular integer
- * or a long integer, according to whether the indicated value will fit.
- */
-#if PY_MAJOR_VERSION < 3
-EXPCL_INTERROGATEDB PyObject *
-PyLongOrInt_FromUnsignedLong(unsigned long value) {
-  if ((long)value < 0) {
-    return PyLong_FromUnsignedLong(value);
-  } else {
-    return PyInt_FromLong((long)value);
-  }
-}
-#endif
-
 #endif  // HAVE_PYTHON

+ 39 - 49
dtool/src/interrogatedb/py_panda.h

@@ -103,10 +103,6 @@ inline PyObject* doPy_RETURN_FALSE()
 #define nb_inplace_divide nb_inplace_true_divide
 
 #define PyLongOrInt_Check(x) PyLong_Check(x)
-#define PyLongOrInt_FromSize_t PyLong_FromSize_t
-#define PyLongOrInt_FromSsize_t PyLong_FromSsize_t
-#define PyLongOrInt_FromLong PyLong_FromLong
-#define PyLongOrInt_FromUnsignedLong PyLong_FromUnsignedLong
 #define PyLongOrInt_AS_LONG PyLong_AS_LONG
 #define PyInt_Check PyLong_Check
 #define PyInt_AsLong PyLong_AsLong
@@ -114,9 +110,6 @@ inline PyObject* doPy_RETURN_FALSE()
 #else
 #define PyLongOrInt_Check(x) (PyInt_Check(x) || PyLong_Check(x))
 // PyInt_FromSize_t automatically picks the right type.
-#define PyLongOrInt_FromSize_t PyInt_FromSize_t
-#define PyLongOrInt_FromSsize_t PyInt_FromSsize_t
-#define PyLongOrInt_FromLong PyInt_FromLong
 #define PyLongOrInt_AS_LONG PyInt_AsLong
 
 // For more portably defining hash functions.
@@ -159,9 +152,6 @@ typedef void *(*DowncastFunction)(void *, Dtool_PyTypedObject *);
 typedef void *(*CoerceFunction)(PyObject *, void *);
 typedef void (*ModuleClassInitFunction)(PyObject *module);
 
-// inline          Dtool_PyTypedObject *  Dtool_RuntimeTypeDtoolType(int
-// type); 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....
 struct Dtool_PyInstDef {
   PyObject_HEAD
@@ -300,17 +290,7 @@ EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyT
 EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
                                                               void **answer, const char *method_name);
 
-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;
-}
+template<class T> INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into);
 
 // Functions related to error reporting.
 EXPCL_INTERROGATEDB bool _Dtool_CheckErrorOccurred();
@@ -348,6 +328,12 @@ EXPCL_INTERROGATEDB PyObject *_Dtool_Return(PyObject *value);
 #define Dtool_Return(value) _Dtool_Return(value)
 #endif
 
+/**
+ * Wrapper around Python 3.4's enum library, which does not have a C API.
+ */
+EXPCL_INTERROGATEDB PyObject *Dtool_EnumType_Create(const char *name, PyObject *names,
+                                                    const char *module = NULL);
+
 /**
 
  */
@@ -359,29 +345,10 @@ EXPCL_INTERROGATEDB PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyT
 
 // 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());
-}
+template<class T> INLINE PyObject *DTool_CreatePyInstance(const T *obj, bool memory_rules);
+template<class T> INLINE PyObject *DTool_CreatePyInstance(T *obj, bool memory_rules);
+template<class T> INLINE PyObject *DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules);
+template<class T> INLINE PyObject *DTool_CreatePyInstanceTyped(T *obj, bool memory_rules);
 
 // Macro(s) class definition .. Used to allocate storage and init some values
 // for a Dtool Py Type object.
@@ -474,11 +441,32 @@ copy_from_copy_constructor(PyObject *self, PyObject *noargs);
 EXPCL_INTERROGATEDB 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_INTERROGATEDB PyObject *
-PyLongOrInt_FromUnsignedLong(unsigned long value);
+/**
+ * These functions convert a C++ value into the corresponding Python object.
+ * This used to be generated by the code generator, but it seems more reliable
+ * and maintainable to define these as overloads and have the compiler sort
+ * it out.
+ */
+ALWAYS_INLINE PyObject *Dtool_WrapValue(int value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned int value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(long value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(long long value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long long value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(bool value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(double value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const char *value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const wchar_t *value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string &value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring &value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string *value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring *value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(char value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(wchar_t value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(PyObject *value);
+
+#if PY_MAJOR_VERSION >= 0x02060000
+ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value);
 #endif
 
 EXPCL_INTERROGATEDB extern struct Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE;
@@ -486,6 +474,8 @@ EXPCL_INTERROGATEDB extern void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObjec
 
 #define Dtool_Ptr_DTOOL_SUPER_BASE (&Dtool_DTOOL_SUPER_BASE)
 
+#include "py_panda.I"
+
 #endif  // HAVE_PYTHON && !CPPPARSER
 
 #endif // PY_PANDA_H_

+ 1 - 8
panda/src/express/globPattern_ext.cxx

@@ -25,14 +25,7 @@ match_files(const Filename &cwd) const {
 
   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);
+    PyList_SET_ITEM(result, i, Dtool_WrapValue(contents[i]));
   }
 
   return result;

+ 1 - 13
panda/src/linmath/lpoint2_ext_src.I

@@ -11,16 +11,6 @@
  * @date 2011-01-02
  */
 
-#ifdef FLOATTYPE_IS_INT
-#if PY_MAJOR_VERSION >= 3
-#define PY_FROM_FLOATTYPE PyLong_FromLong
-#else
-#define PY_FROM_FLOATTYPE PyInt_FromLong
-#endif
-#else
-#define PY_FROM_FLOATTYPE PyFloat_FromDouble
-#endif
-
 /**
  *
  */
@@ -53,7 +43,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
+      return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2);
@@ -89,5 +79,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase2.
   return invoke_extension<FLOATNAME(LVecBase2)>(_this).__setattr__(self, attr_name, assign);
 }
-
-#undef PY_FROM_FLOATTYPE

+ 1 - 13
panda/src/linmath/lpoint3_ext_src.I

@@ -11,16 +11,6 @@
  * @date 2011-01-02
  */
 
-#ifdef FLOATTYPE_IS_INT
-#if PY_MAJOR_VERSION >= 3
-#define PY_FROM_FLOATTYPE PyLong_FromLong
-#else
-#define PY_FROM_FLOATTYPE PyInt_FromLong
-#endif
-#else
-#define PY_FROM_FLOATTYPE PyFloat_FromDouble
-#endif
-
 /**
  *
  */
@@ -54,7 +44,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
+      return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2);
@@ -90,5 +80,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase2.
   return invoke_extension<FLOATNAME(LVecBase3)>(_this).__setattr__(self, attr_name, assign);
 }
-
-#undef PY_FROM_FLOATTYPE

+ 2 - 14
panda/src/linmath/lpoint4_ext_src.I

@@ -11,16 +11,6 @@
  * @date 2011-01-02
  */
 
-#ifdef FLOATTYPE_IS_INT
-#if PY_MAJOR_VERSION >= 3
-#define PY_FROM_FLOATTYPE PyLong_FromLong
-#else
-#define PY_FROM_FLOATTYPE PyInt_FromLong
-#endif
-#else
-#define PY_FROM_FLOATTYPE PyFloat_FromDouble
-#endif
-
 /**
  *
  */
@@ -56,9 +46,9 @@ __getattr__(PyObject *self, const string &attr_name) const {
   switch (attr_name.size()) {
     case 1:
       if (attr_name[0] == 'w') {
-        return PY_FROM_FLOATTYPE(_this->_v(3));
+        return Dtool_WrapValue(_this->_v(3));
       } else {
-        return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
+        return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
       }
 
     case 2: {
@@ -95,5 +85,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase4.
   return invoke_extension<FLOATNAME(LVecBase4)>(_this).__setattr__(self, attr_name, assign);
 }
-
-#undef PY_FROM_FLOATTYPE

+ 1 - 5
panda/src/linmath/lvecBase2_ext_src.I

@@ -14,16 +14,13 @@
 #ifdef FLOATTYPE_IS_INT
 #if PY_MAJOR_VERSION >= 3
 #define PYNUMBER_FLOATTYPE PyNumber_Long
-#define PY_FROM_FLOATTYPE PyLong_FromLong
 #define PY_AS_FLOATTYPE PyLong_AS_LONG
 #else
 #define PYNUMBER_FLOATTYPE PyNumber_Int
-#define PY_FROM_FLOATTYPE PyInt_FromLong
 #define PY_AS_FLOATTYPE PyInt_AS_LONG
 #endif
 #else
 #define PYNUMBER_FLOATTYPE PyNumber_Float
-#define PY_FROM_FLOATTYPE PyFloat_FromDouble
 #define PY_AS_FLOATTYPE (FLOATTYPE)PyFloat_AsDouble
 #endif
 
@@ -88,7 +85,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
+      return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2);
@@ -222,5 +219,4 @@ __ipow__(PyObject *self, FLOATTYPE exponent) {
 }
 
 #undef PYNUMBER_FLOATTYPE
-#undef PY_FROM_FLOATTYPE
 #undef PY_AS_FLOATTYPE

+ 1 - 5
panda/src/linmath/lvecBase3_ext_src.I

@@ -14,16 +14,13 @@
 #ifdef FLOATTYPE_IS_INT
 #if PY_MAJOR_VERSION >= 3
 #define PYNUMBER_FLOATTYPE PyNumber_Long
-#define PY_FROM_FLOATTYPE PyLong_FromLong
 #define PY_AS_FLOATTYPE PyLong_AS_LONG
 #else
 #define PYNUMBER_FLOATTYPE PyNumber_Int
-#define PY_FROM_FLOATTYPE PyInt_FromLong
 #define PY_AS_FLOATTYPE PyInt_AS_LONG
 #endif
 #else
 #define PYNUMBER_FLOATTYPE PyNumber_Float
-#define PY_FROM_FLOATTYPE PyFloat_FromDouble
 #define PY_AS_FLOATTYPE (FLOATTYPE)PyFloat_AsDouble
 #endif
 
@@ -89,7 +86,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
+      return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2);
@@ -225,5 +222,4 @@ __ipow__(PyObject *self, FLOATTYPE exponent) {
 }
 
 #undef PYNUMBER_FLOATTYPE
-#undef PY_FROM_FLOATTYPE
 #undef PY_AS_FLOATTYPE

+ 2 - 6
panda/src/linmath/lvecBase4_ext_src.I

@@ -14,16 +14,13 @@
 #ifdef FLOATTYPE_IS_INT
 #if PY_MAJOR_VERSION >= 3
 #define PYNUMBER_FLOATTYPE PyNumber_Long
-#define PY_FROM_FLOATTYPE PyLong_FromLong
 #define PY_AS_FLOATTYPE PyLong_AS_LONG
 #else
 #define PYNUMBER_FLOATTYPE PyNumber_Int
-#define PY_FROM_FLOATTYPE PyInt_FromLong
 #define PY_AS_FLOATTYPE PyInt_AS_LONG
 #endif
 #else
 #define PYNUMBER_FLOATTYPE PyNumber_Float
-#define PY_FROM_FLOATTYPE PyFloat_FromDouble
 #define PY_AS_FLOATTYPE (FLOATTYPE)PyFloat_AsDouble
 #endif
 
@@ -91,9 +88,9 @@ __getattr__(PyObject *self, const string &attr_name) const {
   switch (attr_name.size()) {
     case 1:
       if (attr_name[0] == 'w') {
-        return PY_FROM_FLOATTYPE(_this->_v(3));
+        return Dtool_WrapValue(_this->_v(3));
       } else {
-        return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
+        return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
       }
 
     case 2: {
@@ -233,5 +230,4 @@ __ipow__(PyObject *self, FLOATTYPE exponent) {
 }
 
 #undef PYNUMBER_FLOATTYPE
-#undef PY_FROM_FLOATTYPE
 #undef PY_AS_FLOATTYPE

+ 1 - 13
panda/src/linmath/lvector2_ext_src.I

@@ -11,16 +11,6 @@
  * @date 2011-01-02
  */
 
-#ifdef FLOATTYPE_IS_INT
-#if PY_MAJOR_VERSION >= 3
-#define PY_FROM_FLOATTYPE PyLong_FromLong
-#else
-#define PY_FROM_FLOATTYPE PyInt_FromLong
-#endif
-#else
-#define PY_FROM_FLOATTYPE PyFloat_FromDouble
-#endif
-
 /**
  *
  */
@@ -53,7 +43,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
+      return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2);
@@ -89,5 +79,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase2.
   return invoke_extension<FLOATNAME(LVecBase2)>(_this).__setattr__(self, attr_name, assign);
 }
-
-#undef PY_FROM_FLOATTYPE

+ 1 - 13
panda/src/linmath/lvector3_ext_src.I

@@ -11,16 +11,6 @@
  * @date 2011-01-02
  */
 
-#ifdef FLOATTYPE_IS_INT
-#if PY_MAJOR_VERSION >= 3
-#define PY_FROM_FLOATTYPE PyLong_FromLong
-#else
-#define PY_FROM_FLOATTYPE PyInt_FromLong
-#endif
-#else
-#define PY_FROM_FLOATTYPE PyFloat_FromDouble
-#endif
-
 /**
  *
  */
@@ -54,7 +44,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
 
   switch (attr_name.size()) {
     case 1:
-      return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
+      return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
 
     case 2: {
       FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2);
@@ -90,5 +80,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase3.
   return invoke_extension<FLOATNAME(LVecBase3)>(_this).__setattr__(self, attr_name, assign);
 }
-
-#undef PY_FROM_FLOATTYPE

+ 2 - 14
panda/src/linmath/lvector4_ext_src.I

@@ -11,16 +11,6 @@
  * @date 2011-01-02
  */
 
-#ifdef FLOATTYPE_IS_INT
-#if PY_MAJOR_VERSION >= 3
-#define PY_FROM_FLOATTYPE PyLong_FromLong
-#else
-#define PY_FROM_FLOATTYPE PyInt_FromLong
-#endif
-#else
-#define PY_FROM_FLOATTYPE PyFloat_FromDouble
-#endif
-
 /**
  *
  */
@@ -56,9 +46,9 @@ __getattr__(PyObject *self, const string &attr_name) const {
   switch (attr_name.size()) {
     case 1:
       if (attr_name[0] == 'w') {
-        return PY_FROM_FLOATTYPE(_this->_v(3));
+        return Dtool_WrapValue(_this->_v(3));
       } else {
-        return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
+        return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
       }
 
     case 2: {
@@ -95,5 +85,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
   // Upcall to LVecBase4.
   return invoke_extension<FLOATNAME(LVecBase4)>(_this).__setattr__(self, attr_name, assign);
 }
-
-#undef PY_FROM_FLOATTYPE

+ 4 - 16
panda/src/pgraph/pandaNode_ext.cxx

@@ -187,15 +187,9 @@ get_tag_keys() const {
   vector_string keys;
   _this->get_tag_keys(keys);
 
-  PyObject *result = PyList_New(keys.size());
+  PyObject *result = PyTuple_New(keys.size());
   for (size_t i = 0; i < keys.size(); ++i) {
-    const string &tag_name = keys[i];
-#if PY_MAJOR_VERSION >= 3
-    PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
-#else
-    PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
-#endif
-    PyList_SET_ITEM(result, i, str);
+    PyTuple_SET_ITEM(result, i, Dtool_WrapValue(keys[i]));
   }
 
   return result;
@@ -209,15 +203,9 @@ get_python_tag_keys() const {
   vector_string keys;
   get_python_tag_keys(keys);
 
-  PyObject *result = PyList_New(keys.size());
+  PyObject *result = PyTuple_New(keys.size());
   for (size_t i = 0; i < keys.size(); ++i) {
-    const string &tag_name = keys[i];
-#if PY_MAJOR_VERSION >= 3
-    PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
-#else
-    PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
-#endif
-    PyList_SET_ITEM(result, i, str);
+    PyTuple_SET_ITEM(result, i, Dtool_WrapValue(keys[i]));
   }
 
   return result;

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