Merge branch 'interrogate-overhaul'

Conflicts:
	panda/src/gobj/texture.h
	panda/src/pnmimage/pnmImage.h
This commit is contained in:
rdb 2015-03-22 21:50:08 +01:00
commit 0570d9536e
148 changed files with 7633 additions and 3254 deletions

View File

@ -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 ')'
{

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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

View File

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

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

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

View File

@ -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();

View File

@ -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.

View File

@ -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);

View File

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

View File

@ -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);

View 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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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; */
}

View File

@ -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

View File

@ -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"

View File

@ -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;

View File

@ -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

View File

@ -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 &copy);
#ifdef HAVE_PYTHON
static PyObject *make(PyObject *classobj);
#endif // HAVE_PYTHON
EXTENSION(static TypeHandle make(PyTypeObject *classobj));
INLINE bool operator == (const TypeHandle &other) const;
INLINE bool operator != (const TypeHandle &other) const;

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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,

View File

@ -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();

View File

@ -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();

View File

@ -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"

View File

@ -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 &params =
_ftype->_parameters->_parameters;
for (int i = 0; i < (int)params.size() - _num_default_parameters; i++) {
CPPType *type = params[i]->_type->resolve_type(&parser, _cppscope);
//CPPType *type = params[i]->_type->resolve_type(&parser, _cppscope);
CPPType *type = params[i]->_type;
Parameter param;
param._has_name = true;
param._name = params[i]->get_simple_name();
@ -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;
}

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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 *&param
// Also, if this is really some local type, we can presumably
// just move it?
out << "MOVE(" << variable_name.substr(1) << ")";
} else {
out << "*" << variable_name;
}
}
////////////////////////////////////////////////////////////////////

View File

@ -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 *&param
// 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;
}
}
////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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);
};

View File

@ -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

View File

@ -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

View File

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

View File

@ -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;

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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;

View File

@ -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 &copy);
void operator = (const basic_string &copy);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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.

View File

@ -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))

View File

@ -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.

View File

@ -94,7 +94,7 @@ pointer_and_keyboard(GraphicsWindow *host, const string &name) {
// Description:
////////////////////////////////////////////////////////////////////
GraphicsWindowInputDevice::
GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy)
GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy)
{
*this = copy;
}
@ -105,7 +105,7 @@ GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy)
// Description:
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
operator = (const GraphicsWindowInputDevice &copy)
operator = (const GraphicsWindowInputDevice &copy)
{
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::

View File

@ -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:

View File

@ -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;

View File

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

View File

@ -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;
}
}

View File

@ -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;
}
////////////////////////////////////////////////////////////////////

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -84,27 +84,14 @@ PUBLISHED:
int compression_level);
#ifdef HAVE_OPENSSL
class EXPCL_PANDAEXPRESS CertRecord {
public:
CertRecord(X509 *cert);
CertRecord(const CertRecord &copy);
~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 &copy);
INLINE ~CertRecord();
INLINE void operator = (const CertRecord &other);
X509 *_cert;
};
typedef pvector<CertRecord> CertChain;
bool add_signature(X509 *certificate, STACK_OF(X509) *chain, EVP_PKEY *pkey);
bool add_signature(const CertChain &chain, EVP_PKEY *pkey);
const CertChain &get_signature(int n) const;
#endif // HAVE_OPENSSL
bool read_subfile(int index, string &result);
bool read_subfile(int index, pvector<unsigned char> &result);

View File

@ -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"

View File

@ -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