Merge branch 'interrogate-overhaul'
Conflicts: panda/src/gobj/texture.h panda/src/pnmimage/pnmImage.h
This commit is contained in:
commit
0570d9536e
|
|
@ -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"
|
||||
|
|
@ -241,7 +241,8 @@ pop_struct() {
|
|||
%token KW_BOOL
|
||||
%token KW_CATCH
|
||||
%token KW_CHAR
|
||||
%token KW_WCHAR_T
|
||||
%token KW_CHAR16_T
|
||||
%token KW_CHAR32_T
|
||||
%token KW_CLASS
|
||||
%token KW_CONST
|
||||
%token KW_DELETE
|
||||
|
|
@ -294,6 +295,7 @@ pop_struct() {
|
|||
%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
|
||||
|
|
@ -325,8 +327,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
|
||||
|
|
@ -334,6 +335,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
|
||||
|
|
@ -353,7 +355,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 '{' ',' ';'
|
||||
|
||||
|
|
@ -717,7 +719,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -726,19 +729,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);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -746,20 +745,16 @@ 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);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -1585,11 +1580,7 @@ type:
|
|||
{
|
||||
$$ = CPPType::new_type($1);
|
||||
}
|
||||
| anonymous_enum
|
||||
{
|
||||
$$ = CPPType::new_type($1);
|
||||
}
|
||||
| named_enum
|
||||
| enum
|
||||
{
|
||||
$$ = CPPType::new_type($1);
|
||||
}
|
||||
|
|
@ -1609,7 +1600,7 @@ 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) {
|
||||
|
|
@ -1649,11 +1640,7 @@ type_decl:
|
|||
{
|
||||
$$ = new CPPTypeDeclaration(CPPType::new_type($1));
|
||||
}
|
||||
| anonymous_enum
|
||||
{
|
||||
$$ = new CPPTypeDeclaration(CPPType::new_type($1));
|
||||
}
|
||||
| named_enum
|
||||
| enum
|
||||
{
|
||||
$$ = new CPPTypeDeclaration(CPPType::new_type($1));
|
||||
}
|
||||
|
|
@ -1673,7 +1660,7 @@ 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) {
|
||||
|
|
@ -1858,27 +1845,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);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -1994,6 +1995,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
|
||||
{
|
||||
|
|
@ -2132,7 +2141,8 @@ element:
|
|||
| 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
|
||||
|
|
@ -2369,6 +2379,18 @@ const_expr:
|
|||
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 ')'
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -399,3 +399,24 @@ is_less(const CPPDeclaration *other) const {
|
|||
return this < other;
|
||||
}
|
||||
|
||||
|
||||
ostream &
|
||||
operator << (ostream &out, const CPPDeclaration::SubstDecl &subst) {
|
||||
CPPDeclaration::SubstDecl::const_iterator it;
|
||||
for (it = subst.begin(); it != subst.end(); ++it) {
|
||||
out << " ";
|
||||
if (it->first == NULL) {
|
||||
out << "(null)";
|
||||
} else {
|
||||
out << *(it->first);
|
||||
}
|
||||
out << " -> ";
|
||||
if (it->second == NULL) {
|
||||
out << "(null)";
|
||||
} else {
|
||||
out << *(it->second);
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
@ -157,4 +157,7 @@ operator << (ostream &out, const CPPDeclaration &decl) {
|
|||
return out;
|
||||
}
|
||||
|
||||
ostream &
|
||||
operator << (ostream &out, const CPPDeclaration::SubstDecl &decl);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "cppEnumType.h"
|
||||
#include "cppTypedef.h"
|
||||
#include "cppTypedefType.h"
|
||||
#include "cppExpression.h"
|
||||
#include "cppSimpleType.h"
|
||||
#include "cppConstType.h"
|
||||
|
|
@ -24,14 +24,37 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// 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)
|
||||
{
|
||||
if (ident != NULL) {
|
||||
ident->_native_scope = current_scope;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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)
|
||||
{
|
||||
if (ident != NULL) {
|
||||
ident->_native_scope = current_scope;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -41,12 +64,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 +116,38 @@ 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
|
||||
|
|
@ -95,12 +162,34 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
|
|||
}
|
||||
|
||||
CPPEnumType *rep = new CPPEnumType(*this);
|
||||
|
||||
if (_ident != NULL) {
|
||||
rep->_ident =
|
||||
_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]) {
|
||||
rep->_elements[i] = elem_rep;
|
||||
any_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rep->_ident == _ident &&
|
||||
rep->_element_type == _element_type &&
|
||||
!any_changed) {
|
||||
delete rep;
|
||||
rep = this;
|
||||
}
|
||||
|
|
@ -124,15 +213,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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -147,6 +147,30 @@ as_pointer() const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::Result::as_boolean
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CPPExpression::Result::
|
||||
as_boolean() const {
|
||||
switch (_type) {
|
||||
case RT_integer:
|
||||
return (_u._integer != 0);
|
||||
|
||||
case RT_real:
|
||||
return (_u._real != 0.0);
|
||||
|
||||
case RT_pointer:
|
||||
return (_u._pointer != NULL);
|
||||
|
||||
default:
|
||||
cerr << "Invalid type\n";
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::Result::output
|
||||
// Access: Public
|
||||
|
|
@ -226,7 +250,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 +269,7 @@ CPPExpression(CPPIdentifier *ident, CPPScope *current_scope,
|
|||
|
||||
_type = T_unknown_ident;
|
||||
_u._ident = ident;
|
||||
_u._ident->_native_scope = current_scope;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -801,6 +826,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 +912,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 +922,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 +1032,9 @@ is_tbd() const {
|
|||
|
||||
return true;
|
||||
|
||||
case T_unknown_ident:
|
||||
return true;
|
||||
|
||||
case T_typecast:
|
||||
case T_construct:
|
||||
case T_new:
|
||||
|
|
@ -996,8 +1122,12 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
|||
break;
|
||||
|
||||
case T_variable:
|
||||
// We can just refer to the variable by name, except if it's a
|
||||
// private constant, in which case we have to compute the value,
|
||||
// since we may have to use it in generated code.
|
||||
if (_u._variable->_type != NULL &&
|
||||
_u._variable->_initializer != NULL) {
|
||||
_u._variable->_initializer != NULL &&
|
||||
_u._variable->_vis > V_public) {
|
||||
// A const variable. Fetch its assigned value.
|
||||
CPPConstType *const_type = _u._variable->_type->as_const_type();
|
||||
if (const_type != NULL) {
|
||||
|
|
@ -1434,4 +1564,3 @@ is_less(const CPPDeclaration *other) const {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ public:
|
|||
int as_integer() const;
|
||||
double as_real() const;
|
||||
void *as_pointer() const;
|
||||
bool as_boolean() const;
|
||||
void output(ostream &out) const;
|
||||
|
||||
ResultType _type;
|
||||
|
|
@ -78,6 +79,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);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
|
||||
#include "cppExtensionType.h"
|
||||
#include "cppTypedef.h"
|
||||
#include "cppTypedefType.h"
|
||||
#include "cppIdentifier.h"
|
||||
#include "cppParser.h"
|
||||
#include "indent.h"
|
||||
|
|
@ -130,6 +130,29 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
|
|||
return rep;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExtensionType::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 *CPPExtensionType::
|
||||
resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
|
||||
if (_ident == NULL) {
|
||||
// We can't resolve anonymous types. But that's OK, since they
|
||||
// can't be forward declared anyway.
|
||||
return this;
|
||||
}
|
||||
|
||||
// Maybe it has been defined by now.
|
||||
CPPType *type = _ident->find_type(current_scope, global_scope);
|
||||
if (type != NULL) {
|
||||
return type;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExtensionType::is_equivalent_type
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ class CPPIdentifier;
|
|||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : CPPExtensionType
|
||||
// Description :
|
||||
// Description : Base class of enum, class, struct, and union types.
|
||||
// An instance of the base class (instead of one of
|
||||
// the specializations) is used for forward references.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class CPPExtensionType : public CPPType {
|
||||
public:
|
||||
|
|
@ -50,6 +52,9 @@ public:
|
|||
CPPScope *current_scope,
|
||||
CPPScope *global_scope);
|
||||
|
||||
virtual CPPType *resolve_type(CPPScope *current_scope,
|
||||
CPPScope *global_scope);
|
||||
|
||||
virtual bool is_equivalent(const CPPType &other) const;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -146,8 +146,10 @@ get_local_name(CPPScope *scope) const {
|
|||
|
||||
if (scope == NULL || (_native_scope == NULL && _names.size() == 1)) {
|
||||
result = _names.back().get_name_with_templ(scope);
|
||||
|
||||
} else if (_names.front().empty()) {
|
||||
result = get_fully_scoped_name();
|
||||
|
||||
} else {
|
||||
// Determine the scope of everything up until but not including the
|
||||
// last name.
|
||||
|
|
@ -382,6 +384,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 +401,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,6 +426,7 @@ 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());
|
||||
|
|
@ -446,6 +449,43 @@ find_symbol(CPPScope *current_scope, CPPScope *global_scope,
|
|||
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()) {
|
||||
// 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_template
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -432,10 +432,14 @@ warning(const string &message, int line, int col, CPPFile file) {
|
|||
if (file.empty()) {
|
||||
file = get_file();
|
||||
}
|
||||
indent(cerr, _files.size() * 2)
|
||||
int indent_level = 0;
|
||||
if (_verbose >= 3) {
|
||||
indent_level = _files.size() * 2;
|
||||
}
|
||||
indent(cerr, indent_level)
|
||||
<< "*** Warning in " << file
|
||||
<< " near line " << line << ", column " << col << ":\n";
|
||||
indent(cerr, _files.size() * 2)
|
||||
indent(cerr, indent_level)
|
||||
<< message << "\n";
|
||||
}
|
||||
_warning_count++;
|
||||
|
|
@ -452,7 +456,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) {
|
||||
|
|
@ -462,11 +466,20 @@ error(const string &message, int line, int col, CPPFile file) {
|
|||
if (file.empty()) {
|
||||
file = get_file();
|
||||
}
|
||||
indent(cerr, _files.size() * 2)
|
||||
int indent_level = 0;
|
||||
if (_verbose >= 3) {
|
||||
indent_level = _files.size() * 2;
|
||||
}
|
||||
indent(cerr, indent_level)
|
||||
<< "*** Error in " << file
|
||||
<< " near line " << line << ", column " << col << ":\n";
|
||||
indent(cerr, _files.size() * 2)
|
||||
indent(cerr, indent_level)
|
||||
<< message << "\n";
|
||||
|
||||
if (_error_abort) {
|
||||
cerr << "Aborting.\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
_error_count++;
|
||||
}
|
||||
|
|
@ -603,7 +616,7 @@ init_type(const string &type) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool CPPPreprocessor::
|
||||
push_file(const CPPFile &file) {
|
||||
if (_verbose >= 2) {
|
||||
if (_verbose >= 3) {
|
||||
indent(cerr, _files.size() * 2)
|
||||
<< "Reading " << file << "\n";
|
||||
}
|
||||
|
|
@ -2009,7 +2022,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;
|
||||
|
|
@ -2061,6 +2075,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;
|
||||
|
||||
// These are alternative ways to refer to built-in operators.
|
||||
|
|
@ -2287,7 +2302,6 @@ unget(int c) {
|
|||
_unget = c;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPPreprocessor::nested_parse_template_instantiation
|
||||
// Access: Private
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ private:
|
|||
|
||||
int _warning_count;
|
||||
int _error_count;
|
||||
bool _error_abort;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -136,7 +136,7 @@ add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
|
|||
|
||||
_declarations.push_back(decl);
|
||||
|
||||
handle_declaration(decl, global_scope);
|
||||
handle_declaration(decl, global_scope, preprocessor);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -185,9 +185,12 @@ add_enum_value(CPPInstance *inst, CPPPreprocessor *preprocessor,
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CPPScope::
|
||||
define_extension_type(CPPExtensionType *type) {
|
||||
define_extension_type(CPPExtensionType *type, CPPPreprocessor *error_sink) {
|
||||
assert(type != NULL);
|
||||
string name = type->get_simple_name();
|
||||
string name = type->get_local_name(this);
|
||||
if (name.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type->_type) {
|
||||
case CPPExtensionType::T_class:
|
||||
|
|
@ -204,31 +207,55 @@ define_extension_type(CPPExtensionType *type) {
|
|||
|
||||
case CPPExtensionType::T_enum:
|
||||
_enums[name] = type;
|
||||
break;
|
||||
}
|
||||
|
||||
// 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;
|
||||
if (type->is_template() && !other_type->is_template()) {
|
||||
(*result.first).second = td;
|
||||
// overrides it only if the other is a forward declaration.
|
||||
CPPType *other_type = (*result.first).second;
|
||||
|
||||
// Or if the other one is a forward reference.
|
||||
} else if (other_type->get_subtype() == CPPDeclaration::ST_extension) {
|
||||
(*result.first).second = td;
|
||||
if (other_type->get_subtype() == CPPDeclaration::ST_extension) {
|
||||
CPPExtensionType *other_ext = other_type->as_extension_type();
|
||||
|
||||
if (other_ext->_type != type->_type) {
|
||||
if (error_sink != NULL) {
|
||||
ostringstream errstr;
|
||||
errstr << other_ext->_type << " " << type->get_fully_scoped_name()
|
||||
<< " was previously declared as " << other_ext->_type << "\n";
|
||||
error_sink->error(errstr.str());
|
||||
}
|
||||
}
|
||||
(*result.first).second = type;
|
||||
|
||||
} else {
|
||||
CPPTypedefType *other_td = other_type->as_typedef_type();
|
||||
|
||||
// Error out if the declaration is different than the previous one.
|
||||
if (other_type != type &&
|
||||
(other_td == NULL || other_td->_type != type)) {
|
||||
|
||||
if (error_sink != NULL) {
|
||||
ostringstream errstr;
|
||||
type->output(errstr, 0, NULL, false);
|
||||
errstr << " has conflicting declaration as ";
|
||||
other_type->output(errstr, 0, NULL, true);
|
||||
error_sink->error(errstr.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type->is_template()) {
|
||||
string simple_name = type->get_simple_name();
|
||||
|
||||
pair<Templates::iterator, bool> result =
|
||||
_templates.insert(Templates::value_type(name, type));
|
||||
_templates.insert(Templates::value_type(simple_name, type));
|
||||
|
||||
if (!result.second) {
|
||||
// The template was not inserted because we already had a
|
||||
|
|
@ -278,7 +305,7 @@ add_using(CPPUsing *using_decl, CPPScope *global_scope,
|
|||
} else {
|
||||
CPPDeclaration *decl = using_decl->_ident->find_symbol(this, global_scope);
|
||||
if (decl != NULL) {
|
||||
handle_declaration(decl, global_scope);
|
||||
handle_declaration(decl, global_scope, error_sink);
|
||||
} else {
|
||||
if (error_sink != NULL) {
|
||||
error_sink->warning("Attempt to use unknown symbol: " + using_decl->_ident->get_fully_scoped_name());
|
||||
|
|
@ -392,11 +419,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -466,10 +495,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;
|
||||
|
|
@ -510,11 +539,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();
|
||||
}
|
||||
|
||||
|
|
@ -563,10 +592,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;
|
||||
|
|
@ -614,10 +647,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;
|
||||
}
|
||||
|
||||
|
|
@ -632,10 +672,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;
|
||||
|
|
@ -756,9 +796,14 @@ get_local_name(CPPScope *scope) const {
|
|||
}
|
||||
*/
|
||||
|
||||
if (scope != NULL && _parent_scope != NULL && _parent_scope != scope) {
|
||||
return _parent_scope->get_local_name(scope) + "::" +
|
||||
_name.get_name_with_templ();
|
||||
if (scope != NULL && _parent_scope != NULL/* && _parent_scope != scope*/) {
|
||||
string parent_scope_name = _parent_scope->get_local_name(scope);
|
||||
if (parent_scope_name.empty()) {
|
||||
return _name.get_name_with_templ();
|
||||
} else {
|
||||
return parent_scope_name + "::" +
|
||||
_name.get_name_with_templ();
|
||||
}
|
||||
} else {
|
||||
return _name.get_name_with_templ();
|
||||
}
|
||||
|
|
@ -817,8 +862,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;
|
||||
}
|
||||
|
||||
|
|
@ -881,7 +925,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;
|
||||
|
||||
|
|
@ -986,11 +1030,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;
|
||||
}
|
||||
|
|
@ -1000,6 +1044,19 @@ copy_substitute_decl(CPPScope *to_scope, CPPDeclaration::SubstDecl &subst,
|
|||
CPPInstance *inst =
|
||||
(*vi).second->substitute_decl(subst, to_scope, global_scope)->as_instance();
|
||||
to_scope->_variables.insert(Variables::value_type((*vi).first, inst));
|
||||
if (inst != (*vi).second) {
|
||||
// I don't know if this _native_scope assignment is right, but it
|
||||
// fixes some issues with variables in instantiated template scopes
|
||||
// being printed out with an uninstantiated template scope prefix. ~rdb
|
||||
inst->_ident->_native_scope = to_scope;
|
||||
anything_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -1027,25 +1084,41 @@ copy_substitute_decl(CPPScope *to_scope, CPPDeclaration::SubstDecl &subst,
|
|||
// functions, or whatever.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CPPScope::
|
||||
handle_declaration(CPPDeclaration *decl, CPPScope *global_scope) {
|
||||
CPPTypedef *def = decl->as_typedef();
|
||||
handle_declaration(CPPDeclaration *decl, CPPScope *global_scope,
|
||||
CPPPreprocessor *error_sink) {
|
||||
CPPTypedefType *def = decl->as_typedef_type();
|
||||
if (def != NULL) {
|
||||
string name = def->get_simple_name();
|
||||
_typedefs[name] = def;
|
||||
|
||||
pair<Types::iterator, bool> result =
|
||||
_types.insert(Types::value_type(name, def));
|
||||
|
||||
if (!result.second) {
|
||||
CPPType *other_type = result.first->second;
|
||||
CPPTypedefType *other_td = other_type->as_typedef_type();
|
||||
|
||||
// We don't do redefinitions of typedefs. But we don't complain
|
||||
// as long as this is actually a typedef to the previous definition.
|
||||
if (other_type != def->_type &&
|
||||
(other_td == NULL || other_td->_type != def->_type)) {
|
||||
|
||||
if (error_sink != NULL) {
|
||||
ostringstream errstr;
|
||||
def->output(errstr, 0, NULL, false);
|
||||
errstr << " has conflicting declaration as ";
|
||||
other_type->output(errstr, 0, NULL, true);
|
||||
error_sink->error(errstr.str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_types[name] = def;
|
||||
}
|
||||
|
||||
CPPExtensionType *et = def->_type->as_extension_type();
|
||||
if (et != NULL) {
|
||||
define_extension_type(et);
|
||||
define_extension_type(et, error_sink);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -1053,7 +1126,7 @@ handle_declaration(CPPDeclaration *decl, CPPScope *global_scope) {
|
|||
if (typedecl != (CPPTypeDeclaration *)NULL) {
|
||||
CPPExtensionType *et = typedecl->_type->as_extension_type();
|
||||
if (et != NULL) {
|
||||
define_extension_type(et);
|
||||
define_extension_type(et, error_sink);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -1062,6 +1135,13 @@ handle_declaration(CPPDeclaration *decl, CPPScope *global_scope) {
|
|||
if (inst != NULL) {
|
||||
inst->check_for_constructor(this, global_scope);
|
||||
|
||||
if (inst->_ident != NULL) {
|
||||
// Not sure if this is the best place to assign this. However,
|
||||
// this fixes a bug with variables in expressions not having
|
||||
// the proper scoping prefix. ~rdb
|
||||
inst->_ident->_native_scope = this;
|
||||
}
|
||||
|
||||
string name = inst->get_simple_name();
|
||||
if (!name.empty() && inst->get_scope(this, global_scope) == this) {
|
||||
if (inst->_type->as_function_type()) {
|
||||
|
|
@ -1108,6 +1188,6 @@ handle_declaration(CPPDeclaration *decl, CPPScope *global_scope) {
|
|||
|
||||
CPPExtensionType *et = decl->as_extension_type();
|
||||
if (et != NULL) {
|
||||
define_extension_type(et);
|
||||
define_extension_type(et, error_sink);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class CPPExtensionType;
|
|||
class CPPStructType;
|
||||
class CPPNamespace;
|
||||
class CPPUsing;
|
||||
class CPPTypedef;
|
||||
class CPPTypedefType;
|
||||
class CPPInstance;
|
||||
class CPPFunctionGroup;
|
||||
class CPPTemplateScope;
|
||||
|
|
@ -66,7 +66,8 @@ public:
|
|||
virtual void add_enum_value(CPPInstance *inst,
|
||||
CPPPreprocessor *preprocessor,
|
||||
const cppyyltype &pos);
|
||||
virtual void define_extension_type(CPPExtensionType *type);
|
||||
virtual void define_extension_type(CPPExtensionType *type,
|
||||
CPPPreprocessor *error_sink = NULL);
|
||||
virtual void define_namespace(CPPNamespace *scope);
|
||||
virtual void add_using(CPPUsing *using_decl, CPPScope *global_scope,
|
||||
CPPPreprocessor *error_sink = NULL);
|
||||
|
|
@ -113,7 +114,8 @@ private:
|
|||
copy_substitute_decl(CPPScope *to_scope, CPPDeclaration::SubstDecl &subst,
|
||||
CPPScope *global_scope) const;
|
||||
|
||||
void handle_declaration(CPPDeclaration *decl, CPPScope *global_scope);
|
||||
void handle_declaration(CPPDeclaration *decl, CPPScope *global_scope,
|
||||
CPPPreprocessor *error_sink = NULL);
|
||||
|
||||
public:
|
||||
typedef vector<CPPDeclaration *> Declarations;
|
||||
|
|
@ -128,8 +130,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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 ©) {
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include "cppExtensionType.h"
|
||||
#include "cppClassTemplateParameter.h"
|
||||
#include "cppIdentifier.h"
|
||||
#include "cppTypedef.h"
|
||||
#include "cppTypedefType.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPTemplateScope::Constructor
|
||||
|
|
@ -64,10 +64,10 @@ add_enum_value(CPPInstance *inst, CPPPreprocessor *preprocessor,
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CPPTemplateScope::
|
||||
define_extension_type(CPPExtensionType *type) {
|
||||
define_extension_type(CPPExtensionType *type, CPPPreprocessor *error_sink) {
|
||||
type->_template_scope = this;
|
||||
assert(_parent_scope != NULL);
|
||||
_parent_scope->define_extension_type(type);
|
||||
_parent_scope->define_extension_type(type, error_sink);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ public:
|
|||
virtual void add_enum_value(CPPInstance *inst,
|
||||
CPPPreprocessor *preprocessor,
|
||||
const cppyyltype &pos);
|
||||
virtual void define_extension_type(CPPExtensionType *type);
|
||||
virtual void define_extension_type(CPPExtensionType *type,
|
||||
CPPPreprocessor *error_sink = NULL);
|
||||
virtual void define_namespace(CPPNamespace *scope);
|
||||
virtual void add_using(CPPUsing *using_decl, CPPScope *global_scope,
|
||||
CPPPreprocessor *error_sink = NULL);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
|
||||
#include "cppType.h"
|
||||
#include "cppTypedef.h"
|
||||
#include "cppTypedefType.h"
|
||||
#include <algorithm>
|
||||
|
||||
CPPType::Types CPPType::_types;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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; */
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -64,13 +64,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
|
||||
|
|
@ -104,9 +97,7 @@ PUBLISHED:
|
|||
INLINE TypeHandle();
|
||||
INLINE TypeHandle(const TypeHandle ©);
|
||||
|
||||
#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;
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -375,6 +375,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ PUBLISHED:
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
PyObject *__reduce__(PyObject *self) const;
|
||||
EXTENSION(PyObject *__reduce__(PyObject *self) const);
|
||||
#endif
|
||||
|
||||
// Static constructors to explicitly create a filename that refers
|
||||
|
|
@ -126,6 +126,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;
|
||||
|
|
@ -200,11 +202,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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
@ -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();
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "interrogate.h"
|
||||
#include "parameterRemap.h"
|
||||
#include "parameterRemapThis.h"
|
||||
#include "parameterRemapUnchanged.h"
|
||||
#include "interfaceMaker.h"
|
||||
#include "interrogateBuilder.h"
|
||||
|
||||
|
|
@ -200,7 +201,7 @@ call_function(ostream &out, int indent_level, bool convert_result,
|
|||
|
||||
// Now a simple special-case test. Often, we will have converted
|
||||
// the reference-returning assignment operator to a pointer. In
|
||||
// this case, we might inadventent generate code like "return
|
||||
// this case, we might inadvertently generate code like "return
|
||||
// &(*this)", when "return this" would do. We check for this here
|
||||
// and undo it as a special case.
|
||||
|
||||
|
|
@ -226,7 +227,8 @@ call_function(ostream &out, int indent_level, bool convert_result,
|
|||
return_expr = get_call_str(container, pexprs);
|
||||
|
||||
} else {
|
||||
if (_return_type->return_value_should_be_simple()) {
|
||||
//if (_return_type->return_value_should_be_simple()) {
|
||||
if (false) {
|
||||
// We have to assign the result to a temporary first; this makes
|
||||
// it a bit easier on poor old VC++.
|
||||
InterfaceMaker::indent(out, indent_level);
|
||||
|
|
@ -234,8 +236,14 @@ call_function(ostream &out, int indent_level, bool convert_result,
|
|||
&parser);
|
||||
out << " = " << call << ";\n";
|
||||
|
||||
// MOVE() expands to std::move() when we are compiling with a
|
||||
// compiler that supports rvalue references. It basically turns
|
||||
// an lvalue into an rvalue, allowing a move constructor to be
|
||||
// called instead of a copy constructor (since we won't be using
|
||||
// the return value any more), which is usually more efficient if
|
||||
// it exists. If it doesn't, it shouldn't do any harm.
|
||||
string new_str =
|
||||
_return_type->prepare_return_expr(out, indent_level, "result");
|
||||
_return_type->prepare_return_expr(out, indent_level, "MOVE(result)");
|
||||
return_expr = _return_type->get_return_expr(new_str);
|
||||
|
||||
} else {
|
||||
|
|
@ -258,11 +266,11 @@ call_function(ostream &out, int indent_level, bool convert_result,
|
|||
// comment.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void FunctionRemap::
|
||||
write_orig_prototype(ostream &out, int indent_level, bool local) const {
|
||||
write_orig_prototype(ostream &out, int indent_level, bool local, int num_default_args) const {
|
||||
if (local) {
|
||||
_cppfunc->output(out, indent_level, NULL, false, _num_default_parameters);
|
||||
_cppfunc->output(out, indent_level, NULL, false, num_default_args);
|
||||
} else {
|
||||
_cppfunc->output(out, indent_level, &parser, false, _num_default_parameters);
|
||||
_cppfunc->output(out, indent_level, &parser, false, num_default_args);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -287,7 +295,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.
|
||||
|
|
@ -356,7 +363,7 @@ make_wrapper_entry(FunctionIndex function_index) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FunctionRemap::get_call_str
|
||||
// Access: Private
|
||||
// Access: Public
|
||||
// Description: Returns a string suitable for calling the wrapped
|
||||
// function. If pexprs is nonempty, it represents
|
||||
// the list of expressions that will evaluate to each
|
||||
|
|
@ -412,7 +419,12 @@ get_call_str(const string &container, const vector_string &pexprs) const {
|
|||
} else if (_has_this && !container.empty()) {
|
||||
// If we have a "this" parameter, the calling convention is also
|
||||
// a bit different.
|
||||
call << "(" << container << ")->" << _cppfunc->get_local_name();
|
||||
if (container == "local_this") {
|
||||
// This isn't important, it just looks a bit prettier.
|
||||
call << container << "->" << _cppfunc->get_local_name();
|
||||
} else {
|
||||
call << "(" << container << ")->" << _cppfunc->get_local_name();
|
||||
}
|
||||
|
||||
} else {
|
||||
call << _cppfunc->get_local_name(&parser);
|
||||
|
|
@ -426,14 +438,27 @@ 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 = pexprs.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) {
|
||||
nassertd(pn < _parameters.size()) break;
|
||||
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();
|
||||
|
|
@ -497,6 +522,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) &&
|
||||
|
|
@ -533,13 +559,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 ¶ms =
|
||||
_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();
|
||||
|
|
@ -557,10 +592,16 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
|||
if (param._remap == (ParameterRemap *)NULL) {
|
||||
// If we can't handle one of the parameter types, we can't call
|
||||
// the function.
|
||||
//nout << "Can't handle parameter " << i << " of method " << *_cppfunc << "\n";
|
||||
return false;
|
||||
if (fname == "__traverse__") {
|
||||
// Hack to record this even though we can't wrap visitproc.
|
||||
param._remap = new ParameterRemapUnchanged(type);
|
||||
} else {
|
||||
//nout << "Can't handle parameter " << i << " of method " << *_cppfunc << "\n";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
param._remap->set_default_value(params[i]->_initializer);
|
||||
}
|
||||
param._remap->set_default_value(params[i]->_initializer);
|
||||
|
||||
if (!param._remap->is_valid()) {
|
||||
nout << "Invalid remap for parameter " << i << " of method " << *_cppfunc << "\n";
|
||||
|
|
@ -601,9 +642,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);
|
||||
|
|
@ -663,9 +734,10 @@ 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 &&
|
||||
_parameters[first_param]._remap->get_default_value() == NULL) {
|
||||
_args_type = InterfaceMaker::AT_single_arg;
|
||||
} else {
|
||||
_args_type = InterfaceMaker::AT_varargs;
|
||||
|
|
@ -682,8 +754,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;
|
||||
|
|
@ -691,6 +763,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())) {
|
||||
|
|
@ -735,11 +817,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 {
|
||||
|
|
@ -750,6 +841,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()) ==
|
||||
|
|
@ -758,7 +862,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,14 +52,17 @@ public:
|
|||
~FunctionRemap();
|
||||
|
||||
string get_parameter_name(int n) const;
|
||||
string call_function(ostream &out, int indent_level,
|
||||
string call_function(ostream &out, int indent_level,
|
||||
bool convert_result, const string &container,
|
||||
const vector_string &pexprs = vector_string()) const;
|
||||
|
||||
void write_orig_prototype(ostream &out, int indent_level, bool local=false) const;
|
||||
void write_orig_prototype(ostream &out, int indent_level, bool local=false,
|
||||
int num_default_args=0) const;
|
||||
|
||||
FunctionWrapperIndex make_wrapper_entry(FunctionIndex function_index);
|
||||
|
||||
string get_call_str(const string &container, const vector_string &pexprs) const;
|
||||
|
||||
class Parameter {
|
||||
public:
|
||||
bool _has_name;
|
||||
|
|
@ -76,21 +79,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;
|
||||
|
|
@ -126,8 +133,8 @@ public:
|
|||
CPPFunctionType *_ftype;
|
||||
|
||||
bool _is_valid;
|
||||
|
||||
private:
|
||||
string get_call_str(const string &container, const vector_string &pexprs) const;
|
||||
string get_parameter_expr(int n, const vector_string &pexprs) const;
|
||||
bool setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_maker);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -141,9 +141,15 @@ check_protocols() {
|
|||
for (fi = _methods.begin(); fi != _methods.end(); ++fi) {
|
||||
Function *func = (*fi);
|
||||
flags |= func->_flags;
|
||||
|
||||
if (func->_ifunc.get_name() == "__traverse__") {
|
||||
// If we have a method named __traverse__, we implement Python's
|
||||
// cyclic garbage collection protocol.
|
||||
_protocol_types |= PT_python_gc;
|
||||
}
|
||||
}
|
||||
|
||||
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 +175,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 +273,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 +315,7 @@ generate_wrappers() {
|
|||
FunctionIndex func_index = ielement.get_setter();
|
||||
record_function(dummy_type, func_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -396,7 +390,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 +448,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 +547,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 +584,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 +672,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 +737,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 +751,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 +779,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,8 +875,14 @@ 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 (TypeManager::is_pointer_to_base(remap->_return_type->get_temporary_type())) {
|
||||
// Actually, we have it stored in a PointerTo. No need to do anything.
|
||||
return;
|
||||
}
|
||||
|
||||
if (remap->_type == FunctionRemap::T_constructor ||
|
||||
remap->_type == FunctionRemap::T_typecast) {
|
||||
// In either of these cases, we can safely assume the pointer will
|
||||
|
|
@ -915,8 +911,14 @@ 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 (TypeManager::is_pointer_to_base(remap->_return_type->get_temporary_type())) {
|
||||
// Actually, we have it stored in a PointerTo. No need to do anything.
|
||||
return;
|
||||
}
|
||||
|
||||
if (remap->_type == FunctionRemap::T_constructor ||
|
||||
remap->_type == FunctionRemap::T_typecast) {
|
||||
// In either of these cases, we can safely assume the pointer will
|
||||
|
|
@ -931,8 +933,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 +978,7 @@ hash_function_signature(FunctionRemap *remap) {
|
|||
nout << "Internal error! Function signature "
|
||||
<< remap->_function_signature << " repeated!\n";
|
||||
remap->_hash = hash;
|
||||
abort();
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ public:
|
|||
PT_make_copy = 0x0004,
|
||||
PT_copy_constructor = 0x0008,
|
||||
PT_iter = 0x0010,
|
||||
PT_python_gc = 0x0020,
|
||||
};
|
||||
int _protocol_types;
|
||||
};
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -31,32 +31,33 @@ 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 bool separate_overloading();
|
||||
|
||||
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 +66,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 +77,34 @@ private:
|
|||
WT_getbuffer,
|
||||
WT_releasebuffer,
|
||||
WT_iter_next,
|
||||
WT_one_or_two_params,
|
||||
WT_ternary_operator,
|
||||
WT_inplace_binary_operator,
|
||||
WT_inplace_ternary_operator,
|
||||
WT_traverse,
|
||||
};
|
||||
|
||||
// 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,40 +112,59 @@ private:
|
|||
string _answer_location;
|
||||
WrapperType _wrapper_type;
|
||||
int _min_version;
|
||||
Function *_func;
|
||||
string _wrapper_name;
|
||||
set<FunctionRemap*> _remaps;
|
||||
};
|
||||
|
||||
static bool get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def);
|
||||
typedef std::map<string, SlottedFunctionDef> SlottedFunctions;
|
||||
|
||||
static bool get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap, SlottedFunctionDef &def);
|
||||
static void write_function_slot(ostream &out, int indent_level,
|
||||
const SlottedFunctions &slots,
|
||||
const string &slot, const string &def = "0");
|
||||
|
||||
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);
|
||||
|
||||
int collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
|
||||
int max_required_args);
|
||||
|
||||
void write_function_forset(ostream &out,
|
||||
const std::set<FunctionRemap*> &remaps,
|
||||
int min_num_args, int max_num_args,
|
||||
string &expected_params, int indent_level,
|
||||
bool coercion_allowed, bool report_errors,
|
||||
ArgsType args_type, int return_flags,
|
||||
bool check_exceptions = true,
|
||||
bool verify_const = 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,
|
||||
int min_num_args, int max_num_args,
|
||||
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 error_raise_return(ostream &out, int indent_level, int return_flags,
|
||||
const string &exc_type, const string &message,
|
||||
const string &format_args = "");
|
||||
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);
|
||||
std::string return_expr);
|
||||
|
||||
void write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
|
||||
MakeSeq *make_seq);
|
||||
const std::string &cClassName, MakeSeq *make_seq);
|
||||
|
||||
void write_class_prototypes(ostream &out) ;
|
||||
void write_class_declarations(ostream &out, ostream *out_h, Object *obj);
|
||||
|
|
@ -126,7 +172,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,17 +193,18 @@ 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);
|
||||
int NeedsAReprFunction(const InterrogateType &itype_class);
|
||||
bool NeedsARichCompareFunction(const InterrogateType &itype_class);
|
||||
|
||||
void output_quoted(ostream &out, int indent_level, const std::string &str);
|
||||
|
||||
void output_quoted(ostream &out, int indent_level, const std::string &str,
|
||||
bool first_line=true);
|
||||
|
||||
// stash the forward declarations for this compile pass..
|
||||
std::set<std::string> _external_imports;
|
||||
std::set<CPPType *> _external_imports;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -286,7 +286,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.
|
||||
|
|
@ -295,13 +296,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) {
|
||||
|
|
@ -329,7 +333,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;
|
||||
|
||||
|
|
@ -394,9 +399,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();
|
||||
|
|
@ -413,7 +419,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);
|
||||
}
|
||||
|
|
@ -427,8 +432,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);
|
||||
|
|
@ -438,21 +441,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -461,7 +462,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.
|
||||
|
|
@ -504,7 +505,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["
|
||||
|
|
@ -518,9 +518,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.
|
||||
|
|
@ -544,7 +541,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 {
|
||||
|
|
@ -565,7 +562,6 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
|
|||
<< "}\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: InterrogateBuilder::make_module_def
|
||||
|
|
@ -887,6 +883,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());
|
||||
}
|
||||
|
|
@ -1145,7 +1150,7 @@ scan_function(CPPInstance *function) {
|
|||
}
|
||||
|
||||
get_function(function, "",
|
||||
(CPPStructType *)NULL, scope,
|
||||
(CPPStructType *)NULL, scope,
|
||||
InterrogateFunction::F_global);
|
||||
}
|
||||
|
||||
|
|
@ -1181,8 +1186,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;
|
||||
|
|
@ -1192,6 +1196,7 @@ scan_struct_type(CPPStructType *type) {
|
|||
++di) {
|
||||
if ((*di)->_vis <= min_vis) {
|
||||
any_exported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1241,6 +1246,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
|
||||
|
|
@ -1683,6 +1775,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);
|
||||
|
||||
|
|
@ -1698,18 +1795,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;
|
||||
|
|
@ -1764,7 +1860,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) {
|
||||
|
|
@ -1974,7 +2070,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);
|
||||
|
|
@ -2044,29 +2140,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2092,8 +2198,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);
|
||||
|
|
@ -2129,6 +2242,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;
|
||||
|
|
@ -2150,7 +2273,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;
|
||||
}
|
||||
|
||||
|
|
@ -2204,7 +2328,7 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
|
|||
TypeIndex type_index, bool forced) {
|
||||
if (cpptype->get_simple_name().empty()) {
|
||||
// If the type has no name, forget it. We don't export anonymous
|
||||
// types.
|
||||
// structs.
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2265,23 +2389,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;
|
||||
|
|
@ -2289,7 +2415,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;
|
||||
|
||||
|
|
@ -2297,12 +2423,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
|
||||
|
|
@ -2318,13 +2444,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.
|
||||
|
|
@ -2371,8 +2495,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);
|
||||
}
|
||||
|
|
@ -2382,11 +2507,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);
|
||||
|
|
@ -2483,7 +2628,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 ||
|
||||
|
|
@ -2505,8 +2650,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);
|
||||
}
|
||||
|
|
@ -2642,7 +2786,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);
|
||||
}
|
||||
|
|
@ -2683,7 +2827,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);
|
||||
|
|
@ -2692,6 +2844,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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,14 @@ ParameterRemapConcreteToPointer(CPPType *orig_type) :
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void ParameterRemapConcreteToPointer::
|
||||
pass_parameter(ostream &out, const string &variable_name) {
|
||||
out << "*" << variable_name;
|
||||
if (variable_name.size() > 1 && variable_name[0] == '&') {
|
||||
// Prevent generating something like *¶m
|
||||
// Also, if this is really some local type, we can presumably
|
||||
// just move it?
|
||||
out << "MOVE(" << variable_name.substr(1) << ")";
|
||||
} else {
|
||||
out << "*" << variable_name;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -42,7 +42,16 @@ ParameterRemapReferenceToPointer(CPPType *orig_type) :
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void ParameterRemapReferenceToPointer::
|
||||
pass_parameter(ostream &out, const string &variable_name) {
|
||||
out << "*" << variable_name;
|
||||
if (variable_name.size() > 1 && variable_name[0] == '&') {
|
||||
// Prevent generating something like *¶m
|
||||
// Also, if this is really some local type, we can presumably just
|
||||
// move it? This is only relevant if this parameter is an rvalue
|
||||
// reference, but CPPParser can't know that, and it might have an overload
|
||||
// that takes an rvalue reference. It shouldn't hurt either way.
|
||||
out << "MOVE(" << variable_name.substr(1) << ")";
|
||||
} else {
|
||||
out << "*" << variable_name;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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
Load Diff
|
|
@ -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,8 @@ 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_ssize(CPPType *type);
|
||||
static bool is_short(CPPType *type);
|
||||
static bool is_unsigned_short(CPPType *type);
|
||||
static bool is_longlong(CPPType *type);
|
||||
|
|
@ -94,6 +103,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);
|
||||
|
|
@ -133,8 +144,8 @@ public:
|
|||
static bool has_protected_destructor(CPPType *type);
|
||||
|
||||
|
||||
static bool IsExported(CPPType *type);
|
||||
static bool IsLocal(CPPType *type);
|
||||
static bool is_exported(CPPType *type);
|
||||
static bool is_local(CPPType *type);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#include "py_panda.h"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
|
||||
class EmptyClass {
|
||||
};
|
||||
Define_Module_Class_Private(dtoolconfig, DTOOL_SUPER_BASE, EmptyClass, DTOOL_SUPER_BASE111);
|
||||
|
|
@ -30,7 +30,7 @@ PyMethodDef Dtool_Methods_DTOOL_SUPER_BASE[] = {
|
|||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static Py_hash_t DTool_HashKey_Methods_DTOOL_SUPER_BASE(PyObject *self) {
|
||||
static Py_hash_t Dtool_HashKey_DTOOL_SUPER_BASE(PyObject *self) {
|
||||
void *local_this = DTOOL_Call_GetPointerThis(self);
|
||||
if (local_this == NULL) {
|
||||
return -1;
|
||||
|
|
@ -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) {
|
||||
|
||||
|
|
@ -46,15 +46,6 @@ inline void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module) {
|
|||
Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_dict = PyDict_New();
|
||||
PyDict_SetItemString(Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_dict, "DtoolClassDict", Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_dict);
|
||||
|
||||
// __hash__
|
||||
Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_hash = &DTool_HashKey_Methods_DTOOL_SUPER_BASE;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
// Python 3 removed the regular tp_compare function - there is only tp_richcompare.
|
||||
Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_richcompare = &DTOOL_PyObject_RichCompare;
|
||||
#else
|
||||
Dtool_DTOOL_SUPER_BASE.As_PyTypeObject().tp_compare = &DTOOL_PyObject_Compare;
|
||||
#endif
|
||||
|
||||
if (PyType_Ready(&Dtool_DTOOL_SUPER_BASE.As_PyTypeObject()) < 0) {
|
||||
PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_DTOOL_SUPER_BASE)");
|
||||
return;
|
||||
|
|
@ -83,9 +74,66 @@ 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;
|
||||
}
|
||||
EXPORT_THIS Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE = {
|
||||
{
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"dtoolconfig.DTOOL_SUPER_BASE",
|
||||
sizeof(Dtool_PyInstDef),
|
||||
0,
|
||||
&Dtool_FreeInstance_DTOOL_SUPER_BASE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
0,
|
||||
#else
|
||||
&DTOOL_PyObject_Compare,
|
||||
#endif
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&Dtool_HashKey_DTOOL_SUPER_BASE,
|
||||
0,
|
||||
0,
|
||||
PyObject_GenericGetAttr,
|
||||
PyObject_GenericSetAttr,
|
||||
0,
|
||||
(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
&DTOOL_PyObject_RichCompare,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
Dtool_Methods_DTOOL_SUPER_BASE,
|
||||
standard_type_members,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
Dtool_Init_DTOOL_SUPER_BASE,
|
||||
PyType_GenericAlloc,
|
||||
Dtool_new_DTOOL_SUPER_BASE,
|
||||
PyObject_Del,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
Dtool_UpcastInterface_DTOOL_SUPER_BASE,
|
||||
Dtool_DowncastInterface_DTOOL_SUPER_BASE,
|
||||
TypeHandle::none(),
|
||||
};
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ©) {
|
|||
_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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -18,19 +18,26 @@
|
|||
#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_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", (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_BOOL, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"},
|
||||
{(char *)"this_const", T_BOOL, 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"},
|
||||
{(char *)"this_metatype", T_OBJECT, offsetof(Dtool_PyInstDef, _My_Type), READONLY, (char *)"The dtool meta object"},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// Simple Recognition Functions..
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DtoolCanThisBeAPandaInstance
|
||||
// Description: Given a valid (non-NULL) PyObject, does a simple
|
||||
// check to see if it might be an instance of a Panda
|
||||
// type. It does this using a signature that is
|
||||
// encoded on each instance.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
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) {
|
||||
|
|
@ -56,101 +63,51 @@ 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.
|
||||
// Function: Dtool_Call_ExtractThisPointer
|
||||
// Description: This is a support function for the Python bindings:
|
||||
// it extracts the underlying C++ pointer of the given
|
||||
// type for a given Python object. If it was of the
|
||||
// wrong type, raises an AttributeError.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
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();
|
||||
bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer) {
|
||||
if (self == NULL || !DtoolCanThisBeAPandaInstance(self)) {
|
||||
Dtool_Raise_TypeError("C++ object is not yet constructed, or already destructed.");
|
||||
return false;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
*answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, &classdef);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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_ExtractThisPointer_NonConst
|
||||
// Description: The same thing as Dtool_Call_ExtractThisPointer,
|
||||
// except that it performs the additional check that
|
||||
// the pointer is a non-const pointer. This is called
|
||||
// by function wrappers for functions of which all
|
||||
// overloads are non-const, and saves a bit of code.
|
||||
//
|
||||
// The extra method_name argument is used in formatting
|
||||
// the error message.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
|
||||
void **answer, const char *method_name) {
|
||||
|
||||
if (self == NULL || !DtoolCanThisBeAPandaInstance(self)) {
|
||||
Dtool_Raise_TypeError("C++ object is not yet constructed, or already destructed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((Dtool_PyInstDef *)self)->_is_const) {
|
||||
// All overloads of this function are non-const.
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"Cannot call %s() on a const object.",
|
||||
method_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
*answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, &classdef);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -176,18 +133,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 +140,36 @@ 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) {
|
||||
return Dtool_Raise_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());
|
||||
}
|
||||
if (DtoolCanThisBeAPandaInstance(self)) {
|
||||
void *result = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, classdef);
|
||||
|
||||
} 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());
|
||||
}
|
||||
}
|
||||
|
||||
} 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 ";
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
string msg = str.str();
|
||||
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
||||
return PyErr_Format(PyExc_TypeError,
|
||||
"%s() argument %d may not be const",
|
||||
function_name.c_str(), param);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (report_errors) {
|
||||
PyErr_SetString(PyExc_TypeError, "self is NULL");
|
||||
}
|
||||
}
|
||||
|
||||
if (report_errors) {
|
||||
return Dtool_Raise_ArgTypeError(self, param, function_name.c_str(), classdef->_PyType.tp_name);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
@ -304,31 +182,175 @@ void *DTOOL_Call_GetPointerThis(PyObject *self) {
|
|||
return pyself->_ptr_to_object;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Dtool_CheckErrorOccurred
|
||||
// Description: This is similar to a PyErr_Occurred() check, except
|
||||
// that it also checks Notify to see if an assertion
|
||||
// has occurred. If that is the case, then it raises
|
||||
// an AssertionError.
|
||||
//
|
||||
// Returns true if there is an active exception, false
|
||||
// otherwise.
|
||||
//
|
||||
// In the NDEBUG case, this is simply a #define to
|
||||
// _PyErr_OCCURRED() (which is an undocumented inline
|
||||
// version of PyErr_Occurred()).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Dtool_CheckErrorOccurred() {
|
||||
if (_PyErr_OCCURRED()) {
|
||||
return true;
|
||||
}
|
||||
if (Notify::ptr()->has_assert_failed()) {
|
||||
Dtool_Raise_AssertionError();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Dtool_Raise_AssertionError
|
||||
// Description: Raises an AssertionError containing the last thrown
|
||||
// assert message, and clears the assertion flag.
|
||||
// Returns NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PyObject *Dtool_Raise_AssertionError() {
|
||||
Notify *notify = Notify::ptr();
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject *message = PyUnicode_FromString(notify->get_assert_error_message().c_str());
|
||||
#else
|
||||
PyObject *message = PyString_FromString(notify->get_assert_error_message().c_str());
|
||||
#endif
|
||||
Py_INCREF(PyExc_AssertionError);
|
||||
PyErr_Restore(PyExc_AssertionError, message, (PyObject *)NULL);
|
||||
notify->clear_assert_failed();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Dtool_Raise_TypeError
|
||||
// Description: Raises a TypeError with the given message, and
|
||||
// returns NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PyObject *Dtool_Raise_TypeError(const char *message) {
|
||||
// PyErr_Restore is what PyErr_SetString would have ended up calling
|
||||
// eventually anyway, so we might as well just get to the point.
|
||||
Py_INCREF(PyExc_TypeError);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyErr_Restore(PyExc_TypeError, PyUnicode_FromString(message), (PyObject *)NULL);
|
||||
#else
|
||||
PyErr_Restore(PyExc_TypeError, PyString_FromString(message), (PyObject *)NULL);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Dtool_Raise_ArgTypeError
|
||||
// Description: Raises a TypeError of the form:
|
||||
// function_name() argument n must be type, not type
|
||||
// for a given object passed to a function.
|
||||
//
|
||||
// Always returns NULL so that it can be conveniently
|
||||
// used as a return expression for wrapper functions
|
||||
// that return a PyObject pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PyObject *Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject *message = PyUnicode_FromFormat(
|
||||
#else
|
||||
PyObject *message = PyString_FromFormat(
|
||||
#endif
|
||||
"%s() argument %d must be %s, not %s",
|
||||
function_name, param, type_name,
|
||||
Py_TYPE(obj)->tp_name);
|
||||
|
||||
Py_INCREF(PyExc_TypeError);
|
||||
PyErr_Restore(PyExc_TypeError, message, (PyObject *)NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Dtool_Raise_BadArgumentsError
|
||||
// Description: Raises a TypeError of the form:
|
||||
// Arguments must match:
|
||||
// <list of overloads>
|
||||
//
|
||||
// However, in release builds, this instead is defined
|
||||
// to a function that just prints out a generic
|
||||
// message, to help reduce the amount of strings in
|
||||
// the compiled library.
|
||||
//
|
||||
// Always returns NULL so that it can be conveniently
|
||||
// used as a return expression for wrapper functions
|
||||
// that return a PyObject pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PyObject *_Dtool_Raise_BadArgumentsError() {
|
||||
return Dtool_Raise_TypeError("arguments do not match any function overload");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Dtool_Return_None
|
||||
// Description: Convenience method that checks for exceptions, and
|
||||
// if one occurred, returns NULL, otherwise Py_None.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PyObject *_Dtool_Return_None() {
|
||||
if (_PyErr_OCCURRED()) {
|
||||
return NULL;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
if (Notify::ptr()->has_assert_failed()) {
|
||||
return Dtool_Raise_AssertionError();
|
||||
}
|
||||
#endif
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Dtool_Return_Bool
|
||||
// Description: Convenience method that checks for exceptions, and
|
||||
// if one occurred, returns NULL, otherwise the given
|
||||
// boolean value as a PyObject *.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PyObject *Dtool_Return_Bool(bool value) {
|
||||
if (_PyErr_OCCURRED()) {
|
||||
return NULL;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
if (Notify::ptr()->has_assert_failed()) {
|
||||
return Dtool_Raise_AssertionError();
|
||||
}
|
||||
#endif
|
||||
PyObject *result = (value ? Py_True : Py_False);
|
||||
Py_INCREF(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Function : DTool_CreatePyInstanceTyped
|
||||
//
|
||||
// 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) {
|
||||
if (local_this_in == NULL) {
|
||||
// Let's not be stupid..
|
||||
PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this'");
|
||||
return NULL;
|
||||
}
|
||||
PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &known_class_type, bool memory_rules, bool is_const, int type_index) {
|
||||
// We can't do the NULL check here like in DTool_CreatePyInstance, since
|
||||
// the caller will have to get the type index to pass to this function
|
||||
// to begin with. That code probably would have crashed by now if it was
|
||||
// really NULL for whatever reason.
|
||||
nassertr(local_this_in != NULL, NULL);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// 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 +365,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 +382,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;
|
||||
|
|
@ -372,8 +394,10 @@ PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &
|
|||
////////////////////////////////////////////////////////////////////////
|
||||
PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_classdef, bool memory_rules, bool is_const) {
|
||||
if (local_this == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "C Function Return Null 'this'");
|
||||
return NULL;
|
||||
// This is actually a very common case, so let's allow this, but return
|
||||
// Py_None consistently. This eliminates code in the wrappers.
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
Dtool_PyTypedObject *classdef = &in_classdef;
|
||||
|
|
@ -425,7 +449,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 +460,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -495,11 +520,10 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
|
|||
|
||||
if (module == NULL) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyErr_SetString(PyExc_TypeError, "PyModule_Create returned NULL");
|
||||
return Dtool_Raise_TypeError("PyModule_Create returned NULL");
|
||||
#else
|
||||
PyErr_SetString(PyExc_TypeError, "Py_InitModule returned NULL");
|
||||
return Dtool_Raise_TypeError("Py_InitModule returned NULL");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// the constant inits... enums, classes ...
|
||||
|
|
@ -508,7 +532,6 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
|
|||
}
|
||||
|
||||
PyModule_AddIntConstant(module, "Dtool_PyNativeInterface", 1);
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
|
|
@ -523,20 +546,26 @@ 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??");
|
||||
|
||||
return 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 ??");
|
||||
return Dtool_Raise_TypeError("One of these does not appear to be DTOOL Instance ??");
|
||||
}
|
||||
}
|
||||
return (PyObject *) NULL;
|
||||
|
|
@ -551,16 +580,17 @@ PyObject *Dtool_AddToDictionary(PyObject *self1, PyObject *args) {
|
|||
PyObject *key;
|
||||
if (PyArg_ParseTuple(args, "OSO", &self, &key, &subject)) {
|
||||
PyObject *dict = ((PyTypeObject *)self)->tp_dict;
|
||||
if (dict == NULL && !PyDict_Check(dict)) {
|
||||
PyErr_SetString(PyExc_TypeError, "No dictionary On Object");
|
||||
if (dict == NULL || !PyDict_Check(dict)) {
|
||||
return Dtool_Raise_TypeError("No dictionary On Object");
|
||||
} else {
|
||||
PyDict_SetItem(dict,key,subject);
|
||||
PyDict_SetItem(dict, key, subject);
|
||||
}
|
||||
}
|
||||
if (PyErr_Occurred()) {
|
||||
return (PyObject *)NULL;
|
||||
}
|
||||
return Py_BuildValue("");
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -725,7 +755,7 @@ PyObject *make_list_for_item(PyObject *self, const char *num_name,
|
|||
Py_DECREF(list);
|
||||
return NULL;
|
||||
}
|
||||
PyList_SetItem(list, i, element);
|
||||
PyList_SET_ITEM(list, i, element);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
@ -772,18 +802,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
|
||||
|
|
|
|||
|
|
@ -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,31 @@ inline PyObject* doPy_RETURN_FALSE()
|
|||
#define Py_TPFLAGS_CHECKTYPES 0
|
||||
#endif
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
#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_Check(x) PyLong_Check(x)
|
||||
#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
|
||||
#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_FromLong PyInt_FromLong
|
||||
|
||||
// For more portably defining hash functions.
|
||||
typedef long Py_hash_t;
|
||||
#endif
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
#define nb_nonzero nb_bool
|
||||
#define nb_divide nb_true_divide
|
||||
#define nb_inplace_divide nb_inplace_true_divide
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define PY_PANDA_SMALLER_FOOTPRINT 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// this is tempory .. untill this is glued better into the panda build system
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -138,42 +150,39 @@ 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 ;
|
||||
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;
|
||||
// This is a pointer to the Dtool_PyTypedObject type. It's tempting
|
||||
// not to store this and to instead use PY_TYPE(self) and upcast that,
|
||||
// but that breaks when someone inherits from our class in Python.
|
||||
struct Dtool_PyTypedObject *_My_Type;
|
||||
|
||||
// Pointer to the underlying C++ object.
|
||||
void *_ptr_to_object;
|
||||
|
||||
// This is always set to PY_PANDA_SIGNATURE, so that we can quickly
|
||||
// detect whether an object is a Panda object.
|
||||
unsigned short _signature;
|
||||
|
||||
// True if we own the pointer and should delete it or unref it.
|
||||
bool _memory_rules;
|
||||
|
||||
// True if this is a "const" pointer.
|
||||
bool _is_const;
|
||||
};
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// A Offset Dictionary Defining How to read the Above Object..
|
||||
|
|
@ -188,144 +197,85 @@ 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; };
|
||||
inline PyObject &As_PyObject() { return (PyObject &)_PyType; };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Macros from Hell.. May want to just add this to the code generator..
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
#define Define_Dtool_PyTypedObject(MODULE_NAME, CLASS_NAME, PUBLIC_NAME) \
|
||||
EXPORT_THIS Dtool_PyTypedObject Dtool_##CLASS_NAME = \
|
||||
{ \
|
||||
{ \
|
||||
PyVarObject_HEAD_INIT(NULL, 0) \
|
||||
#MODULE_NAME "." #PUBLIC_NAME, /*type name with module */ \
|
||||
sizeof(Dtool_PyInstDef), /* tp_basicsize */ \
|
||||
0, /* tp_itemsize */ \
|
||||
&Dtool_Deallocate_General, /* tp_dealloc */ \
|
||||
0, /* tp_print */ \
|
||||
0, /* tp_getattr */ \
|
||||
0, /* tp_setattr */ \
|
||||
0, /* tp_compare */ \
|
||||
0, /* tp_repr */ \
|
||||
&Dtool_PyNumberMethods_##CLASS_NAME, /* tp_as_number */ \
|
||||
&Dtool_PySequenceMethods_##CLASS_NAME, /* tp_as_sequence */ \
|
||||
&Dtool_PyMappingMethods_##CLASS_NAME, /* tp_as_mapping */ \
|
||||
0, /* tp_hash */ \
|
||||
0, /* tp_call */ \
|
||||
0, /* tp_str */ \
|
||||
PyObject_GenericGetAttr, /* tp_getattro */ \
|
||||
PyObject_GenericSetAttr, /* tp_setattro */ \
|
||||
&Dtool_PyBufferProcs_##CLASS_NAME, /* tp_as_buffer */ \
|
||||
(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES), /* tp_flags */ \
|
||||
0, /* tp_doc */ \
|
||||
0, /* tp_traverse */ \
|
||||
0, /* tp_clear */ \
|
||||
0, /* tp_richcompare */ \
|
||||
0, /* tp_weaklistoffset */ \
|
||||
0, /* tp_iter */ \
|
||||
0, /* tp_iternext */ \
|
||||
Dtool_Methods_##CLASS_NAME, /* tp_methods */ \
|
||||
standard_type_members, /* tp_members */ \
|
||||
0, /* tp_getset */ \
|
||||
0, /* tp_base */ \
|
||||
0, /* tp_dict */ \
|
||||
0, /* tp_descr_get */ \
|
||||
0, /* tp_descr_set */ \
|
||||
0, /* tp_dictoffset */ \
|
||||
Dtool_Init_##CLASS_NAME, /* tp_init */ \
|
||||
PyType_GenericAlloc, /* tp_alloc */ \
|
||||
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 \
|
||||
};
|
||||
|
||||
#define Define_Dtool_Class(MODULE_NAME, CLASS_NAME, PUBLIC_NAME) \
|
||||
static PyNumberMethods Dtool_PyNumberMethods_##CLASS_NAME = {0}; \
|
||||
static PySequenceMethods Dtool_PySequenceMethods_##CLASS_NAME = {0}; \
|
||||
static PyMappingMethods Dtool_PyMappingMethods_##CLASS_NAME = {0}; \
|
||||
static PyBufferProcs Dtool_PyBufferProcs_##CLASS_NAME = {0}; \
|
||||
Define_Dtool_PyTypedObject(MODULE_NAME, CLASS_NAME, PUBLIC_NAME)
|
||||
// This is now simply a forward declaration. The actual definition is created
|
||||
// by the code generator.
|
||||
#define Define_Dtool_Class(MODULE_NAME, CLASS_NAME, PUBLIC_NAME) \
|
||||
extern Dtool_PyTypedObject Dtool_##CLASS_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);\
|
||||
}
|
||||
|
||||
#define Define_Dtool_Simple_FreeInstance(CLASS_NAME, CNAME)\
|
||||
static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
|
||||
((Dtool_InstDef_##CLASS_NAME *)self)->_value.~##CLASS_NAME();\
|
||||
Py_TYPE(self)->tp_free(self);\
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -333,38 +283,124 @@ 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);
|
||||
|
||||
EXPCL_DTOOLCONFIG bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer);
|
||||
|
||||
EXPCL_DTOOLCONFIG 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;
|
||||
}
|
||||
|
||||
// Functions related to error reporting.
|
||||
|
||||
#ifdef NDEBUG
|
||||
// _PyErr_OCCURRED is an undocumented inline version of PyErr_Occurred.
|
||||
#define Dtool_CheckErrorOccurred() (_PyErr_OCCURRED() != NULL)
|
||||
#else
|
||||
EXPCL_DTOOLCONFIG bool Dtool_CheckErrorOccurred();
|
||||
#endif
|
||||
|
||||
EXPCL_DTOOLCONFIG PyObject *Dtool_Raise_AssertionError();
|
||||
EXPCL_DTOOLCONFIG PyObject *Dtool_Raise_TypeError(const char *message);
|
||||
EXPCL_DTOOLCONFIG PyObject *Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name);
|
||||
|
||||
EXPCL_DTOOLCONFIG PyObject *_Dtool_Raise_BadArgumentsError();
|
||||
#ifdef NDEBUG
|
||||
// Define it to a function that just prints a generic message.
|
||||
#define Dtool_Raise_BadArgumentsError(x) _Dtool_Raise_BadArgumentsError()
|
||||
#else
|
||||
// Expand this to a TypeError listing all of the overloads.
|
||||
#define Dtool_Raise_BadArgumentsError(x) Dtool_Raise_TypeError("Arguments must match:\n" x)
|
||||
#endif
|
||||
|
||||
EXPCL_DTOOLCONFIG PyObject *_Dtool_Return_None();
|
||||
EXPCL_DTOOLCONFIG PyObject *Dtool_Return_Bool(bool value);
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define Dtool_Return_None() (_PyErr_OCCURRED() != NULL ? NULL : (Py_INCREF(Py_None), Py_None))
|
||||
#else
|
||||
#define Dtool_Return_None() _Dtool_Return_None()
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -372,13 +408,10 @@ EXPCL_DTOOLCONFIG PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTyp
|
|||
|
||||
#define Define_Module_Class_Internal(MODULE_NAME,CLASS_NAME,CNAME)\
|
||||
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)\
|
||||
|
|
@ -408,14 +441,13 @@ Define_Dtool_new(CLASS_NAME,CNAME)\
|
|||
Define_Dtool_FreeInstanceRef(CLASS_NAME,CNAME)\
|
||||
Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME)
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Th Finalizer for simple instances..
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
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_
|
||||
|
|
|
|||
|
|
@ -26,14 +26,31 @@ 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;
|
||||
struct Py_buffer;
|
||||
|
||||
// We need to define these accurately since interrogate may want to
|
||||
// write these out to default value assignments.
|
||||
PyObject _Py_NoneStruct;
|
||||
PyObject _Py_TrueStruct;
|
||||
#define Py_None (&_Py_NoneStruct)
|
||||
#define Py_True ((PyObject *) &_Py_TrueStruct)
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject _Py_ZeroStruct;
|
||||
#define Py_False ((PyObject *) &_Py_ZeroStruct)
|
||||
#else
|
||||
PyObject _Py_FalseStruct;
|
||||
#define Py_False ((PyObject *) &_Py_FalseStruct)
|
||||
#endif
|
||||
|
||||
// This file defines PY_VERSION_HEX, which is used in some places.
|
||||
#include "patchlevel.h"
|
||||
|
||||
typedef void *visitproc;
|
||||
|
||||
#endif // PYTHON_H
|
||||
|
|
|
|||
|
|
@ -20,11 +20,12 @@
|
|||
#ifndef CG_H
|
||||
#define CG_H
|
||||
|
||||
typedef int CGcontext;
|
||||
typedef int CGprogram;
|
||||
typedef int CGparameter;
|
||||
typedef int CGprofile;
|
||||
typedef int CGerror;
|
||||
typedef struct _CGcontext *CGcontext;
|
||||
typedef struct _CGcontext *CGcontext;
|
||||
typedef struct _CGprogram *CGprogram;
|
||||
typedef struct _CGparameter *CGparameter;
|
||||
|
||||
typedef enum {} CGprofile;
|
||||
typedef enum {} CGerror;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@ __published:
|
|||
};
|
||||
enum openmode {
|
||||
};
|
||||
// Don't define these lest interrogate get tempted to actually
|
||||
// substitute in the values, which are implementation-defined.
|
||||
static const openmode app;
|
||||
static const openmode binary;
|
||||
static const openmode in;
|
||||
static const openmode out;
|
||||
static const openmode trunc;
|
||||
};
|
||||
class ios : public ios_base {
|
||||
__published:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -38,7 +38,11 @@ typedef unsigned long ulong;
|
|||
typedef unsigned short ushort;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
typedef int fd_set;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@
|
|||
template<class ctype>
|
||||
class basic_string {
|
||||
public:
|
||||
typedef typename size_t size_type;
|
||||
static const size_t npos;
|
||||
|
||||
basic_string();
|
||||
basic_string(const basic_string ©);
|
||||
void operator = (const basic_string ©);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ typedef long DWORD;
|
|||
typedef long LONG;
|
||||
typedef long UINT;
|
||||
typedef unsigned long ULONG;
|
||||
typedef signed __int64 LONGLONG;
|
||||
typedef signed long long LONGLONG;
|
||||
typedef long HRESULT;
|
||||
typedef int CRITICAL_SECTION;
|
||||
typedef int HANDLE;
|
||||
|
|
@ -45,12 +45,12 @@ typedef struct _STICKYKEYS STICKYKEYS;
|
|||
typedef struct _TOGGLEKEYS TOGGLEKEYS;
|
||||
typedef struct _FILTERKEYS FILTERKEYS;
|
||||
|
||||
#define CALLBACK
|
||||
#define CALLBACK
|
||||
|
||||
#define WINAPI
|
||||
|
||||
union LARGE_INTEGER {
|
||||
__int64 QuadPart;
|
||||
long long QuadPart;
|
||||
};
|
||||
|
||||
class IGraphBuilder;
|
||||
|
|
|
|||
|
|
@ -2,16 +2,8 @@
|
|||
#define _WINSOCK2API_
|
||||
#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
|
||||
|
||||
typedef int SOCKET ;
|
||||
typedef int SOCKET;
|
||||
|
||||
struct sockaddr_in
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
typedef struct fd_set {
|
||||
unsigned int fd_count; /* how many are SET? */
|
||||
SOCKET fd_array[10]; /* an array of SOCKETs */
|
||||
} fd_set;
|
||||
struct sockaddr_in;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -182,54 +182,6 @@ get_assert_handler() const {
|
|||
return _assert_handler;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Notify::has_assert_failed
|
||||
// Access: Public
|
||||
// Description: Returns true if an assertion test has failed (and not
|
||||
// been ignored) since the last call to
|
||||
// clear_assert_failed().
|
||||
//
|
||||
// When an assertion test fails, the assert handler
|
||||
// may decide either to abort, return, or ignore the
|
||||
// assertion. Naturally, if it decides to abort, this
|
||||
// flag is irrelevant. If it chooses to ignore the
|
||||
// assertion, the flag is not set. However, if the
|
||||
// assert handler chooses to return out of the
|
||||
// function (the normal case), it will also set this
|
||||
// flag to indicate that an assertion failure has
|
||||
// occurred.
|
||||
//
|
||||
// This will also be the behavior in the absence of a
|
||||
// user-defined assert handler.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Notify::
|
||||
has_assert_failed() const {
|
||||
return _assert_failed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Notify::get_assert_error_message
|
||||
// Access: Public
|
||||
// Description: Returns the error message that corresponds to the
|
||||
// assertion that most recently failed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const string &Notify::
|
||||
get_assert_error_message() const {
|
||||
return _assert_error_message;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Notify::clear_assert_failed
|
||||
// Access: Public
|
||||
// Description: Resets the assert_failed flag that is set whenever an
|
||||
// assertion test fails. See has_assert_failed().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Notify::
|
||||
clear_assert_failed() {
|
||||
_assert_failed = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Notify::get_top_category
|
||||
// Access: Public
|
||||
|
|
@ -269,7 +221,7 @@ get_category(const string &basename, NotifyCategory *parent_category) {
|
|||
}
|
||||
}
|
||||
|
||||
pair<Categories::iterator, bool> result =
|
||||
pair<Categories::iterator, bool> result =
|
||||
_categories.insert(Categories::value_type(fullname, (NotifyCategory *)NULL));
|
||||
|
||||
bool inserted = result.second;
|
||||
|
|
@ -458,7 +410,7 @@ assert_failure(const char *expression, int line,
|
|||
// the debugger? abort() doesn't do it. We used to be able to
|
||||
// assert(false), but in VC++ 7 that just throws an exception, and
|
||||
// an uncaught exception just exits, without offering to open the
|
||||
// debugger.
|
||||
// debugger.
|
||||
|
||||
// DebugBreak() seems to be provided for this purpose, but it
|
||||
// doesn't seem to work properly either, since we don't seem to
|
||||
|
|
@ -567,7 +519,7 @@ config_initialized() {
|
|||
dup2(logfile_fd, STDOUT_FILENO);
|
||||
dup2(logfile_fd, STDERR_FILENO);
|
||||
close(logfile_fd);
|
||||
|
||||
|
||||
set_ostream_ptr(&cerr, false);
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -12,3 +12,50 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Notify::has_assert_failed
|
||||
// Access: Public
|
||||
// Description: Returns true if an assertion test has failed (and not
|
||||
// been ignored) since the last call to
|
||||
// clear_assert_failed().
|
||||
//
|
||||
// When an assertion test fails, the assert handler
|
||||
// may decide either to abort, return, or ignore the
|
||||
// assertion. Naturally, if it decides to abort, this
|
||||
// flag is irrelevant. If it chooses to ignore the
|
||||
// assertion, the flag is not set. However, if the
|
||||
// assert handler chooses to return out of the
|
||||
// function (the normal case), it will also set this
|
||||
// flag to indicate that an assertion failure has
|
||||
// occurred.
|
||||
//
|
||||
// This will also be the behavior in the absence of a
|
||||
// user-defined assert handler.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Notify::
|
||||
has_assert_failed() const {
|
||||
return _assert_failed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Notify::get_assert_error_message
|
||||
// Access: Public
|
||||
// Description: Returns the error message that corresponds to the
|
||||
// assertion that most recently failed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &Notify::
|
||||
get_assert_error_message() const {
|
||||
return _assert_error_message;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Notify::clear_assert_failed
|
||||
// Access: Public
|
||||
// Description: Resets the assert_failed flag that is set whenever an
|
||||
// assertion test fails. See has_assert_failed().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Notify::
|
||||
clear_assert_failed() {
|
||||
_assert_failed = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ PUBLISHED:
|
|||
bool has_assert_handler() const;
|
||||
AssertHandler *get_assert_handler() const;
|
||||
|
||||
bool has_assert_failed() const;
|
||||
const string &get_assert_error_message() const;
|
||||
void clear_assert_failed();
|
||||
INLINE bool has_assert_failed() const;
|
||||
INLINE const string &get_assert_error_message() const;
|
||||
INLINE void clear_assert_failed();
|
||||
|
||||
NotifyCategory *get_top_category();
|
||||
NotifyCategory *get_category(const string &basename,
|
||||
|
|
|
|||
|
|
@ -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(...);
|
||||
|
|
@ -122,6 +123,7 @@ extern "C" {
|
|||
EXPCL_PYSTUB int PySequence_Tuple(...);
|
||||
EXPCL_PYSTUB int PyString_AsString(...);
|
||||
EXPCL_PYSTUB int PyString_AsStringAndSize(...);
|
||||
EXPCL_PYSTUB int PyString_FromFormat(...);
|
||||
EXPCL_PYSTUB int PyString_FromString(...);
|
||||
EXPCL_PYSTUB int PyString_FromStringAndSize(...);
|
||||
EXPCL_PYSTUB int PyString_InternFromString(...);
|
||||
|
|
@ -153,6 +155,8 @@ 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_FromFormat(...);
|
||||
EXPCL_PYSTUB int PyUnicode_FromString(...);
|
||||
EXPCL_PYSTUB int PyUnicode_FromStringAndSize(...);
|
||||
EXPCL_PYSTUB int PyUnicode_FromWideChar(...);
|
||||
|
|
@ -192,6 +196,7 @@ extern "C" {
|
|||
EXPCL_PYSTUB extern void *PyExc_SystemExit;
|
||||
EXPCL_PYSTUB extern void *PyExc_TypeError;
|
||||
EXPCL_PYSTUB extern void *PyExc_ValueError;
|
||||
EXPCL_PYSTUB extern void *_PyThreadState_Current;
|
||||
EXPCL_PYSTUB extern void *_Py_FalseStruct;
|
||||
EXPCL_PYSTUB extern void *_Py_NoneStruct;
|
||||
EXPCL_PYSTUB extern void *_Py_NotImplementedStruct;
|
||||
|
|
@ -264,6 +269,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; }
|
||||
|
|
@ -307,6 +313,7 @@ int PySequence_Size(...) { return 0; }
|
|||
int PySequence_Tuple(...) { return 0; }
|
||||
int PyString_AsString(...) { return 0; }
|
||||
int PyString_AsStringAndSize(...) { return 0; }
|
||||
int PyString_FromFormat(...) { return 0; }
|
||||
int PyString_FromString(...) { return 0; }
|
||||
int PyString_FromStringAndSize(...) { return 0; }
|
||||
int PyString_InternFromString(...) { return 0; }
|
||||
|
|
@ -338,6 +345,8 @@ 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_FromFormat(...) { return 0; }
|
||||
int PyUnicode_FromString(...) { return 0; }
|
||||
int PyUnicode_FromStringAndSize(...) { return 0; }
|
||||
int PyUnicode_FromWideChar(...) { return 0; }
|
||||
|
|
@ -382,6 +391,7 @@ void *PyExc_StopIteration = (void *)NULL;
|
|||
void *PyExc_SystemExit = (void *)NULL;
|
||||
void *PyExc_TypeError = (void *)NULL;
|
||||
void *PyExc_ValueError = (void *)NULL;
|
||||
void *_PyThreadState_Current = (void *)NULL;
|
||||
void *_Py_FalseStruct = (void *)NULL;
|
||||
void *_Py_NoneStruct = (void *)NULL;
|
||||
void *_Py_NotImplementedStruct = (void *)NULL;
|
||||
|
|
|
|||
|
|
@ -1262,7 +1262,7 @@ def CompileIgate(woutd,wsrc,opts):
|
|||
|
||||
cmd += ' -srcdir %s -I%s -Dvolatile -Dmutable' % (srcdir, srcdir)
|
||||
if (COMPILER=="MSVC"):
|
||||
cmd += ' -DCPPPARSER -D__STDC__=1 -D__cplusplus -D__inline -longlong __int64 -D_X86_ -DWIN32_VC -DWIN32 -D_WIN32'
|
||||
cmd += ' -DCPPPARSER -D__STDC__=1 -D__cplusplus -D__inline -D_X86_ -DWIN32_VC -DWIN32 -D_WIN32'
|
||||
if GetTargetArch() == 'x64':
|
||||
cmd += ' -DWIN64_VC -DWIN64 -D_WIN64'
|
||||
# NOTE: this 1600 value is the version number for VC2010.
|
||||
|
|
|
|||
|
|
@ -2463,13 +2463,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))
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ get_raw_pointer() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::set_device_index
|
||||
// Access: Public
|
||||
// Description: Set the device index. This is reported in pointer
|
||||
// Description: Set the device index. This is reported in pointer
|
||||
// events. The device index will be equal to the position
|
||||
// of the GraphicsWindowInputDevice in the window's list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -117,9 +117,116 @@ disable_pointer_events() {
|
|||
_pointer_events.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::button_down
|
||||
// Access: Published
|
||||
// Description: Records that the indicated button has been depressed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsWindowInputDevice::
|
||||
button_down(ButtonHandle button) {
|
||||
button_down(button, ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::button_resume_down
|
||||
// Access: Published
|
||||
// Description: Records that the indicated button was depressed
|
||||
// earlier, and we only just detected the event after
|
||||
// the fact. This is mainly useful for tracking the
|
||||
// state of modifier keys.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsWindowInputDevice::
|
||||
button_resume_down(ButtonHandle button) {
|
||||
button_resume_down(button, ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::button_up
|
||||
// Access: Published
|
||||
// Description: Records that the indicated button has been released.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsWindowInputDevice::
|
||||
button_up(ButtonHandle button) {
|
||||
button_up(button, ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::keystroke
|
||||
// Access: Published
|
||||
// Description: Records that the indicated keystroke has been
|
||||
// generated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsWindowInputDevice::
|
||||
keystroke(int keycode) {
|
||||
keystroke(keycode, ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::focus_lost
|
||||
// Access: Published
|
||||
// Description: This should be called when the window focus is lost,
|
||||
// so that we may miss upcoming button events
|
||||
// (especially "up" events) for the next period of time.
|
||||
// It generates keyboard and mouse "up" events for those
|
||||
// buttons that we previously sent unpaired "down"
|
||||
// events, so that the Panda application will believe
|
||||
// all buttons are now released.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsWindowInputDevice::
|
||||
focus_lost() {
|
||||
focus_lost(ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::raw_button_down
|
||||
// Access: Published
|
||||
// Description: Records that the indicated button has been depressed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsWindowInputDevice::
|
||||
raw_button_down(ButtonHandle button) {
|
||||
raw_button_down(button, ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::raw_button_up
|
||||
// Access: Published
|
||||
// Description: Records that the indicated button has been released.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsWindowInputDevice::
|
||||
raw_button_up(ButtonHandle button) {
|
||||
raw_button_up(button, ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::set_pointer_in_window
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: To be called by a particular kind of GraphicsWindow
|
||||
// to indicate that the pointer is within the window, at
|
||||
// the given pixel coordinates.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsWindowInputDevice::
|
||||
set_pointer_in_window(double x, double y) {
|
||||
// mutex is handled in set pointer .. convience function
|
||||
set_pointer(true, x, y, ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::set_pointer_out_of_window
|
||||
// Access: Published
|
||||
// Description: To be called by a particular kind of GraphicsWindow
|
||||
// to indicate that the pointer is no longer within the
|
||||
// window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsWindowInputDevice::
|
||||
set_pointer_out_of_window() {
|
||||
// mutex is handled in set pointer .. convience function
|
||||
set_pointer(false, _mouse_data._xpos, _mouse_data._ypos,
|
||||
ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::set_pointer_in_window
|
||||
// Access: Published
|
||||
// Description: To be called by a particular kind of GraphicsWindow
|
||||
// to indicate that the pointer is within the window, at
|
||||
// the given pixel coordinates.
|
||||
|
|
@ -132,7 +239,7 @@ set_pointer_in_window(double x, double y, double time) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::set_pointer_out_of_window
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: To be called by a particular kind of GraphicsWindow
|
||||
// to indicate that the pointer is no longer within the
|
||||
// window.
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ pointer_and_keyboard(GraphicsWindow *host, const string &name) {
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsWindowInputDevice::
|
||||
GraphicsWindowInputDevice(const GraphicsWindowInputDevice ©)
|
||||
GraphicsWindowInputDevice(const GraphicsWindowInputDevice ©)
|
||||
{
|
||||
*this = copy;
|
||||
}
|
||||
|
|
@ -105,7 +105,7 @@ GraphicsWindowInputDevice(const GraphicsWindowInputDevice ©)
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindowInputDevice::
|
||||
operator = (const GraphicsWindowInputDevice ©)
|
||||
operator = (const GraphicsWindowInputDevice ©)
|
||||
{
|
||||
LightMutexHolder holder(_lock);
|
||||
LightMutexHolder holder1(copy._lock);
|
||||
|
|
@ -165,7 +165,7 @@ get_button_event() {
|
|||
// Function: GraphicsWindowInputDevice::has_pointer_event
|
||||
// Access: Public
|
||||
// Description: Returns true if this device has a pending pointer
|
||||
// event (a mouse movement), or false otherwise. If
|
||||
// event (a mouse movement), or false otherwise. If
|
||||
// this returns true, the particular event may be
|
||||
// extracted via get_pointer_event().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -234,7 +234,7 @@ disable_pointer_mode() {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::set_pointer
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Records that a mouse movement has taken place.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindowInputDevice::
|
||||
|
|
@ -264,7 +264,7 @@ set_pointer(bool inwin, double x, double y, double time) {
|
|||
} else {
|
||||
_mouse_data = _true_mouse_data;
|
||||
}
|
||||
|
||||
|
||||
if (_enable_pointer_events) {
|
||||
int seq = _event_sequence++;
|
||||
if (_pointer_events == 0) {
|
||||
|
|
@ -279,7 +279,7 @@ set_pointer(bool inwin, double x, double y, double time) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::button_down
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Records that the indicated button has been depressed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindowInputDevice::
|
||||
|
|
@ -291,7 +291,7 @@ button_down(ButtonHandle button, double time) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::button_resume_down
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Records that the indicated button was depressed
|
||||
// earlier, and we only just detected the event after
|
||||
// the fact. This is mainly useful for tracking the
|
||||
|
|
@ -300,14 +300,13 @@ button_down(ButtonHandle button, double time) {
|
|||
void GraphicsWindowInputDevice::
|
||||
button_resume_down(ButtonHandle button, double time) {
|
||||
LightMutexHolder holder(_lock);
|
||||
_button_events.push_back(ButtonEvent(button, ButtonEvent::T_resume_down, time)
|
||||
);
|
||||
_button_events.push_back(ButtonEvent(button, ButtonEvent::T_resume_down, time));
|
||||
_buttons_held.insert(button);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::button_up
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Records that the indicated button has been released.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindowInputDevice::
|
||||
|
|
@ -319,7 +318,7 @@ button_up(ButtonHandle button, double time) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::keystroke
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Records that the indicated keystroke has been
|
||||
// generated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -331,24 +330,24 @@ keystroke(int keycode, double time) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::candidate
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Records that the indicated candidate string has been
|
||||
// highlighted. This is used to implement IME support
|
||||
// for typing in international languages, especially
|
||||
// Chinese/Japanese/Korean.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindowInputDevice::
|
||||
candidate(const wstring &candidate_string, size_t highlight_start,
|
||||
candidate(const wstring &candidate_string, size_t highlight_start,
|
||||
size_t highlight_end, size_t cursor_pos) {
|
||||
LightMutexHolder holder(_lock);
|
||||
_button_events.push_back(ButtonEvent(candidate_string,
|
||||
_button_events.push_back(ButtonEvent(candidate_string,
|
||||
highlight_start, highlight_end,
|
||||
cursor_pos));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::focus_lost
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: This should be called when the window focus is lost,
|
||||
// so that we may miss upcoming button events
|
||||
// (especially "up" events) for the next period of time.
|
||||
|
|
@ -369,7 +368,7 @@ focus_lost(double time) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::raw_button_down
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Records that the indicated button has been depressed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindowInputDevice::
|
||||
|
|
@ -380,7 +379,7 @@ raw_button_down(ButtonHandle button, double time) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindowInputDevice::raw_button_up
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Records that the indicated button has been released.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindowInputDevice::
|
||||
|
|
|
|||
|
|
@ -76,18 +76,28 @@ public:
|
|||
PUBLISHED:
|
||||
// The following interface is for the various kinds of
|
||||
// GraphicsWindows to record the data incoming on the device.
|
||||
void button_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
|
||||
void button_resume_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
|
||||
void button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
|
||||
void keystroke(int keycode, double time = ClockObject::get_global_clock()->get_frame_time());
|
||||
void candidate(const wstring &candidate_string, size_t highlight_start,
|
||||
size_t highlight_end, size_t cursor_pos);
|
||||
void focus_lost(double time = ClockObject::get_global_clock()->get_frame_time());
|
||||
void raw_button_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
|
||||
void raw_button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
|
||||
INLINE void button_down(ButtonHandle button);
|
||||
INLINE void button_resume_down(ButtonHandle button);
|
||||
INLINE void button_up(ButtonHandle button);
|
||||
INLINE void keystroke(int keycode);
|
||||
INLINE void focus_lost();
|
||||
INLINE void raw_button_down(ButtonHandle button);
|
||||
INLINE void raw_button_up(ButtonHandle button);
|
||||
INLINE void set_pointer_in_window(double x, double y);
|
||||
INLINE void set_pointer_out_of_window();
|
||||
|
||||
INLINE void set_pointer_in_window(double x, double y, double time = ClockObject::get_global_clock()->get_frame_time());
|
||||
INLINE void set_pointer_out_of_window(double time = ClockObject::get_global_clock()->get_frame_time());
|
||||
void button_down(ButtonHandle button, double time);
|
||||
void button_resume_down(ButtonHandle button, double time);
|
||||
void button_up(ButtonHandle button, double time);
|
||||
void keystroke(int keycode, double time);
|
||||
void candidate(const wstring &candidate_string, size_t highlight_start,
|
||||
size_t highlight_end, size_t cursor_pos);
|
||||
void focus_lost(double time);
|
||||
void raw_button_down(ButtonHandle button, double time);
|
||||
void raw_button_up(ButtonHandle button, double time);
|
||||
|
||||
INLINE void set_pointer_in_window(double x, double y, double time);
|
||||
INLINE void set_pointer_out_of_window(double time);
|
||||
void set_pointer(bool inwin, double x, double y, double time);
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ PUBLISHED:
|
|||
|
||||
virtual void write(ostream &out, int indent_level) const;
|
||||
|
||||
public:
|
||||
Curves _curves_on_surface;
|
||||
Trims _trims;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,17 +51,11 @@ 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
|
||||
// to go.
|
||||
// Ensure that the Python threading system is initialized and ready to go.
|
||||
#ifdef WITH_THREAD // This symbol defined within Python.h
|
||||
|
||||
#if PY_VERSION_HEX >= 0x03020000
|
||||
Py_Initialize();
|
||||
#endif
|
||||
|
||||
PyEval_InitThreads();
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -76,7 +70,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);
|
||||
|
|
@ -123,7 +117,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);
|
||||
|
|
@ -254,53 +248,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
|
||||
|
|
@ -309,8 +286,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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -323,43 +324,64 @@ __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());
|
||||
__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.
|
||||
|
||||
} else if (attr_name == "name") {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyUnicode_FromString(get_name().c_str());
|
||||
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 PyString_FromString(get_name().c_str());
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
"'PythonTask' object has no attribute '%U'",
|
||||
attr);
|
||||
#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);
|
||||
#else
|
||||
return PyInt_FromLong(_task_id);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
return PyMapping_GetItemString(_dict, (char *)attr_name.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// PyDict_GetItem returns a borrowed reference.
|
||||
Py_INCREF(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PythonTask::__traverse__
|
||||
// Access: Published
|
||||
// Description: Called by Python to implement cycle detection.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PythonTask::
|
||||
__traverse__(visitproc visit, void *arg) {
|
||||
Py_VISIT(_function);
|
||||
Py_VISIT(_args);
|
||||
Py_VISIT(_upon_death);
|
||||
Py_VISIT(_owner);
|
||||
Py_VISIT(__dict__);
|
||||
Py_VISIT(_generator);
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PythonTask::__clear__
|
||||
// Access: Published
|
||||
// Description: Called by Python to implement cycle breaking.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PythonTask::
|
||||
__clear__() {
|
||||
Py_CLEAR(_function);
|
||||
Py_CLEAR(_args);
|
||||
Py_CLEAR(_upon_death);
|
||||
Py_CLEAR(_owner);
|
||||
Py_CLEAR(__dict__);
|
||||
Py_CLEAR(_generator);
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#include "asyncTask.h"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
#include "py_panda.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PythonTask
|
||||
// Description : This class exists to allow association of a Python
|
||||
|
|
@ -43,9 +45,47 @@ 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;
|
||||
|
||||
int __traverse__(visitproc visit, void *arg);
|
||||
int __clear__();
|
||||
|
||||
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 +107,6 @@ private:
|
|||
PyObject *_upon_death;
|
||||
PyObject *_owner;
|
||||
bool _registered_to_owner;
|
||||
PyObject *_dict;
|
||||
|
||||
PyObject *_generator;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -84,27 +84,14 @@ PUBLISHED:
|
|||
int compression_level);
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
class EXPCL_PANDAEXPRESS CertRecord {
|
||||
public:
|
||||
CertRecord(X509 *cert);
|
||||
CertRecord(const CertRecord ©);
|
||||
~CertRecord();
|
||||
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 ©);
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -109,6 +109,22 @@ operator T * () const {
|
|||
return (To *)(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointerTo::cheat
|
||||
// Access: Public
|
||||
// Description: Returns a reference to the underlying pointer. This
|
||||
// is a very unsafe method. It's only used by some
|
||||
// interrogate code. If you think this method might be
|
||||
// useful to you, you're probably wrong.
|
||||
//
|
||||
// Promise me you won't use this, okay?
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE T *&PointerTo<T>::
|
||||
cheat() {
|
||||
return (To *&)(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointerTo::p
|
||||
// Access: Published
|
||||
|
|
@ -274,13 +290,28 @@ operator -> () const {
|
|||
// don't care which way it goes because either will be
|
||||
// correct.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T>
|
||||
INLINE ConstPointerTo<T>::
|
||||
operator const T * () const {
|
||||
return (To *)(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConstPointerTo::cheat
|
||||
// Access: Public
|
||||
// Description: Returns a reference to the underlying pointer. This
|
||||
// is a very unsafe method. It's only used by some
|
||||
// interrogate code. If you think this method might be
|
||||
// useful to you, you're probably wrong.
|
||||
//
|
||||
// Promise me you won't use this, okay?
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE const T *&ConstPointerTo<T>::
|
||||
cheat() {
|
||||
return (const To *&)(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConstPointerTo::p
|
||||
// Access: Published
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue