This commit is contained in:
David Rose 2017-01-04 16:28:42 -08:00
commit 63eb1636a9
210 changed files with 12004 additions and 5847 deletions

5
.gitignore vendored
View File

@ -45,3 +45,8 @@ CTestTestfile.cmake
# Windows
Thumbs.db
ehthumbs.db
# Python
__pycache__
*.pyc
*.pyo

9
contrib/.gitignore vendored
View File

@ -1,9 +0,0 @@
*.pyc
*.pyo
/__init__.py
# These are files that are generated within the source tree by the
# ppremake system.
Makefile
pp.dep
/built/
Opt?-*

View File

@ -1,2 +0,0 @@
/build
/dist

9
direct/.gitignore vendored
View File

@ -1,9 +0,0 @@
*.pyc
*.pyo
/__init__.py
# These are files that are generated within the source tree by the
# ppremake system.
Makefile
pp.dep
/built/
Opt?-*

View File

@ -1 +0,0 @@
/40_direct.prc

View File

@ -1,3 +0,0 @@
/dcLexer.cxx
/dcParser.cxx
/dcParser.h

View File

@ -88,3 +88,7 @@ class EggCacher:
progress += size
cacher = EggCacher(sys.argv[1:])
# Dummy main function so this can be added to console_scripts.
def main():
return 0

View File

@ -419,3 +419,6 @@ else:
if not(os.path.exists("/usr/bin/rpmbuild") or os.path.exists("/usr/bin/dpkg-deb")):
exit("To build an installer, either rpmbuild or dpkg-deb must be present on your system!")
# Dummy main function so this can be added to console_scripts.
def main():
return 0

View File

@ -26,11 +26,7 @@ class DistributedObjectGlobalUD(DistributedObjectUD):
def execCommand(self, command, mwMgrId, avId, zoneId):
text = str(self.__execMessage(command))[:config.GetInt("ai-debug-length",300)]
dclass = uber.air.dclassesByName.get("PiratesMagicWordManagerAI")
dg = dclass.aiFormatUpdate(
"setMagicWordResponse", mwMgrId, (1<<32)+avId, uber.air.ourChannel, [text])
uber.air.send(dg)
self.notify.info(text)
def __execMessage(self, message):
if not self.ExecNamespace:

View File

@ -403,7 +403,7 @@ send_datagram(const Datagram &dg) {
#ifdef WANT_NATIVE_NET
if (_native) {
bool result = _bdc.SendMessage();
bool result = _bdc.SendMessage(dg);
if (!result && _bdc.IsConnected()) {
#ifdef HAVE_PYTHON
ostringstream s;
@ -415,8 +415,8 @@ send_datagram(const Datagram &dg) {
#endif
s << endl << "Error sending message: " << endl;
msg.dump_hex(s);
s << "Message data: " << msg.get_data() << endl;
dg.dump_hex(s);
s << "Message data: " << dg.get_data() << endl;
string message = s.str();
PyErr_SetString(exc_type, message.c_str());

View File

@ -1 +0,0 @@
/extensions_darwin.py

View File

@ -1,2 +0,0 @@
/NL*
/Nested*

View File

@ -20,7 +20,7 @@ class DirectScrolledListItem(DirectButton):
def __init__(self, parent=None, **kw):
assert self.notify.debugStateCall(self)
self.parent = parent
self._parent = parent
if "command" in kw:
self.nextCommand = kw.get("command")
del kw["command"]
@ -28,7 +28,7 @@ class DirectScrolledListItem(DirectButton):
self.nextCommandExtraArgs = kw.get("extraArgs")
del kw["extraArgs"]
optiondefs = (
('parent', self.parent, None),
('parent', self._parent, None),
('command', self.select, None),
)
# Merge keyword options with default options
@ -39,7 +39,7 @@ class DirectScrolledListItem(DirectButton):
def select(self):
assert self.notify.debugStateCall(self)
self.nextCommand(*self.nextCommandExtraArgs)
self.parent.selectListItem(self)
self._parent.selectListItem(self)
class DirectScrolledList(DirectFrame):

View File

@ -1,8 +0,0 @@
/_vfsimporter.exp
/_vfsimporter.lib
/_vfsimporter.pyd
/_vfsimporter.pyd.manifest
/packp3d
/ppackage
/ppatcher
/vc90.pdb

View File

@ -1 +0,0 @@
/p3d_plugin_config.h

View File

@ -1 +0,0 @@
/P3DActiveX.rc

View File

@ -1 +0,0 @@
/nppanda3d.rc

View File

@ -1,2 +0,0 @@
/p3d_plugin_config.h
/panda3d.rc

View File

@ -38,7 +38,6 @@ import os
import sys
import random
import time
import importlib
__report_indent = 3
@ -61,6 +60,42 @@ def Functor(function, *args, **kArgs):
return functor
"""
try:
import importlib
except ImportError:
# Backward compatibility for Python 2.6.
def _resolve_name(name, package, level):
if not hasattr(package, 'rindex'):
raise ValueError("'package' not set to a string")
dot = len(package)
for x in xrange(level, 1, -1):
try:
dot = package.rindex('.', 0, dot)
except ValueError:
raise ValueError("attempted relative import beyond top-level "
"package")
return "%s.%s" % (package[:dot], name)
def import_module(name, package=None):
if name.startswith('.'):
if not package:
raise TypeError("relative imports require the 'package' argument")
level = 0
for character in name:
if character != '.':
break
level += 1
name = _resolve_name(name[level:], package, level)
__import__(name)
return sys.modules[name]
imp = import_module('imp')
importlib = imp.new_module("importlib")
importlib._resolve_name = _resolve_name
importlib.import_module = import_module
sys.modules['importlib'] = importlib
class Functor:
def __init__(self, function, *args, **kargs):
assert callable(function), "function should be a callable obj"

View File

@ -1 +0,0 @@
/runp3d

7
dmodels/.gitignore vendored
View File

@ -1,7 +0,0 @@
*.egg
*.pt
/built/
Makefile
bams/
optchar/
pal_egg/

View File

@ -1,6 +0,0 @@
/*.buildings
/game_options.txt
/prefixstrip
/retarget/
/textures.boo
/topstrip/

View File

@ -2,6 +2,7 @@
This issue fixes several bugs that were still found in 1.9.2.
* Fix crash when using homebrew Python on Mac OS X
* Fix crash when running in Steam on Linux when using OpenAL
* Fix crash using wx/tkinter on Mac as long as want-wx/tk is set
* Fix loading models from 'models' package with models/ prefix
@ -45,6 +46,15 @@ This issue fixes several bugs that were still found in 1.9.2.
* Fix rare X11 .ico cursor bug; also now supports PNG-compressed icons
* Add keyword argument support to make() methods such as Shader.make()
* Fix compilation errors with Bullet 2.84
* Fix exception when trying to pickle NodePathCollection objects
* Fix error when trying to raise vectors to a power
* GLSL: fix error when legacy matrix generator inputs are mat3
* Now tries to preserve refresh rate when switching fullscreen on Windows
* Fix back-to-front sorting when gl-coordinate-system is changed
* Now also compiles on older Linux distros (eg. CentOS 5 / manylinux1)
* get_keyboard_map now includes keys on layouts with special characters
* Fix crash due to incorrect alignment when compiling Eigen with AVX
* Fix crash when writing 16-bit .tif file (now silently downsamples)
------------------------ RELEASE 1.9.2 ------------------------

7
dtool/.gitignore vendored
View File

@ -1,7 +0,0 @@
/dtool_config.h
# These are files that are generated within the source tree by the
# ppremake system.
Makefile
pp.dep
/built/
Opt?-*

View File

@ -1,2 +0,0 @@
/cppBison.cxx
/cppBison.h

View File

@ -13,6 +13,7 @@
#include "cppArrayType.h"
#include "cppExpression.h"
#include "cppPointerType.h"
/**
*
@ -63,6 +64,14 @@ is_tbd() const {
return _element_type->is_tbd();
}
/**
* Returns true if the type is considered a standard layout type.
*/
bool CPPArrayType::
is_standard_layout() const {
return _element_type->is_standard_layout();
}
/**
* Returns true if the type is considered a Plain Old Data (POD) type.
*/
@ -76,7 +85,7 @@ is_trivial() const {
*/
bool CPPArrayType::
is_default_constructible() const {
return _element_type->is_default_constructible();
return _bounds != NULL && _element_type->is_default_constructible();
}
/**

View File

@ -38,6 +38,7 @@ public:
virtual CPPType *resolve_type(CPPScope *current_scope,
CPPScope *global_scope);
virtual bool is_tbd() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;

File diff suppressed because it is too large Load Diff

View File

@ -54,120 +54,138 @@ extern int cppyydebug;
CUSTOM_LITERAL = 264,
IDENTIFIER = 265,
TYPENAME_IDENTIFIER = 266,
SCOPING = 267,
TYPEDEFNAME = 268,
ELLIPSIS = 269,
OROR = 270,
ANDAND = 271,
EQCOMPARE = 272,
NECOMPARE = 273,
LECOMPARE = 274,
GECOMPARE = 275,
LSHIFT = 276,
RSHIFT = 277,
POINTSAT_STAR = 278,
DOT_STAR = 279,
UNARY = 280,
UNARY_NOT = 281,
UNARY_NEGATE = 282,
UNARY_MINUS = 283,
UNARY_PLUS = 284,
UNARY_STAR = 285,
UNARY_REF = 286,
POINTSAT = 287,
SCOPE = 288,
PLUSPLUS = 289,
MINUSMINUS = 290,
TIMESEQUAL = 291,
DIVIDEEQUAL = 292,
MODEQUAL = 293,
PLUSEQUAL = 294,
MINUSEQUAL = 295,
OREQUAL = 296,
ANDEQUAL = 297,
XOREQUAL = 298,
LSHIFTEQUAL = 299,
RSHIFTEQUAL = 300,
KW_ALIGNAS = 301,
KW_ALIGNOF = 302,
KW_AUTO = 303,
KW_BEGIN_PUBLISH = 304,
KW_BLOCKING = 305,
KW_BOOL = 306,
KW_CATCH = 307,
KW_CHAR = 308,
KW_CHAR16_T = 309,
KW_CHAR32_T = 310,
KW_CLASS = 311,
KW_CONST = 312,
KW_CONSTEXPR = 313,
KW_CONST_CAST = 314,
KW_DECLTYPE = 315,
KW_DEFAULT = 316,
KW_DELETE = 317,
KW_DOUBLE = 318,
KW_DYNAMIC_CAST = 319,
KW_ELSE = 320,
KW_END_PUBLISH = 321,
KW_ENUM = 322,
KW_EXTENSION = 323,
KW_EXTERN = 324,
KW_EXPLICIT = 325,
KW_PUBLISHED = 326,
KW_FALSE = 327,
KW_FINAL = 328,
KW_FLOAT = 329,
KW_FRIEND = 330,
KW_FOR = 331,
KW_GOTO = 332,
KW_IF = 333,
KW_INLINE = 334,
KW_INT = 335,
KW_LONG = 336,
KW_MAKE_MAP_PROPERTY = 337,
KW_MAKE_PROPERTY = 338,
KW_MAKE_PROPERTY2 = 339,
KW_MAKE_SEQ = 340,
KW_MAKE_SEQ_PROPERTY = 341,
KW_MUTABLE = 342,
KW_NAMESPACE = 343,
KW_NEW = 344,
KW_NOEXCEPT = 345,
KW_NULLPTR = 346,
KW_OPERATOR = 347,
KW_OVERRIDE = 348,
KW_PRIVATE = 349,
KW_PROTECTED = 350,
KW_PUBLIC = 351,
KW_REGISTER = 352,
KW_REINTERPRET_CAST = 353,
KW_RETURN = 354,
KW_SHORT = 355,
KW_SIGNED = 356,
KW_SIZEOF = 357,
KW_STATIC = 358,
KW_STATIC_ASSERT = 359,
KW_STATIC_CAST = 360,
KW_STRUCT = 361,
KW_TEMPLATE = 362,
KW_THREAD_LOCAL = 363,
KW_THROW = 364,
KW_TRUE = 365,
KW_TRY = 366,
KW_TYPEDEF = 367,
KW_TYPEID = 368,
KW_TYPENAME = 369,
KW_UNION = 370,
KW_UNSIGNED = 371,
KW_USING = 372,
KW_VIRTUAL = 373,
KW_VOID = 374,
KW_VOLATILE = 375,
KW_WCHAR_T = 376,
KW_WHILE = 377,
START_CPP = 378,
START_CONST_EXPR = 379,
START_TYPE = 380
TYPEPACK_IDENTIFIER = 267,
SCOPING = 268,
TYPEDEFNAME = 269,
ELLIPSIS = 270,
OROR = 271,
ANDAND = 272,
EQCOMPARE = 273,
NECOMPARE = 274,
LECOMPARE = 275,
GECOMPARE = 276,
LSHIFT = 277,
RSHIFT = 278,
POINTSAT_STAR = 279,
DOT_STAR = 280,
UNARY = 281,
UNARY_NOT = 282,
UNARY_NEGATE = 283,
UNARY_MINUS = 284,
UNARY_PLUS = 285,
UNARY_STAR = 286,
UNARY_REF = 287,
POINTSAT = 288,
SCOPE = 289,
PLUSPLUS = 290,
MINUSMINUS = 291,
TIMESEQUAL = 292,
DIVIDEEQUAL = 293,
MODEQUAL = 294,
PLUSEQUAL = 295,
MINUSEQUAL = 296,
OREQUAL = 297,
ANDEQUAL = 298,
XOREQUAL = 299,
LSHIFTEQUAL = 300,
RSHIFTEQUAL = 301,
KW_ALIGNAS = 302,
KW_ALIGNOF = 303,
KW_AUTO = 304,
KW_BEGIN_PUBLISH = 305,
KW_BLOCKING = 306,
KW_BOOL = 307,
KW_CATCH = 308,
KW_CHAR = 309,
KW_CHAR16_T = 310,
KW_CHAR32_T = 311,
KW_CLASS = 312,
KW_CONST = 313,
KW_CONSTEXPR = 314,
KW_CONST_CAST = 315,
KW_DECLTYPE = 316,
KW_DEFAULT = 317,
KW_DELETE = 318,
KW_DOUBLE = 319,
KW_DYNAMIC_CAST = 320,
KW_ELSE = 321,
KW_END_PUBLISH = 322,
KW_ENUM = 323,
KW_EXTENSION = 324,
KW_EXTERN = 325,
KW_EXPLICIT = 326,
KW_PUBLISHED = 327,
KW_FALSE = 328,
KW_FINAL = 329,
KW_FLOAT = 330,
KW_FRIEND = 331,
KW_FOR = 332,
KW_GOTO = 333,
KW_HAS_VIRTUAL_DESTRUCTOR = 334,
KW_IF = 335,
KW_INLINE = 336,
KW_INT = 337,
KW_IS_ABSTRACT = 338,
KW_IS_BASE_OF = 339,
KW_IS_CLASS = 340,
KW_IS_CONSTRUCTIBLE = 341,
KW_IS_CONVERTIBLE_TO = 342,
KW_IS_DESTRUCTIBLE = 343,
KW_IS_EMPTY = 344,
KW_IS_ENUM = 345,
KW_IS_FINAL = 346,
KW_IS_FUNDAMENTAL = 347,
KW_IS_POD = 348,
KW_IS_POLYMORPHIC = 349,
KW_IS_STANDARD_LAYOUT = 350,
KW_IS_TRIVIAL = 351,
KW_IS_UNION = 352,
KW_LONG = 353,
KW_MAKE_MAP_PROPERTY = 354,
KW_MAKE_PROPERTY = 355,
KW_MAKE_PROPERTY2 = 356,
KW_MAKE_SEQ = 357,
KW_MAKE_SEQ_PROPERTY = 358,
KW_MUTABLE = 359,
KW_NAMESPACE = 360,
KW_NEW = 361,
KW_NOEXCEPT = 362,
KW_NULLPTR = 363,
KW_OPERATOR = 364,
KW_OVERRIDE = 365,
KW_PRIVATE = 366,
KW_PROTECTED = 367,
KW_PUBLIC = 368,
KW_REGISTER = 369,
KW_REINTERPRET_CAST = 370,
KW_RETURN = 371,
KW_SHORT = 372,
KW_SIGNED = 373,
KW_SIZEOF = 374,
KW_STATIC = 375,
KW_STATIC_ASSERT = 376,
KW_STATIC_CAST = 377,
KW_STRUCT = 378,
KW_TEMPLATE = 379,
KW_THREAD_LOCAL = 380,
KW_THROW = 381,
KW_TRUE = 382,
KW_TRY = 383,
KW_TYPEDEF = 384,
KW_TYPEID = 385,
KW_TYPENAME = 386,
KW_UNDERLYING_TYPE = 387,
KW_UNION = 388,
KW_UNSIGNED = 389,
KW_USING = 390,
KW_VIRTUAL = 391,
KW_VOID = 392,
KW_VOLATILE = 393,
KW_WCHAR_T = 394,
KW_WHILE = 395,
START_CPP = 396,
START_CONST_EXPR = 397,
START_TYPE = 398
};
#endif
/* Tokens. */
@ -180,120 +198,138 @@ extern int cppyydebug;
#define CUSTOM_LITERAL 264
#define IDENTIFIER 265
#define TYPENAME_IDENTIFIER 266
#define SCOPING 267
#define TYPEDEFNAME 268
#define ELLIPSIS 269
#define OROR 270
#define ANDAND 271
#define EQCOMPARE 272
#define NECOMPARE 273
#define LECOMPARE 274
#define GECOMPARE 275
#define LSHIFT 276
#define RSHIFT 277
#define POINTSAT_STAR 278
#define DOT_STAR 279
#define UNARY 280
#define UNARY_NOT 281
#define UNARY_NEGATE 282
#define UNARY_MINUS 283
#define UNARY_PLUS 284
#define UNARY_STAR 285
#define UNARY_REF 286
#define POINTSAT 287
#define SCOPE 288
#define PLUSPLUS 289
#define MINUSMINUS 290
#define TIMESEQUAL 291
#define DIVIDEEQUAL 292
#define MODEQUAL 293
#define PLUSEQUAL 294
#define MINUSEQUAL 295
#define OREQUAL 296
#define ANDEQUAL 297
#define XOREQUAL 298
#define LSHIFTEQUAL 299
#define RSHIFTEQUAL 300
#define KW_ALIGNAS 301
#define KW_ALIGNOF 302
#define KW_AUTO 303
#define KW_BEGIN_PUBLISH 304
#define KW_BLOCKING 305
#define KW_BOOL 306
#define KW_CATCH 307
#define KW_CHAR 308
#define KW_CHAR16_T 309
#define KW_CHAR32_T 310
#define KW_CLASS 311
#define KW_CONST 312
#define KW_CONSTEXPR 313
#define KW_CONST_CAST 314
#define KW_DECLTYPE 315
#define KW_DEFAULT 316
#define KW_DELETE 317
#define KW_DOUBLE 318
#define KW_DYNAMIC_CAST 319
#define KW_ELSE 320
#define KW_END_PUBLISH 321
#define KW_ENUM 322
#define KW_EXTENSION 323
#define KW_EXTERN 324
#define KW_EXPLICIT 325
#define KW_PUBLISHED 326
#define KW_FALSE 327
#define KW_FINAL 328
#define KW_FLOAT 329
#define KW_FRIEND 330
#define KW_FOR 331
#define KW_GOTO 332
#define KW_IF 333
#define KW_INLINE 334
#define KW_INT 335
#define KW_LONG 336
#define KW_MAKE_MAP_PROPERTY 337
#define KW_MAKE_PROPERTY 338
#define KW_MAKE_PROPERTY2 339
#define KW_MAKE_SEQ 340
#define KW_MAKE_SEQ_PROPERTY 341
#define KW_MUTABLE 342
#define KW_NAMESPACE 343
#define KW_NEW 344
#define KW_NOEXCEPT 345
#define KW_NULLPTR 346
#define KW_OPERATOR 347
#define KW_OVERRIDE 348
#define KW_PRIVATE 349
#define KW_PROTECTED 350
#define KW_PUBLIC 351
#define KW_REGISTER 352
#define KW_REINTERPRET_CAST 353
#define KW_RETURN 354
#define KW_SHORT 355
#define KW_SIGNED 356
#define KW_SIZEOF 357
#define KW_STATIC 358
#define KW_STATIC_ASSERT 359
#define KW_STATIC_CAST 360
#define KW_STRUCT 361
#define KW_TEMPLATE 362
#define KW_THREAD_LOCAL 363
#define KW_THROW 364
#define KW_TRUE 365
#define KW_TRY 366
#define KW_TYPEDEF 367
#define KW_TYPEID 368
#define KW_TYPENAME 369
#define KW_UNION 370
#define KW_UNSIGNED 371
#define KW_USING 372
#define KW_VIRTUAL 373
#define KW_VOID 374
#define KW_VOLATILE 375
#define KW_WCHAR_T 376
#define KW_WHILE 377
#define START_CPP 378
#define START_CONST_EXPR 379
#define START_TYPE 380
#define TYPEPACK_IDENTIFIER 267
#define SCOPING 268
#define TYPEDEFNAME 269
#define ELLIPSIS 270
#define OROR 271
#define ANDAND 272
#define EQCOMPARE 273
#define NECOMPARE 274
#define LECOMPARE 275
#define GECOMPARE 276
#define LSHIFT 277
#define RSHIFT 278
#define POINTSAT_STAR 279
#define DOT_STAR 280
#define UNARY 281
#define UNARY_NOT 282
#define UNARY_NEGATE 283
#define UNARY_MINUS 284
#define UNARY_PLUS 285
#define UNARY_STAR 286
#define UNARY_REF 287
#define POINTSAT 288
#define SCOPE 289
#define PLUSPLUS 290
#define MINUSMINUS 291
#define TIMESEQUAL 292
#define DIVIDEEQUAL 293
#define MODEQUAL 294
#define PLUSEQUAL 295
#define MINUSEQUAL 296
#define OREQUAL 297
#define ANDEQUAL 298
#define XOREQUAL 299
#define LSHIFTEQUAL 300
#define RSHIFTEQUAL 301
#define KW_ALIGNAS 302
#define KW_ALIGNOF 303
#define KW_AUTO 304
#define KW_BEGIN_PUBLISH 305
#define KW_BLOCKING 306
#define KW_BOOL 307
#define KW_CATCH 308
#define KW_CHAR 309
#define KW_CHAR16_T 310
#define KW_CHAR32_T 311
#define KW_CLASS 312
#define KW_CONST 313
#define KW_CONSTEXPR 314
#define KW_CONST_CAST 315
#define KW_DECLTYPE 316
#define KW_DEFAULT 317
#define KW_DELETE 318
#define KW_DOUBLE 319
#define KW_DYNAMIC_CAST 320
#define KW_ELSE 321
#define KW_END_PUBLISH 322
#define KW_ENUM 323
#define KW_EXTENSION 324
#define KW_EXTERN 325
#define KW_EXPLICIT 326
#define KW_PUBLISHED 327
#define KW_FALSE 328
#define KW_FINAL 329
#define KW_FLOAT 330
#define KW_FRIEND 331
#define KW_FOR 332
#define KW_GOTO 333
#define KW_HAS_VIRTUAL_DESTRUCTOR 334
#define KW_IF 335
#define KW_INLINE 336
#define KW_INT 337
#define KW_IS_ABSTRACT 338
#define KW_IS_BASE_OF 339
#define KW_IS_CLASS 340
#define KW_IS_CONSTRUCTIBLE 341
#define KW_IS_CONVERTIBLE_TO 342
#define KW_IS_DESTRUCTIBLE 343
#define KW_IS_EMPTY 344
#define KW_IS_ENUM 345
#define KW_IS_FINAL 346
#define KW_IS_FUNDAMENTAL 347
#define KW_IS_POD 348
#define KW_IS_POLYMORPHIC 349
#define KW_IS_STANDARD_LAYOUT 350
#define KW_IS_TRIVIAL 351
#define KW_IS_UNION 352
#define KW_LONG 353
#define KW_MAKE_MAP_PROPERTY 354
#define KW_MAKE_PROPERTY 355
#define KW_MAKE_PROPERTY2 356
#define KW_MAKE_SEQ 357
#define KW_MAKE_SEQ_PROPERTY 358
#define KW_MUTABLE 359
#define KW_NAMESPACE 360
#define KW_NEW 361
#define KW_NOEXCEPT 362
#define KW_NULLPTR 363
#define KW_OPERATOR 364
#define KW_OVERRIDE 365
#define KW_PRIVATE 366
#define KW_PROTECTED 367
#define KW_PUBLIC 368
#define KW_REGISTER 369
#define KW_REINTERPRET_CAST 370
#define KW_RETURN 371
#define KW_SHORT 372
#define KW_SIGNED 373
#define KW_SIZEOF 374
#define KW_STATIC 375
#define KW_STATIC_ASSERT 376
#define KW_STATIC_CAST 377
#define KW_STRUCT 378
#define KW_TEMPLATE 379
#define KW_THREAD_LOCAL 380
#define KW_THROW 381
#define KW_TRUE 382
#define KW_TRY 383
#define KW_TYPEDEF 384
#define KW_TYPEID 385
#define KW_TYPENAME 386
#define KW_UNDERLYING_TYPE 387
#define KW_UNION 388
#define KW_UNSIGNED 389
#define KW_USING 390
#define KW_VIRTUAL 391
#define KW_VOID 392
#define KW_VOLATILE 393
#define KW_WCHAR_T 394
#define KW_WHILE 395
#define START_CPP 396
#define START_CONST_EXPR 397
#define START_TYPE 398
/* Value type. */

View File

@ -212,7 +212,7 @@ pop_struct() {
%token <u.integer> CHAR_TOK
%token <str> SIMPLE_STRING SIMPLE_IDENTIFIER
%token <u.expr> STRING_LITERAL CUSTOM_LITERAL
%token <u.identifier> IDENTIFIER TYPENAME_IDENTIFIER SCOPING
%token <u.identifier> IDENTIFIER TYPENAME_IDENTIFIER TYPEPACK_IDENTIFIER SCOPING
%token <u.type> TYPEDEFNAME
%token ELLIPSIS
@ -280,9 +280,25 @@ pop_struct() {
%token KW_FRIEND
%token KW_FOR
%token KW_GOTO
%token KW_HAS_VIRTUAL_DESTRUCTOR
%token KW_IF
%token KW_INLINE
%token KW_INT
%token KW_IS_ABSTRACT
%token KW_IS_BASE_OF
%token KW_IS_CLASS
%token KW_IS_CONSTRUCTIBLE
%token KW_IS_CONVERTIBLE_TO
%token KW_IS_DESTRUCTIBLE
%token KW_IS_EMPTY
%token KW_IS_ENUM
%token KW_IS_FINAL
%token KW_IS_FUNDAMENTAL
%token KW_IS_POD
%token KW_IS_POLYMORPHIC
%token KW_IS_STANDARD_LAYOUT
%token KW_IS_TRIVIAL
%token KW_IS_UNION
%token KW_LONG
%token KW_MAKE_MAP_PROPERTY
%token KW_MAKE_PROPERTY
@ -317,6 +333,7 @@ pop_struct() {
%token KW_TYPEDEF
%token KW_TYPEID
%token KW_TYPENAME
%token KW_UNDERLYING_TYPE
%token KW_UNION
%token KW_UNSIGNED
%token KW_USING
@ -354,9 +371,10 @@ pop_struct() {
%type <u.instance> formal_parameter
%type <u.inst_ident> not_paren_formal_parameter_identifier
%type <u.inst_ident> formal_parameter_identifier
%type <u.inst_ident> parameter_pack_identifier
%type <u.inst_ident> not_paren_empty_instance_identifier
%type <u.inst_ident> empty_instance_identifier
%type <u.type> type
%type <u.type> type type_pack
%type <u.decl> type_decl
%type <u.decl> var_type_decl
%type <u.type> predefined_type
@ -447,6 +465,10 @@ constructor_init:
name '(' optional_const_expr_comma ')'
{
delete $3;
}
| name '(' optional_const_expr_comma ')' ELLIPSIS
{
delete $3;
}
| name '{' optional_const_expr_comma '}'
{
@ -1187,26 +1209,38 @@ function_post:
{
$$ = 0;
}
| KW_CONST
| function_post KW_CONST
{
$$ = (int)CPPFunctionType::F_const_method;
$$ = $1 | (int)CPPFunctionType::F_const_method;
}
| function_post KW_VOLATILE
{
$$ = $1 | (int)CPPFunctionType::F_volatile_method;
}
| function_post KW_NOEXCEPT
{
$$ = (int)CPPFunctionType::F_noexcept;
$$ = $1 | (int)CPPFunctionType::F_noexcept;
}
| function_post KW_FINAL
{
$$ = (int)CPPFunctionType::F_final;
$$ = $1 | (int)CPPFunctionType::F_final;
}
| function_post KW_OVERRIDE
{
$$ = (int)CPPFunctionType::F_override;
$$ = $1 | (int)CPPFunctionType::F_override;
}
| function_post '&'
{
$$ = $1 | (int)CPPFunctionType::F_lvalue_method;
}
| function_post ANDAND
{
$$ = $1 | (int)CPPFunctionType::F_rvalue_method;
}
| function_post KW_MUTABLE
{
// Used for lambdas, currently ignored.
$$ = 0;
$$ = $1;
}
| function_post KW_THROW '(' ')'
{
@ -1215,6 +1249,10 @@ function_post:
| function_post KW_THROW '(' name ')'
{
$$ = $1;
}
| function_post KW_THROW '(' name ELLIPSIS ')'
{
$$ = $1;
}
/* | function_post '[' '[' attribute_specifiers ']' ']'
{
@ -1418,22 +1456,35 @@ template_nonempty_formal_parameters:
}
;
typename_keyword:
KW_CLASS
| KW_TYPENAME
;
template_formal_parameter:
KW_CLASS name
typename_keyword
{
$$ = CPPType::new_type(new CPPClassTemplateParameter((CPPIdentifier *)NULL));
}
| typename_keyword name
{
$$ = CPPType::new_type(new CPPClassTemplateParameter($2));
}
| KW_CLASS name '=' full_type
| typename_keyword name '=' full_type
{
$$ = CPPType::new_type(new CPPClassTemplateParameter($2, $4));
}
| KW_TYPENAME name
| typename_keyword ELLIPSIS
{
$$ = CPPType::new_type(new CPPClassTemplateParameter($2));
CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter((CPPIdentifier *)NULL);
ctp->_packed = true;
$$ = CPPType::new_type(ctp);
}
| KW_TYPENAME name '=' full_type
| typename_keyword ELLIPSIS name
{
$$ = CPPType::new_type(new CPPClassTemplateParameter($2, $4));
CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter($3);
ctp->_packed = true;
$$ = CPPType::new_type(ctp);
}
| template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize
{
@ -1447,6 +1498,17 @@ template_formal_parameter:
CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file);
inst->set_initializer($4);
$$ = inst;
}
| template_formal_parameter_type parameter_pack_identifier
{
CPPInstance *inst = new CPPInstance($1, $2, 0, @2.file);
$$ = inst;
}
| KW_CONST template_formal_parameter_type parameter_pack_identifier
{
$3->add_modifier(IIT_const);
CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file);
$$ = inst;
}
;
@ -1467,6 +1529,14 @@ template_formal_parameter_type:
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
}
assert($$ != NULL);
}
| TYPEPACK_IDENTIFIER
{
$$ = $1->find_type(current_scope, global_scope, false, current_lexer);
if ($$ == NULL) {
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
}
assert($$ != NULL);
}
;
@ -1547,7 +1617,16 @@ instance_identifier:
}
| instance_identifier '('
{
push_scope($1->get_scope(current_scope, global_scope));
// Create a scope for this function (in case it is a function)
CPPScope *scope = new CPPScope($1->get_scope(current_scope, global_scope),
CPPNameComponent(""), V_private);
// It still needs to be able to pick up any template arguments, if this is
// a definition for a method template. Add a fake "using" declaration to
// accomplish this.
scope->_using.insert(current_scope);
push_scope(scope);
}
formal_parameter_list ')' function_post
{
@ -1785,6 +1864,23 @@ function_parameter:
$4->add_modifier(IIT_const);
$$ = new CPPInstance($3, $4, 0, @3.file);
$$->set_initializer($5);
}
| type_pack parameter_pack_identifier maybe_initialize
{
$$ = new CPPInstance($1, $2, 0, @2.file);
$$->set_initializer($3);
}
| KW_CONST type_pack parameter_pack_identifier maybe_initialize
{
$3->add_modifier(IIT_const);
$$ = new CPPInstance($2, $3, 0, @3.file);
$$->set_initializer($4);
}
| KW_CONST KW_REGISTER type_pack parameter_pack_identifier maybe_initialize
{
$4->add_modifier(IIT_const);
$$ = new CPPInstance($3, $4, 0, @3.file);
$$->set_initializer($5);
}
| KW_REGISTER function_parameter
{
@ -1913,10 +2009,79 @@ formal_parameter_identifier:
}
;
parameter_pack_identifier:
ELLIPSIS
{
$$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
$$->_packed = true;
}
| ELLIPSIS name
{
$$ = new CPPInstanceIdentifier($2);
$$->_packed = true;
}
| KW_CONST parameter_pack_identifier %prec UNARY
{
$$ = $2;
$$->add_modifier(IIT_const);
}
| KW_VOLATILE parameter_pack_identifier %prec UNARY
{
$$ = $2;
$$->add_modifier(IIT_volatile);
}
| '*' parameter_pack_identifier %prec UNARY
{
$$ = $2;
$$->add_modifier(IIT_pointer);
}
| '&' parameter_pack_identifier %prec UNARY
{
$$ = $2;
$$->add_modifier(IIT_reference);
}
| ANDAND parameter_pack_identifier %prec UNARY
{
$$ = $2;
$$->add_modifier(IIT_rvalue_reference);
}
| SCOPING '*' parameter_pack_identifier %prec UNARY
{
$$ = $3;
$$->add_scoped_pointer_modifier($1);
}
| parameter_pack_identifier '[' optional_const_expr ']'
{
$$ = $1;
$$->add_array_modifier($3);
}
| '(' parameter_pack_identifier ')' '(' function_parameter_list ')' function_post
{
$$ = $2;
$$->add_modifier(IIT_paren);
$$->add_func_modifier($5, $7);
}
| '(' parameter_pack_identifier ')'
{
$$ = $2;
$$->add_modifier(IIT_paren);
}
;
not_paren_empty_instance_identifier:
empty
{
$$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
}
| ELLIPSIS
{
$$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
$$->_packed = true;
}
| ELLIPSIS name
{
$$ = new CPPInstanceIdentifier($2);
$$->_packed = true;
}
| KW_CONST not_paren_empty_instance_identifier %prec UNARY
{
@ -1959,6 +2124,16 @@ empty_instance_identifier:
empty
{
$$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
}
| ELLIPSIS
{
$$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
$$->_packed = true;
}
| ELLIPSIS name
{
$$ = new CPPInstanceIdentifier($2);
$$->_packed = true;
}
| KW_CONST empty_instance_identifier %prec UNARY
{
@ -2093,6 +2268,16 @@ type:
str << *$3;
yyerror("could not determine type of " + str.str(), @3);
}
}
| KW_UNDERLYING_TYPE '(' full_type ')'
{
CPPEnumType *enum_type = $3->as_enum_type();
if (enum_type == NULL) {
yyerror("an enumeration type is required", @3);
$$ = $3;
} else {
$$ = enum_type->get_underlying_type();
}
}
| KW_AUTO
{
@ -2100,6 +2285,17 @@ type:
}
;
type_pack:
TYPEPACK_IDENTIFIER
{
$$ = $1->find_type(current_scope, global_scope, false, current_lexer);
if ($$ == NULL) {
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
}
assert($$ != NULL);
}
;
type_decl:
simple_type
{
@ -2187,6 +2383,16 @@ type_decl:
str << *$3;
yyerror("could not determine type of " + str.str(), @3);
}
}
| KW_UNDERLYING_TYPE '(' full_type ')'
{
CPPEnumType *enum_type = $3->as_enum_type();
if (enum_type == NULL) {
yyerror("an enumeration type is required", @3);
$$ = $3;
} else {
$$ = enum_type->get_underlying_type();
}
}
| KW_AUTO
{
@ -2251,6 +2457,16 @@ predefined_type:
str << *$3;
yyerror("could not determine type of " + str.str(), @3);
}
}
| KW_UNDERLYING_TYPE '(' full_type ')'
{
CPPEnumType *enum_type = $3->as_enum_type();
if (enum_type == NULL) {
yyerror("an enumeration type is required", @3);
$$ = $3;
} else {
$$ = enum_type->get_underlying_type();
}
}
| KW_AUTO
{
@ -2279,6 +2495,15 @@ full_type:
{
$3->add_modifier(IIT_const);
$$ = $3->unroll_type($2);
}
| type_pack empty_instance_identifier
{
$$ = $2->unroll_type($1);
}
| KW_CONST type_pack empty_instance_identifier
{
$3->add_modifier(IIT_const);
$$ = $3->unroll_type($2);
}
;
@ -2693,6 +2918,7 @@ element:
| CHAR_TOK
| IDENTIFIER
| TYPENAME_IDENTIFIER
| TYPEPACK_IDENTIFIER
| SCOPING
| SIMPLE_IDENTIFIER
| ELLIPSIS | OROR | ANDAND
@ -2711,10 +2937,11 @@ element:
| KW_OPERATOR | KW_OVERRIDE | KW_PRIVATE | KW_PROTECTED
| KW_PUBLIC | KW_PUBLISHED | KW_REGISTER | KW_REINTERPRET_CAST
| KW_RETURN | KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC
| KW_STATIC_ASSERT | KW_STATIC_CAST | KW_STRUCT
| KW_STATIC_ASSERT | KW_STATIC_CAST | KW_STRUCT | KW_TEMPLATE
| KW_THREAD_LOCAL | KW_THROW | KW_TRUE | KW_TRY | KW_TYPEDEF
| KW_TYPEID | KW_TYPENAME | KW_UNION | KW_UNSIGNED | KW_USING
| KW_VIRTUAL | KW_VOID | KW_VOLATILE | KW_WCHAR_T | KW_WHILE
| KW_TYPEID | KW_TYPENAME | KW_UNDERLYING_TYPE | KW_UNION
| KW_UNSIGNED | KW_USING | KW_VIRTUAL | KW_VOID | KW_VOLATILE
| KW_WCHAR_T | KW_WHILE
{
}
| '+' | '-' | '*' | '/' | '&' | '|' | '^' | '!' | '~' | '=' | '%'
@ -2783,6 +3010,10 @@ no_angle_bracket_const_expr:
| KW_SIZEOF '(' full_type ')' %prec UNARY
{
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
}
| KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
{
$$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4));
}
| KW_ALIGNOF '(' full_type ')' %prec UNARY
{
@ -3021,6 +3252,10 @@ const_expr:
| KW_SIZEOF '(' full_type ')' %prec UNARY
{
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
}
| KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
{
$$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4));
}
| KW_ALIGNOF '(' full_type ')' %prec UNARY
{
@ -3238,6 +3473,74 @@ const_operand:
| '[' capture_list ']' '(' function_parameter_list ')' function_post maybe_trailing_return_type '{' code '}'
{
$$ = NULL;
}
| KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_HAS_VIRTUAL_DESTRUCTOR, $3));
}
| KW_IS_ABSTRACT '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_ABSTRACT, $3));
}
| KW_IS_BASE_OF '(' full_type ',' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, $3, $5));
}
| KW_IS_CLASS '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, $3));
}
| KW_IS_CONSTRUCTIBLE '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, $3));
}
| KW_IS_CONSTRUCTIBLE '(' full_type ',' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, $3, $5));
}
| KW_IS_CONVERTIBLE_TO '(' full_type ',' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONVERTIBLE_TO, $3, $5));
}
| KW_IS_DESTRUCTIBLE '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_DESTRUCTIBLE, $3));
}
| KW_IS_EMPTY '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_EMPTY, $3));
}
| KW_IS_ENUM '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_ENUM, $3));
}
| KW_IS_FINAL '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_FINAL, $3));
}
| KW_IS_FUNDAMENTAL '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_FUNDAMENTAL, $3));
}
| KW_IS_POD '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_POD, $3));
}
| KW_IS_POLYMORPHIC '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_POLYMORPHIC, $3));
}
| KW_IS_STANDARD_LAYOUT '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_STANDARD_LAYOUT, $3));
}
| KW_IS_TRIVIAL '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_TRIVIAL, $3));
}
| KW_IS_UNION '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_UNION, $3));
}
;
@ -3276,6 +3579,10 @@ formal_const_expr:
| KW_SIZEOF '(' full_type ')' %prec UNARY
{
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
}
| KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
{
$$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4));
}
| KW_ALIGNOF '(' full_type ')' %prec UNARY
{
@ -3518,6 +3825,12 @@ class_derivation_name:
| KW_TYPENAME name
{
$$ = CPPType::new_type(new CPPTBDType($2));
}
| name ELLIPSIS
{
CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter($1);
ctp->_packed = true;
$$ = CPPType::new_type(ctp);
}
;
@ -3550,6 +3863,10 @@ name:
| TYPENAME_IDENTIFIER
{
$$ = $1;
}
| TYPEPACK_IDENTIFIER
{
$$ = $1;
}
| KW_FINAL
{
@ -3595,6 +3912,10 @@ name_no_final:
| TYPENAME_IDENTIFIER
{
$$ = $1;
}
| TYPEPACK_IDENTIFIER
{
$$ = $1;
}
| KW_OVERRIDE
{

View File

@ -21,7 +21,8 @@ CPPClassTemplateParameter::
CPPClassTemplateParameter(CPPIdentifier *ident, CPPType *default_type) :
CPPType(CPPFile()),
_ident(ident),
_default_type(default_type)
_default_type(default_type),
_packed(false)
{
}
@ -41,8 +42,14 @@ is_fully_specified() const {
void CPPClassTemplateParameter::
output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
if (complete) {
out << "class ";
_ident->output(out, scope);
out << "class";
if (_packed) {
out << "...";
}
if (_ident != NULL) {
out << " ";
_ident->output(out, scope);
}
if (_default_type) {
out << " = ";
_default_type->output(out, indent_level, scope, false);
@ -82,6 +89,14 @@ is_equal(const CPPDeclaration *other) const {
return false;
}
if (_packed != ot->_packed) {
return false;
}
if (_ident == NULL || ot->_ident == NULL) {
return _ident == ot->_ident;
}
return *_ident == *ot->_ident;
}
@ -99,5 +114,13 @@ is_less(const CPPDeclaration *other) const {
return _default_type < ot->_default_type;
}
if (_packed != ot->_packed) {
return _packed < ot->_packed;
}
if (_ident == NULL || ot->_ident == NULL) {
return _ident < ot->_ident;
}
return *_ident < *ot->_ident;
}

View File

@ -37,6 +37,7 @@ public:
CPPIdentifier *_ident;
CPPType *_default_type;
bool _packed;
protected:
virtual bool is_equal(const CPPDeclaration *other) const;

View File

@ -86,6 +86,22 @@ is_tbd() const {
return _wrapped_around->is_tbd();
}
/**
* Returns true if the type is considered a fundamental type.
*/
bool CPPConstType::
is_fundamental() const {
return _wrapped_around->is_fundamental();
}
/**
* Returns true if the type is considered a standard layout type.
*/
bool CPPConstType::
is_standard_layout() const {
return _wrapped_around->is_standard_layout();
}
/**
* Returns true if the type is considered a Plain Old Data (POD) type.
*/
@ -94,12 +110,20 @@ is_trivial() const {
return _wrapped_around->is_trivial();
}
/**
* Returns true if the type can be constructed using the given argument.
*/
bool CPPConstType::
is_constructible(const CPPType *given_type) const {
return _wrapped_around->is_constructible(given_type);
}
/**
* Returns true if the type is default-constructible.
*/
bool CPPConstType::
is_default_constructible() const {
return false;
return _wrapped_around->is_default_constructible();
}
/**
@ -110,6 +134,23 @@ is_copy_constructible() const {
return _wrapped_around->is_copy_constructible();
}
/**
* Returns true if the type is destructible.
*/
bool CPPConstType::
is_destructible() const {
return _wrapped_around->is_destructible();
}
/**
* Returns true if variables of this type may be implicitly converted to
* the other type.
*/
bool CPPConstType::
is_convertible_to(const CPPType *other) const {
return _wrapped_around->is_convertible_to(other);
}
/**
* 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

View File

@ -36,9 +36,14 @@ public:
CPPScope *global_scope);
virtual bool is_tbd() const;
virtual bool is_fundamental() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;
virtual bool is_destructible() const;
virtual bool is_convertible_to(const CPPType *other) const;
virtual bool is_equivalent(const CPPType &other) const;
virtual void output(ostream &out, int indent_level, CPPScope *scope,

View File

@ -41,8 +41,13 @@ CPPDeclaration(const CPPDeclaration &copy) :
/**
*
*/
CPPDeclaration::
~CPPDeclaration() {
CPPDeclaration &CPPDeclaration::
operator = (const CPPDeclaration &copy) {
_vis = copy._vis;
_template_scope = copy._template_scope;
_file = copy._file;
_leading_comment = copy._leading_comment;
return *this;
}
/**
@ -124,6 +129,7 @@ CPPDeclaration *CPPDeclaration::
substitute_decl(SubstDecl &subst, CPPScope *, CPPScope *) {
SubstDecl::const_iterator si = subst.find(this);
if (si != subst.end()) {
assert((*si).second != NULL);
return (*si).second;
}
return this;

View File

@ -89,7 +89,9 @@ public:
CPPDeclaration(const CPPFile &file);
CPPDeclaration(const CPPDeclaration &copy);
virtual ~CPPDeclaration();
virtual ~CPPDeclaration() {};
CPPDeclaration &operator = (const CPPDeclaration &copy);
bool operator == (const CPPDeclaration &other) const;
bool operator != (const CPPDeclaration &other) const;
@ -139,6 +141,73 @@ public:
virtual CPPMakeProperty *as_make_property();
virtual CPPMakeSeq *as_make_seq();
inline const CPPInstance *as_instance() const {
return ((CPPDeclaration *)this)->as_instance();
}
inline const CPPClassTemplateParameter *as_class_template_parameter() const {
return ((CPPDeclaration *)this)->as_class_template_parameter();
}
inline const CPPTypedefType *as_typedef_type() const {
return ((CPPDeclaration *)this)->as_typedef_type();
}
inline const CPPTypeDeclaration *as_type_declaration() const {
return ((CPPDeclaration *)this)->as_type_declaration();
}
inline const CPPExpression *as_expression() const {
return ((CPPDeclaration *)this)->as_expression();
}
inline const CPPType *as_type() const {
return ((CPPDeclaration *)this)->as_type();
}
inline const CPPNamespace *as_namespace() const {
return ((CPPDeclaration *)this)->as_namespace();
}
inline const CPPUsing *as_using() const {
return ((CPPDeclaration *)this)->as_using();
}
inline const CPPSimpleType *as_simple_type() const {
return ((CPPDeclaration *)this)->as_simple_type();
}
inline const CPPPointerType *as_pointer_type() const {
return ((CPPDeclaration *)this)->as_pointer_type();
}
inline const CPPReferenceType *as_reference_type() const {
return ((CPPDeclaration *)this)->as_reference_type();
}
inline const CPPArrayType *as_array_type() const {
return ((CPPDeclaration *)this)->as_array_type();
}
inline const CPPConstType *as_const_type() const {
return ((CPPDeclaration *)this)->as_const_type();
}
inline const CPPFunctionType *as_function_type() const {
return ((CPPDeclaration *)this)->as_function_type();
}
inline const CPPFunctionGroup *as_function_group() const {
return ((CPPDeclaration *)this)->as_function_group();
}
inline const CPPExtensionType *as_extension_type() const {
return ((CPPDeclaration *)this)->as_extension_type();
}
inline const CPPStructType *as_struct_type() const {
return ((CPPDeclaration *)this)->as_struct_type();
}
inline const CPPEnumType *as_enum_type() const {
return ((CPPDeclaration *)this)->as_enum_type();
}
inline const CPPTBDType *as_tbd_type() const {
return ((CPPDeclaration *)this)->as_tbd_type();
}
inline const CPPTypeProxy *as_type_proxy() const {
return ((CPPDeclaration *)this)->as_type_proxy();
}
inline const CPPMakeProperty *as_make_property() const {
return ((CPPDeclaration *)this)->as_make_property();
}
inline const CPPMakeSeq *as_make_seq() const {
return ((CPPDeclaration *)this)->as_make_seq();
}
CPPVisibility _vis;
CPPTemplateScope *_template_scope;
CPPFile _file;

View File

@ -24,6 +24,7 @@
#include "cppInstance.h"
#include "cppFunctionGroup.h"
#include "cppFunctionType.h"
#include "cppStructType.h"
#include "cppBison.h"
#include "pdtoa.h"
@ -389,6 +390,19 @@ typeid_op(CPPExpression *op1, CPPType *std_type_info) {
return expr;
}
/**
* Creates an expression that returns a particular type trait.
*/
CPPExpression CPPExpression::
type_trait(int trait, CPPType *type, CPPType *arg) {
CPPExpression expr(0);
expr._type = T_type_trait;
expr._u._type_trait._trait = trait;
expr._u._type_trait._type = type;
expr._u._type_trait._arg = arg;
return expr;
}
/**
*
*/
@ -401,6 +415,17 @@ sizeof_func(CPPType *type) {
return expr;
}
/**
*
*/
CPPExpression CPPExpression::
sizeof_ellipsis_func(CPPIdentifier *ident) {
CPPExpression expr(0);
expr._type = T_sizeof_ellipsis;
expr._u._ident = ident;
return expr;
}
/**
*
*/
@ -492,13 +517,6 @@ get_delete() {
return expr;
}
/**
*
*/
CPPExpression::
~CPPExpression() {
}
/**
*
*/
@ -579,6 +597,7 @@ evaluate() const {
case T_new:
case T_default_new:
case T_sizeof:
case T_sizeof_ellipsis:
return Result();
case T_alignof:
@ -801,6 +820,95 @@ evaluate() const {
case T_typeid_expr:
return Result();
case T_type_trait:
switch (_u._type_trait._trait) {
case KW_HAS_VIRTUAL_DESTRUCTOR:
{
CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
return Result(struct_type != NULL && struct_type->has_virtual_destructor());
}
case KW_IS_ABSTRACT:
{
CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
return Result(struct_type != NULL && struct_type->is_abstract());
}
case KW_IS_BASE_OF:
{
CPPStructType *struct_type1 = _u._type_trait._type->as_struct_type();
CPPStructType *struct_type2 = _u._type_trait._arg->as_struct_type();
return Result(struct_type1 != NULL && struct_type2 != NULL && struct_type1->is_base_of(struct_type2));
}
case KW_IS_CLASS:
{
CPPExtensionType *ext_type = _u._type_trait._type->as_extension_type();
return Result(ext_type != NULL && (
ext_type->_type == CPPExtensionType::T_class ||
ext_type->_type == CPPExtensionType::T_struct));
}
case KW_IS_CONSTRUCTIBLE:
if (_u._type_trait._arg == NULL) {
return Result(_u._type_trait._type->is_default_constructible());
} else {
return Result(_u._type_trait._type->is_constructible(_u._type_trait._arg));
}
case KW_IS_CONVERTIBLE_TO:
assert(_u._type_trait._arg != NULL);
return Result(_u._type_trait._type->is_convertible_to(_u._type_trait._arg));
case KW_IS_DESTRUCTIBLE:
return Result(_u._type_trait._type->is_destructible());
case KW_IS_EMPTY:
{
CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
return Result(struct_type != NULL && struct_type->is_empty());
}
case KW_IS_ENUM:
return Result(_u._type_trait._type->is_enum());
case KW_IS_FINAL:
{
CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
return Result(struct_type != NULL && struct_type->is_final());
}
case KW_IS_FUNDAMENTAL:
return Result(_u._type_trait._type->is_fundamental());
case KW_IS_POD:
return Result(_u._type_trait._type->is_trivial() &&
_u._type_trait._type->is_standard_layout());
case KW_IS_POLYMORPHIC:
{
CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
return Result(struct_type != NULL && struct_type->is_polymorphic());
}
case KW_IS_STANDARD_LAYOUT:
return Result(_u._type_trait._type->is_standard_layout());
case KW_IS_TRIVIAL:
return Result(_u._type_trait._type->is_trivial());
case KW_IS_UNION:
{
CPPExtensionType *ext_type = _u._type_trait._type->as_extension_type();
return Result(ext_type != NULL &&
ext_type->_type == CPPExtensionType::T_union);
}
default:
cerr << "**unexpected type trait**\n";
abort();
}
default:
cerr << "**invalid operand**\n";
abort();
@ -916,6 +1024,7 @@ determine_type() const {
return CPPType::new_type(new CPPPointerType(_u._typecast._to));
case T_sizeof:
case T_sizeof_ellipsis:
case T_alignof:
// Note: this should actually be size_t, but that is defined as a typedef
// in parser-inc. We could try to resolve it, but that's hacky. Eh, it's
@ -1057,6 +1166,9 @@ determine_type() const {
case T_typeid_expr:
return _u._typeid._std_type_info;
case T_type_trait:
return bool_type;
default:
cerr << "**invalid operand**\n";
abort();
@ -1113,6 +1225,9 @@ is_fully_specified() const {
case T_alignof:
return _u._typecast._to->is_fully_specified();
case T_sizeof_ellipsis:
return _u._ident->is_fully_specified();
case T_trinary_operation:
if (!_u._op._op3->is_fully_specified()) {
return false;
@ -1141,6 +1256,9 @@ is_fully_specified() const {
case T_typeid_expr:
return _u._typeid._expr->is_fully_specified();
case T_type_trait:
return _u._type_trait._type->is_fully_specified();
default:
return true;
}
@ -1276,6 +1394,13 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
any_changed = any_changed || (rep->_u._typeid._expr != _u._typeid._expr);
break;
case T_type_trait:
rep->_u._type_trait._type =
_u._type_trait._type->substitute_decl(subst, current_scope, global_scope)
->as_type();
any_changed = any_changed || (rep->_u._type_trait._type != _u._type_trait._type);
break;
default:
break;
}
@ -1350,6 +1475,9 @@ is_tbd() const {
case T_typeid_expr:
return _u._typeid._expr->is_tbd();
case T_type_trait:
return _u._type_trait._type->is_tbd();
default:
return false;
}
@ -1541,6 +1669,12 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
out << ")";
break;
case T_sizeof_ellipsis:
out << "sizeof...(";
_u._ident->output(out, scope);
out << ")";
break;
case T_alignof:
out << "alignof(";
_u._typecast._to->output(out, indent_level, scope, false);
@ -1753,6 +1887,65 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
out << "delete";
break;
case T_type_trait:
switch (_u._type_trait._trait) {
case KW_HAS_VIRTUAL_DESTRUCTOR:
out << "__has_virtual_destructor";
break;
case KW_IS_ABSTRACT:
out << "__is_abstract";
break;
case KW_IS_BASE_OF:
out << "__is_base_of";
break;
case KW_IS_CLASS:
out << "__is_class";
break;
case KW_IS_CONSTRUCTIBLE:
out << "__is_constructible";
break;
case KW_IS_CONVERTIBLE_TO:
out << "__is_convertible_to";
break;
case KW_IS_DESTRUCTIBLE:
out << "__is_destructible";
break;
case KW_IS_EMPTY:
out << "__is_empty";
break;
case KW_IS_ENUM:
out << "__is_enum";
break;
case KW_IS_FINAL:
out << "__is_final";
break;
case KW_IS_FUNDAMENTAL:
out << "__is_fundamental";
break;
case KW_IS_POD:
out << "__is_pod";
break;
case KW_IS_POLYMORPHIC:
out << "__is_polymorphic";
break;
case KW_IS_STANDARD_LAYOUT:
out << "__is_standard_layout";
break;
case KW_IS_TRIVIAL:
out << "__is_trivial";
break;
case KW_IS_UNION:
out << "__is_union";
break;
default:
out << (evaluate().as_boolean() ? "true" : "false");
return;
}
out << '(';
_u._type_trait._type->output(out, indent_level, scope, false);
out << ')';
break;
default:
out << "(** invalid operand type " << (int)_type << " **)";
}
@ -1864,6 +2057,7 @@ is_equal(const CPPDeclaration *other) const {
return _u._fgroup == ot->_u._fgroup;
case T_unknown_ident:
case T_sizeof_ellipsis:
return *_u._ident == *ot->_u._ident;
case T_typecast:
@ -1907,6 +2101,10 @@ is_equal(const CPPDeclaration *other) const {
case T_typeid_expr:
return _u._typeid._expr == ot->_u._typeid._expr;
case T_type_trait:
return _u._type_trait._trait == ot->_u._type_trait._trait &&
_u._type_trait._type == ot->_u._type_trait._type;
default:
cerr << "(** invalid operand type " << (int)_type << " **)";
}
@ -1954,6 +2152,7 @@ is_less(const CPPDeclaration *other) const {
return *_u._fgroup < *ot->_u._fgroup;
case T_unknown_ident:
case T_sizeof_ellipsis:
return *_u._ident < *ot->_u._ident;
case T_typecast:
@ -2007,6 +2206,12 @@ is_less(const CPPDeclaration *other) const {
case T_typeid_expr:
return *_u._typeid._expr < *ot->_u._typeid._expr;
case T_type_trait:
if (_u._type_trait._trait != ot->_u._type_trait._trait) {
return _u._type_trait._trait < ot->_u._type_trait._trait;
}
return *_u._type_trait._type < *ot->_u._type_trait._type;
default:
cerr << "(** invalid operand type " << (int)_type << " **)";
}

View File

@ -51,6 +51,7 @@ public:
T_new,
T_default_new,
T_sizeof,
T_sizeof_ellipsis,
T_alignof,
T_unary_operation,
T_binary_operation,
@ -59,6 +60,7 @@ public:
T_raw_literal,
T_typeid_type,
T_typeid_expr,
T_type_trait,
// These are used when parsing =default and =delete methods.
T_default,
@ -81,7 +83,9 @@ public:
static CPPExpression new_op(CPPType *type, CPPExpression *op1 = NULL);
static CPPExpression typeid_op(CPPType *type, CPPType *std_type_info);
static CPPExpression typeid_op(CPPExpression *op1, CPPType *std_type_info);
static CPPExpression type_trait(int trait, CPPType *type, CPPType *arg = NULL);
static CPPExpression sizeof_func(CPPType *type);
static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident);
static CPPExpression alignof_func(CPPType *type);
static CPPExpression literal(unsigned long long value, CPPInstance *lit_op);
@ -93,8 +97,6 @@ public:
static const CPPExpression &get_default();
static const CPPExpression &get_delete();
~CPPExpression();
enum ResultType {
RT_integer,
RT_real,
@ -170,6 +172,11 @@ public:
CPPInstance *_operator;
CPPExpression *_value;
} _literal;
struct {
int _trait;
CPPType *_type;
CPPType *_arg;
} _type_trait;
} _u;
protected:

View File

@ -87,12 +87,32 @@ is_tbd() const {
return false;
}
/**
* Returns true if the type is considered a standard layout type.
*/
bool CPPExtensionType::
is_standard_layout() const {
return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
}
/**
* Returns true if the type is considered a Plain Old Data (POD) type.
*/
bool CPPExtensionType::
is_trivial() const {
return (_type == T_enum);
return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
}
/**
* Returns true if the type can be constructed using the given argument.
*/
bool CPPExtensionType::
is_constructible(const CPPType *given_type) const {
if (_type == T_enum || _type == T_enum_class || _type == T_enum_struct) {
const CPPExtensionType *other = ((CPPType *)given_type)->remove_reference()->remove_const()->as_extension_type();
return other != NULL && is_equal(other);
}
return false;
}
/**
@ -100,7 +120,7 @@ is_trivial() const {
*/
bool CPPExtensionType::
is_default_constructible() const {
return (_type == T_enum);
return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
}
/**
@ -108,7 +128,7 @@ is_default_constructible() const {
*/
bool CPPExtensionType::
is_copy_constructible() const {
return (_type == T_enum);
return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
}
/**

View File

@ -47,7 +47,9 @@ public:
virtual bool is_incomplete() const;
virtual bool is_tbd() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;

View File

@ -55,7 +55,7 @@ public:
Filename _filename;
Filename _filename_as_referenced;
Source _source;
mutable Source _source;
mutable bool _pragma_once;
};

View File

@ -89,9 +89,11 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
}
CPPFunctionType *rep = new CPPFunctionType(*this);
rep->_return_type =
_return_type->substitute_decl(subst, current_scope, global_scope)
->as_type();
if (_return_type != NULL) {
rep->_return_type =
_return_type->substitute_decl(subst, current_scope, global_scope)
->as_type();
}
rep->_parameters =
_parameters->substitute_decl(subst, current_scope, global_scope);
@ -265,6 +267,9 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
if (_flags & F_const_method) {
out << " const";
}
if (_flags & F_volatile_method) {
out << " volatile";
}
if (_flags & F_noexcept) {
out << " noexcept";
}
@ -321,14 +326,17 @@ as_function_type() {
* This is similar to is_equal(), except it is more forgiving: it considers
* the functions to be equivalent only if the return type and the types of all
* parameters match.
*
* Note that this isn't symmetric to account for covariant return types.
*/
bool CPPFunctionType::
is_equivalent_function(const CPPFunctionType &other) const {
if (!_return_type->is_equivalent(*other._return_type)) {
match_virtual_override(const CPPFunctionType &other) const {
if (!_return_type->is_equivalent(*other._return_type) &&
!_return_type->is_convertible_to(other._return_type)) {
return false;
}
if (_flags != other._flags) {
if (((_flags ^ other._flags) & ~(F_override | F_final)) != 0) {
return false;
}

View File

@ -40,6 +40,9 @@ public:
F_trailing_return_type = 0x800,
F_final = 0x1000,
F_override = 0x2000,
F_volatile_method = 0x4000,
F_lvalue_method = 0x8000,
F_rvalue_method = 0x10000,
};
CPPFunctionType(CPPType *return_type, CPPParameterList *parameters,
@ -81,7 +84,7 @@ public:
virtual CPPFunctionType *as_function_type();
bool is_equivalent_function(const CPPFunctionType &other) const;
bool match_virtual_override(const CPPFunctionType &other) const;
CPPIdentifier *_class_owner;

View File

@ -82,6 +82,10 @@ CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
// anyway.
}
if (ii->_packed) {
_storage_class |= SC_parameter_pack;
}
delete ii;
}
@ -353,11 +357,7 @@ check_for_constructor(CPPScope *current_scope, CPPScope *global_scope) {
CPPReferenceType *ref_type = param_type->as_reference_type();
if (ref_type != NULL) {
param_type = ref_type->_pointing_at;
if (param_type->get_subtype() == CPPDeclaration::ST_const) {
param_type = param_type->as_const_type()->_wrapped_around;
}
param_type = ref_type->_pointing_at->remove_cv();
if (class_name == param_type->get_simple_name()) {
if (ref_type->_value_category == CPPReferenceType::VC_rvalue) {
@ -563,6 +563,9 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
if (_ident != NULL) {
name = _ident->get_local_name(scope);
}
if (_storage_class & SC_parameter_pack) {
name = "..." + name;
}
if (_type->as_function_type()) {
_type->as_function_type()->

View File

@ -68,6 +68,9 @@ public:
// This isn't really a storage class. It's only used temporarily by the
// parser, to make parsing specifier sequences a bit easier.
SC_const = 0x20000,
// Used to indicate that this is a parameter pack.
SC_parameter_pack = 0x40000,
};
CPPInstance(CPPType *type, const string &name, int storage_class = 0);

View File

@ -26,12 +26,11 @@
*/
CPPInstanceIdentifier::Modifier::
Modifier(CPPInstanceIdentifierType type) :
_type(type)
{
_func_params = NULL;
_func_flags = 0;
_scoping = NULL;
_expr = NULL;
_type(type),
_func_params(NULL),
_func_flags(0),
_scoping(NULL),
_expr(NULL) {
}
/**
@ -83,7 +82,8 @@ initializer_type(CPPParameterList *params) {
CPPInstanceIdentifier::
CPPInstanceIdentifier(CPPIdentifier *ident) :
_ident(ident),
_bit_width(-1) {
_bit_width(-1),
_packed(false) {
}
/**

View File

@ -88,8 +88,12 @@ public:
typedef vector<Modifier> Modifiers;
Modifiers _modifiers;
// If not -1, indicates a bitfield
int _bit_width;
// Indicates a parameter pack
bool _packed;
private:
CPPType *
r_unroll_type(CPPType *start_type, Modifiers::const_iterator mi);

View File

@ -45,7 +45,20 @@ is_fully_specified() const {
*/
bool CPPParser::
parse_file(const Filename &filename) {
if (!init_cpp(CPPFile(filename, filename, CPPFile::S_local))) {
Filename canonical(filename);
canonical.make_canonical();
CPPFile file(canonical, filename, CPPFile::S_local);
// Don't read it if we included it before and it had #pragma once.
ParsedFiles::iterator it = _parsed_files.find(file);
if (it != _parsed_files.end() && it->_pragma_once) {
// But mark it as local.
it->_source = CPPFile::S_local;
return true;
}
if (!init_cpp(file)) {
cerr << "Unable to read " << filename << "\n";
return false;
}

View File

@ -14,6 +14,9 @@
#include "cppPointerType.h"
#include "cppFunctionType.h"
#include "cppIdentifier.h"
#include "cppArrayType.h"
#include "cppStructType.h"
#include "cppSimpleType.h"
/**
*
@ -88,6 +91,14 @@ is_tbd() const {
return _pointing_at->is_tbd();
}
/**
* Returns true if the type is considered a standard layout type.
*/
bool CPPPointerType::
is_standard_layout() const {
return true;
}
/**
* Returns true if the type is considered a Plain Old Data (POD) type.
*/
@ -96,6 +107,60 @@ is_trivial() const {
return true;
}
/**
* Returns true if the type can be constructed using the given argument.
*/
bool CPPPointerType::
is_constructible(const CPPType *given_type) const {
given_type = ((CPPType *)given_type)->remove_reference()->remove_cv();
// Can convert from compatible pointer or array type.
CPPType *other_target;
switch (given_type->get_subtype()) {
case ST_array:
other_target = given_type->as_array_type()->_element_type;
break;
case ST_pointer:
other_target = given_type->as_pointer_type()->_pointing_at;
break;
case ST_simple:
// Can initialize from nullptr.
return given_type->as_simple_type()->_type == CPPSimpleType::T_nullptr;
default:
return false;
}
// Can't convert const to non-const pointer.
if (other_target->is_const() && !_pointing_at->is_const()) {
return false;
}
// Are we pointing to the same type? That's always OK.
const CPPType *a = _pointing_at->remove_cv();
const CPPType *b = other_target->remove_cv();
if (a == b || *a == *b) {
return true;
}
// Can initialize void pointer with any pointer.
const CPPSimpleType *simple_type = a->as_simple_type();
if (simple_type != NULL) {
return simple_type->_type == CPPSimpleType::T_void;
}
// Can initialize from derived class pointer.
const CPPStructType *a_struct = a->as_struct_type();
const CPPStructType *b_struct = b->as_struct_type();
if (a_struct != NULL && b_struct != NULL) {
return a_struct->is_base_of(b_struct);
}
return false;
}
/**
* Returns true if the type is default-constructible.
*/

View File

@ -36,7 +36,9 @@ public:
CPPScope *global_scope);
virtual bool is_tbd() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_constructible(const CPPType *other) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;
virtual bool is_equivalent(const CPPType &other) const;

View File

@ -18,6 +18,7 @@
#include "cppIdentifier.h"
#include "cppTemplateScope.h"
#include "cppTemplateParameterList.h"
#include "cppClassTemplateParameter.h"
#include "cppConstType.h"
#include "cppFunctionGroup.h"
#include "cppFunctionType.h"
@ -416,7 +417,14 @@ get_next_token0() {
int token_type = IDENTIFIER;
CPPDeclaration *decl = ident->find_symbol(current_scope, global_scope);
if (decl != NULL && decl->as_type() != NULL) {
token_type = TYPENAME_IDENTIFIER;
// We need to see type pack template parameters as a different type of
// identifier to resolve a parser ambiguity.
CPPClassTemplateParameter *ctp = decl->as_class_template_parameter();
if (ctp && ctp->_packed) {
token_type = TYPEPACK_IDENTIFIER;
} else {
token_type = TYPENAME_IDENTIFIER;
}
}
_last_token_loc = loc;
@ -801,6 +809,8 @@ expand_manifests(const string &input_expr, bool expand_undefined,
// Here's an identifier. Is it "defined"?
if (ident == "defined") {
expand_defined_function(expr, q, p);
} else if (expand_undefined && ident == "__has_include") {
expand_has_include_function(expr, q, p, loc);
} else {
// Is it a manifest?
Manifests::const_iterator mi = _manifests.find(ident);
@ -809,6 +819,20 @@ expand_manifests(const string &input_expr, bool expand_undefined,
expand_manifest_inline(expr, q, p, manifest);
manifest_found = true;
} else if (ident == "__FILE__") {
// Special case: this is a dynamic definition.
string file = string("\"") + loc.file._filename_as_referenced.get_fullpath() + "\"";
expr = expr.substr(0, q) + file + expr.substr(p);
p = q + file.size();
manifest_found = true;
} else if (ident == "__LINE__") {
// So is this.
string line = format_string(loc.first_line);
expr = expr.substr(0, q) + line + expr.substr(p);
p = q + line.size();
manifest_found = true;
} else if (expand_undefined && ident != "true" && ident != "false") {
// It is not found. Expand it to 0, but only if we are currently
// parsing an #if expression.
@ -951,7 +975,7 @@ internal_get_next_token() {
case ',':
if (_paren_nesting <= 0) {
_state = S_end_nested;
return CPPToken::eof();
return CPPToken(0, loc);
}
break;
@ -959,7 +983,7 @@ internal_get_next_token() {
if (_paren_nesting <= 0) {
_parsing_template_params = false;
_state = S_end_nested;
return CPPToken::eof();
return CPPToken(0, loc);
}
}
}
@ -1453,7 +1477,6 @@ handle_define_directive(const string &args, const YYLTYPE &loc) {
CPPManifest *other = result.first->second;
warning("redefinition of macro '" + manifest->_name + "'", loc);
warning("previous definition is here", other->_loc);
delete other;
result.first->second = manifest;
}
}
@ -1479,14 +1502,10 @@ handle_undef_directive(const string &args, const YYLTYPE &loc) {
*/
void CPPPreprocessor::
handle_ifdef_directive(const string &args, const YYLTYPE &loc) {
Manifests::const_iterator mi = _manifests.find(args);
if (mi != _manifests.end()) {
// The macro is defined. We continue.
return;
if (!is_manifest_defined(args)) {
// The macro is undefined. Skip stuff.
skip_false_if_block(true);
}
// The macro is undefined. Skip stuff.
skip_false_if_block(true);
}
/**
@ -1494,17 +1513,12 @@ handle_ifdef_directive(const string &args, const YYLTYPE &loc) {
*/
void CPPPreprocessor::
handle_ifndef_directive(const string &args, const YYLTYPE &loc) {
Manifests::const_iterator mi = _manifests.find(args);
if (mi == _manifests.end()) {
// The macro is undefined. We continue.
return;
if (is_manifest_defined(args)) {
// The macro is defined. Skip stuff.
skip_false_if_block(true);
}
// The macro is defined. Skip stuff.
skip_false_if_block(true);
}
/**
*
*/
@ -1586,6 +1600,8 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
_angle_includes.insert(filename);
}
}
} else {
warning("Ignoring invalid #include directive", loc);
}
filename.set_text();
@ -1593,71 +1609,30 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
// Now look for the filename. If we didn't use angle quotes, look first in
// the current directory.
bool found_file = false;
CPPFile::Source source = CPPFile::S_none;
if (okflag) {
found_file = false;
if (find_include(filename, angle_quotes, source)) {
_last_c = '\0';
// Search the current directory.
if (!angle_quotes && !found_file && filename.exists()) {
found_file = true;
// If it was explicitly named on the command-line, mark it S_local.
filename.make_canonical();
if (_explicit_files.count(filename)) {
source = CPPFile::S_local;
}
// Search the same directory as the includer.
if (!angle_quotes && !found_file) {
Filename match(get_file()._filename.get_dirname(), filename);
if (match.exists()) {
filename = match;
found_file = true;
source = CPPFile::S_alternate;
}
CPPFile file(filename, filename_as_referenced, source);
// Don't include it if we included it before and it had #pragma once.
ParsedFiles::const_iterator it = _parsed_files.find(file);
if (it != _parsed_files.end() && it->_pragma_once) {
return;
}
// Now search the angle-include-path
if (angle_quotes && !found_file && filename.resolve_filename(_angle_include_path)) {
found_file = true;
source = CPPFile::S_system;
}
// Now search the quote-include-path
if (!angle_quotes && !found_file) {
for (size_t dir=0; dir<_quote_include_path.get_num_directories(); dir++) {
Filename match(_quote_include_path.get_directory(dir), filename);
if (match.exists()) {
filename = match;
found_file = true;
source = _quote_include_kind[dir];
}
}
}
if (!found_file) {
warning("Cannot find " + filename.get_fullpath(), loc);
} else {
_last_c = '\0';
// If it was explicitly named on the command-line, mark it S_local.
filename.make_absolute();
if (_explicit_files.count(filename)) {
source = CPPFile::S_local;
}
CPPFile file(filename, filename_as_referenced, source);
// Don't include it if we included it before and it had #pragma once.
ParsedFiles::const_iterator it = _parsed_files.find(file);
if (it != _parsed_files.end() && it->_pragma_once) {
return;
}
if (!push_file(file)) {
warning("Unable to read " + filename.get_fullpath(), loc);
}
if (!push_file(file)) {
warning("Unable to read " + filename.get_fullpath(), loc);
}
} else {
warning("Ignoring invalid #include directive", loc);
warning("Cannot find " + filename.get_fullpath(), loc);
}
}
@ -1671,6 +1646,38 @@ handle_pragma_directive(const string &args, const YYLTYPE &loc) {
assert(it != _parsed_files.end());
it->_pragma_once = true;
}
char macro[64];
if (sscanf(args.c_str(), "push_macro ( \"%63[^\"]\" )", macro) == 1) {
// We just mark it as pushed for now, so that the next time someone tries
// to override it, we save the old value.
Manifests::iterator mi = _manifests.find(macro);
if (mi != _manifests.end()) {
_manifest_stack[macro].push_back(mi->second);
} else {
_manifest_stack[macro].push_back(NULL);
}
} else if (sscanf(args.c_str(), "pop_macro ( \"%63[^\"]\" )", macro) == 1) {
ManifestStack &stack = _manifest_stack[macro];
if (stack.size() > 0) {
CPPManifest *manifest = stack.back();
stack.pop_back();
Manifests::iterator mi = _manifests.find(macro);
if (manifest == NULL) {
// It was undefined when it was pushed, so make it undefined again.
if (mi != _manifests.end()) {
_manifests.erase(mi);
}
} else if (mi != _manifests.end()) {
mi->second = manifest;
} else {
_manifests.insert(Manifests::value_type(macro, manifest));
}
} else {
warning("pop_macro without matching push_macro", loc);
}
}
}
/**
@ -1740,6 +1747,69 @@ skip_false_if_block(bool consider_elifs) {
_save_comments = true;
}
/**
* Returns true if the given manifest is defined.
*/
bool CPPPreprocessor::
is_manifest_defined(const string &manifest_name) {
Manifests::const_iterator mi = _manifests.find(manifest_name);
if (mi != _manifests.end()) {
return true;
}
if (manifest_name == "__has_include" ||
manifest_name == "__FILE__" ||
manifest_name == "__LINE__") {
// Special built-in directives that are considered "defined".
return true;
}
return false;
}
/**
* Locates the given filename. Changes the first argument to the full path.
*/
bool CPPPreprocessor::
find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source) {
// Now look for the filename. If we didn't use angle quotes, look first in
// the current directory.
if (!angle_quotes && filename.exists()) {
source = CPPFile::S_local;
return true;
}
// Search the same directory as the includer.
if (!angle_quotes) {
Filename match(get_file()._filename.get_dirname(), filename);
if (match.exists()) {
filename = match;
source = CPPFile::S_alternate;
return true;
}
}
// Now search the angle-include-path
if (angle_quotes && filename.resolve_filename(_angle_include_path)) {
source = CPPFile::S_system;
return true;
}
// Now search the quote-include-path
if (!angle_quotes) {
for (size_t dir = 0; dir < _quote_include_path.get_num_directories(); ++dir) {
Filename match(_quote_include_path.get_directory(dir), filename);
if (match.exists()) {
filename = match;
source = _quote_include_kind[dir];
return true;
}
}
}
return false;
}
/**
*
*/
@ -1846,6 +1916,14 @@ get_identifier(int c) {
if (mi != _manifests.end() && !should_ignore_manifest((*mi).second)) {
return expand_manifest((*mi).second);
}
if (name == "__FILE__") {
return get_literal(SIMPLE_STRING, loc, loc.file._filename_as_referenced);
}
if (name == "__LINE__") {
YYSTYPE result;
result.u.integer = loc.first_line;
return CPPToken(INTEGER, loc, "", result);
}
// Check for keywords.
int kw = check_keyword(name);
@ -2188,9 +2266,7 @@ expand_defined_function(string &expr, size_t q, size_t &p) {
vector_string args;
extract_manifest_args_inline("defined", 1, -1, args, expr, p);
if (args.size() >= 1) {
const string &manifest_name = args[0];
Manifests::const_iterator mi = _manifests.find(manifest_name);
if (mi != _manifests.end()) {
if (is_manifest_defined(args[0])) {
// The macro is defined; the result is "1".
result = "1";
} else {
@ -2203,6 +2279,70 @@ expand_defined_function(string &expr, size_t q, size_t &p) {
p = q + result.size();
}
/**
* Expands the __has_include(manifest) function to either 1 or 0, depending on
* whether the include file exists.
*/
void CPPPreprocessor::
expand_has_include_function(string &expr, size_t q, size_t &p, YYLTYPE loc) {
bool found_file = false;
// Skip whitespace till paren.
while (p < expr.size() && isspace(expr[p])) {
p++;
}
size_t args_begin = p + 1;
vector_string args;
extract_manifest_args_inline("__has_include", 1, -1, args, expr, p);
if (!args.empty() && args[0].size() >= 2) {
Filename filename;
bool angle_quotes = false;
string inc = args[0];
// Just to play things safe, since our manifest-expansion logic might not
// filter out quotes and angle brackets properly, we'll only expand
// manifests if we don't begin with a quote or bracket.
if (!inc.empty() && (inc[0] != '"' && inc[0] != '<')) {
inc = expand_manifests(inc, false, loc);
}
if (inc[0] == '"' && inc[inc.size() - 1] == '"') {
filename = inc.substr(1, inc.size() - 2);
} else if (inc[0] == '<' && inc[inc.size() - 1] == '>') {
filename = inc.substr(1, inc.size() - 2);
if (!_noangles) {
// If _noangles is true, we don't make a distinction between angle
// brackets and quote marks--all #inc statements are treated the
// same, as if they used quote marks.
angle_quotes = true;
}
} else {
loc.last_column += loc.first_column + p - 2;
loc.first_column += args_begin;
warning("invalid argument for __has_include() directive", loc);
expr = expr.substr(0, q) + "0" + expr.substr(p);
p = q + 1;
return;
}
filename.set_text();
CPPFile::Source source = CPPFile::S_none;
found_file = find_include(filename, angle_quotes, source);
} else {
loc.last_column += loc.first_column + p - 2;
loc.first_column += args_begin;
warning("invalid argument for __has_include() directive", loc);
}
string result = found_file ? "1" : "0";
expr = expr.substr(0, q) + result + expr.substr(p);
p = q + result.size();
}
/**
*
*/
@ -2451,11 +2591,27 @@ check_keyword(const string &name) {
if (name == "friend") return KW_FRIEND;
if (name == "for") return KW_FOR;
if (name == "goto") return KW_GOTO;
if (name == "__has_virtual_destructor") return KW_HAS_VIRTUAL_DESTRUCTOR;
if (name == "if") return KW_IF;
if (name == "inline") return KW_INLINE;
if (name == "__inline") return KW_INLINE;
if (name == "__inline__") return KW_INLINE;
if (name == "int") return KW_INT;
if (name == "__is_abstract") return KW_IS_ABSTRACT;
if (name == "__is_base_of") return KW_IS_BASE_OF;
if (name == "__is_class") return KW_IS_CLASS;
if (name == "__is_constructible") return KW_IS_CONSTRUCTIBLE;
if (name == "__is_convertible_to") return KW_IS_CONVERTIBLE_TO;
if (name == "__is_destructible") return KW_IS_DESTRUCTIBLE;
if (name == "__is_empty") return KW_IS_EMPTY;
if (name == "__is_enum") return KW_IS_ENUM;
if (name == "__is_final") return KW_IS_FINAL;
if (name == "__is_fundamental") return KW_IS_FUNDAMENTAL;
if (name == "__is_pod") return KW_IS_POD;
if (name == "__is_polymorphic") return KW_IS_POLYMORPHIC;
if (name == "__is_standard_layout") return KW_IS_STANDARD_LAYOUT;
if (name == "__is_trivial") return KW_IS_TRIVIAL;
if (name == "__is_union") return KW_IS_UNION;
if (name == "long") return KW_LONG;
if (name == "__make_map_property") return KW_MAKE_MAP_PROPERTY;
if (name == "__make_property") return KW_MAKE_PROPERTY;
@ -2490,6 +2646,7 @@ check_keyword(const string &name) {
if (name == "typedef") return KW_TYPEDEF;
if (name == "typeid") return KW_TYPEID;
if (name == "typename") return KW_TYPENAME;
if (name == "__underlying_type") return KW_UNDERLYING_TYPE;
if (name == "union") return KW_UNION;
if (name == "unsigned") return KW_UNSIGNED;
if (name == "using") return KW_USING;
@ -2751,7 +2908,7 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) {
_parsing_template_params = true;
CPPToken token = internal_get_next_token();
if (token._token == '>') {
if (token._token == '>' || token._token == 0) {
_parsing_template_params = false;
} else {
_saved_tokens.push_back(token);
@ -2760,36 +2917,53 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) {
CPPTemplateParameterList *actual_params = new CPPTemplateParameterList;
for (pi = formal_params._parameters.begin();
pi != formal_params._parameters.end() && _parsing_template_params;
++pi) {
pi != formal_params._parameters.end() && _parsing_template_params;) {
CPPToken token = peek_next_token();
YYLTYPE loc = token._lloc;
CPPDeclaration *decl = (*pi);
if (decl->as_type()) {
CPPClassTemplateParameter *param = decl->as_class_template_parameter();
CPPInstance *inst = decl->as_instance();
if (param) {
// Parse a typename template parameter.
_saved_tokens.push_back(CPPToken(START_TYPE));
CPPType *type = ::parse_type(this, current_scope, global_scope);
if (type == NULL) {
loc.last_line = get_line_number();
loc.last_column = get_col_number() - 1;
warning("Invalid type", loc);
warning("invalid type", loc);
skip_to_end_nested();
type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown));
}
actual_params->_parameters.push_back(type);
} else {
// If this is a variadic template, keep reading using this parameter.
if (!param->_packed) {
++pi;
}
} else if (inst) {
// Parse a constant expression template parameter.
_saved_tokens.push_back(CPPToken(START_CONST_EXPR));
CPPExpression *expr = parse_const_expr(this, current_scope, global_scope);
if (expr == NULL) {
loc.last_line = get_line_number();
loc.last_column = get_col_number() - 1;
warning("Invalid expression", loc);
warning("invalid expression", loc);
skip_to_end_nested();
expr = new CPPExpression(0);
}
actual_params->_parameters.push_back(expr);
// If this is a variadic template, keep reading using this parameter.
if ((inst->_storage_class & CPPInstance::SC_parameter_pack) == 0) {
++pi;
}
} else {
loc.last_line = get_line_number();
loc.last_column = get_col_number() - 1;
warning("invalid template parameter", loc);
skip_to_end_nested();
++pi;
}
_state = S_nested;

View File

@ -72,6 +72,9 @@ public:
typedef map<string, CPPManifest *> Manifests;
Manifests _manifests;
typedef pvector<CPPManifest *> ManifestStack;
map<string, ManifestStack> _manifest_stack;
pvector<CPPFile::Source> _quote_include_kind;
DSearchPath _quote_include_path;
DSearchPath _angle_include_path;
@ -140,6 +143,8 @@ private:
void handle_error_directive(const string &args, const YYLTYPE &loc);
void skip_false_if_block(bool consider_elifs);
bool is_manifest_defined(const string &manifest_name);
bool find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source);
CPPToken get_quoted_char(int c);
CPPToken get_quoted_string(int c);
@ -150,6 +155,7 @@ private:
void extract_manifest_args(const string &name, int num_args,
int va_arg, vector_string &args);
void expand_defined_function(string &expr, size_t q, size_t &p);
void expand_has_include_function(string &expr, size_t q, size_t &p, YYLTYPE loc);
void expand_manifest_inline(string &expr, size_t q, size_t &p,
const CPPManifest *manifest);
void extract_manifest_args_inline(const string &name, int num_args,

View File

@ -12,6 +12,8 @@
*/
#include "cppReferenceType.h"
#include "cppTypedefType.h"
#include "cppStructType.h"
/**
*
@ -87,6 +89,14 @@ is_tbd() const {
return _pointing_at->is_tbd();
}
/**
* Returns true if the type is considered a standard layout type.
*/
bool CPPReferenceType::
is_standard_layout() const {
return false;
}
/**
* Returns true if the type is considered a Plain Old Data (POD) type.
*/
@ -95,6 +105,67 @@ is_trivial() const {
return false;
}
/**
* Returns true if the type can be constructed using the given argument.
*/
bool CPPReferenceType::
is_constructible(const CPPType *given_type) const {
const CPPType *a;
const CPPType *b;
CPPReferenceType *ref_type = ((CPPType *)given_type)->as_reference_type();
if (ref_type != NULL) {
if (ref_type->_value_category == VC_rvalue) {
return is_constructible(ref_type->_pointing_at);
}
if (_value_category == VC_rvalue) {
// Can never initialize an rvalue ref from an lvalue ref.
return false;
}
if (!_pointing_at->is_const()) {
// Cannot initialize a non-const reference using a const one.
if (ref_type->_pointing_at->is_const()) {
return false;
}
}
a = _pointing_at->remove_cv();
b = ref_type->_pointing_at->remove_cv();
} else {
// Initializing using an rvalue.
if (!_pointing_at->is_const()) {
// Cannot initialize a non-const reference using a const one.
if (given_type->is_const()) {
return false;
}
// Cannot initalise a non-const lvalue reference with an rvalue ref.
if (_value_category == VC_lvalue) {
return false;
}
}
a = _pointing_at->remove_cv();
b = ((CPPType *)given_type)->remove_cv();
}
if (a == b || *a == *b) {
return true;
}
// Can initialize from derived class pointer.
const CPPStructType *a_struct = a->as_struct_type();
const CPPStructType *b_struct = b->as_struct_type();
if (a_struct != NULL && b_struct != NULL) {
return a_struct->is_base_of(b_struct);
}
return false;
}
/**
* Returns true if the type is default-constructible.
*/
@ -111,6 +182,14 @@ is_copy_constructible() const {
return (_value_category == VC_lvalue);
}
/**
* Returns true if the type is destructible.
*/
bool CPPReferenceType::
is_destructible() const {
return false;
}
/**
* 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

View File

@ -42,9 +42,12 @@ public:
CPPScope *global_scope);
virtual bool is_tbd() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;
virtual bool is_destructible() const;
virtual bool is_equivalent(const CPPType &other) const;
virtual void output(ostream &out, int indent_level, CPPScope *scope,

View File

@ -27,8 +27,8 @@
#include "cppPreprocessor.h"
#include "cppTemplateScope.h"
#include "cppClassTemplateParameter.h"
#include "cppConstType.h"
#include "cppFunctionType.h"
#include "cppConstType.h"
#include "cppUsing.h"
#include "cppBisonDefs.h"
#include "indent.h"

View File

@ -139,11 +139,12 @@ public:
Templates _templates;
CPPNameComponent _name;
typedef set<CPPScope *> Using;
Using _using;
protected:
CPPScope *_parent_scope;
CPPStructType *_struct_type;
typedef set<CPPScope *> Using;
Using _using;
CPPVisibility _current_vis;
private:

View File

@ -34,6 +34,30 @@ is_tbd() const {
return (_type == T_unknown);
}
/**
* Returns true if the type is a boolean, floating point or integral type.
*/
bool CPPSimpleType::
is_arithmetic() const {
return (_type > T_unknown && _type < T_void);
}
/**
* Returns true if the type is considered a fundamental type.
*/
bool CPPSimpleType::
is_fundamental() const {
return (_type != T_unknown && _type != T_parameter && _type != T_auto);
}
/**
* Returns true if the type is considered a standard layout type.
*/
bool CPPSimpleType::
is_standard_layout() const {
return (_type != T_unknown && _type != T_parameter && _type != T_auto);
}
/**
* Returns true if the type is considered a Plain Old Data (POD) type.
*/
@ -42,6 +66,27 @@ is_trivial() const {
return true;
}
/**
* Returns true if the type can be constructed using the given argument.
*/
bool CPPSimpleType::
is_constructible(const CPPType *given_type) const {
given_type = ((CPPType *)given_type)->remove_reference()->remove_cv();
const CPPSimpleType *simple_type = given_type->as_simple_type();
if (simple_type == NULL) {
return given_type->is_enum() && is_arithmetic();
} else if (_type == T_nullptr) {
return simple_type->_type == T_nullptr;
} else if (_type == T_bool) {
return simple_type->is_arithmetic() || simple_type->_type == T_nullptr;
} else if (is_arithmetic()) {
return simple_type->is_arithmetic();
} else {
return false;
}
}
/**
* Returns true if the type is default-constructible.
*/
@ -58,6 +103,14 @@ is_copy_constructible() const {
return (_type != T_void);
}
/**
* Returns true if the type is destructible.
*/
bool CPPSimpleType::
is_destructible() const {
return (_type != T_void);
}
/**
* Returns true if the type is a special parameter expression type.
*

View File

@ -19,7 +19,7 @@
#include "cppType.h"
/**
*
* Represents a C++ fundamental type.
*/
class CPPSimpleType : public CPPType {
public:
@ -40,12 +40,11 @@ public:
// nullptr_t, which is a typedef of decltype(nullptr).
T_nullptr,
/*
* T_parameter is a special type which is assigned to expressions that are
* discovered where a formal parameter was expected. This is a special case
* for handling cases like this: int foo(0); which really means the same thing
* as: int foo = 0; but it initially looks like a function prototype.
*/
// T_parameter is a special type which is assigned to expressions that are
// discovered where a formal parameter was expected. This is a special
// case for handling cases like this: int foo(0); which really means the
// same thing as: int foo = 0; but it initially looks like a function
// prototype.
T_parameter,
// T_auto is also a special type that corresponds to the "auto" keyword
@ -69,9 +68,14 @@ public:
int _flags;
virtual bool is_tbd() const;
bool is_arithmetic() const;
virtual bool is_fundamental() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;
virtual bool is_destructible() const;
virtual bool is_parameter_expr() const;
virtual string get_preferred_name() const;

View File

@ -13,6 +13,7 @@
#include "cppStructType.h"
#include "cppTypedefType.h"
#include "cppReferenceType.h"
#include "cppScope.h"
#include "cppTypeProxy.h"
#include "cppTemplateScope.h"
@ -126,16 +127,154 @@ is_abstract() const {
return !funcs.empty();
}
/**
* Returns true if this struct declaration is a base class of the other given
* class, or the same class.
*/
bool CPPStructType::
is_base_of(const CPPStructType *other) const {
if (this == other) {
return true;
}
Derivation::const_iterator di;
for (di = other->_derivation.begin(); di != other->_derivation.end(); ++di) {
const CPPStructType *base = (*di)._base->as_struct_type();
if (base != NULL && is_base_of(base)) {
return true;
}
}
return false;
}
/**
* Returns true if this struct declaration defines no non-static data members
* other than bit-fields of size 0, no virtual functions, no virtual base
* classes, and no non-empty base classes, and is not a union.
*/
bool CPPStructType::
is_empty() const {
if (_type == T_union) {
return false;
}
if (check_virtual()) {
return false;
}
// Make sure all base classes are empty and non-virtual.
Derivation::const_iterator di;
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
CPPStructType *base = (*di)._base->as_struct_type();
if ((*di)._is_virtual || (base != NULL && !base->is_empty())) {
return false;
}
}
// Make sure there are no non-static data members.
CPPScope::Variables::const_iterator vi;
for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) {
CPPInstance *instance = (*vi).second;
assert(instance != NULL);
if (instance->_storage_class & CPPInstance::SC_static) {
// Static members don't count.
continue;
}
// Only members with a bit width of 0 are okay.
if (instance->_bit_width != 0) {
return false;
}
}
return true;
}
/**
* Returns true if this class or any of its base classes have virtual methods.
*/
bool CPPStructType::
is_polymorphic() const {
if (_type == T_union) {
return false;
}
return check_virtual();
}
/**
* Returns true if the type is considered a standard layout type.
*/
bool CPPStructType::
is_standard_layout() const {
assert(_scope != NULL);
CPPVisibility member_vis = V_unknown;
// Make sure all data members have the same vis and are standard layout.
CPPScope::Variables::const_iterator vi;
for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) {
CPPInstance *instance = (*vi).second;
assert(instance != NULL);
if (instance->_storage_class & CPPInstance::SC_static) {
// Static members don't count.
continue;
}
// Finally, check if the data member itself is standard layout.
assert(instance->_type != NULL);
if (!instance->_type->is_standard_layout()) {
return false;
}
if (member_vis == V_unknown) {
// The first non-static data member may not be a base class.
CPPStructType *struct_type = instance->_type->remove_cv()->as_struct_type();
if (struct_type != NULL && struct_type->is_base_of(this)) {
return false;
}
member_vis = instance->_vis;
} else if (member_vis != instance->_vis) {
// All members need to have the same access control.
return false;
}
}
// Make sure all base classes are standard-layout and non-virtual.
Derivation::const_iterator di;
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
CPPStructType *base = (*di)._base->as_struct_type();
if ((*di)._is_virtual) {
return false;
}
// If this class had instance members, all base classes need to be empty.
if (member_vis != V_unknown) {
if (!base->is_empty()) {
return false;
}
} else {
if (!base->is_standard_layout()) {
return false;
}
}
}
// Make sure we have no virtual functions.
return !check_virtual();
}
/**
* Returns true if the type is considered a Plain Old Data (POD) type.
*/
bool CPPStructType::
is_trivial() const {
// Make sure all base classes are trivial.
// Make sure all base classes are trivial and non-virtual.
Derivation::const_iterator di;
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
CPPStructType *base = (*di)._base->as_struct_type();
if (base != NULL && !base->is_trivial()) {
if ((*di)._is_virtual || (base != NULL && !base->is_trivial())) {
return false;
}
}
@ -166,7 +305,7 @@ is_trivial() const {
}
}
// Now look for functions that are virtual or condestructors.
// Now look for functions that are virtual or con/destructors.
bool is_default_constructible = true;
CPPScope::Functions::const_iterator fi;
for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) {
@ -193,8 +332,8 @@ is_trivial() const {
if (ftype->_flags & (CPPFunctionType::F_destructor |
CPPFunctionType::F_move_constructor |
CPPFunctionType::F_copy_constructor)) {
// User-provided destructors and copymove constructors are not trivial
// unless they are defaulted (and not virtual).
// User-provided destructors and copy/move constructors are not
// trivial unless they are defaulted (and not virtual).
return false;
}
@ -220,6 +359,66 @@ is_trivial() const {
return is_default_constructible;
}
/**
* Returns true if the type can be constructed using the given argument.
* This implementation is rudimentary, as it does not attempt to follow all of
* the implicit type conversion rules, but it is still useful.
*/
bool CPPStructType::
is_constructible(const CPPType *given_type) const {
// Does the type match the copy constructor or move constructor?
CPPType *base_type = ((CPPType *)given_type)->remove_reference();
if (is_equivalent(*base_type->remove_cv())) {
const CPPReferenceType *ref_type = given_type->as_reference_type();
if (ref_type == NULL ||
ref_type->_value_category == CPPReferenceType::VC_rvalue) {
return is_move_constructible(V_public);
} else {
return is_copy_constructible(V_public);
}
}
if (is_abstract()) {
return false;
}
// Check for a different constructor.
CPPFunctionGroup *fgroup = get_constructor();
if (fgroup != (CPPFunctionGroup *)NULL) {
CPPFunctionGroup::Instances::const_iterator ii;
for (ii = fgroup->_instances.begin();
ii != fgroup->_instances.end();
++ii) {
CPPInstance *inst = (*ii);
assert(inst->_type != (CPPType *)NULL);
CPPFunctionType *ftype = inst->_type->as_function_type();
assert(ftype != (CPPFunctionType *)NULL);
CPPParameterList *params = ftype->_parameters;
if (params->_parameters.size() == 1 && !params->_includes_ellipsis) {
CPPType *param_type = params->_parameters[0]->_type->remove_reference();
if (!param_type->is_const() && base_type->is_const()) {
// Can't pass a const object to a function taking a non-const.
continue;
}
// It's deleted, anyhow.
if ((inst->_storage_class & CPPInstance::SC_deleted) != 0) {
continue;
}
if (param_type->is_equivalent(*base_type)) {
return true;
}
}
}
}
return false;
}
/**
* Returns true if the type is default-constructible.
*/
@ -236,11 +435,23 @@ is_copy_constructible() const {
return is_copy_constructible(V_public);
}
/**
* Returns true if the type is destructible.
*/
bool CPPStructType::
is_destructible() const {
return is_destructible(V_public);
}
/**
* Returns true if the type is default-constructible.
*/
bool CPPStructType::
is_default_constructible(CPPVisibility min_vis) const {
if (is_abstract()) {
return false;
}
CPPInstance *constructor = get_default_constructor();
if (constructor != (CPPInstance *)NULL) {
// It has a default constructor.
@ -295,24 +506,6 @@ is_default_constructible(CPPVisibility min_vis) const {
}
}
// Check that we don't have pure virtual methods.
CPPScope::Functions::const_iterator fi;
for (fi = _scope->_functions.begin();
fi != _scope->_functions.end();
++fi) {
CPPFunctionGroup *fgroup = (*fi).second;
CPPFunctionGroup::Instances::const_iterator ii;
for (ii = fgroup->_instances.begin();
ii != fgroup->_instances.end();
++ii) {
CPPInstance *inst = (*ii);
if (inst->_storage_class & CPPInstance::SC_pure_virtual) {
// Here's a pure virtual function.
return false;
}
}
}
return true;
}
@ -321,6 +514,10 @@ is_default_constructible(CPPVisibility min_vis) const {
*/
bool CPPStructType::
is_copy_constructible(CPPVisibility min_vis) const {
if (is_abstract()) {
return false;
}
CPPInstance *constructor = get_copy_constructor();
if (constructor != (CPPInstance *)NULL) {
// It has a copy constructor.
@ -378,27 +575,146 @@ is_copy_constructible(CPPVisibility min_vis) const {
}
}
// Check that we don't have pure virtual methods.
CPPScope::Functions::const_iterator fi;
for (fi = _scope->_functions.begin();
fi != _scope->_functions.end();
++fi) {
CPPFunctionGroup *fgroup = (*fi).second;
CPPFunctionGroup::Instances::const_iterator ii;
for (ii = fgroup->_instances.begin();
ii != fgroup->_instances.end();
++ii) {
CPPInstance *inst = (*ii);
if (inst->_storage_class & CPPInstance::SC_pure_virtual) {
// Here's a pure virtual function.
return false;
}
return true;
}
/**
* Returns true if the type is move-constructible.
*/
bool CPPStructType::
is_move_constructible(CPPVisibility min_vis) const {
CPPInstance *constructor = get_move_constructor();
if (constructor != (CPPInstance *)NULL) {
// It has a user-declared move constructor.
if (constructor->_vis > min_vis) {
// Inaccessible move constructor.
return false;
}
if (constructor->_storage_class & CPPInstance::SC_deleted) {
// It is deleted.
return false;
}
if (is_abstract()) {
return false;
}
return true;
}
return is_copy_constructible(min_vis);
}
/**
* Returns true if the type is destructible.
*/
bool CPPStructType::
is_destructible(CPPVisibility min_vis) const {
// Do we have an explicit destructor?
CPPInstance *destructor = get_destructor();
if (destructor != (CPPInstance *)NULL) {
if (destructor->_vis > min_vis) {
// Yes, but it's inaccessible.
return false;
}
if (destructor->_storage_class & CPPInstance::SC_deleted) {
// Yes, but it's explicitly been deleted.
return false;
}
return true;
}
// Make sure all base classes are destructible.
Derivation::const_iterator di;
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
CPPStructType *base = (*di)._base->as_struct_type();
if (base != NULL && !base->is_destructible(V_protected)) {
return false;
}
}
assert(_scope != NULL);
// Make sure all members are destructible.
CPPScope::Variables::const_iterator vi;
for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) {
CPPInstance *instance = (*vi).second;
assert(instance != NULL);
if (instance->_storage_class & CPPInstance::SC_static) {
// Static members don't count.
continue;
}
// If the data member is not destructible, no go.
assert(instance->_type != NULL);
if (!instance->_type->is_destructible()) {
return false;
}
}
return true;
}
/**
* Returns true if variables of this type may be implicitly converted to
* the other type.
*/
bool CPPStructType::
is_convertible_to(const CPPType *other) const {
if (CPPType::is_convertible_to(other)) {
return true;
}
// Check all typecast operators to see whether we can cast to a type that is
// convertible to the other type.
CPPScope::Functions::const_iterator fi;
for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) {
CPPFunctionGroup *fgroup = (*fi).second;
CPPFunctionGroup::Instances::const_iterator ii;
for (ii = fgroup->_instances.begin(); ii != fgroup->_instances.end(); ++ii) {
CPPInstance *inst = (*ii);
if (inst->_storage_class & (CPPInstance::SC_deleted | CPPInstance::SC_static | CPPInstance::SC_explicit)) {
// Exclude static/deleted/explicit methods.
continue;
}
// Also, the instance needs to be publicly visible.
if (inst->_vis > V_public) {
continue;
}
assert(inst->_type != (CPPType *)NULL);
CPPFunctionType *ftype = inst->_type->as_function_type();
assert(ftype != (CPPFunctionType *)NULL);
if (ftype->_return_type != NULL &&
(ftype->_flags & CPPFunctionType::F_operator_typecast) != 0) {
// Yes, this is a typecast operator. Test using the return type.
if (ftype->_return_type->is_convertible_to(other)) {
return true;
}
}
}
}
// Check whether any of the base classes are convertible.
Derivation::const_iterator di;
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
CPPStructType *base = (*di)._base->as_struct_type();
if (base != NULL && (*di)._vis <= V_public && !base->is_convertible_to(other)) {
return true;
}
}
return false;
}
/**
* Ensures all functions are correctly marked with the "virtual" flag if they
* are truly virtual by virtue of inheritance, rather than simply being
@ -420,6 +736,30 @@ check_virtual() const {
return !funcs.empty();
}
/**
* Returns true if this class, or any of its base classes, has a virtual
* destructor.
*/
bool CPPStructType::
has_virtual_destructor() const {
CPPInstance *destructor = get_destructor();
if (destructor != NULL) {
if (destructor->_storage_class & CPPInstance::SC_virtual) {
return true;
}
}
Derivation::const_iterator di;
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
CPPStructType *base = (*di)._base->as_struct_type();
if (base != NULL && base->has_virtual_destructor()) {
return true;
}
}
return false;
}
/**
* Returns true if this declaration is an actual, factual declaration, or
* false if some part of the declaration depends on a template parameter which
@ -459,7 +799,7 @@ get_constructor() const {
/**
* Returns the default constructor defined for the struct type, or NULL if
* there is none.
* there is no user-declared constructor that takes 0 arguments.
*/
CPPInstance *CPPStructType::
get_default_constructor() const {
@ -490,7 +830,7 @@ get_default_constructor() const {
/**
* Returns the copy constructor defined for the struct type, or NULL if no
* copy constructor exists.
* user-declared copy constructor exists.
*/
CPPInstance *CPPStructType::
get_copy_constructor() const {
@ -519,7 +859,7 @@ get_copy_constructor() const {
/**
* Returns the move constructor defined for the struct type, or NULL if no
* move constructor exists.
* user-declared move constructor exists.
*/
CPPInstance *CPPStructType::
get_move_constructor() const {
@ -548,7 +888,7 @@ get_move_constructor() const {
/**
* Returns the destructor defined for the struct type, if any, or NULL if no
* destructor is found.
* user-declared destructor is found.
*/
CPPInstance *CPPStructType::
get_destructor() const {
@ -854,7 +1194,7 @@ get_virtual_funcs(VFunctions &funcs) const {
CPPFunctionType *new_ftype = new_inst->_type->as_function_type();
assert(new_ftype != (CPPFunctionType *)NULL);
if (new_ftype->is_equivalent_function(*base_ftype)) {
if (new_ftype->match_virtual_override(*base_ftype)) {
// It's a match! We now know it's virtual. Erase this function
// from the list, so we can add it back in below.
funcs.erase(vfi);

View File

@ -44,14 +44,26 @@ public:
CPPScope *get_scope() const;
bool is_abstract() const;
bool is_base_of(const CPPStructType *other) const;
bool is_empty() const;
bool is_polymorphic() const;
bool check_virtual() const;
bool has_virtual_destructor() const;
virtual bool is_fully_specified() const;
virtual bool is_incomplete() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_constructible(const CPPType *arg_type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;
virtual bool is_destructible() const;
bool is_default_constructible(CPPVisibility min_vis) const;
bool is_copy_constructible(CPPVisibility min_vis) const;
bool is_move_constructible(CPPVisibility min_vis) const;
bool is_destructible(CPPVisibility min_vis) const;
virtual bool is_convertible_to(const CPPType *other) const;
inline bool is_final() const { return _final; }
CPPFunctionGroup *get_constructor() const;
CPPInstance *get_default_constructor() const;

View File

@ -97,8 +97,10 @@ add_template_parameter(CPPDeclaration *param) {
CPPClassTemplateParameter *cl = param->as_class_template_parameter();
if (cl != NULL) {
// Create an implicit typedef for this class parameter.
string name = cl->_ident->get_local_name();
_types[name] = cl;
if (cl->_ident != NULL) {
string name = cl->_ident->get_local_name();
_types[name] = cl;
}
}
CPPInstance *inst = param->as_instance();

View File

@ -12,7 +12,12 @@
*/
#include "cppType.h"
#include "cppConstType.h"
#include "cppPointerType.h"
#include "cppReferenceType.h"
#include "cppStructType.h"
#include "cppTypedefType.h"
#include "cppExtensionType.h"
#include <algorithm>
CPPType::Types CPPType::_types;
@ -57,6 +62,22 @@ is_tbd() const {
return false;
}
/**
* Returns true if the type is considered a fundamental type.
*/
bool CPPType::
is_fundamental() const {
return false;
}
/**
* Returns true if the type is considered a standard layout type.
*/
bool CPPType::
is_standard_layout() const {
return false;
}
/**
* Returns true if the type is considered a Plain Old Data (POD) type.
*/
@ -65,6 +86,14 @@ is_trivial() const {
return false;
}
/**
* Returns true if the type can be constructed using the given argument.
*/
bool CPPType::
is_constructible(const CPPType *given_type) const {
return false;
}
/**
* Returns true if the type is default-constructible.
*/
@ -81,6 +110,14 @@ is_copy_constructible() const {
return false;
}
/**
* Returns true if the type is destructible.
*/
bool CPPType::
is_destructible() const {
return !is_incomplete();
}
/**
* Returns true if the type is a special parameter expression type.
*
@ -92,6 +129,136 @@ is_parameter_expr() const {
return false;
}
/**
* Returns true if this is an enum type, or a typedef to an enum type.
*/
bool CPPType::
is_enum() const {
const CPPTypedefType *td_type = as_typedef_type();
if (td_type != NULL) {
return td_type->_type->is_enum();
}
const CPPExtensionType *ext_type = as_extension_type();
if (ext_type != NULL) {
return ext_type->_type == CPPExtensionType::T_enum ||
ext_type->_type == CPPExtensionType::T_enum_struct ||
ext_type->_type == CPPExtensionType::T_enum_class;
}
return false;
}
/**
* Returns true if this is a const type, or a typedef to a const type.
*/
bool CPPType::
is_const() const {
const CPPTypedefType *td_type = as_typedef_type();
if (td_type != NULL) {
return td_type->_type->is_const();
}
return get_subtype() == ST_const;
}
/**
* Returns true if this is a reference type, or a typedef to a reference type.
*/
bool CPPType::
is_reference() const {
const CPPTypedefType *td_type = as_typedef_type();
if (td_type != NULL) {
return td_type->_type->is_reference();
}
return get_subtype() == ST_reference;
}
/**
* Returns true if this is an unqualified or cv-qualified pointer type, or a
* typedef to one.
*/
bool CPPType::
is_pointer() const {
const CPPTypedefType *td_type = as_typedef_type();
if (td_type != NULL) {
return td_type->_type->is_pointer();
}
const CPPConstType *const_type = as_const_type();
if (const_type != NULL) {
return const_type->_wrapped_around->is_pointer();
}
return get_subtype() == ST_pointer;
}
/**
* Returns the type with any const qualifier stripped off. Will follow
* typedefs, but only if necessary.
*/
CPPType *CPPType::
remove_const() {
const CPPTypedefType *td_type = as_typedef_type();
if (td_type != NULL) {
CPPType *unwrapped = td_type->_type->remove_const();
if (unwrapped != td_type->_type) {
return unwrapped;
} else {
return this;
}
}
const CPPConstType *const_type = as_const_type();
if (const_type != NULL) {
return const_type->_wrapped_around->remove_const();
}
return this;
}
/**
* Returns the type with any reference stripped off.
*/
CPPType *CPPType::
remove_reference() {
const CPPTypedefType *td_type = as_typedef_type();
if (td_type != NULL) {
CPPType *unwrapped = td_type->_type->remove_reference();
if (unwrapped != td_type->_type) {
return unwrapped;
} else {
return this;
}
}
const CPPReferenceType *ref_type = as_reference_type();
if (ref_type != NULL) {
return ref_type->_pointing_at;
}
return this;
}
/**
* Returns the type with any pointer and cv-qualifiers stripped off.
*/
CPPType *CPPType::
remove_pointer() {
switch (get_subtype()) {
case ST_typedef:
{
const CPPTypedefType *td_type = as_typedef_type();
CPPType *unwrapped = td_type->_type->remove_pointer();
if (unwrapped != td_type->_type) {
return unwrapped;
} else {
return this;
}
}
case ST_pointer:
return ((const CPPPointerType *)this)->_pointing_at;
case ST_const:
return ((const CPPConstType *)this)->_wrapped_around->remove_pointer();
default:
return this;
}
}
/**
* Returns true if the type has even been typedef'ed and therefore has a
* simple name available to stand for it. Extension types are all implicitly
@ -229,6 +396,14 @@ is_equivalent(const CPPType &other) const {
return is_equal(&other);
}
/**
* Returns true if variables of this type may be implicitly converted to
* the other type.
*/
bool CPPType::
is_convertible_to(const CPPType *other) const {
return other->is_constructible(this);
}
/**
* Formats a C++-looking line that defines an instance of the given type, with

View File

@ -45,11 +45,27 @@ public:
CPPScope *global_scope);
virtual bool is_tbd() const;
virtual bool is_fundamental() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;
virtual bool is_destructible() const;
virtual bool is_parameter_expr() const;
// Convenience methods.
bool is_enum() const;
bool is_const() const;
bool is_reference() const;
bool is_pointer() const;
CPPType *remove_const();
inline CPPType *remove_volatile() { return this; }
inline CPPType *remove_cv() { return remove_const(); };
CPPType *remove_reference();
CPPType *remove_pointer();
bool has_typedef_name() const;
string get_typedef_name(CPPScope *scope = NULL) const;
@ -61,6 +77,7 @@ public:
string get_alt_name(int n) const;
virtual bool is_incomplete() const;
virtual bool is_convertible_to(const CPPType *other) const;
virtual bool is_equivalent(const CPPType &other) const;
void output_instance(ostream &out, const string &name,

View File

@ -157,6 +157,22 @@ is_tbd() const {
return _type->is_tbd();
}
/**
* Returns true if the type is considered a fundamental type.
*/
bool CPPTypedefType::
is_fundamental() const {
return _type->is_fundamental();
}
/**
* Returns true if the type is considered a standard layout type.
*/
bool CPPTypedefType::
is_standard_layout() const {
return _type->is_standard_layout();
}
/**
* Returns true if the type is considered a Plain Old Data (POD) type.
*/
@ -165,6 +181,14 @@ is_trivial() const {
return _type->is_trivial();
}
/**
* Returns true if the type can be constructed using the given argument.
*/
bool CPPTypedefType::
is_constructible(const CPPType *given_type) const {
return _type->is_constructible(given_type);
}
/**
* Returns true if the type is default-constructible.
*/
@ -181,6 +205,14 @@ is_copy_constructible() const {
return _type->is_copy_constructible();
}
/**
* Returns true if the type is destructible.
*/
bool CPPTypedefType::
is_destructible() const {
return _type->is_destructible();
}
/**
* Returns true if this declaration is an actual, factual declaration, or
* false if some part of the declaration depends on a template parameter which
@ -300,6 +332,15 @@ resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
return this;
}
/**
* Returns true if variables of this type may be implicitly converted to
* the other type.
*/
bool CPPTypedefType::
is_convertible_to(const CPPType *other) const {
return _type->is_convertible_to(other);
}
/**
* 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

View File

@ -42,9 +42,13 @@ public:
virtual bool is_incomplete() const;
virtual bool is_tbd() const;
virtual bool is_fundamental() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;
virtual bool is_destructible() const;
virtual bool is_fully_specified() const;
@ -60,6 +64,7 @@ public:
virtual CPPType *resolve_type(CPPScope *current_scope,
CPPScope *global_scope);
virtual bool is_convertible_to(const CPPType *other) const;
virtual bool is_equivalent(const CPPType &other) const;
virtual void output(ostream &out, int indent_level, CPPScope *scope,

View File

@ -39,7 +39,7 @@ allocate(size_t size, TypeHandle type_handle) {
assert(size <= _buffer_size);
// Determine how much space to allocate.
const size_t alloc_size = _buffer_size + flag_reserved_bytes;
const size_t alloc_size = _buffer_size + flag_reserved_bytes + MemoryHook::get_memory_alignment() - 1;
ObjectNode *obj;
@ -69,7 +69,10 @@ allocate(size_t size, TypeHandle type_handle) {
// If we get here, the deleted_chain is empty; we have to allocate a new
// object from the system pool.
obj = (ObjectNode *)NeverFreeMemory::alloc(alloc_size);
// Allocate memory, and make sure the object starts at the proper alignment.
void *mem = NeverFreeMemory::alloc(alloc_size);
intptr_t pad = (-(intptr_t)flag_reserved_bytes - (intptr_t)mem) % MemoryHook::get_memory_alignment();
obj = (ObjectNode *)((uintptr_t)mem + pad);
#ifdef USE_DELETEDCHAINFLAG
obj->_flag = DCF_alive;
@ -77,6 +80,10 @@ allocate(size_t size, TypeHandle type_handle) {
void *ptr = node_to_buffer(obj);
#ifndef NDEBUG
assert(((uintptr_t)ptr % MemoryHook::get_memory_alignment()) == 0);
#endif
#ifdef DO_MEMORY_USAGE
type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
#endif // DO_MEMORY_USAGE

View File

@ -95,12 +95,8 @@ private:
// Without DELETEDCHAINFLAG, we don't even store the _flag member at all.
static const size_t flag_reserved_bytes = 0;
#elif defined(LINMATH_ALIGN)
// With SSE2 alignment, we need all 16 bytes to preserve alignment.
static const size_t flag_reserved_bytes = 16;
#else
// Otherwise, we only need enough space for the Integer itself.
// Otherwise, we need space for the integer.
static const size_t flag_reserved_bytes = sizeof(AtomicAdjust::Integer);
#endif // USE_DELETEDCHAINFLAG

View File

@ -339,21 +339,26 @@ typedef struct _object PyObject;
#define ALIGN_4BYTE
#define ALIGN_8BYTE
#define ALIGN_16BYTE
#define ALIGN_32BYTE
#define ALIGN_64BYTE
#elif defined(_MSC_VER)
#define ALIGN_4BYTE __declspec(align(4))
#define ALIGN_8BYTE __declspec(align(8))
#define ALIGN_16BYTE __declspec(align(16))
#define ALIGN_32BYTE __declspec(align(32))
#define ALIGN_64BYTE __declspec(align(64))
#elif defined(__GNUC__)
#define ALIGN_4BYTE __attribute__ ((aligned (4)))
#define ALIGN_8BYTE __attribute__ ((aligned (8)))
#define ALIGN_16BYTE __attribute__ ((aligned (16)))
#define ALIGN_32BYTE __attribute__ ((aligned (32)))
#define ALIGN_64BYTE __attribute__ ((aligned (64)))
#else
#define ALIGN_4BYTE
#define ALIGN_8BYTE
#define ALIGN_16BYTE
#define ALIGN_32BYTE
#define ALIGN_64BYTE
#endif
// Do we need to implement memory-alignment enforcement within the MemoryHook
@ -374,7 +379,7 @@ typedef struct _object PyObject;
// externally.
#define MEMORY_HOOK_DO_ALIGN 1
#elif defined(IS_OSX) || defined(_WIN64)
#elif (defined(IS_OSX) || defined(_WIN64)) && !defined(__AVX__)
// The OS-provided malloc implementation will do the required alignment.
#undef MEMORY_HOOK_DO_ALIGN

View File

@ -43,10 +43,16 @@ get_memory_alignment() {
#ifdef LINMATH_ALIGN
// We require 16-byte alignment of certain structures, to support SSE2. We
// don't strictly have to align *everything*, but it's just easier to do so.
const size_t alignment_size = 16;
#ifdef __AVX__
// Eigen requires 32-byte alignment when using AVX instructions.
const size_t alignment_size = 32;
#else
// Otherwise, use word alignment.
const size_t alignment_size = sizeof(void *);
const size_t alignment_size = 16;
#endif
#else
// Otherwise, align to two words. This seems to be pretty standard to the
// point where some code may rely on this being the case.
const size_t alignment_size = sizeof(void *) * 2;
#endif
return alignment_size;
}
@ -64,7 +70,12 @@ get_header_reserved_bytes() {
#ifdef LINMATH_ALIGN
// If we're doing SSE2 alignment, we must reserve a full 16-byte block,
// since anything less than that will spoil the alignment.
#ifdef __AVX__
// Eigen requires 32-byte alignment when using AVX instructions.
static const size_t header_reserved_bytes = 32;
#else
static const size_t header_reserved_bytes = 16;
#endif
#elif defined(MEMORY_HOOK_DO_ALIGN)
// If we're just aligning to words, we reserve a block as big as two words,
@ -72,8 +83,9 @@ get_header_reserved_bytes() {
static const size_t header_reserved_bytes = sizeof(size_t) + sizeof(size_t);
#else
// If we're not aligning, we just need space for the word itself.
static const size_t header_reserved_bytes = sizeof(size_t);
// Virtually all allocators align to two words, so we make sure we preserve
// that alignment for the benefit of anyone who relies upon that.
static const size_t header_reserved_bytes = sizeof(void *) * 2;
#endif
return header_reserved_bytes;

View File

@ -53,8 +53,13 @@
// drose: We require 16-byte alignment of certain structures, to
// support SSE2. We don't strictly have to align *everything*, but
// it's just easier to do so.
#ifdef __AVX__
// Eigen requires 32-byte alignment when using AVX instructions.
#define MALLOC_ALIGNMENT ((size_t)32U)
#else
#define MALLOC_ALIGNMENT ((size_t)16U)
#endif
#endif
#include "dlmalloc_src.cxx"

View File

@ -14,6 +14,8 @@
/**
* Returns a pointer to a newly-allocated block of memory of the indicated
* size.
*
* Please note that the resulting pointer is not aligned to any boundary.
*/
INLINE void *NeverFreeMemory::
alloc(size_t size) {

View File

@ -39,13 +39,9 @@ void *NeverFreeMemory::
ns_alloc(size_t size) {
_lock.acquire();
// We always allocate integer multiples of this many bytes, to guarantee
// this minimum alignment.
static const size_t alignment_size = MemoryHook::get_memory_alignment();
// Round up to the next alignment_size.
size = ((size + alignment_size - 1) / alignment_size) * alignment_size;
//NB: we no longer do alignment here. The only class that uses this is
// DeletedBufferChain, and we can do the alignment potentially more
// efficiently there since we don't end up overallocating as much.
_total_used += size;
// Look for a page that has sufficient space remaining.

View File

@ -1,3 +0,0 @@
/checkPandaVersion.cxx
/checkPandaVersion.h
/pandaVersion.h

View File

@ -38,7 +38,6 @@ Filename(const char *filename) {
(*this) = filename;
}
/**
*
*/
@ -84,6 +83,20 @@ Filename(Filename &&from) NOEXCEPT :
}
#endif // USE_MOVE_SEMANTICS
/**
* Creates an empty Filename.
*/
INLINE Filename::
Filename() :
_dirname_end(0),
_basename_start(0),
_basename_end(string::npos),
_extension_start(string::npos),
_hash_start(string::npos),
_hash_end(string::npos),
_flags(0) {
}
/**
*
*/
@ -155,14 +168,6 @@ pattern_filename(const string &filename) {
return result;
}
/**
*
*/
INLINE Filename::
~Filename() {
}
/**
*
*/
@ -233,7 +238,7 @@ operator = (string &&filename) NOEXCEPT {
*/
INLINE Filename &Filename::
operator = (Filename &&from) NOEXCEPT {
_filename = MOVE(from._filename);
_filename = move(from._filename);
_dirname_end = from._dirname_end;
_basename_start = from._basename_start;
_basename_end = from._basename_end;

View File

@ -55,20 +55,22 @@ public:
};
INLINE Filename(const char *filename);
PUBLISHED:
INLINE Filename(const string &filename = "");
INLINE Filename(const string &filename);
INLINE Filename(const wstring &filename);
INLINE Filename(const Filename &copy);
Filename(const Filename &dirname, const Filename &basename);
INLINE ~Filename();
#ifdef USE_MOVE_SEMANTICS
INLINE Filename(string &&filename) NOEXCEPT;
INLINE Filename(Filename &&from) NOEXCEPT;
#endif
PUBLISHED:
INLINE Filename();
Filename(const Filename &dirname, const Filename &basename);
#ifdef HAVE_PYTHON
EXTENSION(Filename(PyObject *path));
EXTENSION(PyObject *__reduce__(PyObject *self) const);
#endif
@ -118,6 +120,7 @@ PUBLISHED:
INLINE char operator [] (size_t n) const;
EXTENSION(PyObject *__repr__() const);
EXTENSION(PyObject *__fspath__() const);
INLINE string substr(size_t begin) const;
INLINE string substr(size_t begin, size_t end) const;

View File

@ -2344,7 +2344,7 @@ write_module_class(ostream &out, Object *obj) {
string expected_params;
out << " if (arg2 != (PyObject *)NULL) {\n";
out << " if (arg2 != (PyObject *)NULL && arg2 != Py_None) {\n";
out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n";
write_function_forset(out, two_param_remaps, 2, 2, expected_params, 4,
true, true, AT_varargs, RF_pyobject | RF_err_null | RF_decref_args, true);
@ -6142,7 +6142,7 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
write_python_instance(out, indent_level, return_expr, owns_memory, itype, is_const);
}
} else if (TypeManager::is_struct(orig_type->as_pointer_type()->_pointing_at)) {
} else if (TypeManager::is_struct(orig_type->remove_pointer())) {
TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false);
const InterrogateType &itype = idb->get_type(type_index);
@ -6749,6 +6749,8 @@ is_cpp_type_legal(CPPType *in_ctype) {
return true;
} else if (TypeManager::is_pointer_to_simple(type)) {
return true;
} else if (builder.in_forcetype(type->get_local_name(&parser))) {
return true;
} else if (TypeManager::is_exported(type)) {
return true;
} else if (TypeManager::is_pointer_to_PyObject(in_ctype)) {

View File

@ -2401,7 +2401,7 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
cpptype = TypeManager::resolve_type(cpptype)->as_struct_type();
assert(cpptype != (CPPStructType *)NULL);
bool has_virt_methods = cpptype->check_virtual();
bool has_virt_methods = cpptype->is_polymorphic();
switch (cpptype->_type) {
case CPPExtensionType::T_class:
@ -2501,7 +2501,7 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
// (For many compilers, this does not require a pointer change.)
generate_casts = true;
} else if (has_virt_methods && (base_type->as_struct_type() == (CPPStructType *)NULL || !base_type->as_struct_type()->check_virtual())) {
} else if (has_virt_methods && (base_type->as_struct_type() == (CPPStructType *)NULL || !base_type->as_struct_type()->is_polymorphic())) {
// Finally, if this class has virtual methods, but its parent
// doesn't, then we have to upcast (because this class will require
// space for a virtual function table pointer, while the parent
@ -2651,7 +2651,11 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
}
}
if ((itype._flags & InterrogateType::F_inherited_destructor) != 0) {
if (!cpptype->is_destructible()) {
// There's no way to destruct the type.
itype._destructor = 0;
} else if ((itype._flags & InterrogateType::F_inherited_destructor) != 0) {
// If we have inherited our virtual destructor from our base class, go
// ahead and assign the same function index.
assert(!itype._derivations.empty());

View File

@ -0,0 +1,153 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file functional
* @author tobspr
* @date 2016-11-01
*/
// This file, and all the other files in this directory, aren't
// intended to be compiled--they're just parsed by CPPParser (and
// interrogate) in lieu of the actual system headers, to generate the
// interrogate database.
#ifndef FUNCTIONAL_H
#define FUNCTIONAL_H
#include <stddef.h>
namespace std {
// base (deprecated):
template <class Arg, class Result> struct unary_function;
template <class Arg1, class Arg2, class Result> struct binary_function;
// reference_wrapper:
template <class T> class reference_wrapper;
// arithmetic operations:
template <class T> struct plus;
template <class T> struct minus;
template <class T> struct multiplies;
template <class T> struct divides;
template <class T> struct modulus;
template <class T> struct negate;
// comparisons:
template <class T> struct equal_to;
template <class T> struct not_equal_to;
template <class T> struct greater;
template <class T> struct less;
template <class T> struct greater_equal;
template <class T> struct less_equal;
// logical operations:
template <class T> struct logical_and;
template <class T> struct logical_or;
template <class T> struct logical_not;
// bitwise operations:
template <class T> struct bit_and;
template <class T> struct bit_or;
template <class T> struct bit_xor;
// negators:
template <class Predicate> class unary_negate;
template <class Predicate> class binary_negate;
// bind:
template<class T> struct is_bind_expression;
template<class T> struct is_placeholder;
namespace placeholders {
// M is the implementation-defined number of placeholders
// (8 should be enough for interrogate)
extern char _1;
extern char _2;
extern char _3;
extern char _4;
extern char _5;
extern char _6;
extern char _7;
extern char _8;
}
// binders (deprecated):
template <class Fn> class binder1st;
template <class Fn> class binder2nd;
// adaptors (deprecated):
template <class Arg, class Result> class pointer_to_unary_function;
template <class Arg1, class Arg2, class Result>
class pointer_to_binary_function;
// adaptors (deprecated):
template<class S, class T> class mem_fun_t;
template<class S, class T, class A> class mem_fun1_t;
template<class S, class T> class mem_fun_ref_t;
template<class S, class T, class A> class mem_fun1_ref_t;
template <class S, class T> class const_mem_fun_t;
template <class S, class T, class A> class const_mem_fun1_t;
template <class S, class T> class const_mem_fun_ref_t;
template <class S, class T, class A> class const_mem_fun1_ref_t;
// polymorphic function wrappers:
class bad_function_call;
// hash function base template:
template <class T> struct hash;
// Hash function specializations
template <> struct hash<bool>;
template <> struct hash<char>;
template <> struct hash<signed char>;
template <> struct hash<unsigned char>;
template <> struct hash<char16_t>;
template <> struct hash<char32_t>;
template <> struct hash<wchar_t>;
template <> struct hash<short>;
template <> struct hash<unsigned short>;
template <> struct hash<int>;
template <> struct hash<unsigned int>;
template <> struct hash<long>;
template <> struct hash<long long>;
template <> struct hash<unsigned long>;
template <> struct hash<unsigned long long>;
template <> struct hash<float>;
template <> struct hash<double>;
template <> struct hash<long double>;
template<class T> struct hash<T*>;
template <class T> class reference_wrapper {
public :
// types
typedef T type;
typedef void result_type; // not always defined
typedef void argument_type; // not always defined
typedef void first_argument_type; // not always defined
typedef void second_argument_type; // not always defined
};
template<class T> struct is_bind_expression {};
// : integral_constant<bool, true> {};
class bad_function_call : public std::exception {};
// template<class> class function; // undefined
template< class R, class... ArgTypes >
class function {
public:
typedef R result_type;
};
}
#endif

View File

@ -0,0 +1,34 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file initializer_list
* @author tobspr
* @date 2016-11-01
*/
// This file, and all the other files in this directory, aren't
// intended to be compiled--they're just parsed by CPPParser (and
// interrogate) in lieu of the actual system headers, to generate the
// interrogate database.
#ifndef INITIALIZER_LIST_H
#define INITIALIZER_LIST_H
#include <stdtypedefs.h>
namespace std {
template<class E> class initializer_list {
public:
typedef E value_type;
typedef const E& reference;
typedef const E& const_reference;
typedef size_t size_type;
typedef const E* iterator;
typedef const E* const_iterator;
};
}

View File

@ -1,16 +1,15 @@
// Filename: allocator
// Created by: drose (12May00)
//
////////////////////////////////////////////////////////////////////
//
// 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."
//
////////////////////////////////////////////////////////////////////
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file memory
* @author tobspr
* @date 2016-11-01
*/
// This file, and all the other files in this directory, aren't
// intended to be compiled--they're just parsed by CPPParser (and
@ -21,6 +20,8 @@
#define ALLOCATOR_H
#include <stdtypedefs.h>
#include <iterator>
#ifdef GCC_STYLE_ALLOCATOR
@ -33,16 +34,155 @@ public:
#else // GCC_STYLE_ALLOCATOR
namespace std {
template<class Type>
class allocator {
public:
typedef Type *pointer;
typedef const Type *const_pointer;
typedef size_t size_type;
pointer allocate(size_type n, allocator<void>::const_pointer hint = 0);
void deallocate(pointer p, size_type n);
};
// pointer traits
template <class Ptr> struct pointer_traits;
template <class T> struct pointer_traits<T*>;
// pointer safety
enum class pointer_safety { relaxed, preferred, strict };
// allocator argument tag
struct allocator_arg_t { };
constexpr allocator_arg_t allocator_arg = allocator_arg_t();
// uses_allocator
template <class T, class Alloc> struct uses_allocator;
// allocator traits
template <class Alloc> struct allocator_traits;
// the default allocator:
template <class T> class allocator;
template <> class allocator<void>;
// raw storage iterator:
template <class OutputIterator, class T> class raw_storage_iterator;
// class template unique_ptr:
template <class T> class default_delete;
template <class T> class default_delete<T[]>;
template <class T, class D = default_delete<T>> class unique_ptr;
template <class T, class D> class unique_ptr<T[], D>;
// class bad_weak_ptr:
class bad_weak_ptr;
// class template shared_ptr:
template<class T> class shared_ptr;
// class template weak_ptr:
template<class T> class weak_ptr;
// class template owner_less:
template<class T> class owner_less;
// class template enable_shared_from_this:
template<class T> class enable_shared_from_this;
// hash support
template <class T> struct hash;
template <class T, class D> struct hash<unique_ptr<T, D> >;
template <class T> struct hash<shared_ptr<T> >;
// auto_ptr (deprecated)
template <class X> class auto_ptr;
template <class Ptr> struct pointer_traits {
typedef Ptr pointer;
typedef Ptr element_type;
typedef ptrdiff_t difference_type;
template <class U> using rebind = U;
};
template <class T> struct pointer_traits<T*> {
typedef T* pointer;
typedef T element_type;
typedef ptrdiff_t difference_type;
template <class U> using rebind = U*;
};
template <class Alloc> struct allocator_traits {
typedef Alloc allocator_type;
typedef typename Alloc::value_type value_type;
typedef void* pointer;
typedef const void* const_pointer;
typedef void* void_pointer;
typedef const void* const_void_pointer;
typedef std::ptrdiff_t difference_type;
typedef size_t size_type;
struct propagate_on_container_copy_assignment;
struct propagate_on_container_move_assignment;
struct propagate_on_container_swap;
struct is_always_equal;
template <class T> using rebind_alloc = size_t;
template <class T> using rebind_traits = allocator_traits<rebind_alloc<T> >;
};
template <class T> class allocator;
// specialize for void:
template <> class allocator<void> {
public:
typedef void* pointer;
typedef const void* const_pointer;
// reference-to-void members are impossible.
typedef void value_type;
template <class U> struct rebind { typedef allocator<U> other; };
};
template <class T> class allocator {
public:
struct true_type_; // do not depend on type_traits header
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef allocator<U> other; };
typedef true_type_ propagate_on_container_move_assignment;
typedef true_type_ is_always_equal;
};
template <class OutputIterator, class T>
class raw_storage_iterator
: public iterator<output_iterator_tag,void,void,void,void> {
public:
};
template <class T> struct default_delete {};
template <class T> struct default_delete<T[]> {};
// unique_ptr for single objects
template <class T, class D = default_delete<T>> class unique_ptr {
public:
typedef T* pointer;
typedef T element_type;
typedef D deleter_type;
};
class bad_weak_ptr: public std::exception {};
template<class T> class shared_ptr {
public:
typedef T element_type;
};
template<class T> class weak_ptr {
public:
typedef T element_type;
};
template<class T> class enable_shared_from_this {};
}
#endif // GCC_STYLE_ALLOCATOR

View File

@ -20,25 +20,45 @@
#define __WORDSIZE 32
#endif
typedef signed char int8_t;
typedef short int int16_t;
typedef int int32_t;
typedef long long int int64_t;
using intmax_t = long long int;
using uintmax_t = unsigned long long int;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
using int8_t = signed char;
using int16_t = short int;
using int32_t = int;
using int64_t = long long int;
typedef long long int intmax_t;
typedef unsigned long long int uintmax_t;
using uint8_t = unsigned char;
using uint16_t = unsigned short int;
using uint32_t = unsigned int;
using uint64_t = unsigned long long int;
using int_least8_t = int8_t;
using int_least16_t = int16_t;
using int_least32_t = int32_t;
using int_least64_t = int64_t;
using uint_least8_t = uint8_t;
using uint_least16_t = uint16_t;
using uint_least32_t = uint32_t;
using uint_least64_t = uint64_t;
using int_fast8_t = int8_t;
using int_fast16_t = int16_t;
using int_fast32_t = int32_t;
using int_fast64_t = int64_t;
using uint_fast8_t = uint8_t;
using uint_fast16_t = uint16_t;
using uint_fast32_t = uint32_t;
using uint_fast64_t = uint64_t;
#if __WORDSIZE == 64
typedef int64_t intptr_t;
typedef uint64_t uintptr_t;
using intptr_t = int64_t;
using uintptr_t = uint64_t;
#else
typedef int32_t intptr_t;
typedef uint32_t uintptr_t;
using intptr_t = int32_t;
using uintptr_t = uint32_t;
#endif
#endif

View File

@ -39,6 +39,8 @@ inline namespace std {
#endif
}
struct timeval;
#ifdef __cplusplus
#define NULL 0L
#else

View File

@ -0,0 +1,96 @@
#pragma once
#include <stdtypedefs.h>
namespace std {
template<class T, T v>
struct integral_constant {
static constexpr T value = v;
typedef T value_type;
constexpr operator value_type() const noexcept { return value; }
constexpr value_type operator()() const noexcept { return value; }
};
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
template<class T, class U>
struct is_same : std::false_type {};
template<class T>
struct is_same<T, T> : std::true_type {};
template<class T>
struct is_void : std::false_type {};
template<>
struct is_void<void> : std::true_type {};
template<class T>
struct is_enum : integral_constant<bool, __is_enum(T)> {};
template<class T>
struct is_union : integral_constant<bool, __is_union(T)> {};
template<class T>
struct is_class : integral_constant<bool, __is_class(T)> {};
template<class T>
struct is_fundamental : integral_constant<bool, __is_fundamental(T)> {};
template<class T>
struct is_compound : integral_constant<bool, !__is_fundamental(T)> {};
template<class T>
struct is_trivial : integral_constant<bool, __is_trivial(T)> {};
template<class T>
struct is_standard_layout : integral_constant<bool, __is_standard_layout(T)> {};
template<class T>
struct is_pod : integral_constant<bool, __is_pod(T)> {};
template<class T>
struct is_empty : integral_constant<bool, __is_empty(T)> {};
template<class T>
struct is_polymorphic : integral_constant<bool, __is_polymorphic(T)> {};
template<class T>
struct is_abstract : integral_constant<bool, __is_abstract(T)> {};
template<class T>
struct is_final : integral_constant<bool, __is_final(T)> {};
template<class T>
struct is_default_constructible : integral_constant<bool, __is_constructible(T)> {};
template<class T>
struct is_copy_constructible : integral_constant<bool, __is_constructible(T, const T&)> {};
template<class T>
struct is_move_constructible : integral_constant<bool, __is_constructible(T, const T&&)> {};
template<class T>
struct is_destructible : integral_constant<bool, __is_destructible(T)> {};
template<class T>
struct has_virtual_destructor : integral_constant<bool, __has_virtual_destructor(T)> {};
template<class T >
struct alignment_of : std::integral_constant<std::size_t, alignof(T)> {};
template<class T, class U>
struct is_base_of : integral_constant<bool, __is_base_of(T, U)> {};
template<class T, class U>
struct is_convertible : integral_constant<bool, __is_convertible_to(T, U)> {};
template<class T> struct add_cv { typedef const volatile T type; };
template<class T> struct add_const { typedef const T type; };
template<class T> struct add_volatile { typedef volatile T type; };
template<class T> struct add_lvalue_reference { typedef T &type; };
template<class T> struct add_rvalue_reference { typedef T &&type; };
template<class T> struct add_pointer { typedef T *type; };
}

View File

@ -0,0 +1,84 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file unordered_map
* @author tobspr
* @date 2016-11-01
*/
// This file, and all the other files in this directory, aren't
// intended to be compiled--they're just parsed by CPPParser (and
// interrogate) in lieu of the actual system headers, to generate the
// interrogate database.
#ifndef UNORDERED_MAP_H
#define UNORDERED_MAP_H
#include <stdtypedefs.h>
#include <stdcompare.h>
#include <pair>
#include <initializer_list>
#include <functional>
namespace std {
template <class Key,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<const Key, T> > >
class unordered_map
{
public:
// types
typedef Key key_type;
typedef Key value_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Allocator allocator_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
typedef size_t size_type;
typedef std::ptrdiff_t difference_type;
class iterator;
class const_iterator;
class local_iterator;
class const_local_iterator;
};
template <class Key,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<const Key, T> > >
class unordered_multimap
{
public:
// types
typedef Key key_type;
typedef Key value_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Allocator allocator_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
typedef size_t size_type;
typedef std::ptrdiff_t difference_type;
class iterator;
class const_iterator;
class local_iterator;
class const_local_iterator;
};
} // namespace std
#endif

View File

@ -0,0 +1,83 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file unordered_set
* @author tobspr
* @date 2016-11-01
*/
// This file, and all the other files in this directory, aren't
// intended to be compiled--they're just parsed by CPPParser (and
// interrogate) in lieu of the actual system headers, to generate the
// interrogate database.
#ifndef UNORDERED_SET_H
#define UNORDERED_SET_H
#include <stdtypedefs.h>
#include <stdcompare.h>
#include <pair>
#include <initializer_list>
#include <functional>
namespace std {
template <class Key,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<Key> >
class unordered_set
{
public:
// types
typedef Key key_type;
typedef Key value_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Allocator allocator_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
typedef size_t size_type;
typedef std::ptrdiff_t difference_type;
class iterator;
class const_iterator;
class local_iterator;
class const_local_iterator;
};
template <class Key,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<Key> >
class unordered_multiset
{
public:
// types
typedef Key key_type;
typedef Key value_type;
typedef Hash hasher;
typedef Pred key_equal;
typedef Allocator allocator_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
typedef size_t size_type;
typedef std::ptrdiff_t difference_type;
class iterator;
class const_iterator;
class local_iterator;
class const_local_iterator;
};
} // namespace std
#endif

View File

@ -0,0 +1 @@
struct __m128;

View File

@ -1 +0,0 @@
/prc_parameters.h

View File

@ -73,8 +73,8 @@ EncryptStreamBuf() {
_key_length = encryption_key_length;
_iteration_count = encryption_iteration_count;
_read_valid = false;
_write_valid = false;
_read_ctx = NULL;
_write_ctx = NULL;
_read_overflow_buffer = NULL;
_in_read_overflow_buffer = 0;
@ -110,7 +110,11 @@ open_read(istream *source, bool owns_source, const string &password) {
_source = source;
_owns_source = owns_source;
_read_valid = false;
if (_read_ctx != NULL) {
EVP_CIPHER_CTX_free(_read_ctx);
_read_ctx = NULL;
}
// Now read the header information.
StreamReader sr(_source, false);
@ -143,17 +147,21 @@ open_read(istream *source, bool owns_source, const string &password) {
string iv = sr.extract_bytes(iv_length);
_read_ctx = EVP_CIPHER_CTX_new();
nassertv(_read_ctx != NULL);
// Initialize the context
int result;
result = EVP_DecryptInit(&_read_ctx, cipher, NULL, (unsigned char *)iv.data());
result = EVP_DecryptInit(_read_ctx, cipher, NULL, (unsigned char *)iv.data());
nassertv(result > 0);
result = EVP_CIPHER_CTX_set_key_length(&_read_ctx, key_length);
result = EVP_CIPHER_CTX_set_key_length(_read_ctx, key_length);
if (result <= 0) {
prc_cat.error()
<< "Invalid key length " << key_length * 8 << " bits for algorithm "
<< OBJ_nid2sn(nid) << "\n";
EVP_CIPHER_CTX_cleanup(&_read_ctx);
EVP_CIPHER_CTX_free(_read_ctx);
_read_ctx = NULL;
return;
}
@ -167,11 +175,9 @@ open_read(istream *source, bool owns_source, const string &password) {
nassertv(result > 0);
// Store the key within the context.
result = EVP_DecryptInit(&_read_ctx, NULL, key, NULL);
result = EVP_DecryptInit(_read_ctx, NULL, key, NULL);
nassertv(result > 0);
_read_valid = true;
_read_overflow_buffer = new unsigned char[_read_block_size];
_in_read_overflow_buffer = 0;
thread_consider_yield();
@ -182,9 +188,9 @@ open_read(istream *source, bool owns_source, const string &password) {
*/
void EncryptStreamBuf::
close_read() {
if (_read_valid) {
EVP_CIPHER_CTX_cleanup(&_read_ctx);
_read_valid = false;
if (_read_ctx != NULL) {
EVP_CIPHER_CTX_free(_read_ctx);
_read_ctx = NULL;
}
if (_read_overflow_buffer != (unsigned char *)NULL) {
@ -211,7 +217,6 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
close_write();
_dest = dest;
_owns_dest = owns_dest;
_write_valid = false;
const EVP_CIPHER *cipher =
EVP_get_cipherbyname(_algorithm.c_str());
@ -220,21 +225,23 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
prc_cat.error()
<< "Unknown encryption algorithm: " << _algorithm << "\n";
return;
};
}
int nid = EVP_CIPHER_nid(cipher);
int iv_length = EVP_CIPHER_iv_length(cipher);
_write_block_size = EVP_CIPHER_block_size(cipher);
unsigned char *iv = (unsigned char *)alloca(iv_length);
// Generate a random IV. It doesn't need to be cryptographically secure,
// just unique.
unsigned char *iv = (unsigned char *)alloca(iv_length);
RAND_pseudo_bytes(iv, iv_length);
_write_ctx = EVP_CIPHER_CTX_new();
nassertv(_write_ctx != NULL);
int result;
result = EVP_EncryptInit(&_write_ctx, cipher, NULL, iv);
result = EVP_EncryptInit(_write_ctx, cipher, NULL, iv);
nassertv(result > 0);
// Store the appropriate key length in the context.
@ -242,12 +249,13 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
if (key_length == 0) {
key_length = EVP_CIPHER_key_length(cipher);
}
result = EVP_CIPHER_CTX_set_key_length(&_write_ctx, key_length);
result = EVP_CIPHER_CTX_set_key_length(_write_ctx, key_length);
if (result <= 0) {
prc_cat.error()
<< "Invalid key length " << key_length * 8 << " bits for algorithm "
<< OBJ_nid2sn(nid) << "\n";
EVP_CIPHER_CTX_cleanup(&_write_ctx);
EVP_CIPHER_CTX_free(_write_ctx);
_write_ctx = NULL;
return;
}
@ -271,7 +279,7 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
nassertv(result > 0);
// Store the key in the context.
result = EVP_EncryptInit(&_write_ctx, NULL, key, NULL);
result = EVP_EncryptInit(_write_ctx, NULL, key, NULL);
nassertv(result > 0);
// Now write the header information to the stream.
@ -284,7 +292,6 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
sw.add_uint16((uint16_t)count);
sw.append_data(iv, iv_length);
_write_valid = true;
thread_consider_yield();
}
@ -298,15 +305,16 @@ close_write() {
write_chars(pbase(), n);
pbump(-(int)n);
if (_write_valid) {
if (_write_ctx != NULL) {
unsigned char *write_buffer = (unsigned char *)alloca(_write_block_size);
int bytes_written = 0;
EVP_EncryptFinal(&_write_ctx, write_buffer, &bytes_written);
EVP_EncryptFinal(_write_ctx, write_buffer, &bytes_written);
thread_consider_yield();
_dest->write((const char *)write_buffer, bytes_written);
_write_valid = false;
EVP_CIPHER_CTX_free(_write_ctx);
_write_ctx = NULL;
}
if (_owns_dest) {
@ -418,7 +426,7 @@ read_chars(char *start, size_t length) {
do {
// Get more bytes from the stream.
if (!_read_valid) {
if (_read_ctx == NULL) {
return 0;
}
@ -429,20 +437,21 @@ read_chars(char *start, size_t length) {
int result;
if (source_length != 0) {
result =
EVP_DecryptUpdate(&_read_ctx, read_buffer, &bytes_read,
EVP_DecryptUpdate(_read_ctx, read_buffer, &bytes_read,
source_buffer, source_length);
} else {
result =
EVP_DecryptFinal(&_read_ctx, read_buffer, &bytes_read);
_read_valid = false;
EVP_DecryptFinal(_read_ctx, read_buffer, &bytes_read);
EVP_CIPHER_CTX_free(_read_ctx);
_read_ctx = NULL;
}
if (result <= 0) {
prc_cat.error()
<< "Error decrypting stream.\n";
if (_read_valid) {
EVP_CIPHER_CTX_cleanup(&_read_ctx);
_read_valid = false;
if (_read_ctx != NULL) {
EVP_CIPHER_CTX_free(_read_ctx);
_read_ctx = NULL;
}
}
thread_consider_yield();
@ -472,13 +481,13 @@ read_chars(char *start, size_t length) {
*/
void EncryptStreamBuf::
write_chars(const char *start, size_t length) {
if (_write_valid && length != 0) {
if (_write_ctx != NULL && length != 0) {
size_t max_write_buffer = length + _write_block_size;
unsigned char *write_buffer = (unsigned char *)alloca(max_write_buffer);
int bytes_written = 0;
int result =
EVP_EncryptUpdate(&_write_ctx, write_buffer, &bytes_written,
EVP_EncryptUpdate(_write_ctx, write_buffer, &bytes_written,
(unsigned char *)start, length);
if (result <= 0) {
prc_cat.error()

View File

@ -64,14 +64,12 @@ private:
int _key_length;
int _iteration_count;
bool _read_valid;
EVP_CIPHER_CTX _read_ctx;
EVP_CIPHER_CTX *_read_ctx;
size_t _read_block_size;
unsigned char *_read_overflow_buffer;
size_t _in_read_overflow_buffer;
bool _write_valid;
EVP_CIPHER_CTX _write_ctx;
EVP_CIPHER_CTX *_write_ctx;
size_t _write_block_size;
};

View File

@ -343,6 +343,9 @@ assert_failure(const char *expression, int line,
// guarantee it has already been constructed.
ALIGN_16BYTE ConfigVariableBool assert_abort("assert-abort", false);
if (assert_abort) {
// Make sure the error message has been flushed to the output.
nout.flush();
#ifdef WIN32
// How to trigger an exception in VC++ that offers to take us into the
// debugger? abort() doesn't do it. We used to be able to assert(false),

View File

@ -149,12 +149,14 @@ extern "C" {
EXPCL_PYSTUB int PyUnicodeUCS2_FromStringAndSize(...);
EXPCL_PYSTUB int PyUnicodeUCS2_FromWideChar(...);
EXPCL_PYSTUB int PyUnicodeUCS2_AsWideChar(...);
EXPCL_PYSTUB int PyUnicodeUCS2_AsWideCharString(...);
EXPCL_PYSTUB int PyUnicodeUCS2_GetSize(...);
EXPCL_PYSTUB int PyUnicodeUCS4_FromFormat(...);
EXPCL_PYSTUB int PyUnicodeUCS4_FromString(...);
EXPCL_PYSTUB int PyUnicodeUCS4_FromStringAndSize(...);
EXPCL_PYSTUB int PyUnicodeUCS4_FromWideChar(...);
EXPCL_PYSTUB int PyUnicodeUCS4_AsWideChar(...);
EXPCL_PYSTUB int PyUnicodeUCS4_AsWideCharString(...);
EXPCL_PYSTUB int PyUnicodeUCS4_GetSize(...);
EXPCL_PYSTUB int PyUnicode_AsUTF8(...);
EXPCL_PYSTUB int PyUnicode_AsUTF8AndSize(...);
@ -349,12 +351,14 @@ int PyUnicodeUCS2_FromString(...) { return 0; }
int PyUnicodeUCS2_FromStringAndSize(...) { return 0; }
int PyUnicodeUCS2_FromWideChar(...) { return 0; }
int PyUnicodeUCS2_AsWideChar(...) { return 0; }
int PyUnicodeUCS2_AsWideCharString(...) { return 0; }
int PyUnicodeUCS2_GetSize(...) { return 0; }
int PyUnicodeUCS4_FromFormat(...) { return 0; }
int PyUnicodeUCS4_FromString(...) { return 0; }
int PyUnicodeUCS4_FromStringAndSize(...) { return 0; }
int PyUnicodeUCS4_FromWideChar(...) { return 0; }
int PyUnicodeUCS4_AsWideChar(...) { return 0; }
int PyUnicodeUCS4_AsWideCharString(...) { return 0; }
int PyUnicodeUCS4_GetSize(...) { return 0; }
int PyUnicode_AsUTF8(...) { return 0; }
int PyUnicode_AsUTF8AndSize(...) { return 0; }

View File

@ -1,2 +0,0 @@
*.pyc
*.pyo

View File

@ -31,6 +31,7 @@ SetCompressor ${COMPRESSOR}
!include "Sections.nsh"
!include "WinMessages.nsh"
!include "WordFunc.nsh"
!include "x64.nsh"
!define MUI_WELCOMEFINISHPAGE_BITMAP "panda-install.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "panda-install.bmp"
@ -120,6 +121,14 @@ Function runFunction
ExecShell "open" "$SMPROGRAMS\${TITLE}\Panda3D Manual.lnk"
FunctionEnd
Function .onInit
${If} ${REGVIEW} = 64
${AndIfNot} ${RunningX64}
MessageBox MB_OK|MB_ICONEXCLAMATION "You are attempting to install the 64-bit version of Panda3D on a 32-bit version of Windows. Please download and install the 32-bit version of Panda3D instead."
Abort
${EndIf}
FunctionEnd
SectionGroup "Panda3D Libraries"
Section "Core Libraries" SecCore
SectionIn 1 2 RO
@ -134,12 +143,22 @@ SectionGroup "Panda3D Libraries"
SetOutPath "$INSTDIR"
File "${BUILT}\LICENSE"
File /r /x CVS "${BUILT}\ReleaseNotes"
SetOutPath $INSTDIR\bin
File /r /x libpandagl.dll /x libpandadx9.dll /x cgD3D*.dll /x python*.dll /x libpandaode.dll /x libp3fmod_audio.dll /x fmodex*.dll /x libp3ffmpeg.dll /x av*.dll /x postproc*.dll /x swscale*.dll /x swresample*.dll /x NxCharacter*.dll /x cudart*.dll /x PhysX*.dll /x libpandaphysx.dll /x libp3rocket.dll /x boost_python*.dll /x Rocket*.dll /x _rocket*.pyd /x libpandabullet.dll /x OpenAL32.dll /x *_oal.dll /x libp3openal_audio.dll "${BUILT}\bin\*.dll"
File /nonfatal /r "${BUILT}\bin\Microsoft.*.manifest"
SetOutPath $INSTDIR\etc
File /r "${BUILT}\etc\*"
SetOutPath $INSTDIR\bin
File /r /x api-ms-win-*.dll /x ucrtbase.dll /x libpandagl.dll /x libpandadx9.dll /x cgD3D*.dll /x python*.dll /x libpandaode.dll /x libp3fmod_audio.dll /x fmodex*.dll /x libp3ffmpeg.dll /x av*.dll /x postproc*.dll /x swscale*.dll /x swresample*.dll /x NxCharacter*.dll /x cudart*.dll /x PhysX*.dll /x libpandaphysx.dll /x libp3rocket.dll /x boost_python*.dll /x Rocket*.dll /x _rocket*.pyd /x libpandabullet.dll /x OpenAL32.dll /x *_oal.dll /x libp3openal_audio.dll "${BUILT}\bin\*.dll"
File /nonfatal /r "${BUILT}\bin\Microsoft.*.manifest"
; Before Windows 10, we need these stubs for the UCRT as well.
ReadRegDWORD $0 HKLM "Software\Microsoft\Windows NT\CurrentVersion" "CurrentMajorVersionNumber"
${If} $0 < 10
ClearErrors
File /nonfatal /r "${BUILT}\bin\api-ms-win-*.dll"
File /nonfatal "${BUILT}\bin\ucrtbase.dll"
${Endif}
SetDetailsPrint both
DetailPrint "Installing models..."
SetDetailsPrint listonly
@ -147,6 +166,10 @@ SectionGroup "Panda3D Libraries"
SetOutPath $INSTDIR\models
File /r /x CVS "${BUILT}\models\*"
SetDetailsPrint both
DetailPrint "Installing optional components..."
SetDetailsPrint listonly
RMDir /r "$SMPROGRAMS\${TITLE}"
CreateDirectory "$SMPROGRAMS\${TITLE}"
SectionEnd
@ -634,6 +657,9 @@ Section -post
WriteRegStr HKCU "Software\Classes\.pz" "PerceivedType" "compressed"
WriteRegStr HKCU "Software\Classes\.mf" "" "Panda3D.Multifile"
WriteRegStr HKCU "Software\Classes\.mf" "PerceivedType" "compressed"
WriteRegStr HKCU "Software\Classes\.prc" "" "inifile"
WriteRegStr HKCU "Software\Classes\.prc" "Content Type" "text/plain"
WriteRegStr HKCU "Software\Classes\.prc" "PerceivedType" "text"
; For convenience, if nobody registered .pyd, we will.
ReadRegStr $0 HKCR "Software\Classes\.pyd" ""

View File

@ -39,6 +39,7 @@ import sys
COMPILER=0
INSTALLER=0
WHEEL=0
GENMAN=0
COMPRESSOR="zlib"
THREADCOUNT=0
@ -51,6 +52,7 @@ RUNTIME=0
DISTRIBUTOR=""
VERSION=None
DEBVERSION=None
WHLVERSION=None
RPMRELEASE="1"
GIT_COMMIT=None
P3DSUFFIX=None
@ -87,14 +89,13 @@ PkgListSet(["PYTHON", "DIRECT", # Python support
"MFC", "WX", "FLTK", # Used for web plug-in only
"ROCKET", "AWESOMIUM", # GUI libraries
"CARBON", "COCOA", # Mac OS X toolkits
"X11", "XF86DGA", "XRANDR", "XCURSOR", # Unix platform support
"PANDATOOL", "PVIEW", "DEPLOYTOOLS", # Toolchain
"X11", # Unix platform support
"PANDATOOL", "PVIEW", "DEPLOYTOOLS", "DIRECTSCRIPTS",# Toolchain
"SKEL", # Example SKEL project
"PANDAFX", # Some distortion special lenses
"PANDAPARTICLESYSTEM", # Built in particle system
"CONTRIB", # Experimental
"SSE2", "NEON", # Compiler features
"TOUCHINPUT", # Touchinput interface (requires Windows 7)
])
CheckPandaSourceTree()
@ -125,6 +126,7 @@ def usage(problem):
print(" --verbose (print out more information)")
print(" --runtime (build a runtime build instead of an SDK build)")
print(" --installer (build an installer)")
print(" --wheel (build a pip-installable .whl)")
print(" --optimize X (optimization level can be 1,2,3,4)")
print(" --version X (set the panda version number)")
print(" --lzma (use lzma compression when building Windows installer)")
@ -160,17 +162,18 @@ def usage(problem):
os._exit(1)
def parseopts(args):
global INSTALLER,RTDIST,RUNTIME,GENMAN,DISTRIBUTOR,VERSION
global INSTALLER,WHEEL,RTDIST,RUNTIME,GENMAN,DISTRIBUTOR,VERSION
global COMPRESSOR,THREADCOUNT,OSXTARGET,OSX_ARCHS,HOST_URL
global DEBVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX,RTDIST_VERSION
global DEBVERSION,WHLVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX,RTDIST_VERSION
global STRDXSDKVERSION, WINDOWS_SDK, MSVC_VERSION, BOOUSEINTELCOMPILER
longopts = [
"help","distributor=","verbose","runtime","osxtarget=",
"optimize=","everything","nothing","installer","rtdist","nocolor",
"optimize=","everything","nothing","installer","wheel","rtdist","nocolor",
"version=","lzma","no-python","threads=","outputdir=","override=",
"static","host=","debversion=","rpmrelease=","p3dsuffix=","rtdist-version=",
"directx-sdk=", "windows-sdk=", "msvc-version=", "clean", "use-icl",
"universal", "target=", "arch=", "git-commit="]
"universal", "target=", "arch=", "git-commit=",
"use-touchinput", "no-touchinput"]
anything = 0
optimize = ""
target = None
@ -188,6 +191,7 @@ def parseopts(args):
if (option=="--help"): raise Exception
elif (option=="--optimize"): optimize=value
elif (option=="--installer"): INSTALLER=1
elif (option=="--wheel"): WHEEL=1
elif (option=="--verbose"): SetVerbose(True)
elif (option=="--distributor"): DISTRIBUTOR=value
elif (option=="--rtdist"): RTDIST=1
@ -203,8 +207,11 @@ def parseopts(args):
elif (option=="--arch"): target_arch = value.strip()
elif (option=="--nocolor"): DisableColors()
elif (option=="--version"):
VERSION=value
if (len(VERSION.split(".")) != 3): raise Exception
match = re.match(r'^\d+\.\d+\.\d+', value)
if not match:
usage("version requires three digits")
WHLVERSION = value
VERSION = match.group()
elif (option=="--lzma"): COMPRESSOR="lzma"
elif (option=="--override"): AddOverride(value.strip())
elif (option=="--static"): SetLinkAllStatic(True)
@ -316,18 +323,6 @@ def parseopts(args):
print("No Windows SDK version specified. Defaulting to '7.1'.")
WINDOWS_SDK = '7.1'
is_win7 = False
if sys.platform == 'win32':
# Note: not available in cygwin.
winver = sys.getwindowsversion()
if winver[0] >= 6 and winver[1] >= 1:
is_win7 = True
if RUNTIME or not is_win7:
PkgDisable("TOUCHINPUT")
else:
PkgDisable("TOUCHINPUT")
if clean_build and os.path.isdir(GetOutputDir()):
print("Deleting %s" % (GetOutputDir()))
shutil.rmtree(GetOutputDir())
@ -428,9 +423,18 @@ if (RUNTIME):
if (INSTALLER and RTDIST):
exit("Cannot build an installer for the rtdist build!")
if (WHEEL and RUNTIME):
exit("Cannot build a wheel for the runtime build!")
if (WHEEL and RTDIST):
exit("Cannot build a wheel for the rtdist build!")
if (INSTALLER) and (PkgSkip("PYTHON")) and (not RUNTIME) and GetTarget() == 'windows':
exit("Cannot build installer on Windows without python")
if WHEEL and PkgSkip("PYTHON"):
exit("Cannot build wheel without Python")
if (RTDIST) and (PkgSkip("WX") and PkgSkip("FLTK")):
exit("Cannot build rtdist without wx or fltk")
@ -516,9 +520,6 @@ IncDirectory("ALWAYS", GetOutputDir()+"/include")
if (COMPILER == "MSVC"):
PkgDisable("X11")
PkgDisable("XRANDR")
PkgDisable("XF86DGA")
PkgDisable("XCURSOR")
PkgDisable("GLES")
PkgDisable("GLES2")
PkgDisable("EGL")
@ -808,9 +809,13 @@ if (COMPILER=="GCC"):
SmartPkgEnable("JPEG", "", ("jpeg"), "jpeglib.h")
SmartPkgEnable("PNG", "libpng", ("png"), "png.h", tool = "libpng-config")
if GetTarget() == "darwin" and not PkgSkip("FFMPEG"):
LibName("FFMPEG", "-Wl,-read_only_relocs,suppress")
LibName("FFMPEG", "-framework VideoDecodeAcceleration")
if not PkgSkip("FFMPEG"):
if GetTarget() == "darwin":
LibName("FFMPEG", "-Wl,-read_only_relocs,suppress")
LibName("FFMPEG", "-framework VideoDecodeAcceleration")
elif os.path.isfile(GetThirdpartyDir() + "ffmpeg/lib/libavcodec.a"):
# Needed when linking ffmpeg statically on Linux.
LibName("FFMPEG", "-Wl,-Bsymbolic")
cv_lib = ChooseLib(("opencv_core", "cv"), "OPENCV")
if cv_lib == "opencv_core":
@ -840,12 +845,9 @@ if (COMPILER=="GCC"):
if GetTarget() != 'darwin':
# CgGL is covered by the Cg framework, and we don't need X11 components on OSX
if not PkgSkip("NVIDIACG") and not RUNTIME:
SmartPkgEnable("CGGL", "", ("CgGL"), "Cg/cgGL.h")
SmartPkgEnable("CGGL", "", ("CgGL"), "Cg/cgGL.h", thirdparty_dir = "nvidiacg")
if not RUNTIME:
SmartPkgEnable("X11", "x11", "X11", ("X11", "X11/Xlib.h"))
SmartPkgEnable("XRANDR", "xrandr", "Xrandr", "X11/extensions/Xrandr.h")
SmartPkgEnable("XF86DGA", "xxf86dga", "Xxf86dga", "X11/extensions/xf86dga.h")
SmartPkgEnable("XCURSOR", "xcursor", "Xcursor", "X11/Xcursor/Xcursor.h")
if GetHost() != "darwin":
# Workaround for an issue where pkg-config does not include this path
@ -1055,11 +1057,12 @@ def CompileCxx(obj,src,opts):
cmd += "/favor:blend "
cmd += "/wd4996 /wd4275 /wd4273 "
# Enable Windows 7 interfaces if we need Touchinput.
if PkgSkip("TOUCHINPUT") == 0:
cmd += "/DWINVER=0x601 "
else:
cmd += "/DWINVER=0x501 "
# We still target Windows XP.
cmd += "/DWINVER=0x501 "
# Work around a WinXP/2003 bug when using VS 2015+.
if SDK.get("VISUALSTUDIO_VERSION") == '14.0':
cmd += "/Zc:threadSafeInit- "
cmd += "/Fo" + obj + " /nologo /c"
if GetTargetArch() != 'x64' and (not PkgSkip("SSE2") or 'SSE2' in opts):
cmd += " /arch:SSE2"
@ -1109,12 +1112,7 @@ def CompileCxx(obj,src,opts):
if GetTargetArch() == 'x64':
cmd += "/favor:blend "
cmd += "/wd4996 /wd4275 /wd4267 /wd4101 /wd4273 "
# Enable Windows 7 interfaces if we need Touchinput.
if PkgSkip("TOUCHINPUT") == 0:
cmd += "/DWINVER=0x601 "
else:
cmd += "/DWINVER=0x501 "
cmd += "/DWINVER=0x501 "
cmd += "/Fo" + obj + " /c"
for x in ipath: cmd += " /I" + x
for (opt,dir) in INCDIRECTORIES:
@ -1196,7 +1194,7 @@ def CompileCxx(obj,src,opts):
if (COMPILER=="GCC"):
if (src.endswith(".c")): cmd = GetCC() +' -fPIC -c -o ' + obj
else: cmd = GetCXX()+' -ftemplate-depth-70 -fPIC -c -o ' + obj
else: cmd = GetCXX()+' -std=gnu++0x -ftemplate-depth-70 -fPIC -c -o ' + obj
for (opt, dir) in INCDIRECTORIES:
if (opt=="ALWAYS") or (opt in opts): cmd += ' -I' + BracketNameWithQuotes(dir)
for (opt, dir) in FRAMEWORKDIRECTORIES:
@ -1682,11 +1680,7 @@ def CompileLink(dll, obj, opts):
if 'NOARCH:' + arch.upper() not in opts:
cmd += " -arch %s" % arch
if "SYSROOT" in SDK:
cmd += " --sysroot=%s -no-canonical-prefixes" % (SDK["SYSROOT"])
# Android-specific flags.
if GetTarget() == 'android':
elif GetTarget() == 'android':
cmd += " -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now"
if GetTargetArch() == 'armv7a':
cmd += " -march=armv7-a -Wl,--fix-cortex-a8"
@ -1694,9 +1688,17 @@ def CompileLink(dll, obj, opts):
else:
cmd += " -pthread"
if "SYSROOT" in SDK:
cmd += " --sysroot=%s -no-canonical-prefixes" % (SDK["SYSROOT"])
if LDFLAGS != "":
cmd += " " + LDFLAGS
# Don't link libraries with Python.
if "PYTHON" in opts and GetOrigExt(dll) != ".exe" and not RTDIST:
opts = opts[:]
opts.remove("PYTHON")
for (opt, dir) in LIBDIRECTORIES:
if (opt=="ALWAYS") or (opt in opts):
cmd += ' -L' + BracketNameWithQuotes(dir)
@ -2122,17 +2124,13 @@ DTOOL_CONFIG=[
("COMPILE_IN_DEFAULT_FONT", '1', '1'),
("STDFLOAT_DOUBLE", 'UNDEF', 'UNDEF'),
("HAVE_MAYA", '1', '1'),
("MAYA_PRE_5_0", 'UNDEF', 'UNDEF'),
("HAVE_SOFTIMAGE", 'UNDEF', 'UNDEF'),
("SSL_097", 'UNDEF', 'UNDEF'),
("REPORT_OPENSSL_ERRORS", '1', '1'),
("USE_PANDAFILESTREAM", '1', '1'),
("USE_DELETED_CHAIN", '1', '1'),
("HAVE_WIN_TOUCHINPUT", 'UNDEF', 'UNDEF'),
("HAVE_GLX", 'UNDEF', '1'),
("HAVE_WGL", '1', 'UNDEF'),
("HAVE_DX9", 'UNDEF', 'UNDEF'),
("HAVE_CHROMIUM", 'UNDEF', 'UNDEF'),
("HAVE_THREADS", '1', '1'),
("SIMPLE_THREADS", 'UNDEF', 'UNDEF'),
("OS_SIMPLE_THREADS", '1', '1'),
@ -2145,12 +2143,9 @@ DTOOL_CONFIG=[
("DO_COLLISION_RECORDING", 'UNDEF', 'UNDEF'),
("SUPPORT_IMMEDIATE_MODE", 'UNDEF', 'UNDEF'),
("SUPPORT_FIXED_FUNCTION", '1', '1'),
("TRACK_IN_INTERPRETER", 'UNDEF', 'UNDEF'),
("DO_MEMORY_USAGE", 'UNDEF', 'UNDEF'),
("DO_PIPELINING", '1', '1'),
("EXPORT_TEMPLATES", 'yes', 'yes'),
("LINK_IN_GL", 'UNDEF', 'UNDEF'),
("LINK_IN_PHYSICS", 'UNDEF', 'UNDEF'),
("DEFAULT_PATHSEP", '";"', '":"'),
("WORDS_BIGENDIAN", 'UNDEF', 'UNDEF'),
("HAVE_NAMESPACE", '1', '1'),
@ -2206,13 +2201,9 @@ DTOOL_CONFIG=[
("PHAVE_STDINT_H", '1', '1'),
("HAVE_RTTI", '1', '1'),
("HAVE_X11", 'UNDEF', '1'),
("HAVE_XRANDR", 'UNDEF', '1'),
("HAVE_XF86DGA", 'UNDEF', '1'),
("HAVE_XCURSOR", 'UNDEF', '1'),
("IS_LINUX", 'UNDEF', '1'),
("IS_OSX", 'UNDEF', 'UNDEF'),
("IS_FREEBSD", 'UNDEF', 'UNDEF'),
("GLOBAL_OPERATOR_NEW_EXCEPTIONS", 'UNDEF', '1'),
("HAVE_EIGEN", 'UNDEF', 'UNDEF'),
("LINMATH_ALIGN", '1', '1'),
("HAVE_ZLIB", 'UNDEF', 'UNDEF'),
@ -2230,28 +2221,25 @@ DTOOL_CONFIG=[
("HAVE_PNM", '1', '1'),
("HAVE_STB_IMAGE", '1', '1'),
("HAVE_VORBIS", 'UNDEF', 'UNDEF'),
("HAVE_NVIDIACG", 'UNDEF', 'UNDEF'),
("HAVE_FREETYPE", 'UNDEF', 'UNDEF'),
("HAVE_FFTW", 'UNDEF', 'UNDEF'),
("HAVE_OPENSSL", 'UNDEF', 'UNDEF'),
("HAVE_NET", 'UNDEF', 'UNDEF'),
("WANT_NATIVE_NET", '1', '1'),
("SIMULATE_NETWORK_DELAY", 'UNDEF', 'UNDEF'),
("HAVE_EGG", '1', '1'),
("HAVE_CG", 'UNDEF', 'UNDEF'),
("HAVE_CGGL", 'UNDEF', 'UNDEF'),
("HAVE_CGDX9", 'UNDEF', 'UNDEF'),
("HAVE_FFMPEG", 'UNDEF', 'UNDEF'),
("HAVE_SWSCALE", 'UNDEF', 'UNDEF'),
("HAVE_SWRESAMPLE", 'UNDEF', 'UNDEF'),
("HAVE_ARTOOLKIT", 'UNDEF', 'UNDEF'),
("HAVE_OPENCV", 'UNDEF', 'UNDEF'),
("HAVE_DIRECTCAM", 'UNDEF', 'UNDEF'),
("HAVE_SQUISH", 'UNDEF', 'UNDEF'),
("HAVE_FCOLLADA", 'UNDEF', 'UNDEF'),
("HAVE_CARBON", 'UNDEF', 'UNDEF'),
("HAVE_COCOA", 'UNDEF', 'UNDEF'),
("HAVE_OPENAL_FRAMEWORK", 'UNDEF', 'UNDEF'),
("HAVE_ROCKET_PYTHON", '1', '1'),
("HAVE_ROCKET_DEBUGGER", 'UNDEF', 'UNDEF'),
("USE_TAU", 'UNDEF', 'UNDEF'),
("PRC_SAVE_DESCRIPTIONS", '1', '1'),
# ("_SECURE_SCL", '0', 'UNDEF'),
# ("_SECURE_SCL_THROWS", '0', 'UNDEF'),
@ -2298,9 +2286,6 @@ def WriteConfigSettings():
else:
dtool_config["HAVE_"+x] = 'UNDEF'
if not PkgSkip("OPENCV"):
dtool_config["OPENCV_VER_23"] = '1' if OPENCV_VER_23 else 'UNDEF'
dtool_config["HAVE_NET"] = '1'
if (PkgSkip("NVIDIACG")==0):
@ -2320,9 +2305,6 @@ def WriteConfigSettings():
dtool_config["PHAVE_SYS_MALLOC_H"] = '1'
dtool_config["HAVE_OPENAL_FRAMEWORK"] = '1'
dtool_config["HAVE_X11"] = 'UNDEF' # We might have X11, but we don't need it.
dtool_config["HAVE_XRANDR"] = 'UNDEF'
dtool_config["HAVE_XF86DGA"] = 'UNDEF'
dtool_config["HAVE_XCURSOR"] = 'UNDEF'
dtool_config["HAVE_GLX"] = 'UNDEF'
dtool_config["IS_LINUX"] = 'UNDEF'
dtool_config["HAVE_VIDEO4LINUX"] = 'UNDEF'
@ -2357,9 +2339,6 @@ def WriteConfigSettings():
if (PkgSkip("PYTHON") != 0):
dtool_config["HAVE_ROCKET_PYTHON"] = 'UNDEF'
if (PkgSkip("TOUCHINPUT") == 0 and GetTarget() == "windows"):
dtool_config["HAVE_WIN_TOUCHINPUT"] = '1'
if (GetOptimize() <= 3):
dtool_config["HAVE_ROCKET_DEBUGGER"] = '1'
@ -2373,9 +2352,6 @@ def WriteConfigSettings():
if (GetOptimize() <= 3):
dtool_config["DO_COLLISION_RECORDING"] = '1'
#if (GetOptimize() <= 2):
# dtool_config["TRACK_IN_INTERPRETER"] = '1'
if (GetOptimize() <= 3):
dtool_config["DO_MEMORY_USAGE"] = '1'
@ -2790,8 +2766,13 @@ if (GetTarget() == 'darwin'):
# OpenAL is not yet working well on OSX for us, so let's do this for now.
configprc = configprc.replace("p3openal_audio", "p3fmod_audio")
ConditionalWriteFile(GetOutputDir()+"/etc/Config.prc", configprc)
ConditionalWriteFile(GetOutputDir()+"/etc/Confauto.prc", confautoprc)
if GetTarget() == 'windows':
# Convert to Windows newlines.
ConditionalWriteFile(GetOutputDir()+"/etc/Config.prc", configprc, newline='\r\n')
ConditionalWriteFile(GetOutputDir()+"/etc/Confauto.prc", confautoprc, newline='\r\n')
else:
ConditionalWriteFile(GetOutputDir()+"/etc/Config.prc", configprc)
ConditionalWriteFile(GetOutputDir()+"/etc/Confauto.prc", confautoprc)
##########################################################################################
#
@ -2888,22 +2869,75 @@ if tp_dir is not None:
if GetTarget() == 'windows':
CopyAllFiles(GetOutputDir() + "/bin/", tp_dir + "extras/bin/")
if not PkgSkip("PYTHON"):
pydll = "/" + SDK["PYTHONVERSION"].replace(".", "")
if (GetOptimize() <= 2): pydll += "_d.dll"
else: pydll += ".dll"
CopyFile(GetOutputDir() + "/bin" + pydll, SDK["PYTHON"] + pydll)
for fn in glob.glob(SDK["PYTHON"] + "/vcruntime*.dll"):
CopyFile(GetOutputDir() + "/bin/", fn)
if not PkgSkip("PYTHON") and not RTDIST:
#XXX rdb I don't think we need to copy over the Python DLL, do we?
#pydll = "/" + SDK["PYTHONVERSION"].replace(".", "")
#if (GetOptimize() <= 2): pydll += "_d.dll"
#else: pydll += ".dll"
#CopyFile(GetOutputDir() + "/bin" + pydll, SDK["PYTHON"] + pydll)
if not RTDIST:
CopyTree(GetOutputDir() + "/python", SDK["PYTHON"])
if not os.path.isfile(SDK["PYTHON"] + "/ppython.exe") and os.path.isfile(SDK["PYTHON"] + "/python.exe"):
CopyFile(GetOutputDir() + "/python/ppython.exe", SDK["PYTHON"] + "/python.exe")
if not os.path.isfile(SDK["PYTHON"] + "/ppythonw.exe") and os.path.isfile(SDK["PYTHON"] + "/pythonw.exe"):
CopyFile(GetOutputDir() + "/python/ppythonw.exe", SDK["PYTHON"] + "/pythonw.exe")
ConditionalWriteFile(GetOutputDir() + "/python/panda.pth", "..\n../bin\n")
#for fn in glob.glob(SDK["PYTHON"] + "/vcruntime*.dll"):
# CopyFile(GetOutputDir() + "/bin/", fn)
# Copy the whole Python directory.
CopyTree(GetOutputDir() + "/python", SDK["PYTHON"])
# NB: Python does not always ship with the correct manifest/dll.
# Figure out the correct one to ship, and grab it from WinSxS dir.
manifest = GetOutputDir() + '/tmp/python.manifest'
if os.path.isfile(manifest):
os.unlink(manifest)
oscmd('mt -inputresource:"%s\\python.exe";#1 -out:"%s" -nologo' % (SDK["PYTHON"], manifest), True)
if os.path.isfile(manifest):
import xml.etree.ElementTree as ET
tree = ET.parse(manifest)
idents = tree.findall('./{urn:schemas-microsoft-com:asm.v1}dependency/{urn:schemas-microsoft-com:asm.v1}dependentAssembly/{urn:schemas-microsoft-com:asm.v1}assemblyIdentity')
else:
idents = ()
for ident in tree.findall('./{urn:schemas-microsoft-com:asm.v1}dependency/{urn:schemas-microsoft-com:asm.v1}dependentAssembly/{urn:schemas-microsoft-com:asm.v1}assemblyIdentity'):
sxs_name = '_'.join([
ident.get('processorArchitecture'),
ident.get('name').lower(),
ident.get('publicKeyToken'),
ident.get('version'),
])
# Find the manifest matching these parameters.
pattern = os.path.join('C:' + os.sep, 'Windows', 'WinSxS', 'Manifests', sxs_name + '_*.manifest')
manifests = glob.glob(pattern)
if not manifests:
print("%sWARNING:%s Could not locate manifest %s. You may need to reinstall the Visual C++ Redistributable." % (GetColor("red"), GetColor(), pattern))
continue
CopyFile(GetOutputDir() + "/python/" + ident.get('name') + ".manifest", manifests[0])
# Also copy the corresponding msvcr dll.
pattern = os.path.join('C:' + os.sep, 'Windows', 'WinSxS', sxs_name + '_*', 'msvcr*.dll')
for file in glob.glob(pattern):
CopyFile(GetOutputDir() + "/python/", file)
# Copy python.exe to ppython.exe.
if not os.path.isfile(SDK["PYTHON"] + "/ppython.exe") and os.path.isfile(SDK["PYTHON"] + "/python.exe"):
CopyFile(GetOutputDir() + "/python/ppython.exe", SDK["PYTHON"] + "/python.exe")
if not os.path.isfile(SDK["PYTHON"] + "/ppythonw.exe") and os.path.isfile(SDK["PYTHON"] + "/pythonw.exe"):
CopyFile(GetOutputDir() + "/python/ppythonw.exe", SDK["PYTHON"] + "/pythonw.exe")
ConditionalWriteFile(GetOutputDir() + "/python/panda.pth", "..\n../bin\n")
# Copy over the MSVC runtime.
if GetTarget() == 'windows' and "VISUALSTUDIO" in SDK:
vcver = SDK["VISUALSTUDIO_VERSION"].replace('.', '')
crtname = "Microsoft.VC%s.CRT" % (vcver)
dir = os.path.join(SDK["VISUALSTUDIO"], "VC", "redist", GetTargetArch(), crtname)
if os.path.isfile(os.path.join(dir, "msvcr" + vcver + ".dll")):
CopyFile(GetOutputDir() + "/bin/", os.path.join(dir, "msvcr" + vcver + ".dll"))
if os.path.isfile(os.path.join(dir, "msvcp" + vcver + ".dll")):
CopyFile(GetOutputDir() + "/bin/", os.path.join(dir, "msvcp" + vcver + ".dll"))
if os.path.isfile(os.path.join(dir, "vcruntime" + vcver + ".dll")):
CopyFile(GetOutputDir() + "/bin/", os.path.join(dir, "vcruntime" + vcver + ".dll"))
########################################################################
##
@ -2911,8 +2945,14 @@ if tp_dir is not None:
##
########################################################################
CopyFile(GetOutputDir()+"/", "doc/LICENSE")
CopyFile(GetOutputDir()+"/", "doc/ReleaseNotes")
if GetTarget() == 'windows':
# Convert to Windows newlines so they can be opened by notepad.
WriteFile(GetOutputDir() + "/LICENSE", ReadFile("doc/LICENSE"), newline='\r\n')
WriteFile(GetOutputDir() + "/ReleaseNotes", ReadFile("doc/ReleaseNotes"), newline='\r\n')
else:
CopyFile(GetOutputDir()+"/", "doc/LICENSE")
CopyFile(GetOutputDir()+"/", "doc/ReleaseNotes")
if (PkgSkip("PANDATOOL")==0):
CopyAllFiles(GetOutputDir()+"/plugins/", "pandatool/src/scripts/", ".mel")
CopyAllFiles(GetOutputDir()+"/plugins/", "pandatool/src/scripts/", ".ms")
@ -3301,6 +3341,7 @@ if (not RUNTIME):
TargetAdd('interrogate.exe', input='libp3cppParser.ilb')
TargetAdd('interrogate.exe', input=COMMON_DTOOL_LIBS)
TargetAdd('interrogate.exe', input='libp3interrogatedb.dll')
TargetAdd('interrogate.exe', input='libp3pystub.lib')
TargetAdd('interrogate.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER'])
TargetAdd('interrogate_module_interrogate_module.obj', opts=OPTS, input='interrogate_module.cxx')
@ -3308,6 +3349,7 @@ if (not RUNTIME):
TargetAdd('interrogate_module.exe', input='libp3cppParser.ilb')
TargetAdd('interrogate_module.exe', input=COMMON_DTOOL_LIBS)
TargetAdd('interrogate_module.exe', input='libp3interrogatedb.dll')
TargetAdd('interrogate_module.exe', input='libp3pystub.lib')
TargetAdd('interrogate_module.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER'])
if (not RTDIST):
@ -3316,6 +3358,7 @@ if (not RUNTIME):
TargetAdd('parse_file.exe', input='libp3cppParser.ilb')
TargetAdd('parse_file.exe', input=COMMON_DTOOL_LIBS)
TargetAdd('parse_file.exe', input='libp3interrogatedb.dll')
TargetAdd('parse_file.exe', input='libp3pystub.lib')
TargetAdd('parse_file.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER'])
#
@ -3339,6 +3382,7 @@ if (not RTDIST and not RUNTIME):
TargetAdd('test_interrogate.exe', input='test_interrogate_test_interrogate.obj')
TargetAdd('test_interrogate.exe', input='libp3interrogatedb.dll')
TargetAdd('test_interrogate.exe', input=COMMON_DTOOL_LIBS)
TargetAdd('test_interrogate.exe', input='libp3pystub.lib')
TargetAdd('test_interrogate.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER'])
#
@ -4070,8 +4114,20 @@ if (not RUNTIME):
#
if (PkgSkip("VISION") == 0) and (not RUNTIME):
# We want to know whether we have ffmpeg so that we can override the .avi association.
if not PkgSkip("FFMPEG"):
DefSymbol("OPENCV", "HAVE_FFMPEG")
if not PkgSkip("OPENCV"):
DefSymbol("OPENCV", "HAVE_OPENCV")
if OPENCV_VER_23:
DefSymbol("OPENCV", "OPENCV_VER_23")
OPTS=['DIR:panda/src/vision', 'BUILDING:VISION', 'ARTOOLKIT', 'OPENCV', 'DX9', 'DIRECTCAM', 'JPEG', 'EXCEPTIONS']
TargetAdd('p3vision_composite1.obj', opts=OPTS, input='p3vision_composite1.cxx')
TargetAdd('p3vision_composite1.obj', opts=OPTS, input='p3vision_composite1.cxx', dep=[
'dtool_have_ffmpeg.dat',
'dtool_have_opencv.dat',
'dtool_have_directcam.dat',
])
TargetAdd('libp3vision.dll', input='p3vision_composite1.obj')
TargetAdd('libp3vision.dll', input=COMMON_PANDA_LIBS)
@ -4260,8 +4316,15 @@ if (PkgSkip("VRPN")==0 and not RUNTIME):
# DIRECTORY: panda/src/ffmpeg
#
if PkgSkip("FFMPEG") == 0 and not RUNTIME:
if not PkgSkip("SWSCALE"):
DefSymbol("FFMPEG", "HAVE_SWSCALE")
if not PkgSkip("SWRESAMPLE"):
DefSymbol("FFMPEG", "HAVE_SWRESAMPLE")
OPTS=['DIR:panda/src/ffmpeg', 'BUILDING:FFMPEG', 'FFMPEG', 'SWSCALE', 'SWRESAMPLE']
TargetAdd('p3ffmpeg_composite1.obj', opts=OPTS, input='p3ffmpeg_composite1.cxx')
TargetAdd('p3ffmpeg_composite1.obj', opts=OPTS, input='p3ffmpeg_composite1.cxx', dep=[
'dtool_have_swscale.dat', 'dtool_have_swresample.dat'])
TargetAdd('libp3ffmpeg.dll', input='p3ffmpeg_composite1.obj')
TargetAdd('libp3ffmpeg.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libp3ffmpeg.dll', opts=OPTS)
@ -4425,8 +4488,17 @@ if (not RUNTIME):
#
if (not RUNTIME):
OPTS=['DIR:panda/src/framework', 'BUILDING:FRAMEWORK']
TargetAdd('p3framework_composite1.obj', opts=OPTS, input='p3framework_composite1.cxx')
deps = []
# Framework wants to link in a renderer when building statically, so tell it what is available.
if GetLinkAllStatic():
deps = ['dtool_have_gl.dat', 'dtool_have_tinydisplay.dat']
if not PkgSkip("GL"):
DefSymbol("FRAMEWORK", "HAVE_GL")
if not PkgSkip("TINYDISPLAY"):
DefSymbol("FRAMEWORK", "HAVE_TINYDISPLAY")
OPTS=['DIR:panda/src/framework', 'BUILDING:FRAMEWORK', 'FRAMEWORK']
TargetAdd('p3framework_composite1.obj', opts=OPTS, input='p3framework_composite1.cxx', dep=deps)
TargetAdd('libp3framework.dll', input='p3framework_composite1.obj')
TargetAdd('libp3framework.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libp3framework.dll', opts=['ADVAPI'])
@ -4514,7 +4586,7 @@ if (GetTarget() not in ['windows', 'darwin'] and PkgSkip("GL")==0 and PkgSkip("X
TargetAdd('libpandagl.dll', input='p3glgsg_glgsg.obj')
TargetAdd('libpandagl.dll', input='p3glxdisplay_composite1.obj')
TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'X11'])
#
# DIRECTORY: panda/src/cocoadisplay/
@ -4532,7 +4604,7 @@ if (GetTarget() == 'darwin' and PkgSkip("COCOA")==0 and PkgSkip("GL")==0 and not
if (PkgSkip('PANDAFX')==0):
TargetAdd('libpandagl.dll', input='libpandafx.dll')
TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'COCOA'])
TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'COCOA', 'CARBON'])
#
# DIRECTORY: panda/src/osxdisplay/
@ -4589,7 +4661,7 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0 and not RUNTI
TargetAdd('libpandagles.dll', input='p3glesgsg_glesgsg.obj')
TargetAdd('libpandagles.dll', input='pandagles_egldisplay_composite1.obj')
TargetAdd('libpandagles.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libpandagles.dll', opts=['MODULE', 'GLES', 'EGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libpandagles.dll', opts=['MODULE', 'GLES', 'EGL', 'X11'])
#
# DIRECTORY: panda/src/egldisplay/
@ -4607,7 +4679,7 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0 and PkgSkip("X11")==0 and not RUNT
TargetAdd('libpandagles2.dll', input='p3gles2gsg_gles2gsg.obj')
TargetAdd('libpandagles2.dll', input='pandagles2_egldisplay_composite1.obj')
TargetAdd('libpandagles2.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libpandagles2.dll', opts=['MODULE', 'GLES2', 'EGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libpandagles2.dll', opts=['MODULE', 'GLES2', 'EGL', 'X11'])
#
# DIRECTORY: panda/src/ode/
@ -4903,7 +4975,7 @@ if (not RUNTIME and (GetTarget() in ('windows', 'darwin') or PkgSkip("X11")==0)
TargetAdd('libp3tinydisplay.dll', opts=['WINIMM', 'WINGDI', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM'])
else:
TargetAdd('libp3tinydisplay.dll', input='p3x11display_composite1.obj')
TargetAdd('libp3tinydisplay.dll', opts=['X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libp3tinydisplay.dll', opts=['X11'])
TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_composite1.obj')
TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_composite2.obj')
TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_ztriangle_1.obj')
@ -4921,7 +4993,7 @@ if (PkgSkip("DIRECT")==0):
OPTS=['DIR:direct/src/directbase', 'PYTHON']
TargetAdd('p3directbase_directbase.obj', opts=OPTS+['BUILDING:DIRECT'], input='directbase.cxx')
if (PkgSkip("PYTHON")==0 and not RTDIST and not RUNTIME):
if not PkgSkip("PYTHON") and not RTDIST and not RUNTIME and not PkgSkip("DIRECTSCRIPTS"):
DefSymbol("BUILDING:PACKPANDA", "IMPORT_MODULE", "direct.directscripts.packpanda")
TargetAdd('packpanda.obj', opts=OPTS+['BUILDING:PACKPANDA'], input='ppython.cxx')
TargetAdd('packpanda.exe', input='packpanda.obj')
@ -5080,7 +5152,7 @@ if (PkgSkip("DIRECT")==0):
TargetAdd('direct.pyd', input='libp3direct.dll')
TargetAdd('direct.pyd', input='libp3interrogatedb.dll')
TargetAdd('direct.pyd', input=COMMON_PANDA_LIBS)
TargetAdd('direct.pyd', opts=['PYTHON', 'OPENSSL', 'WINUSER', 'WINGDI'])
TargetAdd('direct.pyd', opts=['PYTHON', 'OPENSSL', 'WINUSER', 'WINGDI', 'WINSOCK2'])
#
# DIRECTORY: direct/src/dcparse/
@ -5096,6 +5168,7 @@ if (PkgSkip("PYTHON")==0 and PkgSkip("DIRECT")==0 and not RTDIST and not RUNTIME
TargetAdd('p3dcparse.exe', input='dcparse_dcparse.obj')
TargetAdd('p3dcparse.exe', input='libp3direct.dll')
TargetAdd('p3dcparse.exe', input=COMMON_PANDA_LIBS)
TargetAdd('p3dcparse.exe', input='libp3pystub.lib')
TargetAdd('p3dcparse.exe', opts=['ADVAPI', 'PYTHON'])
#
@ -6005,8 +6078,11 @@ if (PkgSkip("PANDATOOL")==0):
#
if (PkgSkip("PANDATOOL")==0):
if not PkgSkip("FCOLLADA"):
DefSymbol("FCOLLADA", "HAVE_FCOLLADA")
OPTS=['DIR:pandatool/src/ptloader', 'DIR:pandatool/src/flt', 'DIR:pandatool/src/lwo', 'DIR:pandatool/src/xfile', 'DIR:pandatool/src/xfileegg', 'DIR:pandatool/src/daeegg', 'BUILDING:PTLOADER', 'FCOLLADA']
TargetAdd('p3ptloader_config_ptloader.obj', opts=OPTS, input='config_ptloader.cxx')
TargetAdd('p3ptloader_config_ptloader.obj', opts=OPTS, input='config_ptloader.cxx', dep='dtool_have_fcollada.dat')
TargetAdd('p3ptloader_loaderFileTypePandatool.obj', opts=OPTS, input='loaderFileTypePandatool.cxx')
TargetAdd('libp3ptloader.dll', input='p3ptloader_config_ptloader.obj')
TargetAdd('libp3ptloader.dll', input='p3ptloader_loaderFileTypePandatool.obj')
@ -6776,9 +6852,9 @@ def MakeInstallerLinux():
txt = txt.replace("VERSION", DEBVERSION).replace("ARCH", pkg_arch).replace("PV", PV).replace("MAJOR", MAJOR_VERSION)
txt = txt.replace("INSTSIZE", str(GetDirectorySize("targetroot") / 1024))
oscmd("mkdir --mode=0755 -p targetroot/DEBIAN")
oscmd("cd targetroot ; (find usr -type f -exec md5sum {} \;) > DEBIAN/md5sums")
oscmd("cd targetroot && (find usr -type f -exec md5sum {} ;) > DEBIAN/md5sums")
if (not RUNTIME):
oscmd("cd targetroot ; (find etc -type f -exec md5sum {} \;) >> DEBIAN/md5sums")
oscmd("cd targetroot && (find etc -type f -exec md5sum {} ;) >> DEBIAN/md5sums")
WriteFile("targetroot/DEBIAN/conffiles","/etc/Config.prc\n")
WriteFile("targetroot/DEBIAN/postinst","#!/bin/sh\necho running ldconfig\nldconfig\n")
oscmd("cp targetroot/DEBIAN/postinst targetroot/DEBIAN/postrm")
@ -6806,7 +6882,7 @@ def MakeInstallerLinux():
if RUNTIME:
# The runtime doesn't export any useful symbols, so just query the dependencies.
oscmd("cd targetroot; %(dpkg_shlibdeps)s -x%(pkg_name)s %(lib_pattern)s %(bin_pattern)s*" % locals())
oscmd("cd targetroot && %(dpkg_shlibdeps)s -x%(pkg_name)s %(lib_pattern)s %(bin_pattern)s*" % locals())
depends = ReadFile("targetroot/debian/substvars").replace("shlibs:Depends=", "").strip()
recommends = ""
else:
@ -6814,12 +6890,12 @@ def MakeInstallerLinux():
pkg_dir = "debian/panda3d" + MAJOR_VERSION
# Generate a symbols file so that other packages can know which symbols we export.
oscmd("cd targetroot; dpkg-gensymbols -q -ODEBIAN/symbols -v%(pkg_version)s -p%(pkg_name)s -e%(lib_pattern)s" % locals())
oscmd("cd targetroot && dpkg-gensymbols -q -ODEBIAN/symbols -v%(pkg_version)s -p%(pkg_name)s -e%(lib_pattern)s" % locals())
# Library dependencies are required, binary dependencies are recommended.
# We explicitly exclude libphysx-extras since we don't want to depend on PhysX.
oscmd("cd targetroot; LD_LIBRARY_PATH=usr/%(lib_dir)s/panda3d %(dpkg_shlibdeps)s -Tdebian/substvars_dep --ignore-missing-info -x%(pkg_name)s -xlibphysx-extras %(lib_pattern)s" % locals())
oscmd("cd targetroot; LD_LIBRARY_PATH=usr/%(lib_dir)s/panda3d %(dpkg_shlibdeps)s -Tdebian/substvars_rec --ignore-missing-info -x%(pkg_name)s %(bin_pattern)s" % locals())
oscmd("cd targetroot && LD_LIBRARY_PATH=usr/%(lib_dir)s/panda3d %(dpkg_shlibdeps)s -Tdebian/substvars_dep --ignore-missing-info -x%(pkg_name)s -xlibphysx-extras %(lib_pattern)s" % locals())
oscmd("cd targetroot && LD_LIBRARY_PATH=usr/%(lib_dir)s/panda3d %(dpkg_shlibdeps)s -Tdebian/substvars_rec --ignore-missing-info -x%(pkg_name)s %(bin_pattern)s" % locals())
# Parse the substvars files generated by dpkg-shlibdeps.
depends = ReadFile("targetroot/debian/substvars_dep").replace("shlibs:Depends=", "").strip()
@ -7181,6 +7257,11 @@ try:
MakeInstallerFreeBSD()
else:
exit("Do not know how to make an installer for this platform")
if WHEEL:
ProgressOutput(100.0, "Building wheel")
from makewheel import makewheel
makewheel(WHLVERSION, GetOutputDir())
finally:
SaveDependencyCache()

View File

@ -396,10 +396,16 @@ def CrossCompiling():
return GetTarget() != GetHost()
def GetCC():
return os.environ.get('CC', TOOLCHAIN_PREFIX + 'gcc')
if TARGET == 'darwin':
return os.environ.get('CC', TOOLCHAIN_PREFIX + 'clang')
else:
return os.environ.get('CC', TOOLCHAIN_PREFIX + 'gcc')
def GetCXX():
return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'g++')
if TARGET == 'darwin':
return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'clang++')
else:
return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'g++')
def GetStrip():
# Hack
@ -512,6 +518,7 @@ def oscmd(cmd, ignoreError = False):
exit("Cannot find "+exe+" on search path")
res = os.spawnl(os.P_WAIT, exe_path, cmd)
else:
cmd = cmd.replace(';', '\\;')
res = subprocess.call(cmd, shell=True)
sig = res & 0x7F
if (GetVerbose() and res != 0):
@ -966,7 +973,12 @@ def ReadBinaryFile(wfile):
ex = sys.exc_info()[1]
exit("Cannot read %s: %s" % (wfile, ex))
def WriteFile(wfile, data):
def WriteFile(wfile, data, newline=None):
if newline is not None:
data = data.replace('\r\n', '\n')
data = data.replace('\r', '\n')
data = data.replace('\n', newline)
try:
dsthandle = open(wfile, "w")
dsthandle.write(data)
@ -984,18 +996,24 @@ def WriteBinaryFile(wfile, data):
ex = sys.exc_info()[1]
exit("Cannot write to %s: %s" % (wfile, ex))
def ConditionalWriteFile(dest, desiredcontents):
def ConditionalWriteFile(dest, data, newline=None):
if newline is not None:
data = data.replace('\r\n', '\n')
data = data.replace('\r', '\n')
data = data.replace('\n', newline)
try:
rfile = open(dest, 'r')
contents = rfile.read(-1)
rfile.close()
except:
contents = 0
if contents != desiredcontents:
if contents != data:
if VERBOSE:
print("Writing %s" % (dest))
sys.stdout.flush()
WriteFile(dest, desiredcontents)
WriteFile(dest, data)
def DeleteVCS(dir):
if dir == "": dir = "."
@ -1984,6 +2002,11 @@ def SdkLocatePython(prefer_thirdparty_python=False):
SDK["PYTHONVERSION"] = "python" + ver
SDK["PYTHONEXEC"] = "/System/Library/Frameworks/Python.framework/Versions/" + ver + "/bin/python" + ver
# Avoid choosing the one in the thirdparty package dir.
PkgSetCustomLocation("PYTHON")
IncDirectory("PYTHON", py_fwx + "/include")
LibDirectory("PYTHON", "%s/usr/lib" % (SDK.get("MACOSX", "")))
if sys.version[:3] != ver:
print("Warning: building with Python %s instead of %s since you targeted a specific Mac OS X version." % (ver, sys.version[:3]))
@ -2057,6 +2080,10 @@ def SdkLocateWindows(version = '7.1'):
# Choose the latest version of the Windows 10 SDK.
platsdk = GetRegistryKey("SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10")
# Fallback in case we can't read the registry.
if not platsdk or not os.path.isdir(platsdk):
platsdk = "C:\\Program Files (x86)\\Windows Kits\\10\\"
if platsdk and os.path.isdir(platsdk):
incdirs = glob.glob(os.path.join(platsdk, 'Include', version + '.*.*'))
max_version = ()
@ -2089,6 +2116,10 @@ def SdkLocateWindows(version = '7.1'):
# We chose a specific version of the Windows 10 SDK. Verify it exists.
platsdk = GetRegistryKey("SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10")
# Fallback in case we can't read the registry.
if not platsdk or not os.path.isdir(platsdk):
platsdk = "C:\\Program Files (x86)\\Windows Kits\\10\\"
if version.count('.') == 2:
version += '.0'
@ -2098,6 +2129,10 @@ def SdkLocateWindows(version = '7.1'):
elif version == '8.1':
platsdk = GetRegistryKey("SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot81")
# Fallback in case we can't read the registry.
if not platsdk or not os.path.isdir(platsdk):
platsdk = "C:\\Program Files (x86)\\Windows Kits\\8.1\\"
elif version == '8.0':
platsdk = GetRegistryKey("SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot")
@ -2403,9 +2438,19 @@ def SetupVisualStudioEnviron():
# with Visual Studio 2015 requires use of the Universal CRT.
if winsdk_ver == '7.1' and SDK["VISUALSTUDIO_VERSION"] == '14.0':
win_kit = GetRegistryKey("SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10")
# Fallback in case we can't read the registry.
if not win_kit or not os.path.isdir(win_kit):
win_kit = "C:\\Program Files (x86)\\Windows Kits\\10\\"
elif not win_kit.endswith('\\'):
win_kit += '\\'
AddToPathEnv("LIB", win_kit + "Lib\\10.0.10150.0\\ucrt\\" + arch)
AddToPathEnv("INCLUDE", win_kit + "Include\\10.0.10150.0\\ucrt")
# Copy the DLLs to the bin directory.
CopyAllFiles(GetOutputDir() + "/bin/", win_kit + "Redist\\ucrt\\DLLs\\" + arch + "\\")
########################################################################
#
# Include and Lib directories.

598
makepanda/makewheel.py Normal file
View File

@ -0,0 +1,598 @@
"""
Generates a wheel (.whl) file from the output of makepanda.
Since the wheel requires special linking, this will only work if compiled with
the `--wheel` parameter.
Please keep this file work with Panda3D 1.9 until that reaches EOL.
"""
from __future__ import print_function, unicode_literals
from distutils.util import get_platform
import json
import sys
import os
from os.path import join
import shutil
import zipfile
import hashlib
import tempfile
import subprocess
from distutils.sysconfig import get_config_var
from optparse import OptionParser
from makepandacore import ColorText, LocateBinary, ParsePandaVersion, GetExtensionSuffix, SetVerbose, GetVerbose
from base64 import urlsafe_b64encode
default_platform = get_platform()
if default_platform.startswith("linux-"):
# Is this manylinux1?
if os.path.isfile("/lib/libc-2.5.so") and os.path.isdir("/opt/python"):
default_platform = default_platform.replace("linux", "manylinux1")
def get_abi_tag():
if sys.version_info >= (3, 0):
soabi = get_config_var('SOABI')
if soabi and soabi.startswith('cpython-'):
return 'cp' + soabi.split('-')[1]
elif soabi:
return soabi.replace('.', '_').replace('-', '_')
soabi = 'cp%d%d' % (sys.version_info[:2])
debug_flag = get_config_var('Py_DEBUG')
if (debug_flag is None and hasattr(sys, 'gettotalrefcount')) or debug_flag:
soabi += 'd'
malloc_flag = get_config_var('WITH_PYMALLOC')
if malloc_flag is None or malloc_flag:
soabi += 'm'
if sys.version_info < (3, 3):
usize = get_config_var('Py_UNICODE_SIZE')
if (usize is None and sys.maxunicode == 0x10ffff) or usize == 4:
soabi += 'u'
return soabi
def is_exe_file(path):
return os.path.isfile(path) and path.lower().endswith('.exe')
def is_elf_file(path):
base = os.path.basename(path)
return os.path.isfile(path) and '.' not in base and \
open(path, 'rb').read(4) == b'\x7FELF'
def is_mach_o_file(path):
base = os.path.basename(path)
return os.path.isfile(path) and '.' not in base and \
open(path, 'rb').read(4) in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\bCA',
b'\xFE\xED\xFA\xCE', b'\xCE\xFA\xED\xFE',
b'\xFE\xED\xFA\xCF', b'\xCF\xFA\xED\xFE')
def is_fat_file(path):
return os.path.isfile(path) and \
open(path, 'rb').read(4) in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\bCA')
if sys.platform in ('win32', 'cygwin'):
is_executable = is_exe_file
elif sys.platform == 'darwin':
is_executable = is_mach_o_file
else:
is_executable = is_elf_file
# Other global parameters
PY_VERSION = "cp{0}{1}".format(*sys.version_info)
ABI_TAG = get_abi_tag()
EXCLUDE_EXT = [".pyc", ".pyo", ".N", ".prebuilt", ".xcf", ".plist", ".vcproj", ".sln"]
# Plug-ins to install.
PLUGIN_LIBS = ["pandagl", "pandagles", "pandagles2", "pandadx9", "p3tinydisplay", "p3ptloader", "p3assimp", "p3ffmpeg", "p3openal_audio", "p3fmod_audio"]
WHEEL_DATA = """Wheel-Version: 1.0
Generator: makepanda
Root-Is-Purelib: false
Tag: {0}-{1}-{2}
"""
METADATA = {
"license": "BSD",
"name": "Panda3D",
"metadata_version": "2.0",
"generator": "makepanda",
"summary": "Panda3D is a game engine, a framework for 3D rendering and "
"game development for Python and C++ programs.",
"extensions": {
"python.details": {
"project_urls": {
"Home": "https://www.panda3d.org/"
},
"document_names": {
"license": "LICENSE.txt"
},
"contacts": [
{
"role": "author",
"email": "etc-panda3d@lists.andrew.cmu.edu",
"name": "Panda3D Team"
}
]
}
},
"classifiers": [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Intended Audience :: End Users/Desktop",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: C++",
"Programming Language :: Python",
"Topic :: Games/Entertainment",
"Topic :: Multimedia",
"Topic :: Multimedia :: Graphics",
"Topic :: Multimedia :: Graphics :: 3D Rendering"
]
}
PANDA3D_TOOLS_INIT = """import os, sys
import panda3d
if sys.platform in ('win32', 'cygwin'):
path_var = 'PATH'
elif sys.platform == 'darwin':
path_var = 'DYLD_LIBRARY_PATH'
else:
path_var = 'LD_LIBRARY_PATH'
dir = os.path.dirname(panda3d.__file__)
del panda3d
if not os.environ.get(path_var):
os.environ[path_var] = dir
else:
os.environ[path_var] = dir + os.pathsep + os.environ[path_var]
del os, sys, path_var, dir
def _exec_tool(tool):
import os, sys
from subprocess import Popen
tools_dir = os.path.dirname(__file__)
handle = Popen(sys.argv, executable=os.path.join(tools_dir, tool))
try:
try:
return handle.wait()
except KeyboardInterrupt:
# Give the program a chance to handle the signal gracefully.
return handle.wait()
except:
handle.kill()
handle.wait()
raise
# Register all the executables in this directory as global functions.
{0}
"""
def parse_dependencies_windows(data):
""" Parses the given output from dumpbin /dependents to determine the list
of dll's this executable file depends on. """
lines = data.splitlines()
li = 0
while li < len(lines):
line = lines[li]
li += 1
if line.find(' has the following dependencies') != -1:
break
if li < len(lines):
line = lines[li]
if line.strip() == '':
# Skip a blank line.
li += 1
# Now we're finding filenames, until the next blank line.
filenames = []
while li < len(lines):
line = lines[li]
li += 1
line = line.strip()
if line == '':
# We're done.
return filenames
filenames.append(line)
# At least we got some data.
return filenames
def parse_dependencies_unix(data):
""" Parses the given output from otool -XL or ldd to determine the list of
libraries this executable file depends on. """
lines = data.splitlines()
filenames = []
for l in lines:
l = l.strip()
if l != "statically linked":
filenames.append(l.split(' ', 1)[0])
return filenames
def scan_dependencies(pathname):
""" Checks the named file for DLL dependencies, and adds any appropriate
dependencies found into pluginDependencies and dependentFiles. """
if sys.platform == "darwin":
command = ['otool', '-XL', pathname]
elif sys.platform in ("win32", "cygwin"):
command = ['dumpbin', '/dependents', pathname]
else:
command = ['ldd', pathname]
process = subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True)
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
raise subprocess.CalledProcessError(retcode, command[0], output=output)
filenames = None
if sys.platform in ("win32", "cygwin"):
filenames = parse_dependencies_windows(output)
else:
filenames = parse_dependencies_unix(output)
if filenames is None:
sys.exit("Unable to determine dependencies from %s" % (pathname))
if sys.platform == "darwin" and len(filenames) > 0:
# Filter out the library ID.
if os.path.basename(filenames[0]).split('.', 1)[0] == os.path.basename(pathname).split('.', 1)[0]:
del filenames[0]
return filenames
class WheelFile(object):
def __init__(self, name, version, platform):
self.name = name
self.version = version
self.platform = platform
wheel_name = "{0}-{1}-{2}-{3}-{4}.whl".format(
name, version, PY_VERSION, ABI_TAG, platform)
print("Writing %s" % (wheel_name))
self.zip_file = zipfile.ZipFile(wheel_name, 'w', zipfile.ZIP_DEFLATED)
self.records = []
# Used to locate dependency libraries.
self.lib_path = []
self.dep_paths = {}
def consider_add_dependency(self, target_path, dep, search_path=None):
"""Considers adding a dependency library.
Returns the target_path if it was added, which may be different from
target_path if it was already added earlier, or None if it wasn't."""
if dep in self.dep_paths:
# Already considered this.
return self.dep_paths[dep]
self.dep_paths[dep] = None
if dep.lower().startswith("python") or os.path.basename(dep).startswith("libpython"):
# Don't include the Python library.
return
if sys.platform == "darwin" and dep.endswith(".so"):
# Temporary hack for 1.9, which had link deps on modules.
return
source_path = None
if search_path is None:
search_path = self.lib_path
for lib_dir in search_path:
# Ignore static stuff.
path = os.path.join(lib_dir, dep)
if os.path.isfile(path):
source_path = os.path.normpath(path)
break
if not source_path:
# Couldn't find library in the panda3d lib dir.
#print("Ignoring %s" % (dep))
return
self.dep_paths[dep] = target_path
self.write_file(target_path, source_path)
return target_path
def write_file(self, target_path, source_path):
"""Adds the given file to the .whl file."""
# If this is a .so file, we should set the rpath appropriately.
temp = None
ext = os.path.splitext(source_path)[1]
if ext in ('.so', '.dylib') or '.so.' in os.path.basename(source_path) or \
(not ext and is_executable(source_path)):
# Scan and add Unix dependencies.
deps = scan_dependencies(source_path)
for dep in deps:
# Only include dependencies with relative path. Otherwise we
# end up overwriting system files like /lib/ld-linux.so.2!
# Yes, it happened to me.
if '/' not in dep:
target_dep = os.path.dirname(target_path) + '/' + dep
self.consider_add_dependency(target_dep, dep)
suffix = ''
if '.so' in os.path.basename(source_path):
suffix = '.so'
elif ext == '.dylib':
suffix = '.dylib'
temp = tempfile.NamedTemporaryFile(suffix=suffix, prefix='whl', delete=False)
# On macOS, if no fat wheel was requested, extract the right architecture.
if sys.platform == "darwin" and is_fat_file(source_path) and not self.platform.endswith("_intel"):
if self.platform.endswith("_x86_64"):
arch = 'x86_64'
else:
arch = self.platform.split('_')[-1]
subprocess.call(['lipo', source_path, '-extract', arch, '-output', temp.name])
else:
# Otherwise, just copy it over.
temp.write(open(source_path, 'rb').read())
temp.write(open(source_path, 'rb').read())
os.fchmod(temp.fileno(), os.fstat(temp.fileno()).st_mode | 0o111)
temp.close()
# Fix things like @loader_path/../lib references
if sys.platform == "darwin":
loader_path = [os.path.dirname(source_path)]
for dep in deps:
if '@loader_path' not in dep:
continue
dep_path = dep.replace('@loader_path', '.')
target_dep = os.path.dirname(target_path) + '/' + os.path.basename(dep)
target_dep = self.consider_add_dependency(target_dep, dep_path, loader_path)
if not target_dep:
# It won't be included, so no use adjusting the path.
continue
new_dep = os.path.join('@loader_path', os.path.relpath(target_dep, os.path.dirname(target_path)))
subprocess.call(["install_name_tool", "-change", dep, new_dep, temp.name])
else:
subprocess.call(["strip", "-s", temp.name])
subprocess.call(["patchelf", "--set-rpath", "$ORIGIN", temp.name])
source_path = temp.name
ext = ext.lower()
if ext in ('.dll', '.pyd', '.exe'):
# Scan and add Win32 dependencies.
for dep in scan_dependencies(source_path):
target_dep = os.path.dirname(target_path) + '/' + dep
self.consider_add_dependency(target_dep, dep)
# Calculate the SHA-256 hash and size.
sha = hashlib.sha256()
fp = open(source_path, 'rb')
size = 0
data = fp.read(1024 * 1024)
while data:
size += len(data)
sha.update(data)
data = fp.read(1024 * 1024)
fp.close()
# Save it in PEP-0376 format for writing out later.
digest = str(urlsafe_b64encode(sha.digest()))
digest = digest.rstrip('=')
self.records.append("{0},sha256={1},{2}\n".format(target_path, digest, size))
if GetVerbose():
print("Adding %s from %s" % (target_path, source_path))
self.zip_file.write(source_path, target_path)
#if temp:
# os.unlink(temp.name)
def write_file_data(self, target_path, source_data):
"""Adds the given file from a string."""
sha = hashlib.sha256()
sha.update(source_data.encode())
digest = str(urlsafe_b64encode(sha.digest()))
digest = digest.rstrip('=')
self.records.append("{0},sha256={1},{2}\n".format(target_path, digest, len(source_data)))
if GetVerbose():
print("Adding %s from data" % target_path)
self.zip_file.writestr(target_path, source_data)
def write_directory(self, target_dir, source_dir):
"""Adds the given directory recursively to the .whl file."""
for root, dirs, files in os.walk(source_dir):
for file in files:
if os.path.splitext(file)[1] in EXCLUDE_EXT:
continue
source_path = os.path.join(root, file)
target_path = os.path.join(target_dir, os.path.relpath(source_path, source_dir))
target_path = target_path.replace('\\', '/')
self.write_file(target_path, source_path)
def close(self):
# Write the RECORD file.
record_file = "{0}-{1}.dist-info/RECORD".format(self.name, self.version)
self.records.append(record_file + ",,\n")
self.zip_file.writestr(record_file, "".join(self.records))
self.zip_file.close()
def makewheel(version, output_dir, platform=default_platform):
if sys.platform not in ("win32", "darwin") and not sys.platform.startswith("cygwin"):
if not LocateBinary("patchelf"):
raise Exception("patchelf is required when building a Linux wheel.")
platform = platform.replace('-', '_').replace('.', '_')
# Global filepaths
panda3d_dir = join(output_dir, "panda3d")
pandac_dir = join(output_dir, "pandac")
direct_dir = join(output_dir, "direct")
models_dir = join(output_dir, "models")
etc_dir = join(output_dir, "etc")
bin_dir = join(output_dir, "bin")
if sys.platform == "win32":
libs_dir = join(output_dir, "bin")
else:
libs_dir = join(output_dir, "lib")
license_src = "LICENSE"
readme_src = "README.md"
# Update relevant METADATA entries
METADATA['version'] = version
version_classifiers = [
"Programming Language :: Python :: {0}".format(*sys.version_info),
"Programming Language :: Python :: {0}.{1}".format(*sys.version_info),
]
METADATA['classifiers'].extend(version_classifiers)
# Build out the metadata
details = METADATA["extensions"]["python.details"]
homepage = details["project_urls"]["Home"]
author = details["contacts"][0]["name"]
email = details["contacts"][0]["email"]
metadata = ''.join([
"Metadata-Version: {metadata_version}\n" \
"Name: {name}\n" \
"Version: {version}\n" \
"Summary: {summary}\n" \
"License: {license}\n".format(**METADATA),
"Home-page: {0}\n".format(homepage),
"Author: {0}\n".format(author),
"Author-email: {0}\n".format(email),
"Platform: {0}\n".format(platform),
] + ["Classifier: {0}\n".format(c) for c in METADATA['classifiers']])
# Zip it up and name it the right thing
whl = WheelFile('panda3d', version, platform)
whl.lib_path = [libs_dir]
# Add the trees with Python modules.
whl.write_directory('direct', direct_dir)
# Write the panda3d tree. We use a custom empty __init__ since the
# default one adds the bin directory to the PATH, which we don't have.
whl.write_file_data('panda3d/__init__.py', '')
ext_suffix = GetExtensionSuffix()
for file in os.listdir(panda3d_dir):
if file == '__init__.py':
pass
elif file.endswith(ext_suffix) or file.endswith('.py'):
source_path = os.path.join(panda3d_dir, file)
if file.endswith('.pyd') and platform.startswith('cygwin'):
# Rename it to .dll for cygwin Python to be able to load it.
target_path = 'panda3d/' + os.path.splitext(file)[0] + '.dll'
else:
target_path = 'panda3d/' + file
whl.write_file(target_path, source_path)
# Add plug-ins.
for lib in PLUGIN_LIBS:
plugin_name = 'lib' + lib
if sys.platform in ('win32', 'cygwin'):
plugin_name += '.dll'
elif sys.platform == 'darwin':
plugin_name += '.dylib'
else:
plugin_name += '.so'
plugin_path = os.path.join(libs_dir, plugin_name)
if os.path.isfile(plugin_path):
whl.write_file('panda3d/' + plugin_name, plugin_path)
# Add the .data directory, containing additional files.
data_dir = 'panda3d-{0}.data'.format(version)
#whl.write_directory(data_dir + '/data/etc', etc_dir)
#whl.write_directory(data_dir + '/data/models', models_dir)
# Actually, let's not. That seems to install the files to the strangest
# places in the user's filesystem. Let's instead put them in panda3d.
whl.write_directory('panda3d/etc', etc_dir)
whl.write_directory('panda3d/models', models_dir)
# Add the pandac tree for backward compatibility.
for file in os.listdir(pandac_dir):
if file.endswith('.py'):
whl.write_file('pandac/' + file, os.path.join(pandac_dir, file))
# Add a panda3d-tools directory containing the executables.
entry_points = '[console_scripts]\n'
entry_points += 'eggcacher = direct.directscripts.eggcacher:main\n'
entry_points += 'packpanda = direct.directscripts.packpanda:main\n'
tools_init = ''
for file in os.listdir(bin_dir):
basename = os.path.splitext(file)[0]
if basename in ('eggcacher', 'packpanda'):
continue
source_path = os.path.join(bin_dir, file)
if is_executable(source_path):
# Put the .exe files inside the panda3d-tools directory.
whl.write_file('panda3d_tools/' + file, source_path)
# Tell pip to create a wrapper script.
funcname = basename.replace('-', '_')
entry_points += '{0} = panda3d_tools:{1}\n'.format(basename, funcname)
tools_init += '{0} = lambda: _exec_tool({1!r})\n'.format(funcname, file)
whl.write_file_data('panda3d_tools/__init__.py', PANDA3D_TOOLS_INIT.format(tools_init))
# Add the dist-info directory last.
info_dir = 'panda3d-{0}.dist-info'.format(version)
whl.write_file_data(info_dir + '/entry_points.txt', entry_points)
whl.write_file_data(info_dir + '/metadata.json', json.dumps(METADATA, indent=4, separators=(',', ': ')))
whl.write_file_data(info_dir + '/METADATA', metadata)
whl.write_file_data(info_dir + '/WHEEL', WHEEL_DATA.format(PY_VERSION, ABI_TAG, platform))
whl.write_file(info_dir + '/LICENSE.txt', license_src)
whl.write_file(info_dir + '/README.md', readme_src)
whl.write_file_data(info_dir + '/top_level.txt', 'direct\npanda3d\npandac\npanda3d_tools\n')
whl.close()
if __name__ == "__main__":
version = ParsePandaVersion("dtool/PandaVersion.pp")
parser = OptionParser()
parser.add_option('', '--version', dest = 'version', help = 'Panda3D version number (default: %s)' % (version), default = version)
parser.add_option('', '--outputdir', dest = 'outputdir', help = 'Makepanda\'s output directory (default: built)', default = 'built')
parser.add_option('', '--verbose', dest = 'verbose', help = 'Enable verbose output', action = 'store_true', default = False)
parser.add_option('', '--platform', dest = 'platform', help = 'Override platform tag (default: %s)' % (default_platform), default = get_platform())
(options, args) = parser.parse_args()
SetVerbose(options.verbose)
makewheel(options.version, options.outputdir, options.platform)

8
panda/.gitignore vendored
View File

@ -1,8 +0,0 @@
*.pyc
*.pyo
# These are files that are generated within the source tree by the
# ppremake system.
Makefile
pp.dep
/built/
Opt?-*

View File

@ -23,7 +23,7 @@
#include "reMutex.h"
// OSX uses the OpenAL framework
#ifdef IS_OSX
#ifdef HAVE_OPENAL_FRAMEWORK
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#else

View File

@ -21,7 +21,7 @@
#include "openalAudioManager.h"
// OSX uses the OpenAL framework
#ifdef IS_OSX
#ifdef HAVE_OPENAL_FRAMEWORK
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#else

View File

@ -36,6 +36,34 @@ BulletBodyNode(const char *name) : PandaNode(name) {
set_into_collide_mask(CollideMask::all_on());
}
/**
*
*/
BulletBodyNode::
BulletBodyNode(const BulletBodyNode &copy) :
PandaNode(copy),
_shapes(copy._shapes)
{
if (copy._shape && copy._shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
// btCompoundShape does not define a copy constructor. Manually copy.
btCompoundShape *shape = new btCompoundShape;
_shape = shape;
btCompoundShape *copy_shape = (btCompoundShape *)copy._shape;
int num_children = copy_shape->getNumChildShapes();
for (int i = 0; i < num_children; ++i) {
shape->addChildShape(copy_shape->getChildTransform(i),
copy_shape->getChildShape(i));
}
}
else if (copy._shape && copy._shape->getShapeType() == EMPTY_SHAPE_PROXYTYPE) {
_shape = new btEmptyShape();
}
else {
_shape = copy._shape;
}
}
/**
* Returns the subset of CollideMask bits that may be set for this particular
* type of PandaNode. For BodyNodes this returns all bits on.

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