diff --git a/.travis.yml b/.travis.yml index e0bb8ccc85..6c6a399e23 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,11 @@ sudo: false matrix: include: - compiler: gcc - env: PYTHONV=python2.7 + env: PYTHONV=python2.7 FLAGS= - compiler: clang - env: PYTHONV=python3 + env: PYTHONV=python3 FLAGS=--installer + - compiler: clang + env: PYTHONV=python2.7 FLAGS=--override=STDFLOAT_DOUBLE=1 addons: apt: packages: @@ -26,7 +28,7 @@ addons: - python-dev - python3-dev - zlib1g-dev -script: $PYTHONV makepanda/makepanda.py --everything --git-commit $TRAVIS_COMMIT --installer --threads 4 && LD_LIBRARY_PATH=built/lib PYTHONPATH=built $PYTHONV makepanda/test_imports.py +script: $PYTHONV makepanda/makepanda.py --everything --git-commit $TRAVIS_COMMIT $FLAGS --threads 4 && LD_LIBRARY_PATH=built/lib PYTHONPATH=built $PYTHONV makepanda/test_imports.py notifications: irc: channels: diff --git a/README.md b/README.md index 061497dd6d..ceb23f7793 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ are included as part of the Windows 7.1 SDK. You will also need to have the third-party dependency libraries available for the build scripts to use. These are available from one of these two URLs, depending on whether you are on a 32-bit or 64-bit system: -https://www.panda3d.org/download/panda3d-1.9.1/panda3d-1.9.1-tools-win32.zip -https://www.panda3d.org/download/panda3d-1.9.1/panda3d-1.9.1-tools-win64.zip +https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-win32.zip +https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-win64.zip After acquiring these dependencies, you may simply build Panda3D from the command prompt using the following command: @@ -97,7 +97,7 @@ Mac OS X -------- On Mac OS X, you will need to download a set of precompiled thirdparty packages in order to -compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.9.1/panda3d-1.9.1-tools-mac.tar.gz). +compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-mac.tar.gz). After placing the thirdparty directory inside the panda3d source directory, you may build Panda3D using a command like the following: diff --git a/direct/src/dcparser/dcLexer.cxx.prebuilt b/direct/src/dcparser/dcLexer.cxx.prebuilt index c2f607f519..f99b920f81 100644 --- a/direct/src/dcparser/dcLexer.cxx.prebuilt +++ b/direct/src/dcparser/dcLexer.cxx.prebuilt @@ -1550,7 +1550,7 @@ YY_RULE_SETUP dcyylval.u.uint64 = 0; const char *p = dcyytext; while (*p != '\0') { - PN_uint64 next_value = dcyylval.u.uint64 * 10; + uint64_t next_value = dcyylval.u.uint64 * 10; if (next_value < dcyylval.u.uint64) { dcyyerror("Number out of range."); dcyylval.u.uint64 = 1; @@ -1583,9 +1583,9 @@ YY_RULE_SETUP ++p; } - PN_uint64 value = 0; + uint64_t value = 0; while (*p != '\0') { - PN_uint64 next_value = value * 10; + uint64_t next_value = value * 10; if (next_value < value) { dcyyerror("Number out of range."); dcyylval.u.int64 = 1; @@ -1597,13 +1597,13 @@ YY_RULE_SETUP } if (neg) { - dcyylval.u.int64 = -(PN_int64)value; + dcyylval.u.int64 = -(int64_t)value; if (dcyylval.u.int64 > 0) { dcyyerror("Number out of range."); dcyylval.u.int64 = 1; } } else { - dcyylval.u.int64 = (PN_int64)value; + dcyylval.u.int64 = (int64_t)value; if (dcyylval.u.int64 < 0) { dcyyerror("Number out of range."); dcyylval.u.int64 = 1; @@ -1625,7 +1625,7 @@ YY_RULE_SETUP dcyylval.u.uint64 = 0; const char *p = dcyytext + 2; while (*p != '\0') { - PN_uint64 next_value = dcyylval.u.uint64 * 16; + uint64_t next_value = dcyylval.u.uint64 * 16; if (next_value < dcyylval.u.uint64) { dcyyerror("Number out of range."); dcyylval.u.uint64 = 1; diff --git a/direct/src/dcparser/dcLexer.lxx b/direct/src/dcparser/dcLexer.lxx index e6ce9ec44d..4dbd18299d 100644 --- a/direct/src/dcparser/dcLexer.lxx +++ b/direct/src/dcparser/dcLexer.lxx @@ -612,7 +612,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?) dcyylval.u.uint64 = 0; const char *p = dcyytext; while (*p != '\0') { - PN_uint64 next_value = dcyylval.u.uint64 * 10; + uint64_t next_value = dcyylval.u.uint64 * 10; if (next_value < dcyylval.u.uint64) { dcyyerror("Number out of range."); dcyylval.u.uint64 = 1; @@ -642,9 +642,9 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?) ++p; } - PN_uint64 value = 0; + uint64_t value = 0; while (*p != '\0') { - PN_uint64 next_value = value * 10; + uint64_t next_value = value * 10; if (next_value < value) { dcyyerror("Number out of range."); dcyylval.u.int64 = 1; @@ -656,13 +656,13 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?) } if (neg) { - dcyylval.u.int64 = -(PN_int64)value; + dcyylval.u.int64 = -(int64_t)value; if (dcyylval.u.int64 > 0) { dcyyerror("Number out of range."); dcyylval.u.int64 = 1; } } else { - dcyylval.u.int64 = (PN_int64)value; + dcyylval.u.int64 = (int64_t)value; if (dcyylval.u.int64 < 0) { dcyyerror("Number out of range."); dcyylval.u.int64 = 1; @@ -681,7 +681,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?) dcyylval.u.uint64 = 0; const char *p = dcyytext + 2; while (*p != '\0') { - PN_uint64 next_value = dcyylval.u.uint64 * 16; + uint64_t next_value = dcyylval.u.uint64 * 16; if (next_value < dcyylval.u.uint64) { dcyyerror("Number out of range."); dcyylval.u.uint64 = 1; diff --git a/direct/src/dcparser/dcNumericRange.h b/direct/src/dcparser/dcNumericRange.h index f872f39a7a..6539c05422 100644 --- a/direct/src/dcparser/dcNumericRange.h +++ b/direct/src/dcparser/dcNumericRange.h @@ -71,8 +71,8 @@ private: typedef DCNumericRange DCIntRange; typedef DCNumericRange DCUnsignedIntRange; -typedef DCNumericRange DCInt64Range; -typedef DCNumericRange DCUnsignedInt64Range; +typedef DCNumericRange DCInt64Range; +typedef DCNumericRange DCUnsignedInt64Range; typedef DCNumericRange DCDoubleRange; #endif diff --git a/direct/src/dcparser/dcPacker.I b/direct/src/dcparser/dcPacker.I index bb9a10daf9..c159b0cb77 100644 --- a/direct/src/dcparser/dcPacker.I +++ b/direct/src/dcparser/dcPacker.I @@ -178,7 +178,7 @@ pack_uint(unsigned int value) { * Packs the indicated numeric or string value into the stream. */ INLINE void DCPacker:: -pack_int64(PN_int64 value) { +pack_int64(int64_t value) { nassertv(_mode == M_pack || _mode == M_repack); if (_current_field == NULL) { _pack_error = true; @@ -192,7 +192,7 @@ pack_int64(PN_int64 value) { * Packs the indicated numeric or string value into the stream. */ INLINE void DCPacker:: -pack_uint64(PN_uint64 value) { +pack_uint64(uint64_t value) { nassertv(_mode == M_pack || _mode == M_repack); if (_current_field == NULL) { _pack_error = true; @@ -291,9 +291,9 @@ unpack_uint() { /** * Unpacks the current numeric or string value from the stream. */ -INLINE PN_int64 DCPacker:: +INLINE int64_t DCPacker:: unpack_int64() { - PN_int64 value = 0; + int64_t value = 0; nassertr(_mode == M_unpack, value); if (_current_field == NULL) { _pack_error = true; @@ -310,9 +310,9 @@ unpack_int64() { /** * Unpacks the current numeric or string value from the stream. */ -INLINE PN_uint64 DCPacker:: +INLINE uint64_t DCPacker:: unpack_uint64() { - PN_uint64 value = 0; + uint64_t value = 0; nassertr(_mode == M_unpack, value); if (_current_field == NULL) { _pack_error = true; @@ -409,7 +409,7 @@ unpack_uint(unsigned int &value) { * Unpacks the current numeric or string value from the stream. */ INLINE void DCPacker:: -unpack_int64(PN_int64 &value) { +unpack_int64(int64_t &value) { nassertv(_mode == M_unpack); if (_current_field == NULL) { _pack_error = true; @@ -425,7 +425,7 @@ unpack_int64(PN_int64 &value) { * Unpacks the current numeric or string value from the stream. */ INLINE void DCPacker:: -unpack_uint64(PN_uint64 &value) { +unpack_uint64(uint64_t &value) { nassertv(_mode == M_unpack); if (_current_field == NULL) { _pack_error = true; @@ -668,7 +668,7 @@ raw_pack_int32(int value) { * Packs the data into the buffer between packing sessions. */ INLINE void DCPacker:: -raw_pack_int64(PN_int64 value) { +raw_pack_int64(int64_t value) { nassertv(_mode == M_idle); DCPackerInterface::do_pack_int64(_pack_data.get_write_pointer(8), value); } @@ -704,7 +704,7 @@ raw_pack_uint32(unsigned int value) { * Packs the data into the buffer between packing sessions. */ INLINE void DCPacker:: -raw_pack_uint64(PN_uint64 value) { +raw_pack_uint64(uint64_t value) { nassertv(_mode == M_idle); DCPackerInterface::do_pack_uint64(_pack_data.get_write_pointer(8), value); } @@ -761,9 +761,9 @@ raw_unpack_int32() { /** * Unpacks the data from the buffer between unpacking sessions. */ -INLINE PN_int64 DCPacker:: +INLINE int64_t DCPacker:: raw_unpack_int64() { - PN_int64 value = 0; + int64_t value = 0; raw_unpack_int64(value); return value; } @@ -843,9 +843,9 @@ raw_unpack_uint32() { /** * Unpacks the data from the buffer between unpacking sessions. */ -INLINE PN_uint64 DCPacker:: +INLINE uint64_t DCPacker:: raw_unpack_uint64() { - PN_uint64 value = 0; + uint64_t value = 0; raw_unpack_uint64(value); return value; } @@ -874,7 +874,7 @@ raw_unpack_string() { * Unpacks the data from the buffer between unpacking sessions. */ INLINE void DCPacker:: -raw_unpack_int64(PN_int64 &value) { +raw_unpack_int64(int64_t &value) { nassertv(_mode == M_idle && _unpack_data != NULL); if (_unpack_p + 8 > _unpack_length) { _pack_error = true; @@ -930,7 +930,7 @@ raw_unpack_uint32(unsigned int &value) { * Unpacks the data from the buffer between unpacking sessions. */ INLINE void DCPacker:: -raw_unpack_uint64(PN_uint64 &value) { +raw_unpack_uint64(uint64_t &value) { nassertv(_mode == M_idle && _unpack_data != NULL); if (_unpack_p + 8 > _unpack_length) { _pack_error = true; diff --git a/direct/src/dcparser/dcPacker.cxx b/direct/src/dcparser/dcPacker.cxx index 6b789c945c..fe3461a6c1 100644 --- a/direct/src/dcparser/dcPacker.cxx +++ b/direct/src/dcparser/dcPacker.cxx @@ -858,14 +858,14 @@ unpack_object() { case PT_int64: { - PN_int64 value = unpack_int64(); + int64_t value = unpack_int64(); object = PyLong_FromLongLong(value); } break; case PT_uint64: { - PN_uint64 value = unpack_uint64(); + uint64_t value = unpack_uint64(); object = PyLong_FromUnsignedLongLong(value); } break; diff --git a/direct/src/dcparser/dcPacker.h b/direct/src/dcparser/dcPacker.h index df391a8e48..049429e0ec 100644 --- a/direct/src/dcparser/dcPacker.h +++ b/direct/src/dcparser/dcPacker.h @@ -72,8 +72,8 @@ PUBLISHED: INLINE void pack_double(double value); INLINE void pack_int(int value); INLINE void pack_uint(unsigned int value); - INLINE void pack_int64(PN_int64 value); - INLINE void pack_uint64(PN_uint64 value); + INLINE void pack_int64(int64_t value); + INLINE void pack_uint64(uint64_t value); INLINE void pack_string(const string &value); INLINE void pack_literal_value(const string &value); void pack_default_value(); @@ -81,8 +81,8 @@ PUBLISHED: INLINE double unpack_double(); INLINE int unpack_int(); INLINE unsigned int unpack_uint(); - INLINE PN_int64 unpack_int64(); - INLINE PN_uint64 unpack_uint64(); + INLINE int64_t unpack_int64(); + INLINE uint64_t unpack_uint64(); INLINE string unpack_string(); INLINE string unpack_literal_value(); void unpack_validate(); @@ -94,8 +94,8 @@ public: INLINE void unpack_double(double &value); INLINE void unpack_int(int &value); INLINE void unpack_uint(unsigned int &value); - INLINE void unpack_int64(PN_int64 &value); - INLINE void unpack_uint64(PN_uint64 &value); + INLINE void unpack_int64(int64_t &value); + INLINE void unpack_uint64(uint64_t &value); INLINE void unpack_string(string &value); INLINE void unpack_literal_value(string &value); @@ -141,11 +141,11 @@ PUBLISHED: INLINE void raw_pack_int8(int value); INLINE void raw_pack_int16(int value); INLINE void raw_pack_int32(int value); - INLINE void raw_pack_int64(PN_int64 value); + INLINE void raw_pack_int64(int64_t value); INLINE void raw_pack_uint8(unsigned int value); INLINE void raw_pack_uint16(unsigned int value); INLINE void raw_pack_uint32(unsigned int value); - INLINE void raw_pack_uint64(PN_uint64 value); + INLINE void raw_pack_uint64(uint64_t value); INLINE void raw_pack_float64(double value); INLINE void raw_pack_string(const string &value); @@ -158,11 +158,11 @@ PUBLISHED: INLINE int raw_unpack_int8(); INLINE int raw_unpack_int16(); INLINE int raw_unpack_int32(); - INLINE PN_int64 raw_unpack_int64(); + INLINE int64_t raw_unpack_int64(); INLINE unsigned int raw_unpack_uint8(); INLINE unsigned int raw_unpack_uint16(); INLINE unsigned int raw_unpack_uint32(); - INLINE PN_uint64 raw_unpack_uint64(); + INLINE uint64_t raw_unpack_uint64(); INLINE double raw_unpack_float64(); INLINE string raw_unpack_string(); @@ -170,11 +170,11 @@ public: INLINE void raw_unpack_int8(int &value); INLINE void raw_unpack_int16(int &value); INLINE void raw_unpack_int32(int &value); - INLINE void raw_unpack_int64(PN_int64 &value); + INLINE void raw_unpack_int64(int64_t &value); INLINE void raw_unpack_uint8(unsigned int &value); INLINE void raw_unpack_uint16(unsigned int &value); INLINE void raw_unpack_uint32(unsigned int &value); - INLINE void raw_unpack_uint64(PN_uint64 &value); + INLINE void raw_unpack_uint64(uint64_t &value); INLINE void raw_unpack_float64(double &value); INLINE void raw_unpack_string(string &value); diff --git a/direct/src/dcparser/dcPackerInterface.I b/direct/src/dcparser/dcPackerInterface.I index e9ab9f2fb8..a97964bc47 100644 --- a/direct/src/dcparser/dcPackerInterface.I +++ b/direct/src/dcparser/dcPackerInterface.I @@ -142,7 +142,7 @@ do_pack_int32(char *buffer, int value) { * */ INLINE void DCPackerInterface:: -do_pack_int64(char *buffer, PN_int64 value) { +do_pack_int64(char *buffer, int64_t value) { buffer[0] = (char)(value & 0xff); buffer[1] = (char)((value >> 8) & 0xff); buffer[2] = (char)((value >> 16) & 0xff); @@ -185,7 +185,7 @@ do_pack_uint32(char *buffer, unsigned int value) { * */ INLINE void DCPackerInterface:: -do_pack_uint64(char *buffer, PN_uint64 value) { +do_pack_uint64(char *buffer, uint64_t value) { buffer[0] = (char)(value & 0xff); buffer[1] = (char)((value >> 8) & 0xff); buffer[2] = (char)((value >> 16) & 0xff); @@ -244,16 +244,16 @@ do_unpack_int32(const char *buffer) { /** * */ -INLINE PN_int64 DCPackerInterface:: +INLINE int64_t DCPackerInterface:: do_unpack_int64(const char *buffer) { - return (PN_int64)((PN_uint64)(unsigned char)buffer[0] | - ((PN_uint64)(unsigned char)buffer[1] << 8) | - ((PN_uint64)(unsigned char)buffer[2] << 16) | - ((PN_uint64)(unsigned char)buffer[3] << 24) | - ((PN_uint64)(unsigned char)buffer[4] << 32) | - ((PN_uint64)(unsigned char)buffer[5] << 40) | - ((PN_uint64)(unsigned char)buffer[6] << 48) | - ((PN_int64)(signed char)buffer[7] << 54)); + return (int64_t)((uint64_t)(unsigned char)buffer[0] | + ((uint64_t)(unsigned char)buffer[1] << 8) | + ((uint64_t)(unsigned char)buffer[2] << 16) | + ((uint64_t)(unsigned char)buffer[3] << 24) | + ((uint64_t)(unsigned char)buffer[4] << 32) | + ((uint64_t)(unsigned char)buffer[5] << 40) | + ((uint64_t)(unsigned char)buffer[6] << 48) | + ((int64_t)(signed char)buffer[7] << 54)); } /** * @@ -286,16 +286,16 @@ do_unpack_uint32(const char *buffer) { /** * */ -INLINE PN_uint64 DCPackerInterface:: +INLINE uint64_t DCPackerInterface:: do_unpack_uint64(const char *buffer) { - return ((PN_uint64)(unsigned char)buffer[0] | - ((PN_uint64)(unsigned char)buffer[1] << 8) | - ((PN_uint64)(unsigned char)buffer[2] << 16) | - ((PN_uint64)(unsigned char)buffer[3] << 24) | - ((PN_uint64)(unsigned char)buffer[4] << 32) | - ((PN_uint64)(unsigned char)buffer[5] << 40) | - ((PN_uint64)(unsigned char)buffer[6] << 48) | - ((PN_int64)(signed char)buffer[7] << 54)); + return ((uint64_t)(unsigned char)buffer[0] | + ((uint64_t)(unsigned char)buffer[1] << 8) | + ((uint64_t)(unsigned char)buffer[2] << 16) | + ((uint64_t)(unsigned char)buffer[3] << 24) | + ((uint64_t)(unsigned char)buffer[4] << 32) | + ((uint64_t)(unsigned char)buffer[5] << 40) | + ((uint64_t)(unsigned char)buffer[6] << 48) | + ((int64_t)(signed char)buffer[7] << 54)); } @@ -342,8 +342,8 @@ validate_int_limits(int value, int num_bits, bool &range_error) { * true if it does not. */ INLINE void DCPackerInterface:: -validate_int64_limits(PN_int64 value, int num_bits, bool &range_error) { - PN_int64 mask = ((PN_int64)1 << (num_bits - 1)) - 1; +validate_int64_limits(int64_t value, int num_bits, bool &range_error) { + int64_t mask = ((int64_t)1 << (num_bits - 1)) - 1; value |= mask; if (value != mask && value != -1) { @@ -373,8 +373,8 @@ validate_uint_limits(unsigned int value, int num_bits, bool &range_error) { * range_error true if it does not. */ INLINE void DCPackerInterface:: -validate_uint64_limits(PN_uint64 value, int num_bits, bool &range_error) { - PN_uint64 mask = ((PN_uint64)1 << num_bits) - 1; +validate_uint64_limits(uint64_t value, int num_bits, bool &range_error) { + uint64_t mask = ((uint64_t)1 << num_bits) - 1; value &= ~mask; if (value != 0) { diff --git a/direct/src/dcparser/dcPackerInterface.cxx b/direct/src/dcparser/dcPackerInterface.cxx index 796d11039a..dc731a479a 100644 --- a/direct/src/dcparser/dcPackerInterface.cxx +++ b/direct/src/dcparser/dcPackerInterface.cxx @@ -226,7 +226,7 @@ pack_uint(DCPackData &, unsigned int, bool &pack_error, bool &) const { * Packs the indicated numeric or string value into the stream. */ void DCPackerInterface:: -pack_int64(DCPackData &, PN_int64, bool &pack_error, bool &) const { +pack_int64(DCPackData &, int64_t, bool &pack_error, bool &) const { pack_error = true; } @@ -234,7 +234,7 @@ pack_int64(DCPackData &, PN_int64, bool &pack_error, bool &) const { * Packs the indicated numeric or string value into the stream. */ void DCPackerInterface:: -pack_uint64(DCPackData &, PN_uint64, bool &pack_error, bool &) const { +pack_uint64(DCPackData &, uint64_t, bool &pack_error, bool &) const { pack_error = true; } @@ -284,7 +284,7 @@ unpack_uint(const char *, size_t, size_t &, unsigned int &, bool &pack_error, bo * Unpacks the current numeric or string value from the stream. */ void DCPackerInterface:: -unpack_int64(const char *, size_t, size_t &, PN_int64 &, bool &pack_error, bool &) const { +unpack_int64(const char *, size_t, size_t &, int64_t &, bool &pack_error, bool &) const { pack_error = true; } @@ -292,7 +292,7 @@ unpack_int64(const char *, size_t, size_t &, PN_int64 &, bool &pack_error, bool * Unpacks the current numeric or string value from the stream. */ void DCPackerInterface:: -unpack_uint64(const char *, size_t, size_t &, PN_uint64 &, bool &pack_error, bool &) const { +unpack_uint64(const char *, size_t, size_t &, uint64_t &, bool &pack_error, bool &) const { pack_error = true; } diff --git a/direct/src/dcparser/dcPackerInterface.h b/direct/src/dcparser/dcPackerInterface.h index 788feb3fe7..eca03d3257 100644 --- a/direct/src/dcparser/dcPackerInterface.h +++ b/direct/src/dcparser/dcPackerInterface.h @@ -107,9 +107,9 @@ public: bool &pack_error, bool &range_error) const; virtual void pack_uint(DCPackData &pack_data, unsigned int value, bool &pack_error, bool &range_error) const; - virtual void pack_int64(DCPackData &pack_data, PN_int64 value, + virtual void pack_int64(DCPackData &pack_data, int64_t value, bool &pack_error, bool &range_error) const; - virtual void pack_uint64(DCPackData &pack_data, PN_uint64 value, + virtual void pack_uint64(DCPackData &pack_data, uint64_t value, bool &pack_error, bool &range_error) const; virtual void pack_string(DCPackData &pack_data, const string &value, bool &pack_error, bool &range_error) const; @@ -122,9 +122,9 @@ public: virtual void unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value, bool &pack_error, bool &range_error) const; virtual void unpack_int64(const char *data, size_t length, size_t &p, - PN_int64 &value, bool &pack_error, bool &range_error) const; + int64_t &value, bool &pack_error, bool &range_error) const; virtual void unpack_uint64(const char *data, size_t length, size_t &p, - PN_uint64 &value, bool &pack_error, bool &range_error) const; + uint64_t &value, bool &pack_error, bool &range_error) const; virtual void unpack_string(const char *data, size_t length, size_t &p, string &value, bool &pack_error, bool &range_error) const; virtual bool unpack_validate(const char *data, size_t length, size_t &p, @@ -138,30 +138,30 @@ public: INLINE static void do_pack_int8(char *buffer, int value); INLINE static void do_pack_int16(char *buffer, int value); INLINE static void do_pack_int32(char *buffer, int value); - INLINE static void do_pack_int64(char *buffer, PN_int64 value); + INLINE static void do_pack_int64(char *buffer, int64_t value); INLINE static void do_pack_uint8(char *buffer, unsigned int value); INLINE static void do_pack_uint16(char *buffer, unsigned int value); INLINE static void do_pack_uint32(char *buffer, unsigned int value); - INLINE static void do_pack_uint64(char *buffer, PN_uint64 value); + INLINE static void do_pack_uint64(char *buffer, uint64_t value); INLINE static void do_pack_float64(char *buffer, double value); INLINE static int do_unpack_int8(const char *buffer); INLINE static int do_unpack_int16(const char *buffer); INLINE static int do_unpack_int32(const char *buffer); - INLINE static PN_int64 do_unpack_int64(const char *buffer); + INLINE static int64_t do_unpack_int64(const char *buffer); INLINE static unsigned int do_unpack_uint8(const char *buffer); INLINE static unsigned int do_unpack_uint16(const char *buffer); INLINE static unsigned int do_unpack_uint32(const char *buffer); - INLINE static PN_uint64 do_unpack_uint64(const char *buffer); + INLINE static uint64_t do_unpack_uint64(const char *buffer); INLINE static double do_unpack_float64(const char *buffer); INLINE static void validate_int_limits(int value, int num_bits, bool &range_error); - INLINE static void validate_int64_limits(PN_int64 value, int num_bits, + INLINE static void validate_int64_limits(int64_t value, int num_bits, bool &range_error); INLINE static void validate_uint_limits(unsigned int value, int num_bits, bool &range_error); - INLINE static void validate_uint64_limits(PN_uint64 value, int num_bits, + INLINE static void validate_uint64_limits(uint64_t value, int num_bits, bool &range_error); const DCPackerCatalog *get_catalog() const; diff --git a/direct/src/dcparser/dcParserDefs.h b/direct/src/dcparser/dcParserDefs.h index 4b50553bcf..fec0ab95a5 100644 --- a/direct/src/dcparser/dcParserDefs.h +++ b/direct/src/dcparser/dcParserDefs.h @@ -48,8 +48,8 @@ public: union U { int s_int; unsigned int s_uint; - PN_int64 int64; - PN_uint64 uint64; + int64_t int64; + uint64_t uint64; double real; bool flag; DCClass *dclass; diff --git a/direct/src/dcparser/dcSimpleParameter.cxx b/direct/src/dcparser/dcSimpleParameter.cxx index 54f6ab0007..ceead33a5c 100644 --- a/direct/src/dcparser/dcSimpleParameter.cxx +++ b/direct/src/dcparser/dcSimpleParameter.cxx @@ -313,7 +313,7 @@ set_modulus(double modulus) { bool range_error = false; _double_modulus = modulus * _divisor; - _uint64_modulus = (PN_uint64)floor(_double_modulus + 0.5); + _uint64_modulus = (uint64_t)floor(_double_modulus + 0.5); _uint_modulus = (unsigned int)_uint64_modulus; // Check the range. The legitimate range for a modulus value is 1 through @@ -413,8 +413,8 @@ set_range(const DCDoubleRange &range) { case ST_int8array: _int_range.clear(); for (i = 0; i < num_ranges; i++) { - PN_int64 min = (PN_int64)floor(range.get_min(i) * _divisor + 0.5); - PN_int64 max = (PN_int64)floor(range.get_max(i) * _divisor + 0.5); + int64_t min = (int64_t)floor(range.get_min(i) * _divisor + 0.5); + int64_t max = (int64_t)floor(range.get_max(i) * _divisor + 0.5); validate_int64_limits(min, 8, range_error); validate_int64_limits(max, 8, range_error); _int_range.add_range((int)min, (int)max); @@ -425,8 +425,8 @@ set_range(const DCDoubleRange &range) { case ST_int16array: _int_range.clear(); for (i = 0; i < num_ranges; i++) { - PN_int64 min = (PN_int64)floor(range.get_min(i) * _divisor + 0.5); - PN_int64 max = (PN_int64)floor(range.get_max(i) * _divisor + 0.5); + int64_t min = (int64_t)floor(range.get_min(i) * _divisor + 0.5); + int64_t max = (int64_t)floor(range.get_max(i) * _divisor + 0.5); validate_int64_limits(min, 16, range_error); validate_int64_limits(max, 16, range_error); _int_range.add_range((int)min, (int)max); @@ -437,8 +437,8 @@ set_range(const DCDoubleRange &range) { case ST_int32array: _int_range.clear(); for (i = 0; i < num_ranges; i++) { - PN_int64 min = (PN_int64)floor(range.get_min(i) * _divisor + 0.5); - PN_int64 max = (PN_int64)floor(range.get_max(i) * _divisor + 0.5); + int64_t min = (int64_t)floor(range.get_min(i) * _divisor + 0.5); + int64_t max = (int64_t)floor(range.get_max(i) * _divisor + 0.5); validate_int64_limits(min, 32, range_error); validate_int64_limits(max, 32, range_error); _int_range.add_range((int)min, (int)max); @@ -448,8 +448,8 @@ set_range(const DCDoubleRange &range) { case ST_int64: _int64_range.clear(); for (i = 0; i < num_ranges; i++) { - PN_int64 min = (PN_int64)floor(range.get_min(i) * _divisor + 0.5); - PN_int64 max = (PN_int64)floor(range.get_max(i) * _divisor + 0.5); + int64_t min = (int64_t)floor(range.get_min(i) * _divisor + 0.5); + int64_t max = (int64_t)floor(range.get_max(i) * _divisor + 0.5); _int64_range.add_range(min, max); } break; @@ -459,8 +459,8 @@ set_range(const DCDoubleRange &range) { case ST_uint8array: _uint_range.clear(); for (i = 0; i < num_ranges; i++) { - PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5); - PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5); + uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5); + uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5); validate_uint64_limits(min, 8, range_error); validate_uint64_limits(max, 8, range_error); _uint_range.add_range((unsigned int)min, (unsigned int)max); @@ -471,8 +471,8 @@ set_range(const DCDoubleRange &range) { case ST_uint16array: _uint_range.clear(); for (i = 0; i < num_ranges; i++) { - PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5); - PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5); + uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5); + uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5); validate_uint64_limits(min, 16, range_error); validate_uint64_limits(max, 16, range_error); _uint_range.add_range((unsigned int)min, (unsigned int)max); @@ -483,8 +483,8 @@ set_range(const DCDoubleRange &range) { case ST_uint32array: _uint_range.clear(); for (i = 0; i < num_ranges; i++) { - PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5); - PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5); + uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5); + uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5); validate_uint64_limits(min, 32, range_error); validate_uint64_limits(max, 32, range_error); _uint_range.add_range((unsigned int)min, (unsigned int)max); @@ -494,8 +494,8 @@ set_range(const DCDoubleRange &range) { case ST_uint64: _uint64_range.clear(); for (i = 0; i < num_ranges; i++) { - PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5); - PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5); + uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5); + uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5); _uint64_range.add_range(min, max); } break; @@ -513,8 +513,8 @@ set_range(const DCDoubleRange &range) { case ST_blob: _uint_range.clear(); for (i = 0; i < num_ranges; i++) { - PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5); - PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5); + uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5); + uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5); validate_uint64_limits(min, 16, range_error); validate_uint64_limits(max, 16, range_error); _uint_range.add_range((unsigned int)min, (unsigned int)max); @@ -536,8 +536,8 @@ set_range(const DCDoubleRange &range) { case ST_blob32: _uint_range.clear(); for (i = 0; i < num_ranges; i++) { - PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5); - PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5); + uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5); + uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5); validate_uint64_limits(min, 32, range_error); validate_uint64_limits(max, 32, range_error); _uint_range.add_range((unsigned int)min, (unsigned int)max); @@ -634,7 +634,7 @@ pack_double(DCPackData &pack_data, double value, case ST_int64: { - PN_int64 int64_value = (PN_int64)floor(real_value + 0.5); + int64_t int64_value = (int64_t)floor(real_value + 0.5); _int64_range.validate(int64_value, range_error); do_pack_int64(pack_data.get_write_pointer(8), int64_value); } @@ -669,7 +669,7 @@ pack_double(DCPackData &pack_data, double value, case ST_uint64: { - PN_uint64 int64_value = (PN_uint64)floor(real_value + 0.5); + uint64_t int64_value = (uint64_t)floor(real_value + 0.5); _uint64_range.validate(int64_value, range_error); do_pack_uint64(pack_data.get_write_pointer(8), int64_value); } @@ -696,7 +696,7 @@ pack_int(DCPackData &pack_data, int value, if (value != 0 && (int_value / value) != (int)_divisor) { // If we've experienced overflow after applying the divisor, pack it as an // int64 instead. - pack_int64(pack_data, (PN_int64)value, pack_error, range_error); + pack_int64(pack_data, (int64_t)value, pack_error, range_error); return; } @@ -859,9 +859,9 @@ pack_uint(DCPackData &pack_data, unsigned int value, * Packs the indicated numeric or string value into the stream. */ void DCSimpleParameter:: -pack_int64(DCPackData &pack_data, PN_int64 value, +pack_int64(DCPackData &pack_data, int64_t value, bool &pack_error, bool &range_error) const { - PN_int64 int_value = value * _divisor; + int64_t int_value = value * _divisor; if (_has_modulus && _uint64_modulus != 0) { if (int_value < 0) { int_value = _uint64_modulus - 1 - (-int_value - 1) % _uint64_modulus; @@ -899,35 +899,35 @@ pack_int64(DCPackData &pack_data, PN_int64 value, if (int_value < 0) { range_error = true; } - _uint_range.validate((unsigned int)(PN_uint64)int_value, range_error); - validate_uint64_limits((PN_uint64)int_value, 8, range_error); - do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)(PN_uint64)int_value); + _uint_range.validate((unsigned int)(uint64_t)int_value, range_error); + validate_uint64_limits((uint64_t)int_value, 8, range_error); + do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)(uint64_t)int_value); break; case ST_uint16: if (int_value < 0) { range_error = true; } - _uint_range.validate((unsigned int)(PN_uint64)int_value, range_error); - validate_uint64_limits((PN_uint64)int_value, 16, range_error); - do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)(PN_uint64)int_value); + _uint_range.validate((unsigned int)(uint64_t)int_value, range_error); + validate_uint64_limits((uint64_t)int_value, 16, range_error); + do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)(uint64_t)int_value); break; case ST_uint32: if (int_value < 0) { range_error = true; } - _uint_range.validate((unsigned int)(PN_uint64)int_value, range_error); - validate_uint64_limits((PN_uint64)int_value, 32, range_error); - do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)(PN_uint64)int_value); + _uint_range.validate((unsigned int)(uint64_t)int_value, range_error); + validate_uint64_limits((uint64_t)int_value, 32, range_error); + do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)(uint64_t)int_value); break; case ST_uint64: if (int_value < 0) { range_error = true; } - _uint64_range.validate((PN_uint64)int_value, range_error); - do_pack_uint64(pack_data.get_write_pointer(8), (PN_uint64)int_value); + _uint64_range.validate((uint64_t)int_value, range_error); + do_pack_uint64(pack_data.get_write_pointer(8), (uint64_t)int_value); break; case ST_float64: @@ -944,47 +944,47 @@ pack_int64(DCPackData &pack_data, PN_int64 value, * Packs the indicated numeric or string value into the stream. */ void DCSimpleParameter:: -pack_uint64(DCPackData &pack_data, PN_uint64 value, +pack_uint64(DCPackData &pack_data, uint64_t value, bool &pack_error, bool &range_error) const { - PN_uint64 int_value = value * _divisor; + uint64_t int_value = value * _divisor; if (_has_modulus && _uint64_modulus != 0) { int_value = int_value % _uint64_modulus; } switch (_type) { case ST_int8: - if ((PN_int64)int_value < 0) { + if ((int64_t)int_value < 0) { range_error = true; } - _int_range.validate((int)(PN_int64)int_value, range_error); - validate_int64_limits((PN_int64)int_value, 8, range_error); - do_pack_int8(pack_data.get_write_pointer(1), (int)(PN_int64)int_value); + _int_range.validate((int)(int64_t)int_value, range_error); + validate_int64_limits((int64_t)int_value, 8, range_error); + do_pack_int8(pack_data.get_write_pointer(1), (int)(int64_t)int_value); break; case ST_int16: - if ((PN_int64)int_value < 0) { + if ((int64_t)int_value < 0) { range_error = true; } - _int_range.validate((int)(PN_int64)int_value, range_error); - validate_int64_limits((PN_int64)int_value, 16, range_error); - do_pack_int16(pack_data.get_write_pointer(2), (int)(PN_int64)int_value); + _int_range.validate((int)(int64_t)int_value, range_error); + validate_int64_limits((int64_t)int_value, 16, range_error); + do_pack_int16(pack_data.get_write_pointer(2), (int)(int64_t)int_value); break; case ST_int32: - if ((PN_int64)int_value < 0) { + if ((int64_t)int_value < 0) { range_error = true; } - _int_range.validate((int)(PN_int64)int_value, range_error); - validate_int64_limits((PN_int64)int_value, 32, range_error); - do_pack_int32(pack_data.get_write_pointer(4), (int)(PN_int64)int_value); + _int_range.validate((int)(int64_t)int_value, range_error); + validate_int64_limits((int64_t)int_value, 32, range_error); + do_pack_int32(pack_data.get_write_pointer(4), (int)(int64_t)int_value); break; case ST_int64: - if ((PN_int64)int_value < 0) { + if ((int64_t)int_value < 0) { range_error = true; } - _int64_range.validate((PN_int64)int_value, range_error); - do_pack_int64(pack_data.get_write_pointer(8), (PN_int64)int_value); + _int64_range.validate((int64_t)int_value, range_error); + do_pack_int64(pack_data.get_write_pointer(8), (int64_t)int_value); break; case ST_char: @@ -1213,7 +1213,7 @@ unpack_double(const char *data, size_t length, size_t &p, double &value, pack_error = true; return; } - PN_int64 int_value = do_unpack_int64(data + p); + int64_t int_value = do_unpack_int64(data + p); _int64_range.validate(int_value, range_error); value = (double)int_value; p += 8; @@ -1266,7 +1266,7 @@ unpack_double(const char *data, size_t length, size_t &p, double &value, pack_error = true; return; } - PN_uint64 uint_value = do_unpack_uint64(data + p); + uint64_t uint_value = do_unpack_uint64(data + p); _uint64_range.validate(uint_value, range_error); value = (double)uint_value; p += 8; @@ -1340,7 +1340,7 @@ unpack_int(const char *data, size_t length, size_t &p, int &value, pack_error = true; return; } - PN_int64 int_value = do_unpack_uint64(data + p); + int64_t int_value = do_unpack_uint64(data + p); _int64_range.validate(int_value, range_error); value = (int)int_value; if (value != int_value) { @@ -1400,7 +1400,7 @@ unpack_int(const char *data, size_t length, size_t &p, int &value, pack_error = true; return; } - PN_uint64 uint_value = do_unpack_uint64(data + p); + uint64_t uint_value = do_unpack_uint64(data + p); _uint64_range.validate(uint_value, range_error); value = (int)(unsigned int)uint_value; if ((unsigned int)value != uint_value || value < 0) { @@ -1496,7 +1496,7 @@ unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value, pack_error = true; return; } - PN_int64 int_value = do_unpack_int64(data + p); + int64_t int_value = do_unpack_int64(data + p); _int64_range.validate(int_value, range_error); if (int_value < 0) { pack_error = true; @@ -1546,7 +1546,7 @@ unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value, pack_error = true; return; } - PN_uint64 uint_value = do_unpack_uint64(data + p); + uint64_t uint_value = do_unpack_uint64(data + p); _uint64_range.validate(uint_value, range_error); value = (unsigned int)uint_value; if (value != uint_value) { @@ -1585,7 +1585,7 @@ unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value, * Unpacks the current numeric or string value from the stream. */ void DCSimpleParameter:: -unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value, +unpack_int64(const char *data, size_t length, size_t &p, int64_t &value, bool &pack_error, bool &range_error) const { switch (_type) { case ST_int8: @@ -1596,7 +1596,7 @@ unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value, } int int_value = do_unpack_int8(data + p); _int_range.validate(int_value, range_error); - value = (PN_int64)int_value; + value = (int64_t)int_value; p++; } break; @@ -1609,7 +1609,7 @@ unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value, } int int_value = do_unpack_int16(data + p); _int_range.validate(int_value, range_error); - value = (PN_int64)int_value; + value = (int64_t)int_value; p += 2; } break; @@ -1622,7 +1622,7 @@ unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value, } int int_value = do_unpack_int32(data + p); _int_range.validate(int_value, range_error); - value = (PN_int64)int_value; + value = (int64_t)int_value; p += 4; } break; @@ -1646,7 +1646,7 @@ unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value, } unsigned int uint_value = do_unpack_uint8(data + p); _uint_range.validate(uint_value, range_error); - value = (PN_int64)(int)uint_value; + value = (int64_t)(int)uint_value; p++; } break; @@ -1659,7 +1659,7 @@ unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value, } unsigned int uint_value = do_unpack_uint16(data + p); _uint_range.validate(uint_value, range_error); - value = (PN_int64)(int)uint_value; + value = (int64_t)(int)uint_value; p += 2; } break; @@ -1672,7 +1672,7 @@ unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value, } unsigned int uint_value = do_unpack_uint32(data + p); _uint_range.validate(uint_value, range_error); - value = (PN_int64)(int)uint_value; + value = (int64_t)(int)uint_value; p += 4; } break; @@ -1683,9 +1683,9 @@ unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value, pack_error = true; return; } - PN_uint64 uint_value = do_unpack_uint64(data + p); + uint64_t uint_value = do_unpack_uint64(data + p); _uint64_range.validate(uint_value, range_error); - value = (PN_int64)uint_value; + value = (int64_t)uint_value; if (value < 0) { pack_error = true; } @@ -1701,7 +1701,7 @@ unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value, } double real_value = do_unpack_float64(data + p); _double_range.validate(real_value, range_error); - value = (PN_int64)real_value; + value = (int64_t)real_value; p += 8; } break; @@ -1722,7 +1722,7 @@ unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value, * Unpacks the current numeric or string value from the stream. */ void DCSimpleParameter:: -unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value, +unpack_uint64(const char *data, size_t length, size_t &p, uint64_t &value, bool &pack_error, bool &range_error) const { switch (_type) { case ST_int8: @@ -1736,7 +1736,7 @@ unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value, if (int_value < 0) { pack_error = true; } - value = (PN_uint64)(unsigned int)int_value; + value = (uint64_t)(unsigned int)int_value; p++; } break; @@ -1752,7 +1752,7 @@ unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value, if (int_value < 0) { pack_error = true; } - value = (PN_uint64)(unsigned int)int_value; + value = (uint64_t)(unsigned int)int_value; p += 2; } break; @@ -1768,7 +1768,7 @@ unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value, if (int_value < 0) { pack_error = true; } - value = (PN_uint64)(unsigned int)int_value; + value = (uint64_t)(unsigned int)int_value; p += 4; } break; @@ -1779,12 +1779,12 @@ unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value, pack_error = true; return; } - PN_int64 int_value = do_unpack_int64(data + p); + int64_t int_value = do_unpack_int64(data + p); _int64_range.validate(int_value, range_error); if (int_value < 0) { pack_error = true; } - value = (PN_uint64)int_value; + value = (uint64_t)int_value; p += 8; } break; @@ -1798,7 +1798,7 @@ unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value, } unsigned int uint_value = do_unpack_uint8(data + p); _uint_range.validate(uint_value, range_error); - value = (PN_uint64)uint_value; + value = (uint64_t)uint_value; p++; } break; @@ -1811,7 +1811,7 @@ unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value, } unsigned int uint_value = do_unpack_uint16(data + p); _uint_range.validate(uint_value, range_error); - value = (PN_uint64)uint_value; + value = (uint64_t)uint_value; p += 2; } break; @@ -1824,7 +1824,7 @@ unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value, } unsigned int uint_value = do_unpack_uint32(data + p); _uint_range.validate(uint_value, range_error); - value = (PN_uint64)uint_value; + value = (uint64_t)uint_value; p += 4; } break; @@ -1847,7 +1847,7 @@ unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value, } double real_value = do_unpack_float64(data + p); _double_range.validate(real_value, range_error); - value = (PN_uint64)real_value; + value = (uint64_t)real_value; p += 8; } break; @@ -1990,7 +1990,7 @@ unpack_validate(const char *data, size_t length, size_t &p, pack_error = true; return true; } - PN_int64 int_value = do_unpack_int64(data + p); + int64_t int_value = do_unpack_int64(data + p); _int64_range.validate(int_value, range_error); p += 8; } @@ -2039,7 +2039,7 @@ unpack_validate(const char *data, size_t length, size_t &p, pack_error = true; return true; } - PN_uint64 uint_value = do_unpack_uint64(data + p); + uint64_t uint_value = do_unpack_uint64(data + p); _uint64_range.validate(uint_value, range_error); p += 8; } diff --git a/direct/src/dcparser/dcSimpleParameter.h b/direct/src/dcparser/dcSimpleParameter.h index 3a8d53c2aa..747950939a 100644 --- a/direct/src/dcparser/dcSimpleParameter.h +++ b/direct/src/dcparser/dcSimpleParameter.h @@ -56,9 +56,9 @@ public: bool &pack_error, bool &range_error) const; virtual void pack_uint(DCPackData &pack_data, unsigned int value, bool &pack_error, bool &range_error) const; - virtual void pack_int64(DCPackData &pack_data, PN_int64 value, + virtual void pack_int64(DCPackData &pack_data, int64_t value, bool &pack_error, bool &range_error) const; - virtual void pack_uint64(DCPackData &pack_data, PN_uint64 value, + virtual void pack_uint64(DCPackData &pack_data, uint64_t value, bool &pack_error, bool &range_error) const; virtual void pack_string(DCPackData &pack_data, const string &value, bool &pack_error, bool &range_error) const; @@ -71,9 +71,9 @@ public: virtual void unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value, bool &pack_error, bool &range_error) const; virtual void unpack_int64(const char *data, size_t length, size_t &p, - PN_int64 &value, bool &pack_error, bool &range_error) const; + int64_t &value, bool &pack_error, bool &range_error) const; virtual void unpack_uint64(const char *data, size_t length, size_t &p, - PN_uint64 &value, bool &pack_error, bool &range_error) const; + uint64_t &value, bool &pack_error, bool &range_error) const; virtual void unpack_string(const char *data, size_t length, size_t &p, string &value, bool &pack_error, bool &range_error) const; virtual bool unpack_validate(const char *data, size_t length, size_t &p, @@ -125,7 +125,7 @@ private: // All of these modulus values will be filled in, regardless of the type. unsigned int _uint_modulus; - PN_uint64 _uint64_modulus; + uint64_t _uint64_modulus; double _double_modulus; static DCClassParameter *_uint32uint8_type; diff --git a/direct/src/dcparser/dcbase.h b/direct/src/dcparser/dcbase.h index 2e28fca2ef..fae53a46f8 100644 --- a/direct/src/dcparser/dcbase.h +++ b/direct/src/dcparser/dcbase.h @@ -102,17 +102,7 @@ typedef string Filename; #define pmap map #define pset set -#ifdef WIN32 -typedef __int64 PN_int64; -typedef unsigned __int64 PN_uint64; -#else -typedef long long PN_int64; -typedef unsigned long long PN_uint64; -#endif - -typedef unsigned char PN_uint8; -typedef unsigned short PN_uint16; -typedef unsigned int PN_uint32; +#include typedef ifstream pifstream; typedef ofstream pofstream; @@ -121,8 +111,8 @@ typedef fstream pfstream; #endif // WITHIN_PANDA // typedef unsigned long CHANNEL_TYPE; -typedef PN_uint64 CHANNEL_TYPE; -typedef PN_uint32 DOID_TYPE; -typedef PN_uint32 ZONEID_TYPE; +typedef uint64_t CHANNEL_TYPE; +typedef uint32_t DOID_TYPE; +typedef uint32_t ZONEID_TYPE; #endif // DCBASE_H diff --git a/direct/src/directdevices/DirectDeviceManager.py b/direct/src/directdevices/DirectDeviceManager.py index 9744d05bdf..78c8615bdf 100644 --- a/direct/src/directdevices/DirectDeviceManager.py +++ b/direct/src/directdevices/DirectDeviceManager.py @@ -48,10 +48,10 @@ class DirectButtons(ButtonNode, DirectObject): def __init__(self, vrpnClient, device): # Keep track of number of buttons created DirectButtons.buttonCount += 1 - # Create a unique name for this button object - self.name = 'DirectButtons-' + repr(DirectButtons.buttonCount) # Create a new button node for the given device ButtonNode.__init__(self, vrpnClient, device) + # Create a unique name for this button object + self.name = 'DirectButtons-' + repr(DirectButtons.buttonCount) # Attach node to data graph self.nodePath = myBase.dataRoot.attachNewNode(self) @@ -86,10 +86,10 @@ class DirectAnalogs(AnalogNode, DirectObject): def __init__(self, vrpnClient, device): # Keep track of number of analogs created DirectAnalogs.analogCount += 1 - # Create a unique name for this analog object - self.name = 'DirectAnalogs-' + repr(DirectAnalogs.analogCount) # Create a new analog node for the given device AnalogNode.__init__(self, vrpnClient, device) + # Create a unique name for this analog object + self.name = 'DirectAnalogs-' + repr(DirectAnalogs.analogCount) # Attach node to data graph self.nodePath = myBase.dataRoot.attachNewNode(self) # See if any of the general analog parameters are dconfig'd @@ -182,10 +182,10 @@ class DirectTracker(TrackerNode, DirectObject): def __init__(self, vrpnClient, device): # Keep track of number of trackers created DirectTracker.trackerCount += 1 - # Create a unique name for this tracker object - self.name = 'DirectTracker-' + repr(DirectTracker.trackerCount) # Create a new tracker node for the given device TrackerNode.__init__(self, vrpnClient, device) + # Create a unique name for this tracker object + self.name = 'DirectTracker-' + repr(DirectTracker.trackerCount) # Attach node to data graph self.nodePath = myBase.dataRoot.attachNewNode(self) @@ -209,10 +209,10 @@ class DirectDials(DialNode, DirectObject): def __init__(self, vrpnClient, device): # Keep track of number of dials created DirectDials.dialCount += 1 - # Create a unique name for this dial object - self.name = 'DirectDials-' + repr(DirectDials.dialCount) # Create a new dial node for the given device DialNode.__init__(self, vrpnClient, device) + # Create a unique name for this dial object + self.name = 'DirectDials-' + repr(DirectDials.dialCount) # Attach node to data graph self.nodePath = myBase.dataRoot.attachNewNode(self) @@ -249,6 +249,8 @@ class DirectTimecodeReader(AnalogNode, DirectObject): def __init__(self, vrpnClient, device): # Keep track of number of timecodeReader created DirectTimecodeReader.timecodeReaderCount += 1 + # Create a new dial node for the given device + AnalogNode.__init__(self, vrpnClient, device) # Create a unique name for this dial object self.name = ('DirectTimecodeReader-' + repr(DirectTimecodeReader.timecodeReaderCount)) @@ -257,8 +259,6 @@ class DirectTimecodeReader(AnalogNode, DirectObject): self.seconds = 0 self.minutes = 0 self.hours = 0 - # Create a new dial node for the given device - AnalogNode.__init__(self, vrpnClient, device) # Attach node to data graph self.nodePath = myBase.dataRoot.attachNewNode(self) diff --git a/direct/src/directscripts/eggcacher.py b/direct/src/directscripts/eggcacher.py index ebef394890..78070df2ec 100644 --- a/direct/src/directscripts/eggcacher.py +++ b/direct/src/directscripts/eggcacher.py @@ -55,7 +55,7 @@ class EggCacher: size = os.path.getsize(path) eggs.append((path,size)) return - if (path.endswith(".egg.pz")): + if (path.endswith(".egg.pz") or path.endswith(".egg.gz")): size = os.path.getsize(path) if (self.pzkeep): eggs.append((path,size)) else: eggs.append((path[:-3],size)) diff --git a/direct/src/directscripts/packpanda.py b/direct/src/directscripts/packpanda.py index b8dec72610..6d89a9a0d0 100755 --- a/direct/src/directscripts/packpanda.py +++ b/direct/src/directscripts/packpanda.py @@ -274,7 +274,7 @@ def CompileFiles(file): if (os.path.isfile(file)): if (file.endswith(".egg")): egg2bam(file, file[:-4]+'.bam') - elif (file.endswith(".egg.pz")): + elif (file.endswith(".egg.pz") or file.endswith(".egg.gz")): egg2bam(file, file[:-7]+'.bam') elif (file.endswith(".py")): py2pyc(file) diff --git a/direct/src/distributed/DistributedObjectBase.py b/direct/src/distributed/DistributedObjectBase.py index e105e4c891..af5f2678f3 100755 --- a/direct/src/distributed/DistributedObjectBase.py +++ b/direct/src/distributed/DistributedObjectBase.py @@ -13,7 +13,6 @@ class DistributedObjectBase(DirectObject): def __init__(self, cr): assert self.notify.debugStateCall(self) self.cr = cr - self.children = {} self.parentId = None self.zoneId = None diff --git a/direct/src/distributed/DistributedObjectGlobalUD.py b/direct/src/distributed/DistributedObjectGlobalUD.py index ce51d8421c..c5be6f012a 100755 --- a/direct/src/distributed/DistributedObjectGlobalUD.py +++ b/direct/src/distributed/DistributedObjectGlobalUD.py @@ -35,7 +35,11 @@ class DistributedObjectGlobalUD(DistributedObjectUD): def __execMessage(self, message): if not self.ExecNamespace: # Import some useful variables into the ExecNamespace initially. - exec('from pandac.PandaModules import *', globals(), self.ExecNamespace) + import pandac.PandaModules + + for key, value in pandac.PandaModules.__dict__.items(): + if not key.startswith('__'): + self.ExecNamespace[key] = value #self.importExecNamespace() # Now try to evaluate the expression using ChatInputNormal.ExecNamespace as diff --git a/direct/src/distributed/cDistributedSmoothNodeBase.I b/direct/src/distributed/cDistributedSmoothNodeBase.I index 5eba579e2b..56dd8595d3 100644 --- a/direct/src/distributed/cDistributedSmoothNodeBase.I +++ b/direct/src/distributed/cDistributedSmoothNodeBase.I @@ -184,7 +184,7 @@ d_setSmPosHpr(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h, PN_std * */ INLINE void CDistributedSmoothNodeBase:: -d_setSmPosHprL(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r, PN_uint64 l) { +d_setSmPosHprL(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r, uint64_t l) { // cout << "d_setSmPosHprL: " << x << ", " << y << ", " << z << ", " << h << // ", " << p << ", " << r << l << endl; DCPacker packer; diff --git a/direct/src/distributed/cDistributedSmoothNodeBase.cxx b/direct/src/distributed/cDistributedSmoothNodeBase.cxx index 45b65353ee..70a50f33f5 100644 --- a/direct/src/distributed/cDistributedSmoothNodeBase.cxx +++ b/direct/src/distributed/cDistributedSmoothNodeBase.cxx @@ -358,7 +358,7 @@ finish_send_update(DCPacker &packer) { * Appends the timestamp and sends the update. */ void CDistributedSmoothNodeBase:: -set_curr_l(PN_uint64 l) { +set_curr_l(uint64_t l) { _currL[1] = l; } diff --git a/direct/src/distributed/cDistributedSmoothNodeBase.h b/direct/src/distributed/cDistributedSmoothNodeBase.h index b59bd9af2a..53763a6a47 100644 --- a/direct/src/distributed/cDistributedSmoothNodeBase.h +++ b/direct/src/distributed/cDistributedSmoothNodeBase.h @@ -51,7 +51,7 @@ PUBLISHED: void broadcast_pos_hpr_xyh(); void broadcast_pos_hpr_xy(); - void set_curr_l(PN_uint64 l); + void set_curr_l(uint64_t l); void print_curr_l(); private: @@ -67,7 +67,7 @@ private: INLINE void d_setSmXYH(PN_stdfloat x, PN_stdfloat y, PN_stdfloat h); INLINE void d_setSmXYZH(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h); INLINE void d_setSmPosHpr(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r); - INLINE void d_setSmPosHprL(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r, PN_uint64 l); + INLINE void d_setSmPosHprL(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r, uint64_t l); void begin_send_update(DCPacker &packer, const string &field_name); void finish_send_update(DCPacker &packer); @@ -97,7 +97,7 @@ private: bool _store_stop; // contains most recently sent location info as index 0, index 1 contains // most recently set location info - PN_uint64 _currL[2]; + uint64_t _currL[2]; }; #include "cDistributedSmoothNodeBase.I" diff --git a/direct/src/fsm/FSM.py b/direct/src/fsm/FSM.py index a62bede3f0..577c1232b7 100644 --- a/direct/src/fsm/FSM.py +++ b/direct/src/fsm/FSM.py @@ -310,7 +310,7 @@ class FSM(DirectObject): self.name, request, str(args)[1:])) filter = self.getCurrentFilter() - result = list(filter(request, args)) + result = filter(request, args) if result: if isinstance(result, str): # If the return value is a string, it's just the name diff --git a/direct/src/gui/DirectFrame.py b/direct/src/gui/DirectFrame.py index 9db60f727b..9c164038b9 100644 --- a/direct/src/gui/DirectFrame.py +++ b/direct/src/gui/DirectFrame.py @@ -10,9 +10,9 @@ from .OnscreenGeom import OnscreenGeom import sys if sys.version_info >= (3, 0): - stringTypes = (str,) + stringType = str else: - stringTypes = (str, unicode) + stringType = basestring class DirectFrame(DirectGuiWidget): @@ -60,7 +60,7 @@ class DirectFrame(DirectGuiWidget): # Determine if user passed in single string or a sequence if self['text'] == None: textList = (None,) * self['numStates'] - elif isinstance(self['text'], stringTypes): + elif isinstance(self['text'], stringType): # If just passing in a single string, make a tuple out of it textList = (self['text'],) * self['numStates'] else: @@ -103,7 +103,7 @@ class DirectFrame(DirectGuiWidget): # Passed in None geomList = (None,) * self['numStates'] elif isinstance(geom, NodePath) or \ - isinstance(geom, stringTypes): + isinstance(geom, stringType): # Passed in a single node path, make a tuple out of it geomList = (geom,) * self['numStates'] else: @@ -145,14 +145,14 @@ class DirectFrame(DirectGuiWidget): imageList = (None,) * self['numStates'] elif isinstance(arg, NodePath) or \ isinstance(arg, Texture) or \ - isinstance(arg, stringTypes): + isinstance(arg, stringType): # Passed in a single node path, make a tuple out of it imageList = (arg,) * self['numStates'] else: # Otherwise, hope that the user has passed in a tuple/list if ((len(arg) == 2) and - isinstance(arg[0], stringTypes) and - isinstance(arg[1], stringTypes)): + isinstance(arg[0], stringType) and + isinstance(arg[1], stringType)): # Its a model/node pair of strings imageList = (arg,) * self['numStates'] else: diff --git a/direct/src/gui/DirectGuiBase.py b/direct/src/gui/DirectGuiBase.py index 633b9615c0..833bf8ebcb 100644 --- a/direct/src/gui/DirectGuiBase.py +++ b/direct/src/gui/DirectGuiBase.py @@ -12,6 +12,12 @@ from .OnscreenImage import * from direct.directtools.DirectUtil import ROUND_TO from direct.showbase import DirectObject from direct.task import Task +import sys + +if sys.version_info >= (3, 0): + stringType = str +else: + stringType = basestring guiObjectCollector = PStatCollector("Client::GuiObjects") @@ -505,7 +511,7 @@ class DirectGuiBase(DirectObject.DirectObject): # with corresponding keys beginning with *component*. alias = alias + '_' aliasLen = len(alias) - for option in keywords: + for option in keywords.copy(): if len(option) > aliasLen and option[:aliasLen] == alias: newkey = component + '_' + option[aliasLen:] keywords[newkey] = keywords[option] @@ -537,7 +543,7 @@ class DirectGuiBase(DirectObject.DirectObject): # specific than the group arguments, above; we walk through # the list afterwards so they will override. - for option in keywords: + for option in keywords.copy(): if len(option) > nameLen and option[:nameLen] == componentPrefix: # The keyword argument refers to this component, so add # this to the options to use when constructing the widget. @@ -943,7 +949,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath): # Convert None, and string arguments if relief == None: relief = PGFrameStyle.TNone - elif isinstance(relief, str): + elif isinstance(relief, stringType): # Convert string to frame style int relief = DGG.FrameStyleDict[relief] # Set style @@ -984,14 +990,14 @@ class DirectGuiWidget(DirectGuiBase, NodePath): textures = self['frameTexture'] if textures == None or \ isinstance(textures, Texture) or \ - isinstance(textures, str): + isinstance(textures, stringType): textures = (textures,) * self['numStates'] for i in range(self['numStates']): if i >= len(textures): texture = textures[-1] else: texture = textures[i] - if isinstance(texture, str): + if isinstance(texture, stringType): texture = loader.loadTexture(texture) if texture: self.frameStyle[i].setTexture(texture) diff --git a/direct/src/gui/DirectScrolledList.py b/direct/src/gui/DirectScrolledList.py index 79c1661f7e..58d981950b 100644 --- a/direct/src/gui/DirectScrolledList.py +++ b/direct/src/gui/DirectScrolledList.py @@ -8,7 +8,6 @@ from direct.directnotify import DirectNotifyGlobal from direct.task.Task import Task from .DirectFrame import * from .DirectButton import * -import types class DirectScrolledListItem(DirectButton): @@ -49,7 +48,7 @@ class DirectScrolledList(DirectFrame): def __init__(self, parent = None, **kw): assert self.notify.debugStateCall(self) self.index = 0 - self.forceHeight = None + self.__forceHeight = None """ If one were to want a scrolledList that makes and adds its items as needed, simply pass in an items list of strings (type 'str') @@ -115,12 +114,12 @@ class DirectScrolledList(DirectFrame): def setForceHeight(self): assert self.notify.debugStateCall(self) - self.forceHeight = self["forceHeight"] + self.__forceHeight = self["forceHeight"] def recordMaxHeight(self): assert self.notify.debugStateCall(self) - if self.forceHeight is not None: - self.maxHeight = self.forceHeight + if self.__forceHeight is not None: + self.maxHeight = self.__forceHeight else: self.maxHeight = 0.0 for item in self["items"]: @@ -130,24 +129,24 @@ class DirectScrolledList(DirectFrame): def setScrollSpeed(self): assert self.notify.debugStateCall(self) # Items per second to move - self.scrollSpeed = self["scrollSpeed"] - if self.scrollSpeed <= 0: - self.scrollSpeed = 1 + self.__scrollSpeed = self["scrollSpeed"] + if self.__scrollSpeed <= 0: + self.__scrollSpeed = 1 def setNumItemsVisible(self): assert self.notify.debugStateCall(self) # Items per second to move - self.numItemsVisible = self["numItemsVisible"] + self.__numItemsVisible = self["numItemsVisible"] def destroy(self): assert self.notify.debugStateCall(self) taskMgr.remove(self.taskName("scroll")) if hasattr(self, "currentSelected"): del self.currentSelected - if self.incButtonCallback: - self.incButtonCallback = None - if self.decButtonCallback: - self.decButtonCallback = None + if self.__incButtonCallback: + self.__incButtonCallback = None + if self.__decButtonCallback: + self.__decButtonCallback = None self.incButton.destroy() self.decButton.destroy() DirectFrame.destroy(self) @@ -169,10 +168,10 @@ class DirectScrolledList(DirectFrame): #for i in range(len(self["items"])): # print "buttontext[", i,"]", self["items"][i]["text"] - if(len(self["items"])==0): + if len(self["items"]) == 0: return 0 - if(type(self["items"][0])!=types.InstanceType): + if type(self["items"][0]) == type(''): self.notify.warning("getItemIndexForItemID: cant find itemID for non-class list items!") return 0 @@ -309,7 +308,7 @@ class DirectScrolledList(DirectFrame): def __incButtonDown(self, event): assert self.notify.debugStateCall(self) task = Task(self.__scrollByTask) - task.setDelay(1.0 / self.scrollSpeed) + task.setDelay(1.0 / self.__scrollSpeed) task.prevTime = 0.0 task.delta = 1 taskName = self.taskName("scroll") @@ -317,13 +316,13 @@ class DirectScrolledList(DirectFrame): taskMgr.add(task, taskName) self.scrollBy(task.delta) messenger.send('wakeup') - if self.incButtonCallback: - self.incButtonCallback() + if self.__incButtonCallback: + self.__incButtonCallback() def __decButtonDown(self, event): assert self.notify.debugStateCall(self) task = Task(self.__scrollByTask) - task.setDelay(1.0 / self.scrollSpeed) + task.setDelay(1.0 / self.__scrollSpeed) task.prevTime = 0.0 task.delta = -1 taskName = self.taskName("scroll") @@ -331,8 +330,8 @@ class DirectScrolledList(DirectFrame): taskMgr.add(task, taskName) self.scrollBy(task.delta) messenger.send('wakeup') - if self.decButtonCallback: - self.decButtonCallback() + if self.__decButtonCallback: + self.__decButtonCallback() def __buttonUp(self, event): assert self.notify.debugStateCall(self) @@ -345,7 +344,7 @@ class DirectScrolledList(DirectFrame): Add this string and extraArg to the list """ assert self.notify.debugStateCall(self) - if(type(item) == types.InstanceType): + if type(item) != type(''): # cant add attribs to non-classes (like strings & ints) item.itemID = self.nextItemID self.nextItemID += 1 @@ -354,7 +353,7 @@ class DirectScrolledList(DirectFrame): item.reparentTo(self.itemFrame) if refresh: self.refresh() - if(type(item) == types.InstanceType): + if type(item) != type(''): return item.itemID # to pass to scrollToItemID def removeItem(self, item, refresh=1): @@ -466,11 +465,11 @@ class DirectScrolledList(DirectFrame): def setIncButtonCallback(self): assert self.notify.debugStateCall(self) - self.incButtonCallback = self["incButtonCallback"] + self.__incButtonCallback = self["incButtonCallback"] def setDecButtonCallback(self): assert self.notify.debugStateCall(self) - self.decButtonCallback = self["decButtonCallback"] + self.__decButtonCallback = self["decButtonCallback"] """ diff --git a/direct/src/gui/DirectWaitBar.py b/direct/src/gui/DirectWaitBar.py index 149540e5d5..a8eb9a56cc 100644 --- a/direct/src/gui/DirectWaitBar.py +++ b/direct/src/gui/DirectWaitBar.py @@ -5,7 +5,12 @@ __all__ = ['DirectWaitBar'] from panda3d.core import * from . import DirectGuiGlobals as DGG from .DirectFrame import * -import types +import sys + +if sys.version_info >= (3, 0): + stringType = str +else: + stringType = basestring """ import DirectWaitBar @@ -93,7 +98,7 @@ class DirectWaitBar(DirectFrame): """Updates the bar texture, which you can set using bar['barTexture'].""" # this must be a single texture (or a string). texture = self['barTexture'] - if isinstance(texture, str): + if isinstance(texture, stringType): texture = loader.loadTexture(texture) if texture: self.barStyle.setTexture(texture) diff --git a/direct/src/gui/OnscreenGeom.py b/direct/src/gui/OnscreenGeom.py index ac4f93a418..e1a35a77d1 100644 --- a/direct/src/gui/OnscreenGeom.py +++ b/direct/src/gui/OnscreenGeom.py @@ -4,7 +4,12 @@ __all__ = ['OnscreenGeom'] from panda3d.core import * from direct.showbase.DirectObject import DirectObject +import sys +if sys.version_info >= (3, 0): + stringType = str +else: + stringType = basestring class OnscreenGeom(DirectObject, NodePath): def __init__(self, geom = None, @@ -93,7 +98,7 @@ class OnscreenGeom(DirectObject, NodePath): # Assign geometry if isinstance(geom, NodePath): self.assign(geom.copyTo(parent, sort)) - elif isinstance(geom, str): + elif isinstance(geom, stringType): self.assign(loader.loadModel(geom)) self.reparentTo(parent, sort) diff --git a/direct/src/gui/OnscreenImage.py b/direct/src/gui/OnscreenImage.py index a99d4bf0ff..026076fc69 100644 --- a/direct/src/gui/OnscreenImage.py +++ b/direct/src/gui/OnscreenImage.py @@ -4,6 +4,12 @@ __all__ = ['OnscreenImage'] from panda3d.core import * from direct.showbase.DirectObject import DirectObject +import sys + +if sys.version_info >= (3, 0): + stringType = str +else: + stringType = basestring class OnscreenImage(DirectObject, NodePath): @@ -95,7 +101,7 @@ class OnscreenImage(DirectObject, NodePath): # Assign geometry if isinstance(image, NodePath): self.assign(image.copyTo(parent, sort)) - elif isinstance(image, str) or \ + elif isinstance(image, stringType) or \ isinstance(image, Texture): if isinstance(image, Texture): # It's a Texture diff --git a/direct/src/gui/OnscreenText.py b/direct/src/gui/OnscreenText.py index 03beac702b..1af714c44a 100644 --- a/direct/src/gui/OnscreenText.py +++ b/direct/src/gui/OnscreenText.py @@ -4,7 +4,6 @@ __all__ = ['OnscreenText', 'Plain', 'ScreenTitle', 'ScreenPrompt', 'NameConfirm' from panda3d.core import * from . import DirectGuiGlobals as DGG -from direct.showbase.DirectObject import DirectObject import sys ## These are the styles of text we might commonly see. They set the @@ -17,7 +16,7 @@ ScreenPrompt = 3 NameConfirm = 4 BlackOnWhite = 5 -class OnscreenText(DirectObject, NodePath): +class OnscreenText(NodePath): def __init__(self, text = '', style = Plain, diff --git a/direct/src/interval/MetaInterval.py b/direct/src/interval/MetaInterval.py index d7b23afdeb..dc83f3587c 100644 --- a/direct/src/interval/MetaInterval.py +++ b/direct/src/interval/MetaInterval.py @@ -268,7 +268,7 @@ class MetaInterval(CMetaInterval): self.addInterval(ival, maxDuration - ival.getDuration(), TRACK_START) self.popLevel(duration) - def addTrack(self, list, name, relTime, relTo, duration): + def addTrack(self, trackList, name, relTime, relTo, duration): # Adds a "track list". This is a list of tuples of the form: # # (, , @@ -281,19 +281,19 @@ class MetaInterval(CMetaInterval): # (TRACK_START). If the relative code is omitted, the default # is TRACK_START. self.pushLevel(name, relTime, relTo) - for tuple in list: - if isinstance(tuple, tuple) or \ - isinstance(tuple, list): - relTime = tuple[0] - ival = tuple[1] - if len(tuple) >= 3: - relTo = tuple[2] + for tupleObj in trackList: + if isinstance(tupleObj, tuple) or \ + isinstance(tupleObj, list): + relTime = tupleObj[0] + ival = tupleObj[1] + if len(tupleObj) >= 3: + relTo = tupleObj[2] else: relTo = TRACK_START self.addInterval(ival, relTime, relTo) else: - self.notify.error("Not a tuple in Track: %s" % (tuple,)) + self.notify.error("Not a tuple in Track: %s" % (tupleObj,)) self.popLevel(duration) def addInterval(self, ival, relTime, relTo): @@ -593,22 +593,22 @@ class Track(MetaInterval): meta.addTrack(self.ivals, self.getName(), relTime, relTo, self.phonyDuration) - def validateComponent(self, tuple): + def validateComponent(self, tupleObj): # This is called only in debug mode to verify that the # indicated component added to the MetaInterval is appropriate # to this type of MetaInterval. In most cases except Track, # this is the same as asking that the component is itself an # Interval. - if not (isinstance(tuple, tuple) or \ - isinstance(tuple, list)): + if not (isinstance(tupleObj, tuple) or \ + isinstance(tupleObj, list)): # It's not a tuple. return 0 - relTime = tuple[0] - ival = tuple[1] - if len(tuple) >= 3: - relTo = tuple[2] + relTime = tupleObj[0] + ival = tupleObj[1] + if len(tupleObj) >= 3: + relTo = tupleObj[2] else: relTo = TRACK_START diff --git a/direct/src/p3d/DeploymentTools.py b/direct/src/p3d/DeploymentTools.py index 5d63e0e6f5..9c390fbf07 100644 --- a/direct/src/p3d/DeploymentTools.py +++ b/direct/src/p3d/DeploymentTools.py @@ -6,7 +6,6 @@ __all__ = ["Standalone", "Installer"] import os, sys, subprocess, tarfile, shutil, time, zipfile, socket, getpass, struct import gzip, plistlib -from io import BytesIO, TextIOWrapper from direct.directnotify.DirectNotifyGlobal import * from direct.showbase.AppRunnerGlobal import appRunner from panda3d.core import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile @@ -24,6 +23,10 @@ except ImportError: if sys.version_info >= (3, 0): xrange = range + from io import BytesIO, TextIOWrapper +else: + from io import BytesIO + from StringIO import StringIO # Make sure this matches with the magic in p3dEmbedMain.cxx. P3DEMBED_MAGIC = 0xFF3D3D00 @@ -808,17 +811,24 @@ class Installer: # Create a control file in memory. controlfile = BytesIO() - cout = TextIOWrapper(controlfile, encoding='utf-8', newline='') - cout.write(u"Package: %s\n" % self.shortname.lower()) - cout.write(u"Version: %s\n" % self.version) - cout.write(u"Maintainer: %s <%s>\n" % (self.authorname, self.authoremail)) - cout.write(u"Section: games\n") - cout.write(u"Priority: optional\n") - cout.write(u"Architecture: %s\n" % arch) - cout.write(u"Installed-Size: %d\n" % -(-totsize // 1024)) - cout.write(u"Description: %s\n" % self.fullname) - cout.write(u"Depends: libc6, libgcc1, libstdc++6, libx11-6\n") + if sys.version_info >= (3, 0): + cout = TextIOWrapper(controlfile, encoding='utf-8', newline='') + else: + cout = StringIO() + + cout.write("Package: %s\n" % self.shortname.lower()) + cout.write("Version: %s\n" % self.version) + cout.write("Maintainer: %s <%s>\n" % (self.authorname, self.authoremail)) + cout.write("Section: games\n") + cout.write("Priority: optional\n") + cout.write("Architecture: %s\n" % arch) + cout.write("Installed-Size: %d\n" % -(-totsize // 1024)) + cout.write("Description: %s\n" % self.fullname) + cout.write("Depends: libc6, libgcc1, libstdc++6, libx11-6\n") cout.flush() + if sys.version_info < (3, 0): + controlfile.write(cout.getvalue().encode('utf-8')) + controlinfo = TarInfoRoot("control") controlinfo.mtime = modtime controlinfo.size = controlfile.tell() @@ -893,19 +903,26 @@ class Installer: # Create a pkginfo file in memory. pkginfo = BytesIO() - pout = TextIOWrapper(pkginfo, encoding='utf-8', newline='') - pout.write(u"# Generated using pdeploy\n") - pout.write(u"# %s\n" % time.ctime(modtime)) - pout.write(u"pkgname = %s\n" % self.shortname.lower()) - pout.write(u"pkgver = %s\n" % pkgver) - pout.write(u"pkgdesc = %s\n" % self.fullname) - pout.write(u"builddate = %s\n" % modtime) - pout.write(u"packager = %s <%s>\n" % (self.authorname, self.authoremail)) - pout.write(u"size = %d\n" % totsize) - pout.write(u"arch = %s\n" % arch) + if sys.version_info >= (3, 0): + pout = TextIOWrapper(pkginfo, encoding='utf-8', newline='') + else: + pout = StringIO() + + pout.write("# Generated using pdeploy\n") + pout.write("# %s\n" % time.ctime(modtime)) + pout.write("pkgname = %s\n" % self.shortname.lower()) + pout.write("pkgver = %s\n" % pkgver) + pout.write("pkgdesc = %s\n" % self.fullname) + pout.write("builddate = %s\n" % modtime) + pout.write("packager = %s <%s>\n" % (self.authorname, self.authoremail)) + pout.write("size = %d\n" % totsize) + pout.write("arch = %s\n" % arch) if self.licensename != "": - pout.write(u"license = %s\n" % self.licensename) + pout.write("license = %s\n" % self.licensename) pout.flush() + if sys.version_info < (3, 0): + pkginfo.write(pout.getvalue().encode('utf-8')) + pkginfoinfo = TarInfoRoot(".PKGINFO") pkginfoinfo.mtime = modtime pkginfoinfo.size = pkginfo.tell() diff --git a/direct/src/p3d/Packager.py b/direct/src/p3d/Packager.py index b46cda30b7..ccb8589d8c 100644 --- a/direct/src/p3d/Packager.py +++ b/direct/src/p3d/Packager.py @@ -61,7 +61,7 @@ class Packager: self.newName = str(self.filename) ext = Filename(self.newName).getExtension() - if ext == 'pz': + if ext == 'pz' or ext == 'gz': # Strip off a .pz extension; we can compress files # within the Multifile without it. filename = Filename(self.newName) @@ -2484,6 +2484,7 @@ class Packager: GlobPattern('libthr.so*'), GlobPattern('ld-linux.so*'), GlobPattern('ld-linux-*.so*'), + GlobPattern('librt.so*'), ] # A Loader for loading models. @@ -3772,7 +3773,7 @@ class Packager: self.currentPackage.addFile(filename, newName = newName, explicit = False, unprocessed = unprocessed) else: - if ext == 'pz': + if ext == 'pz' or ext == 'gz': # Strip off an implicit .pz extension. newFilename = Filename(filename) newFilename.setExtension('') diff --git a/direct/src/p3d/PatchMaker.py b/direct/src/p3d/PatchMaker.py index b48ad80f24..c1624b3cc1 100644 --- a/direct/src/p3d/PatchMaker.py +++ b/direct/src/p3d/PatchMaker.py @@ -137,7 +137,7 @@ class PatchMaker: startFile, startPv, plan = self.getRecreateFilePlan() - if startFile.getExtension() == 'pz': + if startFile.getExtension() in ('pz', 'gz'): # If the starting file is compressed, we have to # decompress it first. assert startPv.tempFile is None diff --git a/direct/src/p3d/SeqValue.py b/direct/src/p3d/SeqValue.py index 68b655bce3..958132f74b 100644 --- a/direct/src/p3d/SeqValue.py +++ b/direct/src/p3d/SeqValue.py @@ -77,9 +77,14 @@ class SeqValue: """ Compares to another seq value. """ return cmp(self.value, other.value) + def __lt__(self, other): + return self.value < other.value + + def __gt__(self, other): + return self.value > other.value + def __bool__(self): return bool(self.value) def __str__(self): return 'SeqValue%s' % (repr(self.value)) - diff --git a/direct/src/p3d/panda3d.pdef b/direct/src/p3d/panda3d.pdef index 59e53cb39b..5a993a1ada 100644 --- a/direct/src/p3d/panda3d.pdef +++ b/direct/src/p3d/panda3d.pdef @@ -63,8 +63,10 @@ class panda3d(package): # Include various standard Python encodings. The rest is in morepy. module('encodings', 'encodings.aliases', 'encodings.undefined', - 'encodings.utf_8', 'encodings.ascii', 'encodings.string_escape', - 'encodings.mbcs', 'encodings.latin_1', 'io') + 'encodings.utf_8', 'encodings.ascii', 'encodings.mbcs', + 'encodings.latin_1', 'io') + if sys.version_info < (3, 0): + module('encodings.string_escape') # Pick up the shader files that appear in direct/src/filter. import direct @@ -241,7 +243,10 @@ class models(package): # we assume this is the models directory. pathname = getModelPath().findFile('cmss12.egg') if pathname: - dir(pathname.getDirname(), newDir = '') + dir(pathname.getDirname(), newDir = 'models') + + # Some people are used to loading the models without models/ prefix. + file('models.prc', extract = True, text = "model-path $MODELS_ROOT/models") class fmod(package): diff --git a/direct/src/plugin/p3dPackage.cxx b/direct/src/plugin/p3dPackage.cxx index 7646a8c602..0560c0f6da 100644 --- a/direct/src/plugin/p3dPackage.cxx +++ b/direct/src/plugin/p3dPackage.cxx @@ -998,7 +998,8 @@ build_install_plans(TiXmlDocument *doc) { FileSpec new_file = patchfile->_file; string new_filename = new_file.get_filename(); size_t dot = new_filename.rfind('.'); - assert(new_filename.substr(dot) == ".pz"); + string extension = new_filename.substr(dot); + assert(extension == ".pz" || extension == ".gz"); new_filename = new_filename.substr(0, dot); new_file.set_filename(new_filename); step = new InstallStepUncompressFile @@ -1834,7 +1835,7 @@ thread_step() { z.next_in = (Bytef *)decompress_buffer; z.avail_in = (size_t)read_count; - int result = inflateInit(&z); + int result = inflateInit2(&z, 32 + 15); if (result < 0) { nout << z.msg << "\n"; return IT_step_failed; diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index cb7f58fb22..542c47acb8 100644 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -217,6 +217,24 @@ run_python() { PyModule_AddStringConstant(showbase_module, "__package__", "direct.showbase"); } + PyObject *stdpy_module = PyImport_AddModule("direct.stdpy"); + if (stdpy_module != NULL) { + Filename stdpy_dir(direct_dir, "stdpy"); + dir_str = stdpy_dir.to_os_specific(); + PyModule_AddObject(stdpy_module, "__path__", Py_BuildValue("[s#]", dir_str.data(), dir_str.length())); + PyModule_AddStringConstant(stdpy_module, "__package__", "direct.stdpy"); + } + + // And the encodings package as well, since we've presumably picked up a + // bunch of encodings modules as part of the frozen bundle. + Filename encodings_dir(dir, "encodings"); + PyObject *encodings_module = PyImport_AddModule("encodings"); + if (encodings_module != NULL) { + dir_str = encodings_dir.to_os_specific(); + PyModule_AddObject(encodings_module, "__path__", Py_BuildValue("[s#]", dir_str.data(), dir_str.length())); + PyModule_AddStringConstant(encodings_module, "__package__", "encodings"); + } + // And register the VFSImporter. PyObject *result = PyObject_CallMethod(vfsimporter_module, (char *)"register", (char *)""); if (result == NULL) { diff --git a/direct/src/showbase/DistancePhasedNode.py b/direct/src/showbase/DistancePhasedNode.py index dae96991af..a1bd879af0 100755 --- a/direct/src/showbase/DistancePhasedNode.py +++ b/direct/src/showbase/DistancePhasedNode.py @@ -106,10 +106,12 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath): def __repr__(self): outStr = 'DistancePhasedObject(' - outStr += '%s' % repr(self.getName()) + outStr += repr(self.getName()) for param, value in zip(('phaseParamMap', 'autoCleanup', 'enterPrefix', 'exitPrefix', 'phaseCollideMask', 'fromCollideNode'), - ('{}', 'True','\'enter\'','\'exit\'','BitMask32.allOn()','None')): - outStr += eval('(\', ' + param + ' = %s\' % repr(self.' + param + '),\'\')[self.' + param + ' == ' + value + ']') + ({}, True, 'enter', 'exit', BitMask32.allOn(), None)): + pv = getattr(self, param) + if pv != value: + outStr += ', %s = %r' % (param, pv) outStr += ')' return outStr @@ -287,10 +289,12 @@ class BufferedDistancePhasedNode(DistancePhasedNode): def __repr__(self): outStr = 'BufferedDistancePhasedNode(' - outStr += '%s' % repr(self.getName()) + outStr += repr(self.getName()) for param, value in zip(('bufferParamMap', 'autoCleanup', 'enterPrefix', 'exitPrefix', 'phaseCollideMask', 'fromCollideNode'), - ('{}', 'True','\'enter\'','\'exit\'','BitMask32.allOn()', 'None')): - outStr += eval('(\', ' + param + ' = %s\' % repr(self.' + param + '),\'\')[self.' + param + ' == ' + value + ']') + ({}, True, 'enter', 'exit', BitMask32.allOn(), None)): + pv = getattr(self, param) + if pv != value: + outStr += ', %s = %r' % (param, pv) outStr += ')' return outStr diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index ade643f462..0916e83f7d 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -201,7 +201,9 @@ class ShowBase(DirectObject.DirectObject): ## This is used to store the wx.Application object used when want-wx is ## set or base.startWx() is called. self.wxApp = None + self.wxAppCreated = False self.tkRoot = None + self.tkRootCreated = False # This is used for syncing multiple PCs in a distributed cluster try: @@ -259,6 +261,17 @@ class ShowBase(DirectObject.DirectObject): random.seed(seed) #whrandom.seed(seed & 0xff, (seed >> 8) & 0xff, (seed >> 16) & 0xff) + # For some reason, wx needs to be initialized before the graphics window + if sys.platform == "darwin": + if self.config.GetBool("want-wx", 0): + wx = importlib.import_module('wx') + self.wxApp = wx.App() + + # Same goes for Tk, which uses a conflicting NSApplication + if self.config.GetBool("want-tk", 0): + Pmw = importlib.import_module('Pmw') + self.tkRoot = Pmw.initialise() + # Open the default rendering window. if self.windowType != 'none': props = WindowProperties.getDefault() @@ -2828,7 +2841,7 @@ class ShowBase(DirectObject.DirectObject): updated, but wxPython owns the main loop (which seems to make it happier than the other way around). """ - if self.wxApp: + if self.wxAppCreated: # Don't do this twice. return @@ -2838,8 +2851,9 @@ class ShowBase(DirectObject.DirectObject): # by modulefinder when packaging an application. wx = importlib.import_module('wx') - # Create a new base.wxApp. - self.wxApp = wx.PySimpleApp(redirect = False) + if not self.wxApp: + # Create a new base.wxApp. + self.wxApp = wx.PySimpleApp(redirect = False) if ConfigVariableBool('wx-main-loop', True): # Put wxPython in charge of the main loop. It really @@ -2874,6 +2888,7 @@ class ShowBase(DirectObject.DirectObject): return task.again self.taskMgr.add(wxLoop, 'wxLoop') + self.wxAppCreated = True def __wxTimerCallback(self, event): if Thread.getCurrentThread().getCurrentTask(): @@ -2908,7 +2923,7 @@ class ShowBase(DirectObject.DirectObject): updated, but Tkinter owns the main loop (which seems to make it happier than the other way around). """ - if self.tkRoot: + if self.tkRootCreated: # Don't do this twice. return @@ -2918,7 +2933,8 @@ class ShowBase(DirectObject.DirectObject): Pmw = importlib.import_module('Pmw') # Create a new Tk root. - self.tkRoot = Pmw.initialise() + if not self.tkRoot: + self.tkRoot = Pmw.initialise() builtins.tkroot = self.tkRoot init_app_for_gui() @@ -2954,6 +2970,7 @@ class ShowBase(DirectObject.DirectObject): return task.again self.taskMgr.add(tkLoop, 'tkLoop') + self.tkRootCreated = True def __tkTimerCallback(self): if not Thread.getCurrentThread().getCurrentTask(): diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index 0781b06f0e..cf601883cb 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -20,6 +20,7 @@ def inspect(anObject): Inspector = importlib.import_module('direct.tkpanels.Inspector') return Inspector.inspect(anObject) +import sys if sys.version_info >= (3, 0): import builtins else: diff --git a/direct/src/showbase/VFSImporter.py b/direct/src/showbase/VFSImporter.py index 807b931ab0..e6849fd503 100644 --- a/direct/src/showbase/VFSImporter.py +++ b/direct/src/showbase/VFSImporter.py @@ -2,6 +2,7 @@ __all__ = ['register', 'sharedPackages', 'reloadSharedPackage', 'reloadSharedPackages'] from panda3d.core import Filename, VirtualFileSystem, VirtualFileMountSystem, OFileStream, copyStream +from direct.stdpy.file import open import sys import marshal import imp @@ -173,10 +174,7 @@ class VFSLoader: filename = Filename(self.filename) filename.setExtension('py') filename.setText() - vfile = vfs.getFile(filename) - if not vfile: - raise IOError("Could not find '%s'" % (filename)) - return vfile.readFile(True) + return open(self.filename, self.desc[1]).read() def _import_extension_module(self, fullname): """ Loads the binary shared object as a Python module, and diff --git a/direct/src/showbase/pandaSqueezeTool.py b/direct/src/showbase/pandaSqueezeTool.py deleted file mode 100755 index e19d660c22..0000000000 --- a/direct/src/showbase/pandaSqueezeTool.py +++ /dev/null @@ -1,374 +0,0 @@ -"""Undocumented Module""" - -__all__ = ['usage', 'Squeezer', 'Loader', 'boot', 'open', 'explode', 'getloader', 'squeeze', 'searchPath'] - -#!/usr/bin/env python -# -# SQUEEZE -# -# squeeze a python program -# -# installation: -# - use this script as is, or squeeze it using the following command: -# -# python squeezeTool.py -1su -o squeeze -b squeezeTool squeezeTool.py -# -# notes: -# - this is pretty messy. make sure to test everything carefully -# if you change anything -# -# - the name "squeeze" is taken from an ABC800 utility which did -# about the same thing with Basic II bytecodes. -# -# history: -# 1.0 97-04-22 fl Created -# 1.1 97-05-25 fl Added base64 embedding option (-1) -# 97-05-25 fl Check for broken package file -# 1.2 97-05-26 fl Support uncompressed packages (-u) -# 1.3 97-05-27 fl Check byte code magic, eliminated StringIO, etc. -# 1.4 97-06-04 fl Removed last bits of white space, removed try/except -# 1.5 97-06-17 fl Added squeeze archive capabilities (-x) -# 1.6 98-05-04 fl Minor fixes in preparation for public source release -# -# reviews: -# "Fredrik Lundh is a friggin genius" -# -- Aaron Watters, author of 'Internet Programming with Python' -# -# "I agree ... this is a friggin Good Thing" -# -- Paul Everitt, Digital Creations -# -# Copyright (c) 1997 by Fredrik Lundh. -# Copyright (c) 1997-1998 by Secret Labs AB -# -# info@pythonware.com -# http://www.pythonware.com -# -# -------------------------------------------------------------------- -# Permission to use, copy, modify, and distribute this software and -# its associated documentation for any purpose and without fee is -# hereby granted. This software is provided as is. -# -------------------------------------------------------------------- - -VERSION = "1.6/98-05-04" -MAGIC = "[PANDASQUEEZE]" - -import base64, imp, marshal, os, sys - -# -------------------------------------------------------------------- -# usage - -def usage(): - print("\nSQUEEZE", VERSION, "(c) 1997-1998 by Secret Labs AB") - print("""\ -Convert a Python application to a compressed module package. - -Usage: squeeze [-1ux] -o app [-b start] modules... [-d files...] - -This utility creates a compressed package file named "app.pyz", which -contains the given module files. It also creates a bootstrap script -named "app.py", which loads the package and imports the given "start" -module to get things going. Example: - - squeeze -o app -b appMain app*.py - -The -1 option tells squeeze to put the package file inside the boot- -strap script using base64 encoding. The result is a single text file -containing the full application. - -The -u option disables compression. Otherwise, the package will be -compressed using zlib, and the user needs zlib to run the resulting -application. - -The -d option can be used to put additional files in the package file. -You can access these files via "__main__.open(filename)" (returns a -StringIO file object). - -The -x option can be used with -d to create a self-extracting archive, -instead of a package. When the resulting script is executed, the -data files are extracted. Omit the -b option in this case. -""") - sys.exit(1) - - -# -------------------------------------------------------------------- -# squeezer -- collect squeezed modules - -class Squeezer: - - def __init__(self): - - self.rawbytes = self.bytes = 0 - self.modules = {} - - def addmodule(self, file): - - if file[-1] == "c": - file = file[:-1] - - m = os.path.splitext(os.path.split(file)[1])[0] - - # read sourcefile - f = open(file) - codestring = f.read() - f.close() - - # dump to file - self.modules[m] = compile(codestring, m, "exec") - - def adddata(self, file): - - self.modules["+"+file] = open(file, "rb").read() - - def getarchive(self): - - # marshal our module dictionary - data = marshal.dumps(self.modules) - self.rawbytes = len(data) - - # return (compressed) dictionary - data = zlib.compress(data, 9) - self.bytes = len(data) - - return data - - def getstatus(self): - return self.bytes, self.rawbytes - - -# -------------------------------------------------------------------- -# loader (used in bootstrap code) - -loader = """ -import ihooks - -PYZ_MODULE = 64 - -class Loader(ihooks.ModuleLoader): - - def __init__(self, modules): - self.__modules = modules - return ihooks.ModuleLoader.__init__(self) - - def find_module(self, name, path = None): - try: - self.__modules[name] - return None, None, (None, None, PYZ_MODULE) - except KeyError: - return ihooks.ModuleLoader.find_module(self, name, path) - - def load_module(self, name, stuff): - file, filename, (suff, mode, type) = stuff - if type != PYZ_MODULE: - return ihooks.ModuleLoader.load_module(self, name, stuff) - #print "PYZ:", "import", name - basename = name.split('.')[-1] - code = self.__modules[basename] - del self.__modules[basename] # no need to keep this one around - m = self.hooks.add_module(name) - m.__file__ = filename - exec code in m.__dict__ - return m - -def boot(name, fp, size, offset = 0): - - global data - - try: - import %(modules)s - except ImportError: - #print "PYZ:", "failed to load marshal and zlib libraries" - return # cannot boot from PYZ file - #print "PYZ:", "boot from", name+".PYZ" - - # load archive and install import hook - if offset: - data = fp[offset:] - else: - data = fp.read(size) - fp.close() - - if len(data) != size: - raise IOError, "package is truncated" - - data = marshal.loads(%(data)s) - - ihooks.install(ihooks.ModuleImporter(Loader(data))) -""" - -loaderopen = """ - -def open(name): - from io import StringIO - try: - return StringIO(data["+"+name]) - except KeyError: - raise IOError, (0, "no such file") -""" - -loaderexplode = """ - -def explode(): - for k, v in data.items(): - if k[0] == "+": - try: - open(k[1:], "wb").write(v) - print k[1:], "extracted ok" - except IOError, v: - print k[1:], "failed:", "IOError", v - -""" - -def getloader(data, package): - - s = loader - - if data: - if explode: - s = s + loaderexplode - else: - s = s + loaderopen - - dict = { - "modules": "marshal, zlib", - "data": "zlib.decompress(data)", - } - - s = s % dict - - return marshal.dumps(compile(s, "", "exec")) - - -# -------------------------------------------------------------------- -# Main -# -------------------------------------------------------------------- - -# -# parse options - -import sys -import zlib - -embed = 0 -explode = 0 - -def squeeze(app, start, filelist, outputDir): - localMagic = MAGIC - data = None - - bootstrap = os.path.join(outputDir, app + ".py") - archiveBase = app + ".pyz" - archive = os.path.join(outputDir, archiveBase) - - archiveid = app - - # - # avoid overwriting files not generated by squeeze - - try: - fp = open(bootstrap) - s = fp.readline() - s.index(MAGIC) - except IOError: - pass - except ValueError: - print("%s was not created by squeeze. You have to manually" % (bootstrap)) - print("remove the file to proceed.") - sys.exit(1) - - # - # collect modules - - sq = Squeezer() - for file in filelist: - # print 'addmodule:', file - sq.addmodule(file) - - package = sq.getarchive() - size = len(package) - - # - # get loader - - loader = getloader(data, package) - - zbegin, zend = "zlib.decompress(", ")" - loader = zlib.compress(loader, 9) - - loaderlen = len(loader) - - magic = repr(imp.get_magic()) - version = sys.version.split()[0] - - # - # generate script and package files - - if embed: - - # embedded archive - data = base64.encodestring(loader + package) - - fp = open(bootstrap, "w") - fp.write('''\ -#%(localMagic)s %(archiveid)s -import ihooks, zlib, base64, marshal -s=base64.decodestring(""" -%(data)s""") -exec marshal.loads(%(zbegin)ss[:%(loaderlen)d]%(zend)s) -boot("%(app)s", s, %(size)d, %(loaderlen)d) -exec "import %(start)s" -''' % locals()) - bytes = fp.tell() - - else: - - # separate archive file - - fp = open(archive, "wb") - - fp.write(loader) - fp.write(package) - - bytes = fp.tell() - fp.close() - # - # create bootstrap code - - fp = open(bootstrap, "w") - # Note: David Rose adjusted the following to be panda-specific. - fp.write("""\ -#%(localMagic)s %(archiveid)s -import ihooks, zlib, marshal, os, sys - -def searchPath(filename): - # Look along panda3d.__path__ for the indicated filename. Returns - # the located pathname, or None if the filename is not found. - import panda3d - - for dir in panda3d.__path__: - pathname = os.path.join(dir, filename) - if os.path.exists(pathname): - return pathname - - return None - -# Look for %(archiveBase)s along panda3d.__path__. -archiveName = "%(archiveBase)s" -archivePath = searchPath(archiveName) -if archivePath == None: - raise ImportError, "Could not locate panda3d.%%s." %% (archiveName) - -f=open(archivePath,"rb") -exec marshal.loads(%(zbegin)sf.read(%(loaderlen)d)%(zend)s) -boot("%(app)s", f, %(size)d) -exec "from %(start)s import *" -#exec "run()" -""" % locals()) - bytes = bytes + fp.tell() - fp.close() - - # - # show statistics - - dummy, rawbytes = sq.getstatus() - - print("squeezed %s to %s (%d%%)" % (rawbytes, bytes, bytes * 100 / rawbytes)) diff --git a/direct/src/showbase/pandaSqueezer.py b/direct/src/showbase/pandaSqueezer.py deleted file mode 100644 index 84beee7813..0000000000 --- a/direct/src/showbase/pandaSqueezer.py +++ /dev/null @@ -1,57 +0,0 @@ -"""Undocumented Module""" - -__all__ = [] - -import os -import sys -import getopt -from . import pandaSqueezeTool - -# Assumption: We will be squeezing the files from the current directory or the -d directory. - -if __name__ == "__main__": - try: - opts, pargs = getopt.getopt(sys.argv[1:], 'Od:') - except Exception as e: - # User passed in a bad option, print the error and the help, then exit - print(e) - print('Usage: pass in -O for optimized') - print(' pass in -d directory') - sys.exit() - - fOptimized = 0 - # Store the option values into our variables - for opt in opts: - flag, value = opt - if (flag == '-O'): - fOptimized = 1 - print('Squeezing pyo files') - elif (flag == '-d'): - os.chdir(value) - - def getSqueezeableFiles(): - fileList = os.listdir(".") - newFileList = [] - if fOptimized: - targetFileExtension = ".pyo" - else: - targetFileExtension = ".pyc" - for i in fileList: - base, ext = os.path.splitext(i) - if (ext == ".py"): - newFileList.append(i) - return newFileList - - def squeezePandaFiles(): - l = getSqueezeableFiles() - pandaSqueezeTool.squeeze("PandaModules", "PandaModulesUnsqueezed", l) - - # Clean up the source files now that they've been squeezed. If - # you don't like this behavior (e.g. if you want to inspect the - # generated files), use genPyCode -n to avoid squeezing - # altogether. - for i in l: - os.unlink(i) - - - squeezePandaFiles() diff --git a/direct/src/showutil/FreezeTool.py b/direct/src/showutil/FreezeTool.py index 89016e274d..d75a79b56b 100644 --- a/direct/src/showutil/FreezeTool.py +++ b/direct/src/showutil/FreezeTool.py @@ -8,7 +8,7 @@ import marshal import imp import platform from io import StringIO -from distutils.sysconfig import PREFIX, get_python_inc, get_python_version, get_config_var +import distutils.sysconfig as sysconf # Temporary (?) try..except to protect against unbuilt p3extend_frozen. try: @@ -29,9 +29,23 @@ isDebugBuild = (python.lower().endswith('_d')) # These are modules that Python always tries to import up-front. They # must be frozen in any main.exe. startupModules = [ - 'os', 'encodings.cp1252', - 'encodings.latin_1', 'encodings.utf_8', 'io', + 'encodings.cp1252', 'encodings.latin_1', 'encodings.utf_8', ] +if sys.version_info >= (3, 0): + startupModules += ['io', 'marshal', 'importlib.machinery', 'importlib.util'] + +# These are some special init functions for some built-in Python modules that +# deviate from the standard naming convention. A value of None means that a +# dummy entry should be written to the inittab. +builtinInitFuncs = { + 'builtins': None, + '__builtin__': None, + 'sys': None, + 'exceptions': None, + '_imp': 'PyInit_imp', + '_warnings': '_PyWarnings_Init', + 'marshal': 'PyMarshal_Init', +} # These are missing modules that we've reported already this session. reportedMissing = {} @@ -60,8 +74,8 @@ class CompilationEnvironment: # Paths to Python stuff. self.Python = None - self.PythonIPath = get_python_inc() - self.PythonVersion = get_config_var("LDVERSION") or get_python_version() + self.PythonIPath = sysconf.get_python_inc() + self.PythonVersion = sysconf.get_config_var("LDVERSION") or sysconf.get_python_version() # The VC directory of Microsoft Visual Studio (if relevant) self.MSVC = None @@ -85,7 +99,7 @@ class CompilationEnvironment: def determineStandardSetup(self): if self.platform.startswith('win'): - self.Python = PREFIX + self.Python = sysconf.PREFIX if ('VCINSTALLDIR' in os.environ): self.MSVC = os.environ['VCINSTALLDIR'] @@ -122,13 +136,15 @@ class CompilationEnvironment: # If it is run by makepanda, it handles the MSVC and PlatformSDK paths itself. if ('MAKEPANDA' in os.environ): - self.compileObj = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" %(filename)s' + self.compileObjExe = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" %(filename)s' + self.compileObjDll = self.compileObjExe self.linkExe = 'link /nologo /MAP:NUL /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO /LIBPATH:"%(python)s\libs" /out:%(basename)s.exe %(basename)s.obj' self.linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(python)s\libs" /out:%(basename)s%(dllext)s.pyd %(basename)s.obj' else: os.environ['PATH'] += ';' + self.MSVC + '\\bin' + self.suffix64 + ';' + self.MSVC + '\\Common7\\IDE;' + self.PSDK + '\\bin' - self.compileObj = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" /I"%(PSDK)s\include" /I"%(MSVC)s\include" %(filename)s' + self.compileObjExe = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" /I"%(PSDK)s\include" /I"%(MSVC)s\include" %(filename)s' + self.compileObjDll = self.compileObjExe self.linkExe = 'link /nologo /MAP:NUL /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO /LIBPATH:"%(PSDK)s\lib" /LIBPATH:"%(MSVC)s\\lib%(suffix64)s" /LIBPATH:"%(python)s\libs" /out:%(basename)s.exe %(basename)s.obj' self.linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(PSDK)s\lib" /LIBPATH:"%(MSVC)s\\lib%(suffix64)s" /LIBPATH:"%(python)s\libs" /out:%(basename)s%(dllext)s.pyd %(basename)s.obj' @@ -141,22 +157,26 @@ class CompilationEnvironment: self.arch = '-arch ppc' elif proc == 'amd64': self.arch = '-arch x86_64' - self.compileObj = "gcc -fPIC -c %(arch)s -o %(basename)s.o -O2 -I%(pythonIPath)s %(filename)s" + self.compileObjExe = "gcc -c %(arch)s -o %(basename)s.o -O2 -I%(pythonIPath)s %(filename)s" + self.compileObjDll = "gcc -fPIC -c %(arch)s -o %(basename)s.o -O2 -I%(pythonIPath)s %(filename)s" self.linkExe = "gcc %(arch)s -o %(basename)s %(basename)s.o -framework Python" self.linkDll = "gcc %(arch)s -undefined dynamic_lookup -bundle -o %(basename)s.so %(basename)s.o" else: # Unix - self.compileObj = "gcc -fPIC -c -o %(basename)s.o -O2 %(filename)s -I%(pythonIPath)s" - self.linkExe = "gcc -o %(basename)s %(basename)s.o -L/usr/local/lib -lpython%(pythonVersion)s" - self.linkDll = "gcc -shared -o %(basename)s.so %(basename)s.o -L/usr/local/lib -lpython%(pythonVersion)s" + lib_dir = sysconf.get_python_lib(plat_specific=1, standard_lib=1) + #python_a = os.path.join(lib_dir, "config", "libpython%(pythonVersion)s.a") + self.compileObjExe = "%(CC)s %(CFLAGS)s -c -o %(basename)s.o -pthread -O2 %(filename)s -I%(pythonIPath)s" + self.compileObjDll = "%(CC)s %(CFLAGS)s %(CCSHARED)s -c -o %(basename)s.o -O2 %(filename)s -I%(pythonIPath)s" + self.linkExe = "%(CC)s -o %(basename)s %(basename)s.o -L/usr/local/lib -lpython%(pythonVersion)s" + self.linkDll = "%(LDSHARED)s -o %(basename)s.so %(basename)s.o -L/usr/local/lib -lpython%(pythonVersion)s" if (os.path.isdir("/usr/PCBSD/local/lib")): self.linkExe += " -L/usr/PCBSD/local/lib" self.linkDll += " -L/usr/PCBSD/local/lib" - def compileExe(self, filename, basename): - compile = self.compileObj % { + def compileExe(self, filename, basename, extraLink=[]): + compile = self.compileObjExe % dict({ 'python' : self.Python, 'MSVC' : self.MSVC, 'PSDK' : self.PSDK, @@ -167,12 +187,12 @@ class CompilationEnvironment: 'arch' : self.arch, 'filename' : filename, 'basename' : basename, - } + }, **sysconf.get_config_vars()) sys.stderr.write(compile + '\n') if os.system(compile) != 0: raise Exception('failed to compile %s.' % basename) - link = self.linkExe % { + link = self.linkExe % dict({ 'python' : self.Python, 'MSVC' : self.MSVC, 'PSDK' : self.PSDK, @@ -182,13 +202,14 @@ class CompilationEnvironment: 'arch' : self.arch, 'filename' : filename, 'basename' : basename, - } + }, **sysconf.get_config_vars()) + link += ' ' + ' '.join(extraLink) sys.stderr.write(link + '\n') if os.system(link) != 0: raise Exception('failed to link %s.' % basename) - def compileDll(self, filename, basename): - compile = self.compileObj % { + def compileDll(self, filename, basename, extraLink=[]): + compile = self.compileObjDll % dict({ 'python' : self.Python, 'MSVC' : self.MSVC, 'PSDK' : self.PSDK, @@ -199,12 +220,12 @@ class CompilationEnvironment: 'arch' : self.arch, 'filename' : filename, 'basename' : basename, - } + }, **sysconf.get_config_vars()) sys.stderr.write(compile + '\n') if os.system(compile) != 0: raise Exception('failed to compile %s.' % basename) - link = self.linkDll % { + link = self.linkDll % dict({ 'python' : self.Python, 'MSVC' : self.MSVC, 'PSDK' : self.PSDK, @@ -215,7 +236,8 @@ class CompilationEnvironment: 'filename' : filename, 'basename' : basename, 'dllext' : self.dllext, - } + }, **sysconf.get_config_vars()) + link += ' ' + ' '.join(extraLink) sys.stderr.write(link + '\n') if os.system(link) != 0: raise Exception('failed to link %s.' % basename) @@ -233,7 +255,8 @@ frozenMainCode = """ #ifdef MS_WINDOWS extern void PyWinFreeze_ExeInit(void); extern void PyWinFreeze_ExeTerm(void); -extern int PyInitFrozenExtensions(void); + +extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab); #endif /* Main program */ @@ -264,6 +287,8 @@ Py_FrozenMain(int argc, char **argv) #endif Py_FrozenFlag = 1; /* Suppress errors from getpath.c */ + Py_NoSiteFlag = 1; + Py_NoUserSiteDirectory = 1; if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\\0') inspect = 1; @@ -300,7 +325,7 @@ Py_FrozenMain(int argc, char **argv) #endif #ifdef MS_WINDOWS - PyInitFrozenExtensions(); + PyImport_ExtendInittab(extensions); #endif /* MS_WINDOWS */ if (argc >= 1) { @@ -344,8 +369,8 @@ Py_FrozenMain(int argc, char **argv) #endif Py_Finalize(); -error: #if PY_MAJOR_VERSION >= 3 +error: PyMem_RawFree(argv_copy); if (argv_copy2) { for (i = 0; i < argc; i++) @@ -463,10 +488,6 @@ main(int argc, char *argv[]) { # Our own glue code to start up a Python shared library. dllInitCode = """ -static PyMethodDef nullMethods[] = { - {NULL, NULL} -}; - /* * Call this function to extend the frozen modules array with a new * array of frozen modules, provided in a C-style array, at runtime. @@ -508,10 +529,29 @@ extend_frozen_modules(const struct _frozen *new_modules, int new_count) { return orig_count + new_count; } -%(dllexport)svoid init%(moduleName)s() { +#if PY_MAJOR_VERSION >= 3 +static PyModuleDef mdef = { + PyModuleDef_HEAD_INIT, + "%(moduleName)s", + "", + -1, + NULL, NULL, NULL, NULL, NULL +}; + +%(dllexport)sPyObject *PyInit_%(moduleName)s(void) { + extend_frozen_modules(_PyImport_FrozenModules, sizeof(_PyImport_FrozenModules) / sizeof(struct _frozen)); + return PyModule_Create(&mdef); +} +#else +static PyMethodDef nullMethods[] = { + {NULL, NULL} +}; + +%(dllexport)svoid init%(moduleName)s(void) { extend_frozen_modules(_PyImport_FrozenModules, sizeof(_PyImport_FrozenModules) / sizeof(struct _frozen)); Py_InitModule("%(moduleName)s", nullMethods); } +#endif """ programFile = """ @@ -526,24 +566,8 @@ struct _frozen _PyImport_FrozenModules[] = { %(moduleList)s {NULL, NULL, 0} }; - -%(initCode)s """ -# Windows needs this bit. -frozenExtensions = """ - -static struct _inittab extensions[] = { - /* Sentinel */ - {0, 0} -}; -extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab); - -int PyInitFrozenExtensions() -{ - return PyImport_ExtendInittab(extensions); -} -""" okMissing = [ '__main__', '_dummy_threading', 'Carbon', 'Carbon.Files', @@ -645,14 +669,13 @@ class Freezer: if self.platform.startswith('win'): self.objectExtension = '.obj' - self.keepTemporaryFiles = True + self.keepTemporaryFiles = False # Change any of these to change the generated startup and glue # code. self.frozenMainCode = frozenMainCode self.frozenDllMainCode = frozenDllMainCode self.mainInitCode = mainInitCode - self.frozenExtensions = frozenExtensions # Set this true to encode Python files in a Multifile as their # original source if possible, or false to encode them as @@ -664,9 +687,14 @@ class Freezer: # addToMultifile(). It contains a list of all the extension # modules that were discovered, which have not been added to # the output. The list is a list of tuples of the form - # (moduleName, filename). + # (moduleName, filename). filename will be None for built-in + # modules. self.extras = [] + # Set this to true if extension modules should be linked in to + # the resulting executable. + self.linkExtensionModules = False + # End of public interface. These remaining members should not # be directly manipulated by callers. self.previousModules = {} @@ -676,6 +704,10 @@ class Freezer: self.previousModules = dict(previous.modules) self.modules = dict(previous.modules) + # Exclude doctest by default; it is not very useful in production + # builds. It can be explicitly included if desired. + self.modules['doctest'] = self.ModuleDef('doctest', exclude = True) + self.mf = None # Actually, make sure we know how to find all of the @@ -951,8 +983,8 @@ class Freezer: for mdef in includes: try: self.__loadModule(mdef) - except ImportError: - print("Unknown module: %s" % (mdef.moduleName)) + except ImportError as ex: + print("Unknown module: %s (%s)" % (mdef.moduleName, str(ex))) # Also attempt to import any implicit modules. If any of # these fail to import, we don't really care. @@ -1158,7 +1190,7 @@ class Freezer: if self.storePythonSource: filename += '.py' - stream = StringStream('') + stream = StringStream(b'') if multifile.findSubfile(filename) < 0: multifile.addSubfile(filename, stream, 0) multifile.flush() @@ -1296,41 +1328,116 @@ class Freezer: if mdef.forbid: # Explicitly disallow importing this module. moduleList.append(self.makeForbiddenModuleListEntry(moduleName)) - else: - assert not mdef.exclude - # Allow importing this module. - module = self.mf.modules.get(origName, None) - code = getattr(module, "__code__", None) - if code: - code = marshal.dumps(code) + continue - mangledName = self.mangleName(moduleName) - moduleDefs.append(self.makeModuleDef(mangledName, code)) - moduleList.append(self.makeModuleListEntry(mangledName, code, moduleName, module)) + assert not mdef.exclude + # Allow importing this module. + module = self.mf.modules.get(origName, None) + code = getattr(module, "__code__", None) + if code: + code = marshal.dumps(code) - elif moduleName in startupModules: - # Forbid the loading of this startup module. - moduleList.append(self.makeForbiddenModuleListEntry(moduleName)) + mangledName = self.mangleName(moduleName) + moduleDefs.append(self.makeModuleDef(mangledName, code)) + moduleList.append(self.makeModuleListEntry(mangledName, code, moduleName, module)) + continue - else: - # This is a module with no associated Python - # code. It must be an extension module. Get the - # filename. - extensionFilename = getattr(module, '__file__', None) - if extensionFilename: - self.extras.append((moduleName, extensionFilename)) - else: - # It doesn't even have a filename; it must - # be a built-in module. No worries about - # this one, then. - pass + #if moduleName in startupModules: + # # Forbid the loading of this startup module. + # moduleList.append(self.makeForbiddenModuleListEntry(moduleName)) + # continue + + # This is a module with no associated Python code. It is either + # an extension module or a builtin module. Get the filename, if + # it is the former. + extensionFilename = getattr(module, '__file__', None) + + if extensionFilename or self.linkExtensionModules: + self.extras.append((moduleName, extensionFilename)) + + # If it is a submodule of a frozen module, Python will have + # trouble importing it as a builtin module. Synthesize a frozen + # module that loads it as builtin. + if '.' in moduleName and self.linkExtensionModules: + code = compile('import sys;del sys.modules["%s"];import imp;imp.init_builtin("%s")' % (moduleName, moduleName), moduleName, 'exec') + code = marshal.dumps(code) + mangledName = self.mangleName(moduleName) + moduleDefs.append(self.makeModuleDef(mangledName, code)) + moduleList.append(self.makeModuleListEntry(mangledName, code, moduleName, None)) + elif '.' in moduleName: + # Nothing we can do about this case except warn the user they + # are in for some trouble. + print('WARNING: Python cannot import extension modules under ' + 'frozen Python packages; %s will be inaccessible. ' + 'passing either -l to link in extension modules or use ' + '-x %s to exclude the entire package.' % (moduleName, moduleName.split('.')[0])) text = programFile % { 'moduleDefs': '\n'.join(moduleDefs), 'moduleList': '\n'.join(moduleList), - 'initCode': initCode } + if self.linkExtensionModules and self.extras: + # Should we link in extension modules? If so, we write out a new + # built-in module table that directly hooks up with the init + # functions. On Linux, we completely override Python's own + # built-in module table; on Windows, we can't do this, so we + # instead use PyImport_ExtendInittab to add to it. + + # Python 3 case. + text += '#if PY_MAJOR_VERSION >= 3\n' + for module, fn in self.extras: + if sys.platform != "win32" or fn: + libName = module.split('.')[-1] + initFunc = builtinInitFuncs.get(module, 'PyInit_' + libName) + if initFunc: + text += 'extern DL_IMPORT(PyObject) *%s(void);\n' % (initFunc) + text += '\n' + + if sys.platform == "win32": + text += 'static struct _inittab extensions[] = {\n' + else: + text += 'struct _inittab _PyImport_Inittab[] = {\n' + + for module, fn in self.extras: + if sys.platform != "win32" or fn: + libName = module.split('.')[-1] + initFunc = builtinInitFuncs.get(module, 'PyInit_' + libName) or 'NULL' + text += ' {"%s", %s},\n' % (module, initFunc) + text += ' {0, 0},\n' + text += '};\n\n' + + # Python 2 case. + text += '#else\n' + for module, fn in self.extras: + if sys.platform != "win32" or fn: + libName = module.split('.')[-1] + initFunc = builtinInitFuncs.get(module, 'init' + libName) + if initFunc: + text += 'extern DL_IMPORT(void) %s(void);\n' % (initFunc) + text += '\n' + + if sys.platform == "win32": + text += 'static struct _inittab extensions[] = {\n' + else: + text += 'struct _inittab _PyImport_Inittab[] = {\n' + + for module, fn in self.extras: + if sys.platform != "win32" or fn: + libName = module.split('.')[-1] + initFunc = builtinInitFuncs.get(module, 'init' + libName) or 'NULL' + text += ' {"%s", %s},\n' % (module, initFunc) + text += ' {0, 0},\n' + text += '};\n' + text += '#endif\n\n' + + elif sys.platform == "win32": + text += 'static struct _inittab extensions[] = {\n' + text += ' {0, 0},\n' + text += '};\n\n' + + text += initCode + if filename is not None: file = open(filename, 'w') file.write(text) @@ -1375,7 +1482,6 @@ class Freezer: 'dllimport' : dllimport, } if self.platform.startswith('win'): - initCode += self.frozenExtensions target = basename + '.exe' else: target = basename @@ -1397,14 +1503,46 @@ class Freezer: self.writeCode(filename, initCode=initCode) + # Keep track of the files we should clean up after use. + cleanFiles = [filename, basename + self.objectExtension] + + extraLink = [] + if self.linkExtensionModules: + for mod, fn in self.extras: + if not fn: + continue + if sys.platform == 'win32': + # We can't link with a .pyd directly on Windows. Check + # if there is a corresponding .lib file in the Python libs + # directory. + libsdir = os.path.join(sys.exec_prefix, 'libs') + libfile = os.path.join(libsdir, mod + '.lib') + if os.path.isfile(libfile): + extraLink.append(mod + '.lib') + continue + + # No, so we have to generate a .lib file. This is pretty + # easy given that we know the only symbol we need is a + # initmodule or PyInit_module function. + modname = mod.split('.')[-1] + libfile = modname + '.lib' + if sys.version_info >= (3, 0): + symbolName = 'PyInit_' + modname + else: + symbolName = 'init' + modname + os.system('lib /nologo /def /export:%s /name:%s.pyd /out:%s' % (symbolName, modname, libfile)) + extraLink.append(libfile) + cleanFiles += [libfile, modname + '.exp'] + else: + extraLink.append(fn) + try: - compileFunc(filename, basename) + compileFunc(filename, basename, extraLink=extraLink) finally: if not self.keepTemporaryFiles: - if os.path.exists(filename): - os.unlink(filename) - if os.path.exists(basename + self.objectExtension): - os.unlink(basename + self.objectExtension) + for file in cleanFiles: + if os.path.exists(file): + os.unlink(file) return target diff --git a/direct/src/showutil/pfreeze.py b/direct/src/showutil/pfreeze.py index 8676251026..04397d31d9 100755 --- a/direct/src/showutil/pfreeze.py +++ b/direct/src/showutil/pfreeze.py @@ -15,7 +15,7 @@ imported directly or indirectly by the original startfile.py. Usage: - pfreeze.py [opts] startfile + pfreeze.py [opts] [startfile] Options: @@ -40,11 +40,20 @@ Options: of the __path__ variable, and thus must be actually imported to determine the true value of __path__. + -P path + Specifies an additional directory in which we should search for + Python modules. This is equivalent to setting the PYTHONPATH + environment variable. May be repeated. + -s Adds the standard set of modules that are necessary for embedding the Python interpreter. Implicitly set if an executable is generated. + -k + Keeps temporary files generated by pfreeze. Useful when debugging + FreezeTool itself. + """ import getopt @@ -55,7 +64,7 @@ from direct.showutil import FreezeTool def usage(code, msg = ''): if __doc__: sys.stderr.write(__doc__ + '\n') - sys.stderr.write(msg + '\n') + sys.stderr.write(str(msg) + '\n') sys.exit(code) # We're not protecting the next part under a __name__ == __main__ @@ -67,7 +76,7 @@ basename = None addStartupModules = False try: - opts, args = getopt.getopt(sys.argv[1:], 'o:i:x:p:sh') + opts, args = getopt.getopt(sys.argv[1:], 'o:i:x:p:P:slkh') except getopt.error as msg: usage(1, msg) @@ -83,8 +92,14 @@ for opt, arg in opts: elif opt == '-p': for module in arg.split(','): freezer.handleCustomPath(module) + elif opt == '-P': + sys.path.append(arg) elif opt == '-s': addStartupModules = True + elif opt == '-l': + freezer.linkExtensionModules = True + elif opt == '-k': + freezer.keepTemporaryFiles = True elif opt == '-h': usage(0) else: @@ -126,7 +141,7 @@ if args: elif outputType == 'exe': # We must have a main module when making an executable. - usage(0) + usage(1, 'A main file needs to be specified when creating an executable.') freezer.done(addStartupModules = addStartupModules) diff --git a/direct/src/stdpy/pickle.py b/direct/src/stdpy/pickle.py index 57e7c2521c..027888e281 100644 --- a/direct/src/stdpy/pickle.py +++ b/direct/src/stdpy/pickle.py @@ -21,10 +21,14 @@ context between all objects written by that Pickler. Unfortunately, cPickle cannot be supported, because it does not support extensions of this nature. """ -from types import * -from copy_reg import dispatch_table +import sys from panda3d.core import BamWriter, BamReader +if sys.version_info >= (3, 0): + from copyreg import dispatch_table +else: + from copy_reg import dispatch_table + # A funny replacement for "import pickle" so we don't get confused # with the local pickle.py. pickle = __import__('pickle') @@ -60,7 +64,7 @@ class Pickler(pickle.Pickler): # Check for a class with a custom metaclass; treat as regular class try: - issc = issubclass(t, TypeType) + issc = issubclass(t, type) except TypeError: # t is not a class (old Boost; see SF #502085) issc = 0 if issc: @@ -91,12 +95,12 @@ class Pickler(pickle.Pickler): (t.__name__, obj)) # Check for string returned by reduce(), meaning "save as global" - if type(rv) is StringType: + if type(rv) is str: self.save_global(obj, rv) return # Assert that reduce() returned a tuple - if type(rv) is not TupleType: + if type(rv) is not tuple: raise PicklingError("%s must return string or tuple" % reduce) # Assert that it returned an appropriately sized tuple @@ -131,21 +135,20 @@ class Unpickler(pickle.Unpickler): value = func(*args) stack[-1] = value - pickle.Unpickler.dispatch[pickle.REDUCE] = load_reduce + + #FIXME: how to replace in Python 3? + if sys.version_info < (3, 0): + pickle.Unpickler.dispatch[pickle.REDUCE] = load_reduce # Shorthands - -try: - from cStringIO import StringIO -except ImportError: - from io import StringIO +from io import BytesIO def dump(obj, file, protocol=None): Pickler(file, protocol).dump(obj) def dumps(obj, protocol=None): - file = StringIO() + file = BytesIO() Pickler(file, protocol).dump(obj) return file.getvalue() @@ -153,5 +156,5 @@ def load(file): return Unpickler(file).load() def loads(str): - file = StringIO(str) + file = BytesIO(str) return Unpickler(file).load() diff --git a/direct/src/stdpy/threading.py b/direct/src/stdpy/threading.py index 4c0ce1e8fb..5c8af3cc62 100644 --- a/direct/src/stdpy/threading.py +++ b/direct/src/stdpy/threading.py @@ -53,12 +53,6 @@ class ThreadBase: def getName(self): return self.name - def is_alive(self): - return self.__thread.isStarted() - - def isAlive(self): - return self.__thread.isStarted() - def isDaemon(self): return self.daemon @@ -114,6 +108,12 @@ class Thread(ThreadBase): if _thread and _thread._remove_thread_id: _thread._remove_thread_id(self.ident) + def is_alive(self): + return self.__thread.isStarted() + + def isAlive(self): + return self.__thread.isStarted() + def start(self): if self.__thread.isStarted(): raise RuntimeError @@ -151,6 +151,12 @@ class ExternalThread(ThreadBase): self.__dict__['name'] = self.__thread.getName() self.__dict__['ident'] = threadId + def is_alive(self): + return self.__thread.isStarted() + + def isAlive(self): + return self.__thread.isStarted() + def start(self): raise RuntimeError diff --git a/direct/src/task/Task.py b/direct/src/task/Task.py index e12b64078d..300be02f71 100644 --- a/direct/src/task/Task.py +++ b/direct/src/task/Task.py @@ -397,7 +397,6 @@ class TaskManager: 'Task %s does not accept arguments.' % (repr(task))) if name is not None: - assert isinstance(name, str), 'Name must be a string type' task.setName(name) assert task.hasName() @@ -431,16 +430,14 @@ class TaskManager: all tasks with the indicated name are removed. Returns the number of tasks removed. """ - if isinstance(taskOrName, str): - tasks = self.mgr.findTasks(taskOrName) - return self.mgr.remove(tasks) - elif isinstance(taskOrName, AsyncTask): + if isinstance(taskOrName, AsyncTask): return self.mgr.remove(taskOrName) elif isinstance(taskOrName, list): for task in taskOrName: self.remove(task) else: - self.notify.error('remove takes a string or a Task') + tasks = self.mgr.findTasks(taskOrName) + return self.mgr.remove(tasks) def removeTasksMatching(self, taskPattern): """Removes all tasks whose names match the pattern, which can diff --git a/direct/src/tkpanels/ParticlePanel.py b/direct/src/tkpanels/ParticlePanel.py index b712d7c7fb..81d00aefc9 100644 --- a/direct/src/tkpanels/ParticlePanel.py +++ b/direct/src/tkpanels/ParticlePanel.py @@ -1976,9 +1976,9 @@ class ParticlePanel(AppShell): self.particles.renderer.setAlphaDisable( self.getVariable('Sprite Renderer', 'Alpha Disable').get()) def setRendererColorBlendAttrib(self, rendererName, blendMethodStr, incomingOperandStr, fbufferOperandStr): - self.particles.getRenderer().setColorBlendMode(eval('ColorBlendAttrib.'+blendMethodStr), - eval('ColorBlendAttrib.'+incomingOperandStr), - eval('ColorBlendAttrib.'+fbufferOperandStr)) + self.particles.getRenderer().setColorBlendMode(getattr(ColorBlendAttrib, blendMethodStr), + getattr(ColorBlendAttrib, incomingOperandStr), + getattr(ColorBlendAttrib, fbufferOperandStr)) if(blendMethodStr in ['MAdd','MSubtract','MInvSubtract']): self.getWidget(rendererName,'Incoming Op.').pack(fill = X) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index da1575fcdd..a4a0b49a02 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -1,3 +1,45 @@ +------------------------ RELEASE 1.9.3 ------------------------ + +This issue fixes several bugs that were still found in 1.9.2. + +* 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 +* Fix random crashes in task system +* Fix memory leaks in BulletTriangleMesh +* Fix loading old models with MovingPart +* Improve performance of CPU vertex animation somewhat +* Show framebuffer properties when fbprop request fails +* Fix hang on exit when using Python task on threaded task chain +* Fix inability to get RGBA renderbuffer in certain cases +* Work around GLSL issue with #pragma and certain Intel drivers +* Improve performance of texture load and store operations +* Fix crashes with pbuffers on Intel cards on Windows + +------------------------ RELEASE 1.9.2 ------------------------ + +This is a minor bugfix release, fixing a few minor issues that +remained in the 1.9.1 release, including: + +* Fix compile errors with more recent versions of ffmpeg +* Include .lib files for pyd modules in Windows SDK +* packp3d now recognizes default egg-object-type definitions +* Fix issues with sphere-into-box and box-into-sphere collisions +* Texture VRAM usage is now correctly reported by pstats +* Support for reading BMP files with alpha channel +* Fix OpenGL crashes in very ancient OpenGL versions +* Fix rare compile issues and crashes with esoteric Python set-ups +* Fix crash when extracting texture that's not a multiple of 4 bytes +* Work around buggy NVIDIA driver that reports _main_* shader inputs +* Add version of transform_vertices that accepts a SparseArray +* Clamp shininess to 0 to avoid GL error when shininess < 0 +* Fix various bugs in RopeNode and NurbsCurveEvaluator +* Fix clock-mode Config.prc settings +* NodePath render_mode setters no longer reset wireframe color +* Fix constant reloading of texture when gl-ignore-mipmaps is set +* BamReader now releases the GIL (so it can be used threaded) +* Fix AttributeError in direct.stdpy.threading module + ------------------------ RELEASE 1.9.1 ------------------------ This minor release fixes some important regressions and bugs found diff --git a/dtool/src/cppparser/cppBison.cxx.prebuilt b/dtool/src/cppparser/cppBison.cxx.prebuilt index f77f3b77d6..697bc6c30a 100644 --- a/dtool/src/cppparser/cppBison.cxx.prebuilt +++ b/dtool/src/cppparser/cppBison.cxx.prebuilt @@ -1,19 +1,19 @@ -/* A Bison parser, made by GNU Bison 2.7. */ +/* A Bison parser, made by GNU Bison 3.0.4. */ /* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. - + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -26,7 +26,7 @@ special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. - + This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ @@ -44,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.7" +#define YYBISON_VERSION "3.0.4" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -63,15 +63,12 @@ #define yyparse cppyyparse #define yylex cppyylex #define yyerror cppyyerror -#define yylval cppyylval -#define yychar cppyychar #define yydebug cppyydebug #define yynerrs cppyynerrs -#define yylloc cppyylloc + /* Copy the first part of user declarations. */ -/* Line 371 of yacc.c */ -#line 6 "dtool/src/cppparser/cppBison.yxx" +#line 7 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:339 */ #include "cppBisonDefs.h" @@ -265,14 +262,13 @@ pop_struct() { } -/* Line 371 of yacc.c */ -#line 270 "built/tmp/cppBison.yxx.c" +#line 266 "built/tmp/cppBison.yxx.c" /* yacc.c:339 */ -# ifndef YY_NULL +# ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULL nullptr +# define YY_NULLPTR nullptr # else -# define YY_NULL 0 +# define YY_NULLPTR 0 # endif # endif @@ -288,7 +284,7 @@ pop_struct() { by #include "cppBison.yxx.h". */ #ifndef YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED # define YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED -/* Enabling traces. */ +/* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif @@ -296,134 +292,135 @@ pop_struct() { extern int cppyydebug; #endif -/* Tokens. */ +/* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - REAL = 258, - INTEGER = 259, - CHAR_TOK = 260, - SIMPLE_STRING = 261, - SIMPLE_IDENTIFIER = 262, - STRING_LITERAL = 263, - CUSTOM_LITERAL = 264, - IDENTIFIER = 265, - TYPENAME_IDENTIFIER = 266, - SCOPING = 267, - TYPEDEFNAME = 268, - ELLIPSIS = 269, - OROR = 270, - ANDAND = 271, - EQCOMPARE = 272, - NECOMPARE = 273, - LECOMPARE = 274, - GECOMPARE = 275, - LSHIFT = 276, - RSHIFT = 277, - POINTSAT_STAR = 278, - DOT_STAR = 279, - UNARY = 280, - UNARY_NOT = 281, - UNARY_NEGATE = 282, - UNARY_MINUS = 283, - UNARY_PLUS = 284, - UNARY_STAR = 285, - UNARY_REF = 286, - POINTSAT = 287, - SCOPE = 288, - PLUSPLUS = 289, - MINUSMINUS = 290, - TIMESEQUAL = 291, - DIVIDEEQUAL = 292, - MODEQUAL = 293, - PLUSEQUAL = 294, - MINUSEQUAL = 295, - OREQUAL = 296, - ANDEQUAL = 297, - XOREQUAL = 298, - LSHIFTEQUAL = 299, - RSHIFTEQUAL = 300, - KW_ALIGNAS = 301, - KW_ALIGNOF = 302, - KW_AUTO = 303, - KW_BEGIN_PUBLISH = 304, - KW_BLOCKING = 305, - KW_BOOL = 306, - KW_CATCH = 307, - KW_CHAR = 308, - KW_CHAR16_T = 309, - KW_CHAR32_T = 310, - KW_CLASS = 311, - KW_CONST = 312, - KW_CONSTEXPR = 313, - KW_CONST_CAST = 314, - KW_DECLTYPE = 315, - KW_DEFAULT = 316, - KW_DELETE = 317, - KW_DOUBLE = 318, - KW_DYNAMIC_CAST = 319, - KW_ELSE = 320, - KW_END_PUBLISH = 321, - KW_ENUM = 322, - KW_EXTENSION = 323, - KW_EXTERN = 324, - KW_EXPLICIT = 325, - KW_PUBLISHED = 326, - KW_FALSE = 327, - KW_FINAL = 328, - KW_FLOAT = 329, - KW_FRIEND = 330, - KW_FOR = 331, - KW_GOTO = 332, - KW_IF = 333, - KW_INLINE = 334, - KW_INT = 335, - KW_LONG = 336, - KW_MAKE_PROPERTY = 337, - KW_MAKE_PROPERTY2 = 338, - KW_MAKE_SEQ = 339, - KW_MUTABLE = 340, - KW_NAMESPACE = 341, - KW_NEW = 342, - KW_NOEXCEPT = 343, - KW_NULLPTR = 344, - KW_OPERATOR = 345, - KW_OVERRIDE = 346, - KW_PRIVATE = 347, - KW_PROTECTED = 348, - KW_PUBLIC = 349, - KW_REGISTER = 350, - KW_REINTERPRET_CAST = 351, - KW_RETURN = 352, - KW_SHORT = 353, - KW_SIGNED = 354, - KW_SIZEOF = 355, - KW_STATIC = 356, - KW_STATIC_ASSERT = 357, - KW_STATIC_CAST = 358, - KW_STRUCT = 359, - KW_TEMPLATE = 360, - KW_THREAD_LOCAL = 361, - KW_THROW = 362, - KW_TRUE = 363, - KW_TRY = 364, - KW_TYPEDEF = 365, - KW_TYPEID = 366, - KW_TYPENAME = 367, - KW_UNION = 368, - KW_UNSIGNED = 369, - KW_USING = 370, - KW_VIRTUAL = 371, - KW_VOID = 372, - KW_VOLATILE = 373, - KW_WCHAR_T = 374, - KW_WHILE = 375, - START_CPP = 376, - START_CONST_EXPR = 377, - START_TYPE = 378 - }; + enum yytokentype + { + REAL = 258, + INTEGER = 259, + CHAR_TOK = 260, + SIMPLE_STRING = 261, + SIMPLE_IDENTIFIER = 262, + STRING_LITERAL = 263, + CUSTOM_LITERAL = 264, + IDENTIFIER = 265, + TYPENAME_IDENTIFIER = 266, + SCOPING = 267, + TYPEDEFNAME = 268, + ELLIPSIS = 269, + OROR = 270, + ANDAND = 271, + EQCOMPARE = 272, + NECOMPARE = 273, + LECOMPARE = 274, + GECOMPARE = 275, + LSHIFT = 276, + RSHIFT = 277, + POINTSAT_STAR = 278, + DOT_STAR = 279, + UNARY = 280, + UNARY_NOT = 281, + UNARY_NEGATE = 282, + UNARY_MINUS = 283, + UNARY_PLUS = 284, + UNARY_STAR = 285, + UNARY_REF = 286, + POINTSAT = 287, + SCOPE = 288, + PLUSPLUS = 289, + MINUSMINUS = 290, + TIMESEQUAL = 291, + DIVIDEEQUAL = 292, + MODEQUAL = 293, + PLUSEQUAL = 294, + MINUSEQUAL = 295, + OREQUAL = 296, + ANDEQUAL = 297, + XOREQUAL = 298, + LSHIFTEQUAL = 299, + RSHIFTEQUAL = 300, + KW_ALIGNAS = 301, + KW_ALIGNOF = 302, + KW_AUTO = 303, + KW_BEGIN_PUBLISH = 304, + KW_BLOCKING = 305, + KW_BOOL = 306, + KW_CATCH = 307, + KW_CHAR = 308, + KW_CHAR16_T = 309, + KW_CHAR32_T = 310, + KW_CLASS = 311, + KW_CONST = 312, + KW_CONSTEXPR = 313, + KW_CONST_CAST = 314, + KW_DECLTYPE = 315, + KW_DEFAULT = 316, + KW_DELETE = 317, + KW_DOUBLE = 318, + KW_DYNAMIC_CAST = 319, + KW_ELSE = 320, + KW_END_PUBLISH = 321, + KW_ENUM = 322, + KW_EXTENSION = 323, + KW_EXTERN = 324, + KW_EXPLICIT = 325, + KW_PUBLISHED = 326, + KW_FALSE = 327, + KW_FINAL = 328, + KW_FLOAT = 329, + KW_FRIEND = 330, + KW_FOR = 331, + KW_GOTO = 332, + KW_IF = 333, + KW_INLINE = 334, + KW_INT = 335, + KW_LONG = 336, + KW_MAKE_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 + }; #endif /* Tokens. */ #define REAL 258 @@ -505,91 +502,76 @@ extern int cppyydebug; #define KW_INLINE 334 #define KW_INT 335 #define KW_LONG 336 -#define KW_MAKE_PROPERTY 337 -#define KW_MAKE_PROPERTY2 338 -#define KW_MAKE_SEQ 339 -#define KW_MUTABLE 340 -#define KW_NAMESPACE 341 -#define KW_NEW 342 -#define KW_NOEXCEPT 343 -#define KW_NULLPTR 344 -#define KW_OPERATOR 345 -#define KW_OVERRIDE 346 -#define KW_PRIVATE 347 -#define KW_PROTECTED 348 -#define KW_PUBLIC 349 -#define KW_REGISTER 350 -#define KW_REINTERPRET_CAST 351 -#define KW_RETURN 352 -#define KW_SHORT 353 -#define KW_SIGNED 354 -#define KW_SIZEOF 355 -#define KW_STATIC 356 -#define KW_STATIC_ASSERT 357 -#define KW_STATIC_CAST 358 -#define KW_STRUCT 359 -#define KW_TEMPLATE 360 -#define KW_THREAD_LOCAL 361 -#define KW_THROW 362 -#define KW_TRUE 363 -#define KW_TRY 364 -#define KW_TYPEDEF 365 -#define KW_TYPEID 366 -#define KW_TYPENAME 367 -#define KW_UNION 368 -#define KW_UNSIGNED 369 -#define KW_USING 370 -#define KW_VIRTUAL 371 -#define KW_VOID 372 -#define KW_VOLATILE 373 -#define KW_WCHAR_T 374 -#define KW_WHILE 375 -#define START_CPP 376 -#define START_CONST_EXPR 377 -#define START_TYPE 378 +#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 +/* Value type. */ - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - +/* Location type. */ #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE +typedef struct YYLTYPE YYLTYPE; +struct YYLTYPE { int first_line; int first_column; int last_line; int last_column; -} YYLTYPE; -# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +}; # define YYLTYPE_IS_DECLARED 1 # define YYLTYPE_IS_TRIVIAL 1 #endif -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int cppyyparse (void *YYPARSE_PARAM); -#else -int cppyyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus + int cppyyparse (void); -#else -int cppyyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ #endif /* !YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED */ /* Copy the second part of user declarations. */ -/* Line 390 of yacc.c */ -#line 593 "built/tmp/cppBison.yxx.c" +#line 575 "built/tmp/cppBison.yxx.c" /* yacc.c:358 */ #ifdef short # undef short @@ -603,11 +585,8 @@ typedef unsigned char yytype_uint8; #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char yytype_int8; #else -typedef short int yytype_int8; +typedef signed char yytype_int8; #endif #ifdef YYTYPE_UINT16 @@ -627,8 +606,7 @@ typedef short int yytype_int16; # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# elif ! defined YYSIZE_T # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else @@ -650,6 +628,33 @@ typedef short int yytype_int16; # endif #endif +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# endif +#endif + /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) @@ -657,23 +662,25 @@ typedef short int yytype_int16; # define YYUSE(E) /* empty */ #endif -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(N) (N) +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") #else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int yyi) -#else -static int -YYID (yyi) - int yyi; +# define YY_INITIAL_VALUE(Value) Value #endif -{ - return yyi; -} +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END #endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + #if ! defined yyoverflow || YYERROR_VERBOSE @@ -692,8 +699,7 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS # include /* INFRINGES ON USER NAME SPACE */ /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS @@ -705,8 +711,8 @@ YYID (yyi) # endif # ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely @@ -722,7 +728,7 @@ YYID (yyi) # endif # if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) + && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 @@ -730,15 +736,13 @@ YYID (yyi) # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined malloc && ! defined EXIT_SUCCESS void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined free && ! defined EXIT_SUCCESS void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif @@ -748,8 +752,8 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ - || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ - && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ + && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc @@ -775,16 +779,16 @@ union yyalloc elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (YYID (0)) +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) #endif @@ -803,7 +807,7 @@ union yyalloc for (yyi = 0; yyi < (Count); yyi++) \ (Dst)[yyi] = (Src)[yyi]; \ } \ - while (YYID (0)) + while (0) # endif # endif #endif /* !YYCOPY_NEEDED */ @@ -811,40 +815,42 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 85 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 5299 +#define YYLAST 5523 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 148 +#define YYNTOKENS 150 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 109 /* YYNRULES -- Number of rules. */ -#define YYNRULES 669 -/* YYNRULES -- Number of states. */ -#define YYNSTATES 1311 +#define YYNRULES 680 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 1339 -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 378 +#define YYMAXUTOK 380 -#define YYTRANSLATE(YYX) \ +#define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 147, 2, 2, 2, 139, 132, 2, - 142, 144, 137, 135, 125, 136, 141, 138, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 127, 126, - 133, 128, 134, 129, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 149, 2, 2, 2, 141, 134, 2, + 144, 146, 139, 137, 127, 138, 143, 140, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 129, 128, + 135, 130, 136, 131, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 143, 2, 146, 131, 2, 2, 2, 2, 2, + 2, 145, 2, 148, 133, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 124, 130, 145, 140, 2, 2, 2, + 2, 2, 2, 126, 132, 147, 142, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -869,375 +875,83 @@ static const yytype_uint8 yytranslate[] = 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123 + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125 }; #if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint16 yyprhs[] = -{ - 0, 0, 3, 6, 9, 12, 14, 17, 20, 22, - 26, 31, 36, 37, 43, 45, 47, 49, 51, 53, - 55, 58, 60, 62, 65, 68, 71, 74, 82, 92, - 102, 116, 126, 134, 140, 141, 145, 147, 150, 154, - 157, 160, 163, 166, 169, 172, 175, 178, 181, 184, - 187, 194, 196, 200, 202, 207, 209, 213, 217, 221, - 222, 227, 228, 234, 237, 242, 245, 250, 251, 256, - 257, 263, 267, 270, 275, 278, 283, 284, 291, 292, - 299, 300, 308, 309, 321, 322, 335, 336, 345, 346, - 356, 358, 360, 362, 365, 368, 371, 374, 379, 385, - 387, 389, 391, 393, 395, 397, 399, 401, 403, 405, - 407, 409, 411, 413, 415, 417, 419, 421, 423, 425, - 427, 429, 431, 433, 435, 437, 439, 441, 443, 445, - 447, 449, 451, 453, 455, 458, 461, 463, 465, 467, - 469, 470, 477, 480, 482, 484, 486, 490, 493, 498, - 501, 506, 510, 515, 517, 519, 521, 523, 526, 530, - 533, 536, 539, 542, 545, 549, 554, 558, 559, 566, - 569, 573, 575, 579, 584, 586, 588, 590, 594, 597, - 599, 603, 605, 607, 609, 613, 616, 618, 622, 624, - 627, 629, 632, 634, 638, 644, 648, 652, 654, 658, - 662, 666, 670, 675, 677, 679, 682, 684, 688, 692, - 698, 702, 707, 713, 716, 718, 720, 722, 724, 727, - 730, 733, 736, 739, 743, 748, 750, 752, 755, 758, - 761, 764, 767, 771, 776, 784, 788, 790, 793, 796, - 799, 802, 805, 809, 814, 816, 819, 822, 825, 828, - 831, 835, 840, 846, 856, 866, 876, 878, 880, 883, - 885, 887, 889, 892, 897, 902, 904, 906, 908, 911, - 913, 915, 917, 920, 925, 928, 933, 935, 937, 939, - 942, 945, 948, 953, 955, 957, 959, 962, 966, 967, - 973, 974, 983, 985, 987, 989, 991, 994, 998, 1000, - 1003, 1006, 1009, 1013, 1017, 1021, 1025, 1029, 1033, 1038, - 1043, 1046, 1050, 1052, 1054, 1056, 1058, 1062, 1068, 1070, - 1073, 1078, 1080, 1082, 1084, 1086, 1087, 1094, 1095, 1103, - 1108, 1114, 1118, 1124, 1129, 1131, 1133, 1135, 1137, 1139, - 1141, 1143, 1145, 1147, 1149, 1151, 1153, 1155, 1158, 1161, - 1164, 1167, 1169, 1171, 1174, 1176, 1177, 1180, 1182, 1185, - 1187, 1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, - 1207, 1209, 1211, 1213, 1215, 1217, 1219, 1221, 1223, 1225, - 1227, 1229, 1231, 1233, 1235, 1237, 1239, 1241, 1243, 1245, - 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, - 1267, 1269, 1271, 1273, 1275, 1277, 1279, 1281, 1283, 1285, - 1287, 1289, 1291, 1293, 1295, 1297, 1299, 1301, 1303, 1305, - 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, - 1327, 1329, 1331, 1333, 1335, 1337, 1339, 1341, 1343, 1345, - 1347, 1349, 1351, 1353, 1355, 1357, 1359, 1361, 1363, 1365, - 1367, 1369, 1371, 1373, 1375, 1377, 1379, 1381, 1383, 1385, - 1387, 1389, 1391, 1393, 1395, 1397, 1399, 1401, 1403, 1405, - 1407, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1423, 1425, - 1427, 1429, 1431, 1435, 1437, 1439, 1441, 1443, 1445, 1449, - 1451, 1456, 1464, 1472, 1480, 1488, 1493, 1498, 1501, 1504, - 1507, 1510, 1513, 1516, 1520, 1524, 1528, 1532, 1536, 1540, - 1544, 1548, 1552, 1556, 1560, 1564, 1568, 1572, 1576, 1580, - 1586, 1591, 1596, 1600, 1604, 1608, 1612, 1614, 1619, 1627, - 1635, 1643, 1651, 1656, 1661, 1666, 1671, 1676, 1681, 1686, - 1691, 1696, 1701, 1706, 1711, 1716, 1721, 1726, 1729, 1735, - 1740, 1745, 1748, 1751, 1754, 1757, 1760, 1763, 1767, 1771, - 1775, 1779, 1783, 1787, 1791, 1795, 1799, 1803, 1807, 1811, - 1815, 1819, 1823, 1827, 1831, 1835, 1841, 1846, 1851, 1855, - 1859, 1863, 1867, 1869, 1871, 1873, 1875, 1877, 1879, 1881, - 1883, 1885, 1887, 1889, 1898, 1910, 1912, 1917, 1925, 1933, - 1941, 1949, 1954, 1959, 1962, 1968, 1973, 1978, 1981, 1984, - 1987, 1990, 1993, 1997, 2001, 2005, 2009, 2013, 2017, 2021, - 2025, 2029, 2033, 2037, 2041, 2045, 2049, 2053, 2057, 2061, - 2065, 2071, 2076, 2081, 2085, 2089, 2093, 2097, 2099, 2101, - 2103, 2105, 2107, 2109, 2111, 2113, 2115, 2117, 2119, 2121, - 2123, 2127, 2129, 2131, 2134, 2136, 2138, 2141, 2144, 2146, - 2148, 2150, 2152, 2154, 2156, 2158, 2160, 2162, 2165, 2168 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int16 yyrhs[] = -{ - 149, 0, -1, 121, 150, -1, 122, 246, -1, 123, - 214, -1, 256, -1, 150, 126, -1, 150, 155, -1, - 152, -1, 151, 125, 152, -1, 253, 142, 243, 144, - -1, 253, 124, 243, 145, -1, -1, 158, 124, 154, - 150, 145, -1, 161, -1, 184, -1, 153, -1, 230, - -1, 233, -1, 156, -1, 110, 167, -1, 49, -1, - 66, -1, 71, 127, -1, 94, 127, -1, 93, 127, - -1, 92, 127, -1, 82, 142, 253, 125, 10, 144, - 126, -1, 82, 142, 253, 125, 10, 125, 10, 144, - 126, -1, 83, 142, 253, 125, 10, 125, 10, 144, - 126, -1, 83, 142, 253, 125, 10, 125, 10, 125, - 10, 125, 10, 144, 126, -1, 84, 142, 253, 125, - 10, 125, 10, 144, 126, -1, 102, 142, 246, 125, - 255, 144, 126, -1, 102, 142, 246, 144, 126, -1, - -1, 75, 157, 155, -1, 256, -1, 69, 158, -1, - 69, 6, 158, -1, 101, 158, -1, 79, 158, -1, - 116, 158, -1, 70, 158, -1, 95, 158, -1, 118, - 158, -1, 85, 158, -1, 58, 158, -1, 50, 158, - -1, 68, 158, -1, 106, 158, -1, 143, 143, 159, - 146, 146, 158, -1, 160, -1, 160, 125, 159, -1, - 253, -1, 253, 142, 196, 144, -1, 162, -1, 158, - 211, 126, -1, 158, 172, 200, -1, 158, 175, 201, - -1, -1, 158, 213, 163, 165, -1, -1, 158, 57, - 213, 164, 166, -1, 192, 201, -1, 192, 199, 125, - 165, -1, 192, 201, -1, 192, 199, 125, 166, -1, - -1, 158, 213, 168, 170, -1, -1, 158, 57, 213, - 169, 171, -1, 158, 175, 201, -1, 192, 201, -1, - 192, 199, 125, 170, -1, 192, 201, -1, 192, 199, - 125, 171, -1, -1, 10, 142, 173, 194, 144, 181, - -1, -1, 11, 142, 174, 194, 144, 181, -1, -1, - 140, 253, 142, 176, 194, 144, 181, -1, -1, 11, - 142, 137, 190, 144, 142, 177, 194, 144, 181, 193, - -1, -1, 11, 142, 12, 137, 190, 144, 142, 178, - 194, 144, 181, 193, -1, -1, 90, 210, 206, 142, - 179, 194, 144, 181, -1, -1, 90, 57, 210, 206, - 142, 180, 194, 144, 181, -1, 10, -1, 256, -1, - 57, -1, 181, 88, -1, 181, 73, -1, 181, 91, - -1, 181, 85, -1, 181, 107, 142, 144, -1, 181, - 107, 142, 253, 144, -1, 147, -1, 140, -1, 137, - -1, 138, -1, 139, -1, 135, -1, 136, -1, 130, - -1, 132, -1, 131, -1, 15, -1, 16, -1, 17, - -1, 18, -1, 19, -1, 20, -1, 133, -1, 134, - -1, 21, -1, 22, -1, 128, -1, 125, -1, 34, - -1, 35, -1, 36, -1, 37, -1, 38, -1, 39, - -1, 40, -1, 41, -1, 42, -1, 43, -1, 44, - -1, 45, -1, 32, -1, 143, 146, -1, 142, 144, - -1, 87, -1, 62, -1, 161, -1, 184, -1, -1, - 105, 185, 133, 186, 134, 183, -1, 105, 161, -1, - 256, -1, 187, -1, 188, -1, 187, 125, 188, -1, - 56, 253, -1, 56, 253, 128, 214, -1, 112, 253, - -1, 112, 253, 128, 214, -1, 189, 207, 198, -1, - 57, 189, 207, 198, -1, 234, -1, 10, -1, 11, - -1, 254, -1, 90, 182, -1, 90, 6, 10, -1, - 57, 190, -1, 118, 190, -1, 137, 190, -1, 132, - 190, -1, 16, 190, -1, 12, 137, 190, -1, 190, - 143, 242, 146, -1, 142, 190, 144, -1, -1, 190, - 142, 191, 196, 144, 181, -1, 190, 193, -1, 190, - 127, 4, -1, 256, -1, 32, 212, 209, -1, 32, - 57, 212, 209, -1, 256, -1, 14, -1, 195, -1, - 195, 125, 14, -1, 195, 14, -1, 204, -1, 195, - 125, 204, -1, 256, -1, 14, -1, 197, -1, 197, - 125, 14, -1, 197, 14, -1, 205, -1, 197, 125, - 205, -1, 256, -1, 128, 245, -1, 256, -1, 128, - 246, -1, 126, -1, 124, 238, 145, -1, 127, 151, - 124, 238, 145, -1, 128, 61, 126, -1, 128, 62, - 126, -1, 126, -1, 124, 238, 145, -1, 128, 246, - 126, -1, 128, 61, 126, -1, 128, 62, 126, -1, - 128, 124, 202, 145, -1, 256, -1, 203, -1, 203, - 125, -1, 246, -1, 124, 202, 145, -1, 203, 125, - 246, -1, 203, 125, 124, 202, 145, -1, 210, 207, - 199, -1, 57, 210, 207, 199, -1, 57, 95, 210, - 207, 199, -1, 95, 204, -1, 204, -1, 248, -1, - 256, -1, 254, -1, 57, 206, -1, 118, 206, -1, - 137, 206, -1, 132, 206, -1, 16, 206, -1, 12, - 137, 206, -1, 206, 143, 242, 146, -1, 256, -1, - 254, -1, 57, 207, -1, 118, 207, -1, 137, 207, - -1, 132, 207, -1, 16, 207, -1, 12, 137, 207, - -1, 207, 143, 242, 146, -1, 142, 207, 144, 142, - 194, 144, 181, -1, 142, 207, 144, -1, 256, -1, - 57, 208, -1, 118, 208, -1, 137, 208, -1, 132, - 208, -1, 16, 208, -1, 12, 137, 208, -1, 208, - 143, 242, 146, -1, 256, -1, 57, 209, -1, 118, - 209, -1, 137, 208, -1, 132, 208, -1, 16, 208, - -1, 12, 137, 208, -1, 208, 143, 242, 146, -1, - 142, 194, 144, 181, 193, -1, 142, 137, 208, 144, - 142, 194, 144, 181, 193, -1, 142, 132, 208, 144, - 142, 194, 144, 181, 193, -1, 142, 16, 208, 144, - 142, 194, 144, 181, 193, -1, 234, -1, 11, -1, - 112, 253, -1, 215, -1, 217, -1, 223, -1, 229, - 253, -1, 228, 254, 127, 225, -1, 60, 142, 246, - 144, -1, 48, -1, 234, -1, 11, -1, 112, 253, - -1, 215, -1, 217, -1, 223, -1, 229, 253, -1, - 228, 254, 127, 225, -1, 228, 253, -1, 60, 142, - 246, 144, -1, 48, -1, 234, -1, 11, -1, 112, - 253, -1, 229, 253, -1, 228, 253, -1, 60, 142, - 246, 144, -1, 48, -1, 211, -1, 10, -1, 210, - 209, -1, 57, 210, 209, -1, -1, 229, 124, 216, - 150, 145, -1, -1, 229, 254, 218, 219, 220, 124, - 150, 145, -1, 256, -1, 73, -1, 256, -1, 221, - -1, 127, 222, -1, 221, 125, 222, -1, 252, -1, - 94, 252, -1, 93, 252, -1, 92, 252, -1, 116, - 94, 252, -1, 116, 93, 252, -1, 116, 92, 252, - -1, 94, 116, 252, -1, 93, 116, 252, -1, 92, - 116, 252, -1, 224, 124, 227, 145, -1, 228, 254, - 127, 225, -1, 228, 254, -1, 228, 127, 225, -1, - 228, -1, 235, -1, 11, -1, 256, -1, 226, 253, - 125, -1, 226, 253, 128, 246, 125, -1, 226, -1, - 226, 253, -1, 226, 253, 128, 246, -1, 67, -1, - 56, -1, 104, -1, 113, -1, -1, 86, 253, 124, - 231, 150, 145, -1, -1, 79, 86, 253, 124, 232, - 150, 145, -1, 86, 124, 150, 145, -1, 79, 86, - 124, 150, 145, -1, 115, 253, 126, -1, 115, 253, - 128, 214, 126, -1, 115, 86, 253, 126, -1, 235, - -1, 236, -1, 237, -1, 51, -1, 53, -1, 119, - -1, 54, -1, 55, -1, 98, -1, 81, -1, 114, - -1, 99, -1, 80, -1, 98, 235, -1, 81, 235, - -1, 114, 235, -1, 99, 235, -1, 74, -1, 63, - -1, 81, 63, -1, 117, -1, -1, 239, 240, -1, - 256, -1, 240, 241, -1, 3, -1, 4, -1, 6, - -1, 8, -1, 9, -1, 5, -1, 10, -1, 11, - -1, 12, -1, 7, -1, 14, -1, 15, -1, 16, - -1, 17, -1, 18, -1, 19, -1, 20, -1, 21, - -1, 22, -1, 23, -1, 24, -1, 32, -1, 33, - -1, 34, -1, 35, -1, 36, -1, 37, -1, 38, - -1, 39, -1, 40, -1, 41, -1, 42, -1, 43, - -1, 44, -1, 45, -1, 46, -1, 47, -1, 48, - -1, 51, -1, 52, -1, 53, -1, 54, -1, 55, - -1, 56, -1, 57, -1, 58, -1, 59, -1, 60, - -1, 61, -1, 62, -1, 63, -1, 64, -1, 65, - -1, 67, -1, 69, -1, 70, -1, 72, -1, 73, - -1, 74, -1, 75, -1, 76, -1, 77, -1, 78, - -1, 79, -1, 80, -1, 81, -1, 85, -1, 86, - -1, 87, -1, 89, -1, 90, -1, 91, -1, 92, - -1, 93, -1, 94, -1, 71, -1, 95, -1, 96, - -1, 97, -1, 98, -1, 99, -1, 100, -1, 101, - -1, 102, -1, 103, -1, 104, -1, 106, -1, 107, - -1, 108, -1, 109, -1, 110, -1, 111, -1, 112, - -1, 113, -1, 114, -1, 115, -1, 116, -1, 117, - -1, 118, -1, 119, -1, 120, -1, 135, -1, 136, - -1, 137, -1, 138, -1, 132, -1, 130, -1, 131, - -1, 147, -1, 140, -1, 128, -1, 139, -1, 133, - -1, 134, -1, 142, -1, 144, -1, 141, -1, 125, - -1, 126, -1, 127, -1, 143, -1, 146, -1, 129, - -1, 124, 240, 145, -1, 256, -1, 246, -1, 256, - -1, 244, -1, 246, -1, 244, 125, 246, -1, 247, - -1, 142, 214, 144, 245, -1, 103, 133, 214, 134, - 142, 244, 144, -1, 64, 133, 214, 134, 142, 244, - 144, -1, 59, 133, 214, 134, 142, 244, 144, -1, - 96, 133, 214, 134, 142, 244, 144, -1, 100, 142, - 214, 144, -1, 47, 142, 214, 144, -1, 147, 245, - -1, 140, 245, -1, 136, 245, -1, 135, 245, -1, - 137, 245, -1, 132, 245, -1, 245, 137, 245, -1, - 245, 138, 245, -1, 245, 139, 245, -1, 245, 135, - 245, -1, 245, 136, 245, -1, 245, 130, 245, -1, - 245, 131, 245, -1, 245, 132, 245, -1, 245, 15, - 245, -1, 245, 16, 245, -1, 245, 17, 245, -1, - 245, 18, 245, -1, 245, 19, 245, -1, 245, 20, - 245, -1, 245, 21, 245, -1, 245, 22, 245, -1, - 245, 129, 245, 127, 245, -1, 245, 143, 246, 146, - -1, 245, 142, 244, 144, -1, 245, 142, 144, -1, - 245, 141, 245, -1, 245, 32, 245, -1, 142, 244, - 144, -1, 247, -1, 142, 214, 144, 246, -1, 103, - 133, 214, 134, 142, 244, 144, -1, 64, 133, 214, - 134, 142, 244, 144, -1, 59, 133, 214, 134, 142, - 244, 144, -1, 96, 133, 214, 134, 142, 244, 144, - -1, 11, 142, 243, 144, -1, 80, 142, 243, 144, - -1, 53, 142, 243, 144, -1, 119, 142, 243, 144, - -1, 54, 142, 243, 144, -1, 55, 142, 243, 144, - -1, 51, 142, 243, 144, -1, 98, 142, 243, 144, - -1, 81, 142, 243, 144, -1, 114, 142, 243, 144, - -1, 99, 142, 243, 144, -1, 74, 142, 243, 144, - -1, 63, 142, 243, 144, -1, 100, 142, 214, 144, - -1, 47, 142, 214, 144, -1, 87, 212, -1, 87, - 212, 142, 243, 144, -1, 111, 142, 214, 144, -1, - 111, 142, 246, 144, -1, 147, 246, -1, 140, 246, - -1, 136, 246, -1, 135, 246, -1, 137, 246, -1, - 132, 246, -1, 246, 137, 246, -1, 246, 138, 246, - -1, 246, 139, 246, -1, 246, 135, 246, -1, 246, - 136, 246, -1, 246, 130, 246, -1, 246, 131, 246, - -1, 246, 132, 246, -1, 246, 15, 246, -1, 246, - 16, 246, -1, 246, 17, 246, -1, 246, 18, 246, - -1, 246, 19, 246, -1, 246, 20, 246, -1, 246, - 133, 246, -1, 246, 134, 246, -1, 246, 21, 246, - -1, 246, 22, 246, -1, 246, 129, 246, 127, 246, - -1, 246, 143, 246, 146, -1, 246, 142, 244, 144, - -1, 246, 142, 144, -1, 246, 141, 246, -1, 246, - 32, 246, -1, 142, 244, 144, -1, 4, -1, 108, - -1, 72, -1, 5, -1, 3, -1, 255, -1, 9, - -1, 10, -1, 73, -1, 91, -1, 89, -1, 143, - 250, 146, 181, 193, 124, 238, 145, -1, 143, 250, - 146, 142, 194, 144, 181, 193, 124, 238, 145, -1, - 249, -1, 142, 214, 144, 246, -1, 103, 133, 214, - 134, 142, 244, 144, -1, 64, 133, 214, 134, 142, - 244, 144, -1, 59, 133, 214, 134, 142, 244, 144, - -1, 96, 133, 214, 134, 142, 244, 144, -1, 100, - 142, 214, 144, -1, 47, 142, 214, 144, -1, 87, - 212, -1, 87, 212, 142, 243, 144, -1, 111, 142, - 214, 144, -1, 111, 142, 246, 144, -1, 147, 246, - -1, 140, 246, -1, 136, 246, -1, 135, 246, -1, - 132, 246, -1, 248, 137, 246, -1, 248, 138, 246, - -1, 248, 139, 246, -1, 248, 135, 246, -1, 248, - 136, 246, -1, 248, 130, 246, -1, 248, 131, 246, - -1, 248, 132, 246, -1, 248, 15, 246, -1, 248, - 16, 246, -1, 248, 17, 246, -1, 248, 18, 246, - -1, 248, 19, 246, -1, 248, 20, 246, -1, 248, - 133, 246, -1, 248, 134, 246, -1, 248, 21, 246, - -1, 248, 22, 246, -1, 248, 129, 246, 127, 246, - -1, 248, 143, 246, 146, -1, 248, 142, 244, 144, - -1, 248, 142, 144, -1, 248, 141, 246, -1, 248, - 32, 246, -1, 142, 244, 144, -1, 4, -1, 108, - -1, 72, -1, 5, -1, 3, -1, 255, -1, 9, - -1, 10, -1, 73, -1, 91, -1, 89, -1, 256, - -1, 251, -1, 251, 125, 250, -1, 132, -1, 128, - -1, 132, 253, -1, 253, -1, 253, -1, 229, 253, - -1, 112, 253, -1, 10, -1, 11, -1, 73, -1, - 91, -1, 10, -1, 11, -1, 91, -1, 6, -1, - 8, -1, 255, 6, -1, 255, 8, -1, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 421, 421, 422, 426, 433, 434, 435, 439, 440, - 444, 448, 461, 460, 472, 473, 474, 475, 476, 477, - 478, 479, 492, 501, 505, 513, 517, 521, 532, 553, - 575, 608, 630, 641, 655, 654, 669, 673, 677, 688, - 692, 696, 700, 704, 708, 712, 716, 720, 724, 728, - 732, 740, 741, 745, 746, 750, 754, 763, 771, 783, - 782, 798, 797, 819, 827, 838, 847, 861, 860, 876, - 875, 890, 905, 911, 920, 927, 940, 939, 964, 963, - 991, 990, 1021, 1020, 1039, 1038, 1059, 1058, 1090, 1089, - 1115, 1128, 1132, 1136, 1140, 1144, 1148, 1153, 1157, 1168, - 1172, 1176, 1180, 1184, 1188, 1192, 1196, 1200, 1204, 1208, - 1212, 1216, 1220, 1224, 1228, 1232, 1236, 1240, 1244, 1248, - 1252, 1256, 1260, 1264, 1268, 1272, 1276, 1280, 1284, 1288, - 1292, 1296, 1300, 1304, 1308, 1312, 1316, 1320, 1327, 1328, - 1333, 1332, 1340, 1344, 1345, 1349, 1355, 1364, 1368, 1372, - 1376, 1380, 1386, 1396, 1400, 1405, 1417, 1421, 1435, 1450, - 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1491, 1490, 1512, - 1522, 1532, 1536, 1540, 1549, 1553, 1558, 1562, 1567, 1575, - 1580, 1588, 1592, 1597, 1601, 1606, 1614, 1619, 1627, 1631, - 1638, 1642, 1649, 1653, 1657, 1661, 1665, 1672, 1676, 1680, - 1684, 1688, 1692, 1699, 1700, 1701, 1705, 1708, 1709, 1710, - 1714, 1719, 1725, 1731, 1742, 1746, 1756, 1760, 1764, 1769, - 1774, 1779, 1784, 1789, 1794, 1802, 1806, 1810, 1815, 1820, - 1825, 1830, 1835, 1840, 1845, 1851, 1859, 1863, 1868, 1873, - 1878, 1883, 1888, 1893, 1901, 1905, 1910, 1915, 1920, 1925, - 1930, 1935, 1940, 1946, 1953, 1960, 1970, 1974, 1982, 1986, - 1990, 1994, 1998, 2014, 2030, 2039, 2046, 2050, 2058, 2062, - 2066, 2070, 2074, 2090, 2106, 2124, 2133, 2140, 2144, 2152, - 2156, 2172, 2188, 2197, 2204, 2208, 2216, 2220, 2229, 2228, - 2253, 2252, 2282, 2283, 2290, 2291, 2295, 2296, 2300, 2304, - 2308, 2312, 2316, 2320, 2324, 2328, 2332, 2336, 2343, 2351, - 2355, 2359, 2363, 2370, 2374, 2381, 2382, 2388, 2396, 2397, - 2403, 2412, 2419, 2423, 2427, 2435, 2434, 2457, 2456, 2479, - 2480, 2484, 2490, 2497, 2506, 2507, 2508, 2512, 2516, 2520, - 2524, 2528, 2532, 2537, 2542, 2547, 2552, 2556, 2561, 2570, - 2575, 2583, 2587, 2591, 2599, 2609, 2609, 2619, 2620, 2624, - 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, - 2634, 2634, 2635, 2635, 2635, 2635, 2636, 2636, 2636, 2636, - 2636, 2637, 2637, 2637, 2638, 2638, 2638, 2638, 2638, 2639, - 2639, 2639, 2639, 2639, 2640, 2640, 2640, 2640, 2640, 2641, - 2641, 2641, 2641, 2641, 2642, 2642, 2642, 2642, 2643, 2643, - 2643, 2643, 2643, 2644, 2644, 2644, 2644, 2644, 2645, 2645, - 2645, 2645, 2645, 2645, 2646, 2646, 2646, 2646, 2646, 2647, - 2647, 2647, 2647, 2648, 2648, 2648, 2648, 2649, 2649, 2649, - 2649, 2649, 2650, 2650, 2650, 2651, 2651, 2651, 2651, 2651, - 2652, 2652, 2652, 2652, 2652, 2653, 2653, 2653, 2653, 2653, - 2656, 2656, 2656, 2656, 2656, 2656, 2656, 2656, 2656, 2656, - 2656, 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657, 2657, - 2657, 2658, 2658, 2662, 2666, 2673, 2677, 2684, 2688, 2695, - 2699, 2703, 2707, 2711, 2715, 2719, 2723, 2727, 2731, 2735, - 2739, 2743, 2747, 2751, 2755, 2759, 2763, 2767, 2771, 2775, - 2779, 2783, 2787, 2791, 2795, 2799, 2803, 2807, 2811, 2815, - 2819, 2823, 2827, 2831, 2835, 2839, 2847, 2851, 2855, 2859, - 2863, 2867, 2871, 2881, 2887, 2893, 2899, 2905, 2911, 2917, - 2924, 2931, 2938, 2945, 2951, 2957, 2961, 2965, 2969, 2973, - 2984, 2995, 2999, 3003, 3007, 3011, 3015, 3019, 3023, 3027, - 3031, 3035, 3039, 3043, 3047, 3051, 3055, 3059, 3063, 3067, - 3071, 3075, 3079, 3083, 3087, 3091, 3095, 3099, 3103, 3107, - 3111, 3115, 3122, 3126, 3130, 3134, 3138, 3142, 3146, 3150, - 3154, 3160, 3166, 3170, 3174, 3188, 3192, 3196, 3200, 3204, - 3208, 3212, 3216, 3220, 3224, 3228, 3239, 3250, 3254, 3258, - 3262, 3266, 3270, 3274, 3278, 3282, 3286, 3290, 3294, 3298, - 3302, 3306, 3310, 3314, 3318, 3322, 3326, 3330, 3334, 3338, - 3342, 3346, 3350, 3354, 3358, 3362, 3366, 3373, 3377, 3381, - 3385, 3389, 3393, 3397, 3401, 3405, 3411, 3417, 3425, 3426, - 3427, 3431, 3432, 3433, 3434, 3438, 3446, 3454, 3482, 3486, - 3490, 3494, 3505, 3509, 3513, 3521, 3525, 3529, 3535, 3546 + 0, 424, 424, 425, 429, 436, 437, 438, 442, 443, + 447, 451, 464, 463, 475, 476, 477, 478, 479, 480, + 481, 494, 503, 507, 515, 519, 523, 534, 555, 585, + 602, 630, 667, 689, 722, 744, 755, 769, 768, 783, + 787, 791, 802, 806, 810, 814, 818, 822, 826, 830, + 834, 838, 842, 846, 854, 855, 859, 860, 864, 868, + 877, 885, 893, 898, 897, 913, 912, 934, 942, 953, + 962, 976, 975, 991, 990, 1005, 1020, 1026, 1035, 1042, + 1055, 1054, 1079, 1078, 1106, 1105, 1136, 1135, 1154, 1153, + 1174, 1173, 1205, 1204, 1230, 1243, 1247, 1251, 1255, 1259, + 1263, 1268, 1272, 1283, 1287, 1291, 1295, 1299, 1303, 1307, + 1311, 1315, 1319, 1323, 1327, 1331, 1335, 1339, 1343, 1347, + 1351, 1355, 1359, 1363, 1367, 1371, 1375, 1379, 1383, 1387, + 1391, 1395, 1399, 1403, 1407, 1411, 1415, 1419, 1423, 1427, + 1431, 1435, 1442, 1443, 1448, 1447, 1455, 1459, 1460, 1464, + 1470, 1479, 1483, 1487, 1491, 1495, 1501, 1511, 1515, 1520, + 1532, 1536, 1550, 1565, 1570, 1575, 1580, 1585, 1590, 1595, + 1600, 1606, 1605, 1627, 1637, 1647, 1651, 1655, 1664, 1668, + 1673, 1677, 1682, 1690, 1695, 1703, 1707, 1712, 1716, 1721, + 1729, 1734, 1742, 1746, 1753, 1757, 1764, 1768, 1772, 1776, + 1780, 1787, 1791, 1795, 1799, 1803, 1807, 1814, 1815, 1816, + 1820, 1823, 1824, 1825, 1829, 1834, 1840, 1846, 1857, 1861, + 1871, 1875, 1879, 1884, 1889, 1894, 1899, 1904, 1909, 1917, + 1921, 1925, 1930, 1935, 1940, 1945, 1950, 1955, 1960, 1966, + 1974, 1978, 1983, 1988, 1993, 1998, 2003, 2008, 2016, 2020, + 2025, 2030, 2035, 2040, 2045, 2050, 2055, 2061, 2068, 2075, + 2085, 2089, 2097, 2101, 2105, 2109, 2113, 2129, 2145, 2154, + 2161, 2165, 2173, 2177, 2181, 2185, 2189, 2205, 2221, 2239, + 2248, 2255, 2259, 2267, 2271, 2287, 2303, 2312, 2319, 2323, + 2331, 2335, 2344, 2343, 2368, 2367, 2397, 2398, 2405, 2406, + 2410, 2411, 2415, 2419, 2423, 2427, 2431, 2435, 2439, 2443, + 2447, 2451, 2458, 2466, 2470, 2474, 2479, 2487, 2491, 2498, + 2499, 2504, 2511, 2512, 2517, 2525, 2529, 2533, 2540, 2544, + 2548, 2556, 2555, 2578, 2577, 2600, 2601, 2605, 2611, 2618, + 2627, 2628, 2629, 2633, 2637, 2641, 2645, 2649, 2653, 2658, + 2663, 2668, 2673, 2677, 2682, 2691, 2696, 2704, 2708, 2712, + 2720, 2730, 2730, 2740, 2741, 2745, 2746, 2747, 2748, 2749, + 2750, 2751, 2752, 2753, 2754, 2755, 2755, 2755, 2756, 2756, + 2756, 2756, 2757, 2757, 2757, 2757, 2757, 2758, 2758, 2758, + 2759, 2759, 2759, 2759, 2759, 2760, 2760, 2760, 2760, 2760, + 2761, 2761, 2761, 2761, 2761, 2762, 2762, 2762, 2762, 2762, + 2763, 2763, 2763, 2763, 2764, 2764, 2764, 2764, 2764, 2765, + 2765, 2765, 2765, 2765, 2766, 2766, 2766, 2766, 2766, 2766, + 2767, 2767, 2767, 2767, 2767, 2768, 2768, 2768, 2768, 2769, + 2769, 2769, 2769, 2770, 2770, 2770, 2770, 2770, 2771, 2771, + 2771, 2772, 2772, 2772, 2772, 2772, 2773, 2773, 2773, 2773, + 2773, 2774, 2774, 2774, 2774, 2774, 2777, 2777, 2777, 2777, + 2777, 2777, 2777, 2777, 2777, 2777, 2777, 2778, 2778, 2778, + 2778, 2778, 2778, 2778, 2778, 2778, 2778, 2779, 2779, 2783, + 2787, 2794, 2798, 2805, 2809, 2816, 2820, 2824, 2828, 2832, + 2836, 2840, 2844, 2848, 2852, 2856, 2860, 2864, 2868, 2872, + 2876, 2880, 2884, 2888, 2892, 2896, 2900, 2904, 2908, 2912, + 2916, 2920, 2924, 2928, 2932, 2936, 2940, 2944, 2948, 2952, + 2956, 2960, 2968, 2972, 2976, 2980, 2984, 2988, 2992, 3002, + 3008, 3014, 3020, 3026, 3032, 3038, 3045, 3052, 3059, 3066, + 3072, 3078, 3082, 3086, 3090, 3094, 3105, 3116, 3120, 3124, + 3128, 3132, 3136, 3140, 3144, 3148, 3152, 3156, 3160, 3164, + 3168, 3172, 3176, 3180, 3184, 3188, 3192, 3196, 3200, 3204, + 3208, 3212, 3216, 3220, 3224, 3228, 3232, 3236, 3243, 3247, + 3251, 3255, 3259, 3263, 3267, 3271, 3275, 3281, 3287, 3291, + 3295, 3309, 3313, 3317, 3321, 3325, 3329, 3333, 3337, 3341, + 3345, 3349, 3360, 3371, 3375, 3379, 3383, 3387, 3391, 3395, + 3399, 3403, 3407, 3411, 3415, 3419, 3423, 3427, 3431, 3435, + 3439, 3443, 3447, 3451, 3455, 3459, 3463, 3467, 3471, 3475, + 3479, 3483, 3487, 3494, 3498, 3502, 3506, 3510, 3514, 3518, + 3522, 3526, 3532, 3538, 3546, 3547, 3548, 3552, 3553, 3554, + 3555, 3559, 3567, 3575, 3603, 3607, 3611, 3615, 3619, 3625, + 3629, 3633, 3637, 3648, 3652, 3656, 3664, 3668, 3672, 3678, + 3689 }; #endif @@ -1261,19 +975,20 @@ static const char *const yytname[] = "KW_DELETE", "KW_DOUBLE", "KW_DYNAMIC_CAST", "KW_ELSE", "KW_END_PUBLISH", "KW_ENUM", "KW_EXTENSION", "KW_EXTERN", "KW_EXPLICIT", "KW_PUBLISHED", "KW_FALSE", "KW_FINAL", "KW_FLOAT", "KW_FRIEND", "KW_FOR", "KW_GOTO", - "KW_IF", "KW_INLINE", "KW_INT", "KW_LONG", "KW_MAKE_PROPERTY", - "KW_MAKE_PROPERTY2", "KW_MAKE_SEQ", "KW_MUTABLE", "KW_NAMESPACE", - "KW_NEW", "KW_NOEXCEPT", "KW_NULLPTR", "KW_OPERATOR", "KW_OVERRIDE", - "KW_PRIVATE", "KW_PROTECTED", "KW_PUBLIC", "KW_REGISTER", - "KW_REINTERPRET_CAST", "KW_RETURN", "KW_SHORT", "KW_SIGNED", "KW_SIZEOF", - "KW_STATIC", "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", "START_CPP", "START_CONST_EXPR", "START_TYPE", "'{'", "','", - "';'", "':'", "'='", "'?'", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'", - "'-'", "'*'", "'/'", "'%'", "'~'", "'.'", "'('", "'['", "')'", "'}'", - "']'", "'!'", "$accept", "grammar", "cpp", "constructor_inits", + "KW_IF", "KW_INLINE", "KW_INT", "KW_LONG", "KW_MAKE_MAP_PROPERTY", + "KW_MAKE_PROPERTY", "KW_MAKE_PROPERTY2", "KW_MAKE_SEQ", + "KW_MAKE_SEQ_PROPERTY", "KW_MUTABLE", "KW_NAMESPACE", "KW_NEW", + "KW_NOEXCEPT", "KW_NULLPTR", "KW_OPERATOR", "KW_OVERRIDE", "KW_PRIVATE", + "KW_PROTECTED", "KW_PUBLIC", "KW_REGISTER", "KW_REINTERPRET_CAST", + "KW_RETURN", "KW_SHORT", "KW_SIGNED", "KW_SIZEOF", "KW_STATIC", + "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", + "START_CPP", "START_CONST_EXPR", "START_TYPE", "'{'", "','", "';'", + "':'", "'='", "'?'", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'", "'-'", + "'*'", "'/'", "'%'", "'~'", "'.'", "'('", "'['", "')'", "'}'", "']'", + "'!'", "$accept", "grammar", "cpp", "constructor_inits", "constructor_init", "extern_c", "$@1", "declaration", "friend_declaration", "$@2", "storage_class", "attribute_specifiers", "attribute_specifier", "type_like_declaration", @@ -1306,13 +1021,13 @@ static const char *const yytname[] = "const_expr_comma", "no_angle_bracket_const_expr", "const_expr", "const_operand", "formal_const_expr", "formal_const_operand", "capture_list", "capture", "class_derivation_name", "name", - "name_no_final", "string_literal", "empty", YY_NULL + "name_no_final", "string_literal", "empty", YY_NULLPTR }; #endif # ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, @@ -1327,1706 +1042,1750 @@ static const yytype_uint16 yytoknum[] = 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 123, 44, 59, 58, 61, 63, - 124, 94, 38, 60, 62, 43, 45, 42, 47, 37, - 126, 46, 40, 91, 41, 125, 93, 33 + 375, 376, 377, 378, 379, 380, 123, 44, 59, 58, + 61, 63, 124, 94, 38, 60, 62, 43, 45, 42, + 47, 37, 126, 46, 40, 91, 41, 125, 93, 33 }; # endif -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint16 yyr1[] = -{ - 0, 148, 149, 149, 149, 150, 150, 150, 151, 151, - 152, 152, 154, 153, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 157, 156, 158, 158, 158, 158, - 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, - 158, 159, 159, 160, 160, 161, 161, 161, 161, 163, - 162, 164, 162, 165, 165, 166, 166, 168, 167, 169, - 167, 167, 170, 170, 171, 171, 173, 172, 174, 172, - 176, 175, 177, 175, 178, 175, 179, 175, 180, 175, - 175, 181, 181, 181, 181, 181, 181, 181, 181, 182, - 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, - 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, - 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, - 182, 182, 182, 182, 182, 182, 182, 182, 183, 183, - 185, 184, 184, 186, 186, 187, 187, 188, 188, 188, - 188, 188, 188, 189, 189, 189, 190, 190, 190, 190, - 190, 190, 190, 190, 190, 190, 190, 191, 190, 192, - 192, 193, 193, 193, 194, 194, 194, 194, 194, 195, - 195, 196, 196, 196, 196, 196, 197, 197, 198, 198, - 199, 199, 200, 200, 200, 200, 200, 201, 201, 201, - 201, 201, 201, 202, 202, 202, 203, 203, 203, 203, - 204, 204, 204, 204, 205, 205, 206, 206, 206, 206, - 206, 206, 206, 206, 206, 207, 207, 207, 207, 207, - 207, 207, 207, 207, 207, 207, 208, 208, 208, 208, - 208, 208, 208, 208, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 211, 211, 211, 211, - 211, 211, 211, 211, 211, 211, 211, 212, 212, 212, - 212, 212, 212, 212, 213, 213, 214, 214, 216, 215, - 218, 217, 219, 219, 220, 220, 221, 221, 222, 222, - 222, 222, 222, 222, 222, 222, 222, 222, 223, 224, - 224, 224, 224, 225, 225, 226, 226, 226, 227, 227, - 227, 228, 229, 229, 229, 231, 230, 232, 230, 230, - 230, 233, 233, 233, 234, 234, 234, 235, 235, 235, - 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, - 235, 236, 236, 236, 237, 239, 238, 240, 240, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 242, 242, 243, 243, 244, 244, 245, - 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, - 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, - 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, - 245, 245, 245, 245, 245, 245, 246, 246, 246, 246, - 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 247, 247, 247, 247, 247, 247, 247, 247, - 247, 247, 247, 247, 247, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 249, 249, 249, - 249, 249, 249, 249, 249, 249, 249, 249, 250, 250, - 250, 251, 251, 251, 251, 252, 252, 252, 253, 253, - 253, 253, 254, 254, 254, 255, 255, 255, 255, 256 -}; - -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 2, 2, 2, 1, 2, 2, 1, 3, - 4, 4, 0, 5, 1, 1, 1, 1, 1, 1, - 2, 1, 1, 2, 2, 2, 2, 7, 9, 9, - 13, 9, 7, 5, 0, 3, 1, 2, 3, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 6, 1, 3, 1, 4, 1, 3, 3, 3, 0, - 4, 0, 5, 2, 4, 2, 4, 0, 4, 0, - 5, 3, 2, 4, 2, 4, 0, 6, 0, 6, - 0, 7, 0, 11, 0, 12, 0, 8, 0, 9, - 1, 1, 1, 2, 2, 2, 2, 4, 5, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, - 0, 6, 2, 1, 1, 1, 3, 2, 4, 2, - 4, 3, 4, 1, 1, 1, 1, 2, 3, 2, - 2, 2, 2, 2, 3, 4, 3, 0, 6, 2, - 3, 1, 3, 4, 1, 1, 1, 3, 2, 1, - 3, 1, 1, 1, 3, 2, 1, 3, 1, 2, - 1, 2, 1, 3, 5, 3, 3, 1, 3, 3, - 3, 3, 4, 1, 1, 2, 1, 3, 3, 5, - 3, 4, 5, 2, 1, 1, 1, 1, 2, 2, - 2, 2, 2, 3, 4, 1, 1, 2, 2, 2, - 2, 2, 3, 4, 7, 3, 1, 2, 2, 2, - 2, 2, 3, 4, 1, 2, 2, 2, 2, 2, - 3, 4, 5, 9, 9, 9, 1, 1, 2, 1, - 1, 1, 2, 4, 4, 1, 1, 1, 2, 1, - 1, 1, 2, 4, 2, 4, 1, 1, 1, 2, - 2, 2, 4, 1, 1, 1, 2, 3, 0, 5, - 0, 8, 1, 1, 1, 1, 2, 3, 1, 2, - 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, - 2, 3, 1, 1, 1, 1, 3, 5, 1, 2, - 4, 1, 1, 1, 1, 0, 6, 0, 7, 4, - 5, 3, 5, 4, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, - 2, 1, 1, 2, 1, 0, 2, 1, 2, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, - 4, 7, 7, 7, 7, 4, 4, 2, 2, 2, - 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, - 4, 4, 3, 3, 3, 3, 1, 4, 7, 7, - 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 2, 5, 4, - 4, 2, 2, 2, 2, 2, 2, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 5, 4, 4, 3, 3, - 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 8, 11, 1, 4, 7, 7, 7, - 7, 4, 4, 2, 5, 4, 4, 2, 2, 2, - 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 5, 4, 4, 3, 3, 3, 3, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 3, 1, 1, 2, 1, 1, 2, 2, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 0 -}; - -/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const yytype_uint16 yydefact[] = -{ - 0, 669, 0, 0, 0, 669, 5, 586, 582, 585, - 665, 666, 588, 589, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 584, 590, 0, 0, 0, 0, 592, - 591, 0, 0, 0, 0, 0, 583, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 669, 0, 3, 526, - 587, 257, 265, 337, 338, 340, 341, 322, 0, 0, - 352, 321, 351, 346, 343, 342, 345, 323, 0, 324, - 344, 354, 339, 669, 4, 259, 260, 261, 0, 312, - 0, 256, 334, 335, 336, 1, 21, 669, 669, 22, - 669, 669, 669, 0, 34, 669, 0, 0, 0, 669, - 0, 0, 0, 0, 669, 669, 0, 669, 669, 669, - 0, 669, 669, 6, 0, 16, 7, 19, 0, 14, - 55, 15, 17, 18, 36, 669, 0, 669, 669, 669, - 669, 0, 669, 0, 669, 669, 669, 278, 283, 0, - 0, 547, 0, 0, 277, 0, 669, 669, 0, 0, - 0, 669, 669, 556, 554, 553, 555, 552, 257, 337, - 338, 340, 341, 352, 351, 346, 343, 342, 345, 344, - 339, 0, 0, 487, 658, 659, 660, 661, 652, 651, - 0, 649, 654, 648, 551, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 667, 668, - 669, 0, 353, 343, 348, 347, 350, 258, 349, 0, - 669, 669, 669, 669, 669, 669, 0, 286, 244, 669, - 662, 663, 664, 0, 310, 658, 659, 661, 288, 262, - 290, 669, 47, 46, 48, 669, 37, 42, 23, 669, - 0, 40, 0, 0, 0, 45, 669, 0, 26, 25, - 24, 43, 39, 0, 0, 142, 0, 49, 0, 20, - 0, 0, 41, 44, 0, 285, 267, 276, 0, 0, - 0, 0, 12, 0, 0, 0, 284, 59, 269, 270, - 271, 312, 0, 266, 0, 486, 485, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 279, - 669, 281, 280, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 581, 653, 669, 669, 565, 566, - 567, 568, 569, 570, 573, 574, 580, 0, 562, 563, - 564, 571, 572, 560, 561, 557, 558, 559, 579, 578, - 0, 0, 287, 0, 669, 0, 669, 669, 669, 669, - 669, 249, 236, 0, 245, 0, 246, 248, 247, 175, - 669, 0, 0, 669, 669, 0, 176, 179, 669, 174, - 669, 318, 0, 315, 314, 311, 313, 0, 669, 669, - 38, 35, 669, 0, 0, 0, 0, 669, 325, 0, - 669, 285, 267, 0, 0, 284, 67, 0, 331, 0, - 0, 51, 53, 76, 78, 285, 267, 61, 0, 0, - 669, 268, 669, 0, 355, 192, 0, 0, 57, 355, - 197, 0, 58, 56, 0, 274, 310, 272, 532, 546, - 538, 534, 536, 537, 0, 544, 0, 543, 533, 540, - 0, 0, 0, 539, 542, 545, 0, 549, 550, 541, - 535, 527, 488, 92, 669, 669, 91, 650, 0, 577, - 576, 264, 250, 669, 241, 237, 238, 240, 239, 669, - 0, 0, 669, 213, 0, 0, 669, 178, 0, 0, - 669, 669, 669, 669, 669, 669, 669, 226, 225, 0, - 484, 483, 319, 308, 263, 669, 293, 669, 292, 669, - 327, 0, 0, 0, 329, 669, 0, 0, 154, 155, - 0, 0, 0, 0, 144, 145, 669, 153, 143, 0, - 69, 71, 0, 333, 0, 0, 0, 669, 669, 0, - 0, 669, 0, 0, 669, 0, 669, 669, 669, 669, - 669, 0, 217, 216, 669, 80, 0, 669, 0, 8, - 0, 0, 0, 0, 0, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 60, 669, 669, 156, - 0, 0, 0, 282, 548, 0, 0, 0, 0, 94, - 96, 93, 95, 0, 0, 171, 575, 242, 0, 0, - 669, 669, 0, 0, 669, 177, 180, 669, 231, 227, - 228, 230, 229, 0, 0, 669, 210, 190, 251, 316, - 0, 289, 0, 0, 295, 294, 330, 669, 0, 0, - 0, 669, 0, 33, 147, 669, 149, 669, 0, 669, - 0, 68, 669, 332, 669, 52, 641, 637, 640, 643, - 644, 182, 0, 0, 0, 639, 645, 0, 647, 646, - 0, 0, 0, 638, 0, 0, 0, 0, 0, 0, - 0, 0, 183, 214, 186, 215, 595, 642, 181, 0, - 0, 0, 0, 62, 669, 275, 0, 669, 222, 218, - 219, 221, 220, 86, 669, 13, 669, 193, 356, 357, - 355, 0, 669, 669, 195, 196, 198, 200, 201, 669, - 0, 204, 206, 203, 199, 0, 163, 159, 0, 109, - 110, 111, 112, 113, 114, 117, 118, 133, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 137, 136, 120, 119, 106, 108, 107, 115, 116, 104, - 105, 101, 102, 103, 100, 0, 0, 99, 157, 160, - 162, 161, 0, 0, 167, 669, 169, 0, 0, 63, - 273, 0, 0, 0, 0, 669, 0, 669, 0, 355, - 243, 669, 669, 211, 669, 669, 252, 232, 235, 191, - 0, 320, 0, 0, 0, 0, 0, 296, 0, 298, - 655, 669, 0, 669, 0, 0, 0, 0, 326, 0, - 0, 669, 0, 138, 141, 139, 146, 0, 151, 188, - 70, 669, 0, 72, 50, 0, 0, 0, 603, 0, - 0, 0, 0, 611, 610, 609, 608, 0, 0, 607, - 54, 185, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 669, 0, 0, 669, - 0, 65, 88, 223, 669, 0, 0, 359, 360, 364, - 361, 368, 362, 363, 365, 366, 367, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 434, 415, 416, 417, 418, 419, 420, - 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, - 431, 432, 433, 435, 436, 437, 438, 439, 440, 441, - 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, - 452, 453, 454, 455, 456, 457, 458, 459, 669, 476, - 477, 478, 469, 481, 465, 466, 464, 471, 472, 460, - 461, 462, 463, 470, 468, 475, 473, 479, 474, 480, - 467, 358, 0, 9, 0, 0, 0, 202, 205, 164, - 158, 135, 134, 166, 170, 669, 0, 191, 0, 530, - 529, 531, 528, 669, 669, 172, 97, 0, 0, 0, - 212, 0, 0, 669, 233, 317, 0, 301, 0, 300, - 0, 299, 657, 0, 0, 0, 656, 669, 297, 328, - 0, 27, 0, 0, 32, 148, 152, 150, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 189, 489, 0, 74, 0, 0, 0, 0, 669, - 0, 0, 0, 0, 0, 0, 636, 184, 187, 620, - 621, 622, 623, 624, 625, 628, 629, 635, 0, 617, - 618, 619, 626, 627, 615, 616, 612, 613, 614, 634, - 633, 0, 0, 77, 0, 82, 79, 0, 669, 0, - 224, 669, 0, 194, 11, 10, 207, 669, 208, 0, - 165, 64, 0, 173, 98, 593, 669, 669, 669, 0, - 307, 306, 305, 304, 303, 302, 291, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 502, 500, 499, - 501, 498, 0, 0, 497, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 73, 602, 0, - 0, 0, 0, 601, 0, 605, 606, 596, 0, 632, - 631, 84, 669, 66, 0, 669, 81, 482, 0, 669, - 355, 669, 669, 669, 669, 28, 0, 29, 31, 0, - 0, 0, 0, 0, 0, 0, 525, 511, 512, 513, - 514, 515, 516, 517, 518, 524, 0, 508, 509, 510, - 506, 507, 503, 504, 505, 523, 522, 0, 0, 75, - 0, 0, 604, 0, 0, 630, 669, 0, 669, 87, - 209, 168, 0, 255, 254, 253, 234, 0, 496, 0, - 0, 0, 495, 0, 490, 0, 521, 520, 0, 0, - 0, 0, 0, 669, 89, 594, 0, 0, 0, 0, - 0, 519, 599, 598, 600, 597, 669, 669, 0, 0, - 0, 0, 0, 669, 83, 30, 493, 492, 494, 491, - 85 -}; - -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 4, 5, 558, 559, 115, 422, 116, 117, 249, - 118, 410, 411, 119, 120, 434, 542, 576, 683, 269, - 532, 640, 641, 820, 284, 538, 541, 285, 696, 1202, - 1256, 874, 1118, 465, 758, 814, 121, 266, 523, 524, - 525, 526, 577, 1015, 578, 594, 375, 376, 671, 672, - 818, 616, 428, 432, 710, 711, 377, 674, 551, 496, - 226, 227, 73, 405, 141, 287, 74, 75, 388, 76, - 389, 507, 623, 624, 797, 77, 78, 385, 381, 382, - 79, 80, 122, 515, 627, 123, 81, 82, 83, 84, - 556, 557, 698, 1001, 499, 294, 295, 1071, 173, 49, - 675, 676, 180, 181, 799, 800, 579, 50, 124 -}; - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -755 -static const yytype_int16 yypact[] = -{ - 365, -755, 2777, 4408, 50, 2969, -755, -755, -755, -755, - -755, -755, -755, -755, -61, -39, 6, 23, 53, 63, - -34, 93, 10, -755, -755, 98, 102, 104, 4607, -755, - -755, 78, 114, 134, 141, 135, -755, 166, 182, 192, - 2777, 2777, 2777, 2777, 2777, 1416, 84, 2777, 3633, -755, - 117, -755, -755, -755, -755, -755, -755, -755, 4629, 195, - -755, -755, -755, -755, 2652, 2740, 2740, -755, 382, -755, - 2740, -755, -755, 185, -755, -755, -755, -755, 262, 126, - 69, -755, -755, -755, -755, -755, -755, 5156, 5156, -755, - 5156, 359, 5156, 247, -755, 5112, 218, 248, 258, 5156, - 290, 275, 279, 288, 5156, 5156, 299, 5126, 5156, 5156, - 360, 5156, 5156, -755, 302, -755, -755, -755, 3179, -755, - -755, -755, -755, -755, -755, 2777, 4408, 2777, 2777, 2777, - 2777, 4408, 2777, 4408, 2777, 2777, 2777, -755, -755, 311, - 382, 314, 382, 382, -755, 4408, 2777, 2777, 4408, 4408, - 1416, 2777, 2777, 90, 90, 90, 90, 90, -61, 6, - 23, 53, 63, 93, 98, 102, 2119, 2292, 2455, 2540, - 192, 330, -60, 3633, -755, -755, -755, -755, -755, 382, - 333, 373, -755, -755, 90, 2777, 2777, 2777, 2777, 2777, - 2777, 2777, 2777, 2777, 2777, 2777, 2777, 2777, 2777, 2777, - 2777, 2777, 2777, 2777, 2777, 2777, 2217, 2777, -755, -755, - 185, 2777, -755, 2740, -755, -755, -755, -755, -755, 347, - 31, 185, 185, 31, 31, 3948, 356, -755, 366, -755, - -755, -755, -755, 1119, 388, 17, 45, 154, -755, -755, - -755, 5156, -755, -755, -755, 5156, -755, -755, -755, 5059, - 294, -755, 382, 382, 382, -755, -755, 399, -755, -755, - -755, -755, -755, 2777, 3083, -755, 397, -755, 3251, -755, - 382, 115, -755, -755, 382, 226, 384, -755, 4175, 396, - 4475, 382, -755, 382, 393, 238, 398, -755, -755, -755, - -755, 219, 69, -755, 395, 416, -755, 400, 406, 407, - 409, 417, 429, 428, 440, 431, 438, 439, 2777, -755, - 2777, -755, -755, 454, 448, 449, 451, 462, 458, 3356, - 460, 461, 2777, 2777, -755, -755, 64, 84, 3815, 3835, - 946, 946, 486, 486, 206, 206, -755, 3449, 3851, 3899, - 4036, 486, 486, 121, 121, 90, 90, 90, -755, -755, - -47, 1299, -755, 3377, 31, 473, 31, 31, 31, 31, - 31, 468, -755, 356, -755, 356, -755, 468, 468, -755, - 31, 4530, 4386, 31, 31, 469, 27, -755, 1148, -755, - 2777, 382, 467, -755, -755, -755, -755, 1119, -755, 543, - -755, -755, -755, 495, 492, 505, 506, 4681, -755, 1318, - 2876, 403, 478, 4175, 238, -755, -755, 507, -755, 4408, - 489, 511, 498, -755, 34, -755, -755, -755, 2777, 4629, - 500, -755, -755, 502, -755, -755, 382, 15, -755, -755, - -755, 2105, -755, -755, 786, -755, 527, -755, -755, -755, - -755, -755, -755, -755, 514, -755, 515, -755, -755, -755, - 3395, 517, 520, -755, -755, -755, 522, -755, -755, -755, - -755, 90, 3633, -755, 4247, 672, -755, -755, 2777, -755, - -755, -755, 468, 31, 468, 468, 468, 468, 468, 2777, - -4, 4629, 1148, -755, 12, 108, 608, -755, 4319, 529, - 1148, 1148, 1148, 1148, 1148, 1148, -45, -755, -755, 521, - 3633, -755, -12, -755, 544, 4735, -755, 546, -755, 4789, - -755, 665, 667, 669, -755, -755, 315, 556, -755, -755, - 382, 2204, 382, 550, 560, -755, 1148, -755, -755, 34, - -755, -755, 786, -755, 561, 542, 382, 1533, 4247, 552, - 786, 4247, 786, 3413, 500, 553, 500, 500, 500, 500, - 500, 293, -755, -755, 4843, -755, 547, -755, 334, -755, - -68, 568, 570, 562, 579, 583, 2329, 3578, 573, 786, - 786, 3082, 786, 786, 786, 786, -755, 186, 436, -755, - 1119, 2777, 2777, -755, -755, 2777, 2777, 588, 4552, -755, - -755, -755, -755, 592, 612, -755, 3633, 468, 593, 596, - 1148, -45, 599, 600, 672, -755, -755, 1148, 603, 603, - 603, 603, 603, 306, 2777, 2777, -755, -755, 604, -755, - 2777, -755, 2386, 624, 629, -755, -755, -755, -43, 630, - 633, 4897, 36, -755, 621, 1148, 631, 4286, 2876, -13, - 786, -755, 436, -755, 5156, -755, -755, -755, -755, -755, - -755, -755, 619, 632, 635, -755, -755, 4607, -755, -755, - 637, 646, 638, -755, 648, 2777, 2777, 2777, 2777, 1416, - 2777, 622, 57, -755, -755, 3651, -755, 117, -755, 628, - 786, 361, 647, -755, 436, -755, 324, 500, 649, 649, - 649, 649, 649, -755, 2777, -755, 4247, -755, 1843, -755, - -755, 382, 2777, 2777, -755, -755, -755, -755, -755, 2329, - 654, 650, 3633, -755, -755, 786, 328, 328, 763, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, 659, 658, -755, -755, 328, - 328, 328, 391, 801, -755, 2777, -755, 2105, 681, -755, - 544, 39, 66, 123, 149, 608, 4607, 185, 41, -755, - -755, 4247, -45, -755, 4247, 4247, -755, 603, 666, 3633, - 668, 3597, 587, 783, 897, 382, 493, -755, 382, -755, - -755, -755, 2386, 4951, 808, 695, 812, 814, -755, 699, - 4408, -13, 4408, -755, -755, -755, -755, 2889, -755, -755, - -755, 436, 701, -755, -755, 4408, 4408, 4408, 687, 4408, - 4408, 4408, 1416, 90, 90, 90, 90, 686, 152, 90, - -755, -755, 1988, 2777, 2777, 2777, 2777, 2777, 2777, 2777, - 2777, 2777, 2777, 2777, 2777, 2777, 2777, 2777, 2777, 2777, - 2777, 2777, 2777, 2777, 2441, 2777, 608, 465, 689, 608, - 707, -755, -755, 649, 4247, 690, 691, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, -755, -755, -755, -755, -755, -755, -755, -755, - -755, -755, 696, -755, 697, 702, 700, -755, 2553, 328, - -755, -755, -755, -755, -755, 1533, 704, 3578, 786, -755, - -755, -755, -755, 672, 185, -755, -755, 703, 716, 708, - -755, 718, 719, 4247, -755, -755, 1030, -755, 1030, -755, - 1030, -755, -755, 1030, 1030, 1030, -755, 5005, -755, -755, - 720, -755, 163, 722, -755, -755, -755, -755, 727, 737, - 742, 745, 743, 753, 2889, 2889, 2889, 2889, 2889, 1416, - 2889, 3798, -755, 765, -755, 786, 744, 757, 758, 2777, - 759, 750, 764, 756, 3431, 2777, -755, -755, -755, 3815, - 3835, 946, 946, 486, 486, 206, 206, -755, 3615, 3851, - 3899, 4036, 486, 486, 121, 121, 90, 90, 90, -755, - -755, 236, 1553, 325, 760, -755, 325, 786, 4247, 761, - -755, 608, 1698, -755, -755, -755, -755, 2329, 3633, 767, - -755, -755, 779, -755, -755, -755, 608, 608, 608, 768, - -755, -755, -755, -755, -755, -755, -755, 787, 899, 788, - 790, 4408, 4408, 4408, 4408, 4408, 4408, 241, 241, 241, - 241, 241, 773, 250, 241, 2889, 2889, 2889, 2889, 2889, - 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889, 2889, - 2889, 2889, 2889, 2889, 2665, 2777, 786, -755, -755, 777, - 778, 780, 784, -755, 785, -755, -755, 90, 2777, -755, - -755, -755, 4247, -755, 781, 608, 325, -755, 789, 608, - -755, 672, 672, 672, 608, -755, 797, -755, -755, 796, - 798, 807, 809, 806, 818, 2889, -755, 1224, 3882, 3244, - 3244, 2868, 2868, 510, 510, -755, 3669, 4052, 4069, 4078, - 674, 674, 241, 241, 241, -755, -755, 251, 2008, -755, - 2777, 2777, -755, 2777, 2777, 3633, 4247, 810, 608, 325, - -755, 325, 811, -755, -755, -755, 325, 919, -755, 800, - 816, 817, -755, 820, 241, 2889, -755, -755, 278, 282, - 286, 287, 825, 608, 325, -755, 827, 2777, 2777, 2777, - 2777, 3798, -755, -755, -755, -755, 608, 672, 804, 295, - 317, 318, 332, 672, -755, -755, -755, -755, -755, -755, - -755 -}; - -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -755, -755, -230, -755, 259, -755, -755, 723, -755, -755, - 207, 437, -755, -105, -755, -755, -755, -42, -142, -755, - -755, -755, -96, -206, -755, -755, -755, 713, -755, -755, - -755, -755, -755, -386, -755, -755, 345, -755, -755, -755, - 346, 464, -465, -755, -523, -541, -449, -755, -32, -755, - 175, -546, -755, -397, -693, -755, -341, 145, -480, -433, - 795, -197, -41, -98, -551, -166, 28, -70, -755, -65, - -755, -755, -755, -755, 188, -64, -755, -354, -755, -755, - 2, -7, -755, -755, -755, -755, 1, 21, -755, -755, - -428, -755, 13, -755, -445, -124, -27, 233, 526, -119, - -755, -755, 670, -755, -754, 821, 389, -502, -1 -}; - -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -665 -static const yytype_int16 yytable[] = -{ - 6, 563, 265, 298, 299, 300, 301, 531, 303, 642, - 305, 306, 307, 352, 632, 587, 1006, 210, 172, 684, - 286, 143, 314, 315, 364, 366, 397, 320, 321, 144, - 142, 483, 768, 504, 598, 677, 766, 777, 1037, 1039, - 1041, 487, 208, 355, 209, 183, 539, 356, 288, 601, - 85, 174, 175, 289, 290, 783, 702, 608, 609, 610, - 611, 612, 613, 786, 686, 323, 688, 689, 690, 691, - 692, 841, 228, 171, 703, 681, 561, 562, 323, 235, - 236, 125, 804, 614, 324, 214, 215, 216, 357, 679, - -662, 218, 682, 639, 174, 175, 822, 469, 615, 131, - 604, 805, 406, 126, 716, 717, 828, 759, 760, 761, - 762, 292, 417, 619, 176, 817, 620, 821, -663, 293, - 291, 463, 193, 208, 296, 209, 296, 296, 296, 296, - 615, 296, 177, 296, 296, 296, 230, 231, 870, 479, - 599, -662, 176, 133, -662, 296, 296, 606, 127, 358, - 296, 296, 488, 193, 297, 479, 602, 176, 505, 302, - 237, 304, 509, 359, 323, 128, 286, 782, 360, -663, - 790, 540, -663, 313, 787, 177, 316, 317, 318, 350, - 809, 769, 842, 1019, 378, 1026, 451, 214, 215, 216, - 218, 323, 554, 238, 288, 129, 673, 219, 288, 289, - 290, 220, 811, 289, 290, 130, 464, 873, 288, 228, - 1020, 145, 178, 289, 290, 867, 179, 232, 588, 362, - 228, 228, 362, 362, 379, 1024, 770, -664, 383, 235, - 236, 205, 206, 207, 214, 132, 1030, 530, 193, 420, - 134, 408, 221, 409, 135, 823, 136, 876, 323, 875, - 1009, 479, 603, 233, 386, 6, 146, 292, 202, 203, - 204, 292, 205, 206, 207, 293, 291, 1021, 149, 293, - 291, 292, 1002, 1173, 323, 1073, 147, 323, -664, 293, - 291, -664, 1140, 148, 1141, 631, 1142, 871, 1148, 1143, - 1144, 1145, 176, 1022, 242, 243, 1086, 244, 246, 247, - 174, 175, 251, 222, 174, 175, 255, 1149, 150, 296, - 237, 261, 262, 763, 264, 267, 268, 223, 272, 273, - 1016, 10, 224, 11, 151, 466, 183, 225, 764, 765, - 482, 378, 1029, 288, 152, 1031, 1032, 211, 289, 290, - 677, 200, 201, 202, 203, 204, 233, 205, 206, 207, - -90, 1028, -90, 362, -90, 362, 362, 362, 362, 362, - 252, 323, 429, 176, 430, 245, 431, 176, 413, 362, - 174, 175, 362, 362, 248, 323, 323, 498, 544, 501, - 1199, 177, 1183, 1184, 1185, 177, 229, 6, 508, 1023, - 253, 6, 174, 175, 1226, 1276, 292, 803, 589, 528, - 254, 527, 258, 323, 293, 291, 259, 323, 386, 87, - 590, 323, 323, 591, 256, 260, 592, 88, 392, 553, - 323, 6, 1292, 378, 1074, 1119, 1293, 90, 91, 92, - 1294, 1295, 593, 176, 1208, 693, 694, 534, 241, 1306, - 600, 263, 323, 323, 99, 274, 270, 378, 251, 615, - 788, 177, 390, 308, 104, 176, 310, 323, 700, 701, - 105, 1307, 1308, 379, 595, 108, 872, 694, 234, 240, - 764, 765, 362, 177, 322, 111, 1309, 112, 501, 326, - 1113, 498, 1132, 1116, 354, 466, 1, 2, 3, 498, - 498, 498, 498, 498, 498, 617, 378, 378, 327, 380, - 378, 673, 114, 764, 765, 868, 625, 191, 192, -236, - 230, 231, 545, 677, 6, 387, 546, 424, 193, 425, - 426, 427, 527, 398, 433, 498, 414, -90, 48, -90, - 400, -90, 813, 764, 765, 1013, 678, 379, 418, 438, - 379, 323, 1173, 553, 439, 553, 553, 553, 553, 553, - 440, 441, 642, 442, 771, 772, 699, 547, 773, 774, - 429, 443, 430, 444, 767, 713, 153, 154, 155, 156, - 157, 1047, 445, 184, 446, 447, 595, 617, 1004, 1005, - 1025, 143, 448, 449, 1139, 1043, 1044, 1045, 452, 144, - 142, 232, 453, 454, 684, 455, 456, 174, 175, 498, - 617, 386, 457, 595, 459, 460, 498, 764, 765, 1114, - 473, 479, 503, 486, 501, 798, 506, 511, 548, 510, - 529, 200, 201, 202, 203, 204, 6, 205, 206, 207, - 512, 513, 549, 533, 498, 535, 536, 550, 819, 527, - 537, 617, 838, 57, 555, 1178, 1179, 1180, 1181, 1182, - 143, 1183, 1184, 1185, 580, 378, 581, 582, 144, 142, - 176, 584, 585, 821, 586, 463, 607, 618, -309, 1204, - 1263, 1264, 1265, 622, 673, 628, 319, 629, 177, 630, - 436, 240, 633, 617, 637, 638, 553, 643, 644, 680, - 687, 67, 697, 501, 704, 379, 705, 837, 1072, 795, - 69, 296, 296, 1036, 588, 707, 1173, 706, 713, 708, - 715, 328, 329, 330, 331, 332, 333, 334, 335, 336, - 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, 775, 351, 778, 1206, 779, 353, 781, 780, - 378, 784, 785, 378, 378, 589, 615, -243, 801, 810, - 1211, 1212, 1213, 1257, 802, 806, 1304, 590, 807, 812, - 591, 825, 1310, 592, 501, 826, 840, 497, 827, 143, - 829, 831, 866, 1010, 466, 1008, 228, 144, 142, 593, - 379, 617, 1262, 379, 379, 798, 798, 798, 830, 399, - 832, 869, 694, 174, 175, 798, 230, 231, 568, 1007, - 6, 378, 569, 1011, 1012, 1014, 1018, 1282, 1033, 552, - 819, 1180, 1181, 1182, 1034, 1183, 1184, 1185, 1050, 1259, - 617, 1051, 1052, 1261, 1053, 1054, 1075, 1133, 1266, 1079, - 1085, 1115, 1117, 378, 450, 1121, 1120, 1111, 1055, 57, - 1057, 1123, 1124, 570, 264, 1126, 1125, 1134, 461, 462, - 1130, 824, 1136, 1076, 1077, 1078, 176, 1080, 1081, 1082, - 1083, 1135, 1137, 1138, 1147, 466, 1150, 182, 466, 1151, - 1152, 497, 1284, 379, 177, 1153, 571, 232, 1154, 497, - 497, 497, 497, 497, 497, 1155, 1156, 67, 1188, 217, - 1186, 1189, 1190, 1192, 1193, 795, 69, 1297, 1194, 1038, - 1195, 239, 1201, 1210, 572, 1205, 500, 174, 175, 1216, - 1303, 1209, 1214, 1215, 1217, 497, 1218, 1225, 573, 1250, - 1251, 257, 1267, 574, 1252, 1258, 1253, 1254, 575, 1286, - 1305, 271, 1269, 552, 1260, 552, 552, 552, 552, 552, - 1268, 1270, 1287, 1271, 543, 1072, 1072, 1072, 1072, 1072, - 1272, 1072, 1273, 57, 1283, 1191, 1285, 567, 1288, 1289, - 1003, 309, 1290, 311, 312, 189, 190, 191, 192, 1296, - 176, 1298, 391, 645, 378, 1203, 1131, 699, 193, 1187, - 1249, 404, 815, 1129, 816, 635, 1056, 1088, 177, 497, - 1048, 1122, 378, 0, 596, 0, 497, 467, 0, 0, - 325, 67, 0, 0, 0, 500, 0, 0, 0, 795, - 69, 0, 0, 1040, 678, 361, 363, 365, 367, 368, - 0, 0, 595, 228, 497, 0, 0, 0, 0, 798, - 0, 798, 379, 798, 0, 0, 798, 798, 798, 0, - 174, 175, 1163, 0, 0, 0, 1072, 1072, 1072, 1072, - 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, - 1072, 1072, 1072, 1072, 1072, 0, 0, 0, 0, 0, - 0, 393, 0, 394, 395, 396, 552, 378, 296, 198, - 199, 200, 201, 202, 203, 204, 57, 205, 206, 207, - 0, 407, 712, 0, 0, 412, 0, 1162, 0, 0, - 0, 0, 421, 176, 423, 0, 1072, 0, 0, 0, - 0, 0, 435, 437, 0, 0, 0, 379, 0, 0, - 466, 177, 0, 0, 0, 0, 713, 0, 0, 0, - 384, 0, 0, 0, 67, 466, 466, 466, 0, 0, - 789, 500, 795, 69, 0, 0, 791, 0, 182, 472, - 0, 474, 475, 476, 477, 478, 1072, 1247, 230, 231, - 489, 378, 0, 0, 490, 480, 0, 0, 484, 485, - 53, 0, 54, 55, 56, 0, 0, 0, 0, 1219, - 1220, 1221, 1222, 1223, 1224, 0, 0, 0, 0, 0, - 0, 833, 834, 835, 836, 0, 839, 0, 0, 63, - 213, 379, 502, 0, 466, 491, 0, 0, 466, 0, - 595, 595, 595, 466, 0, 378, 0, 65, 66, 0, - 500, 0, 0, 1278, 1279, 0, 1280, 1281, 0, 0, - 0, 0, 0, 70, 0, 712, 0, 0, 72, 232, - 1166, 1167, 1168, 1169, 1170, 1171, 1172, 560, 0, 0, - 0, 0, 0, 0, 0, 379, 1173, 466, 0, 0, - 1299, 1300, 1301, 1302, 0, 0, 492, 0, 597, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 493, 0, 466, 0, 0, 494, 0, 0, 0, 0, - 495, 500, 0, 1017, 0, 466, 595, 1157, 1158, 1159, - 1160, 1161, 595, 1164, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 185, 186, 187, 188, 189, 190, - 191, 192, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 193, 0, 185, 186, 187, 188, 189, 190, 191, - 192, 634, 0, 636, 0, 0, 0, 0, 0, 0, - 193, 0, 0, 0, 1175, 1176, 1177, 412, 1084, 1178, - 1179, 1180, 1181, 1182, 0, 1183, 1184, 1185, 0, 1089, - 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, - 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, - 0, 1112, 0, 0, 0, 0, 0, 0, 1227, 1228, - 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, - 1239, 1240, 1241, 1242, 1243, 1244, 1245, 0, 0, 7, - 8, 9, 10, 0, 11, 12, 13, 158, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 0, - 205, 206, 207, 516, 0, 470, 0, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 1274, 205, - 206, 207, 517, 15, 52, 0, 0, 159, 0, 160, - 161, 162, 57, 58, 0, 20, 59, 0, 0, 163, - 22, 0, 0, 61, 0, 0, 0, 0, 23, 24, - 164, 0, 0, 0, 0, 0, 165, 166, 0, 0, - 0, 0, 0, 28, 0, 29, 0, 30, 1291, 0, - 0, 0, 31, 0, 167, 168, 34, 0, 0, 35, - 67, 0, 560, 0, 36, 0, 0, 37, 68, 69, - 169, 0, 0, 71, 1128, 170, 646, 647, 648, 10, - 0, 11, 649, 650, 51, 0, 0, 651, 40, 0, - 0, 41, 42, 43, 0, 0, 44, 0, 45, 46, - 0, 0, 0, 47, 0, 0, 0, 0, 185, 186, - 187, 188, 189, 190, 191, 192, 0, 0, 0, 0, - 652, 52, 0, 0, 53, 193, 54, 55, 56, 57, - 371, 0, 653, 59, 0, 0, 60, 654, 0, 1027, - 61, 0, 0, 0, 0, 655, 656, 62, 0, 0, - 0, 1197, 0, 63, 64, 0, 1042, 0, 0, 1046, - 657, 0, 658, 0, 659, 0, 0, 0, 372, 660, - 0, 65, 66, 661, 0, 0, 662, 67, 0, 0, - 0, 663, 0, 0, 664, 68, 69, 70, 0, 0, - 71, 0, 72, 712, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 665, 0, 0, 666, 667, - 0, 0, 0, 668, 0, 669, 0, 0, 0, 0, - 670, 0, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 0, 205, 206, 207, 0, 0, 1200, - 0, 877, 878, 879, 880, 881, 882, 883, 884, 885, - 886, 1248, 887, 888, 889, 890, 891, 892, 893, 894, - 895, 896, 897, 0, 1255, 0, 0, 0, 0, 0, - 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, - 908, 909, 910, 911, 912, 913, 914, 0, 0, 915, - 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, - 926, 927, 928, 929, 0, 930, 0, 931, 932, 933, - 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, - 0, 0, 0, 944, 945, 946, 0, 947, 948, 949, - 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, - 960, 961, 962, 0, 963, 964, 965, 966, 967, 968, - 969, 970, 971, 972, 973, 974, 975, 976, 977, 0, - 0, 0, 978, 979, 980, 981, 982, 983, 984, 985, - 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, - 996, 997, 998, 1207, 999, 1000, 877, 878, 879, 880, - 881, 882, 883, 884, 885, 886, 0, 887, 888, 889, - 890, 891, 892, 893, 894, 895, 896, 897, 0, 0, - 0, 0, 0, 0, 0, 898, 899, 900, 901, 902, - 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, - 913, 914, 0, 0, 915, 916, 917, 918, 919, 920, - 921, 922, 923, 924, 925, 926, 927, 928, 929, 0, - 930, 0, 931, 932, 933, 934, 935, 936, 937, 938, - 939, 940, 941, 942, 943, 0, 0, 0, 944, 945, - 946, 0, 947, 948, 949, 950, 951, 952, 953, 954, - 955, 956, 957, 958, 959, 960, 961, 962, 0, 963, - 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, - 974, 975, 976, 977, 0, 0, 0, 978, 979, 980, - 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, - 991, 992, 993, 994, 995, 996, 997, 998, 0, 999, - 1000, 646, 647, 648, 10, 0, 11, 649, 650, 51, - 0, 0, 1087, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 185, 186, 187, 188, 189, 190, 191, - 192, 0, 0, 0, 0, 652, 52, 0, 0, 53, - 193, 54, 55, 56, 57, 371, 0, 653, 59, 0, - 0, 60, 654, 0, 0, 61, 0, 0, 0, 0, - 655, 656, 62, 0, 0, 0, 0, 0, 63, 64, - 0, 0, 0, 0, 0, 657, 0, 658, 0, 659, - 0, 0, 0, 372, 660, 0, 65, 66, 661, 0, - 0, 662, 67, 0, 0, 0, 663, 0, 0, 664, - 68, 69, 70, 0, 0, 71, 0, 72, 7, 8, - 9, 10, 0, 11, 12, 13, 14, 0, 0, 0, - 665, 0, 0, 666, 667, 0, 0, 0, 668, 0, - 669, 0, 0, 0, 0, 670, 0, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 0, 205, - 206, 207, 15, 0, 1277, 0, 16, 0, 17, 18, - 19, 0, 0, 0, 20, 0, 564, 565, 21, 22, - 53, 0, 54, 55, 56, 0, 0, 23, 24, 25, - 0, 0, 212, 0, 0, 26, 27, 0, 0, 0, - 0, 0, 28, 0, 29, 0, 30, 0, 0, 63, - 213, 31, 0, 32, 33, 34, 0, 0, 35, 0, - 0, 0, 0, 36, 518, 519, 37, 65, 66, 38, - 7, 8, 9, 10, 39, 11, 12, 13, 14, 566, - 0, 0, 0, 70, 0, 0, 0, 40, 72, 0, - 41, 42, 43, 0, 0, 44, 0, 45, 46, 0, - 0, 0, 47, 0, 0, 53, 0, 54, 55, 56, - 0, 136, 0, 0, 15, 0, 0, 60, 16, 0, - 17, 18, 19, 0, 0, 0, 20, 0, 62, 0, - 21, 22, 0, 0, 63, 64, 0, 0, 0, 23, - 24, 25, 0, 0, 0, 0, 0, 26, 27, 0, - 0, 0, 65, 66, 28, 0, 29, 0, 30, 0, - 0, 0, 0, 31, 0, 32, 33, 34, 70, 0, - 35, 71, 0, 72, 0, 36, 0, 0, 37, 0, - 0, 38, 7, 8, 9, 10, 39, 11, 12, 13, - 14, 0, 0, 53, 0, 54, 55, 56, 0, 40, - 0, 0, 41, 42, 43, 0, 0, 44, 0, 45, - 46, 349, 0, 0, 47, 0, 0, 0, 0, 0, - 0, 0, 63, 213, 0, 0, 15, 0, 0, 0, - 16, 0, 17, 18, 19, 0, 0, 0, 20, 0, - 65, 66, 21, 22, 0, 0, 174, 175, 0, 0, - 0, 23, 24, 25, 0, 0, 70, 0, 0, 26, - 27, 72, 0, 0, 0, 0, 28, 0, 29, 0, - 30, 0, 0, 0, 0, 31, 0, 32, 33, 34, - 0, 0, 35, 0, 146, 0, 0, 36, 0, 0, - 37, 0, 57, 38, 7, 8, 9, 10, 39, 11, - 12, 13, 14, 709, 0, 0, 0, 0, 0, 176, - 0, 40, 0, 0, 41, 42, 43, 0, 0, 44, - 0, 45, 46, 0, 0, 0, 47, 177, 792, 793, - 794, 0, 0, 0, 0, 0, 0, 0, 15, 0, - 67, 0, 16, 0, 17, 18, 19, 0, 795, 69, - 20, 0, 796, 0, 21, 22, 53, 0, 54, 55, - 56, 0, 0, 23, 24, 25, 0, 0, 0, 0, - 0, 26, 27, 0, 0, 0, 0, 0, 28, 0, - 29, 0, 30, 0, 0, 63, 213, 31, 0, 32, - 33, 34, 0, 0, 35, 0, 0, 0, 0, 36, - 0, 0, 37, 65, 66, 38, 7, 8, 9, 10, - 39, 11, 12, 13, 14, 0, 0, 0, 0, 70, - 0, 0, 0, 40, 72, 0, 41, 42, 43, 0, - 0, 44, 0, 45, 46, 1110, 0, 0, 47, 0, - 0, 53, 0, 54, 55, 56, 0, 147, 0, 0, - 15, 0, 0, 0, 16, 0, 17, 18, 19, 0, - 0, 0, 20, 0, 0, 0, 21, 22, 0, 0, - 63, 213, 0, 0, 0, 23, 24, 25, 0, 0, - 0, 0, 0, 26, 27, 0, 0, 0, 65, 66, - 28, 0, 29, 0, 30, 0, 0, 0, 0, 31, - 0, 32, 33, 34, 70, 0, 35, 0, 0, 72, - 0, 36, 0, 0, 37, 0, 0, 38, 7, 8, - 9, 10, 39, 11, 12, 13, 14, 1127, 0, 0, - 0, 0, 151, 0, 0, 40, 0, 0, 41, 42, - 43, 0, 0, 44, 0, 45, 46, 0, 0, 0, - 47, 0, 0, 53, 0, 54, 55, 56, 0, 0, - 0, 0, 15, 0, 0, 212, 16, 0, 17, 18, - 19, 0, 0, 0, 20, 0, 0, 0, 21, 22, - 0, 0, 63, 213, 0, 0, 0, 23, 24, 25, - 0, 0, 0, 0, 0, 26, 27, 0, 0, 0, - 65, 66, 28, 0, 29, 0, 30, 0, 0, 0, - 0, 31, 0, 32, 33, 34, 70, 0, 35, 0, - 0, 72, 0, 36, 0, 0, 37, 0, 0, 38, - 7, 8, 9, 10, 39, 11, 12, 13, 14, 0, - 0, 53, 0, 54, 55, 56, 0, 40, 0, 0, - 41, 42, 43, 0, 0, 44, 0, 45, 46, 1246, - 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, - 63, 213, 0, 0, 15, 0, 0, 0, 16, 0, - 17, 18, 19, 0, 0, 0, 20, 0, 65, 66, - 21, 22, 0, 0, 0, 0, 0, 0, 0, 23, - 24, 25, 0, 0, 70, 0, 0, 26, 27, 72, - 0, 0, 0, 0, 28, 0, 29, 0, 30, 0, - 0, 0, 0, 31, 0, 32, 33, 34, 0, 0, - 35, 0, 0, 0, 0, 36, 518, 519, 37, 1171, - 1172, 38, 7, 8, 9, 10, 39, 11, 12, 13, - 1173, 0, 0, 0, 0, 0, 0, 0, 0, 40, - 0, 0, 41, 42, 43, 0, 0, 44, 0, 45, - 46, 0, 0, 0, 47, 0, 0, 53, 0, 54, - 55, 56, 520, 521, 0, 0, 1058, 0, 0, 60, - 0, 0, 0, 0, 0, 0, 0, 0, 1059, 0, - 62, 0, 0, 1060, 0, 0, 63, 64, 0, 0, - 0, 23, 24, 0, 0, 0, 0, 0, 0, -2, - 0, 0, 0, 0, 65, 66, 0, 0, 29, 0, - 30, 0, 0, 0, 0, 1061, 0, 0, 522, 1062, - 70, 0, 1063, 71, 0, 72, 0, 36, 0, 0, - 0, 0, 0, 1178, 1179, 1180, 1181, 1182, 0, 1183, - 1184, 1185, 0, 0, 0, 0, 0, 0, 86, 87, - 0, 1064, 0, 0, 1065, 1066, 1067, 88, 0, 1068, - 0, 1069, 46, 0, 0, 89, 1070, 90, 91, 92, - 93, 0, 0, 0, 94, 0, 0, 0, 95, 0, - 0, 96, 97, 98, 99, 100, 0, 0, 0, 0, - 0, 101, 102, 103, 104, 0, 0, 0, 0, 0, - 105, 106, 0, 0, 107, 108, 0, 0, 0, 109, - 0, 0, 0, 0, 110, 111, 0, 112, 718, 0, - 0, 0, 0, 275, 276, 113, 0, 719, 720, 721, - 722, 723, 724, 725, 726, 0, 0, 0, 0, 0, - 0, 0, 114, 0, 727, 0, 728, 729, 730, 731, - 732, 733, 734, 735, 736, 737, 738, 739, 0, 0, - 0, 277, 0, 0, 53, 0, 54, 55, 56, 57, - 278, 0, 0, 279, 740, 0, 60, 0, 0, 0, - 61, 0, 0, 0, 0, 0, 0, 62, 0, 0, - 0, 0, 0, 63, 64, 0, 0, 0, 0, 741, - 0, 0, 0, 280, 0, 0, 0, 0, 0, 0, - 0, 65, 66, 0, 0, 0, 0, 67, 0, 275, - 276, 0, 0, 0, 0, 281, 69, 70, 0, 0, - 71, 0, 72, 0, 0, 0, 0, 742, 0, 0, - 743, 0, 744, 745, 746, 747, 748, 749, 750, 751, - 752, 753, 754, 283, 755, 756, 0, 277, 0, 757, - 53, 0, 54, 55, 56, 57, 278, 0, 0, 279, - 0, 0, 60, 0, 0, 0, 61, 0, 0, 0, - 0, 0, 0, 62, 0, 0, 0, 0, 0, 63, - 64, 401, 402, 1169, 1170, 1171, 1172, 0, 0, 280, - 0, 0, 0, 0, 0, 0, 1173, 65, 66, 0, - 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, - 0, 281, 69, 70, 0, 0, 71, 0, 72, 277, - 0, 0, 53, 282, 54, 55, 56, 57, 403, 0, - 0, 279, 0, 0, 60, 0, 0, 0, 61, 283, - 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, - 0, 63, 64, 0, 0, 0, 0, 0, 0, 0, - 0, 280, 0, 0, 0, 0, 0, 0, 0, 65, - 66, 0, 0, 0, 0, 67, 0, 0, 0, 0, - 0, 0, 0, 281, 69, 70, 0, 0, 71, 0, - 72, 185, 186, 187, 188, 189, 190, 191, 192, 1178, - 1179, 1180, 1181, 1182, 0, 1183, 1184, 1185, 193, 0, - 0, 283, 185, 186, 187, 188, 189, 190, 191, 192, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, - 185, 186, 187, 188, 189, 190, 191, 192, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 193, 185, 186, - 187, 188, 189, 190, 191, 192, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 193, 185, 186, 187, 188, - 189, 190, 191, 192, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 193, 185, 186, 187, 188, 189, 190, - 191, 192, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 193, 0, 0, 0, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 0, 205, 206, 207, - 458, 0, 0, 0, 0, 0, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 0, 205, 206, - 207, 471, 0, 0, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 0, 205, 206, 207, 583, - 0, 0, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 0, 205, 206, 207, 685, 0, 0, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 0, 205, 206, 207, 1196, 468, 0, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 0, - 205, 206, 207, 185, 186, 187, 188, 189, 190, 191, - 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 193, 0, 185, 186, 187, 188, 189, 190, 191, 192, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, - 185, 186, 187, 188, 189, 190, 191, 192, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 193, 185, 186, - 187, 188, 189, 190, 191, 192, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 193, 843, 844, 845, 846, - 847, 848, 849, 850, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 851, 1165, 1166, 1167, 1168, 1169, 1170, - 1171, 1172, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1173, 0, 0, 714, 0, 0, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 0, 205, - 206, 207, 1035, 0, 0, 0, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 0, 205, 206, - 207, 0, 1198, 0, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 0, 205, 206, 207, 0, - 0, 0, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 0, 205, 206, 207, 0, 0, 0, - 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, - 862, 0, 863, 864, 865, 0, 1275, 0, 1174, 1175, - 1176, 1177, 0, 0, 1178, 1179, 1180, 1181, 1182, 0, - 1183, 1184, 1185, 1165, 1166, 1167, 1168, 1169, 1170, 1171, - 1172, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1173, 186, 187, 188, 189, 190, 191, 192, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 193, 0, 0, - 0, 0, 187, 188, 189, 190, 191, 192, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 193, 187, 188, - 189, 190, 191, 192, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 193, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1167, - 1168, 1169, 1170, 1171, 1172, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1173, 0, 187, 188, 189, 190, - 191, 192, 0, 0, 0, 0, 0, 1174, 1175, 1176, - 1177, 193, 0, 1178, 1179, 1180, 1181, 1182, 0, 1183, - 1184, 1185, 0, 0, 0, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 0, 205, 206, 207, 51, - 0, 0, 369, 0, 370, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 0, 205, 206, 207, 0, - 0, 0, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 0, 205, 206, 207, 0, 52, 0, 0, 53, - 0, 54, 55, 56, 57, 371, 0, 0, 59, 0, - 0, 60, 1175, 1176, 1177, 61, 0, 1178, 1179, 1180, - 1181, 1182, 62, 1183, 1184, 1185, 0, 0, 63, 64, - 0, 197, 198, 199, 200, 201, 202, 203, 204, 0, - 205, 206, 207, 372, 0, 0, 65, 66, 0, 0, - 0, 0, 67, 187, 188, 189, 190, 191, 192, 0, - 68, 69, 70, 0, 0, 71, 0, 72, 193, 1167, - 1168, 1169, 1170, 1171, 1172, 0, 0, 0, 0, 0, - 373, 0, 0, 0, 1173, 374, 1167, 1168, 1169, 1170, - 1171, 1172, 0, 0, 0, 1167, 1168, 1169, 1170, 1171, - 1172, 1173, 0, 0, 0, 0, 0, 0, 0, 0, - 1173, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, - 199, 200, 201, 202, 203, 204, 0, 205, 206, 207, - 0, 0, 0, 1176, 1177, 415, 416, 1178, 1179, 1180, - 1181, 1182, 0, 1183, 1184, 1185, 0, 0, 0, 0, - 0, 1177, 0, 0, 1178, 1179, 1180, 1181, 1182, 0, - 1183, 1184, 1185, 1178, 1179, 1180, 1181, 1182, 0, 1183, - 1184, 1185, 0, 277, 0, 0, 53, 0, 54, 55, - 56, 57, 0, 0, 0, 279, 0, 0, 60, 0, - 0, 0, 61, 0, 0, 0, 0, 0, 0, 62, - 0, 0, 0, 0, 0, 63, 64, 0, 51, 0, - 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 65, 66, 0, 0, 0, 0, 67, - 0, 0, 0, 0, 0, 0, 0, 281, 69, 70, - 0, 0, 71, 0, 72, 52, 0, 0, 53, 0, - 54, 55, 56, 57, 371, 0, 0, 59, 0, 0, - 60, 0, 0, 0, 61, 0, 0, 0, 0, 0, - 0, 62, 0, 0, 0, 0, 0, 63, 64, 0, - 51, 0, 0, 605, 0, 0, 87, 0, 0, 0, - 0, 0, 372, 0, 88, 65, 66, 0, 0, 0, - 0, 67, 0, 0, 90, 91, 92, 0, 0, 68, - 69, 70, 0, 0, 71, 241, 72, 52, 0, 0, - 53, 99, 54, 55, 56, 57, 371, 0, 0, 59, - 0, 104, 60, 0, 0, 0, 61, 105, 0, 0, - 0, 107, 108, 62, 0, 0, 0, 51, 0, 63, - 64, 0, 111, 0, 112, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 372, 0, 0, 65, 66, 51, - 0, 0, 0, 67, 0, 0, 0, 0, 0, 114, - 0, 68, 69, 70, 52, 0, 71, 53, 72, 54, - 55, 56, 57, 371, 0, 0, 59, 0, 0, 60, - 0, 0, 0, 61, 0, 0, 52, 0, 0, 53, - 62, 54, 55, 56, 57, 58, 63, 64, 59, 0, - 0, 60, 0, 0, 0, 61, 0, 0, 0, 0, - 0, 372, 62, 0, 65, 66, 51, 0, 63, 64, - 67, 0, 0, 0, 0, 0, 0, 0, 68, 69, - 70, 0, 0, 71, 0, 72, 65, 66, 0, 0, - 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, - 68, 69, 70, 52, 0, 71, 53, 72, 54, 55, - 56, 57, 419, 0, 0, 59, 0, 0, 60, 0, - 0, 51, 61, 0, 0, 0, 0, 0, 0, 62, - 0, 0, 0, 0, 0, 63, 64, 0, 0, 0, - 0, 0, 0, 137, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 65, 66, 0, 0, 0, 52, 67, - 0, 53, 0, 54, 55, 56, 57, 68, 69, 70, - 59, 0, 71, 60, 72, 0, 0, 61, 0, 0, - 138, 0, 0, 53, 62, 54, 55, 56, 57, 776, - 63, 64, 139, 0, 0, 60, 0, 0, 137, 61, - 0, 0, 0, 0, 0, 481, 62, 0, 65, 66, - 0, 0, 63, 64, 67, 0, 0, 0, 0, 0, - 51, 0, 68, 69, 70, 0, 0, 71, 0, 72, - 65, 66, 0, 0, 0, 138, 67, 0, 53, 0, - 54, 55, 56, 57, 140, 69, 70, 139, 0, 71, - 60, 72, 0, 0, 61, 0, 0, 52, 0, 0, - 53, 62, 54, 55, 56, 57, 0, 63, 64, 59, - 0, 0, 60, 0, 0, 0, 61, 0, 0, 0, - 0, 0, 0, 62, 0, 65, 66, 0, 0, 63, - 64, 67, 0, 0, 0, 0, 0, 0, 0, 140, - 69, 70, 0, 0, 71, 0, 72, 65, 66, 0, - 86, 87, 0, 67, 0, 0, 0, 0, 0, 88, - 0, 68, 69, 70, 0, 0, 71, 89, 72, 90, - 91, 92, 93, 0, 0, 0, 94, 0, 0, 0, - 95, 0, 0, 96, 97, 98, 99, 100, 0, 0, - 0, 0, 0, 101, 102, 103, 104, 0, 0, 0, - 0, 0, 105, 106, 86, 87, 107, 108, 0, 0, - 0, 109, 0, 88, 0, 0, 110, 111, 0, 112, - 0, 89, 0, 90, 91, 92, 93, 113, 0, 0, - 94, 0, 0, 0, 95, 0, 0, 96, 97, 98, - 99, 100, 0, 0, 114, 0, 514, 101, 102, 103, - 104, 0, 0, 0, 0, 0, 105, 106, 86, 87, - 107, 108, 0, 0, 0, 109, 0, 88, 0, 0, - 110, 111, 0, 112, 0, 89, 0, 90, 91, 92, - 93, 113, 0, 0, 94, 0, 0, 0, 95, 0, - 0, 96, 97, 98, 99, 100, 0, 0, 114, 0, - 621, 101, 102, 103, 104, 0, 0, 0, 0, 0, - 105, 106, 86, 87, 107, 108, 0, 0, 0, 109, - 0, 88, 0, 0, 110, 111, 0, 112, 0, 89, - 0, 90, 91, 92, 93, 113, 0, 0, 94, 0, - 0, 0, 95, 0, 0, 96, 97, 98, 99, 100, - 0, 0, 114, 0, 626, 101, 102, 103, 104, 0, - 0, 0, 0, 0, 105, 106, 86, 87, 107, 108, - 0, 0, 0, 109, 0, 88, 0, 0, 110, 111, - 0, 112, 0, 89, 0, 90, 91, 92, 93, 113, - 0, 0, 94, 0, 0, 0, 95, 0, 0, 96, - 97, 98, 99, 100, 0, 0, 114, 0, 695, 101, - 102, 103, 104, 0, 0, 0, 0, 0, 105, 106, - 86, 87, 107, 108, 0, 0, 0, 109, 0, 88, - 0, 0, 110, 111, 0, 112, 0, 89, 0, 90, - 91, 92, 93, 113, 0, 0, 94, 0, 0, 0, - 95, 0, 0, 96, 97, 98, 99, 100, 0, 0, - 114, 0, 808, 101, 102, 103, 104, 0, 0, 0, - 0, 0, 105, 106, 86, 87, 107, 108, 0, 0, - 0, 109, 0, 88, 0, 0, 110, 111, 0, 112, - 0, 89, 0, 90, 91, 92, 93, 113, 0, 0, - 94, 0, 0, 0, 95, 0, 0, 96, 97, 98, - 99, 100, 0, 0, 114, 0, 1049, 101, 102, 103, - 104, 0, 0, 0, 0, 0, 105, 106, 86, 87, - 107, 108, 0, 0, 0, 109, 0, 88, 0, 0, - 110, 111, 0, 112, 0, 89, 0, 90, 91, 92, - 93, 113, 0, 0, 94, 0, 0, 0, 95, 0, - 0, 96, 97, 98, 99, 100, 0, 0, 114, 0, - 1146, 101, 102, 103, 104, 0, 0, 0, 0, 0, - 105, 106, 87, 0, 107, 108, 0, 0, 0, 109, - 88, 0, 0, 0, 110, 111, 87, 112, 0, 0, - 90, 91, 92, 0, 88, 0, 0, 0, 0, 0, - 0, 241, 0, 0, 90, 91, 92, 99, 250, 0, - 0, 0, 114, 0, 0, 241, 87, 104, 0, 0, - 0, 99, 0, 105, 88, 0, 0, 0, 108, 0, - 0, 104, 0, 0, 90, 91, 92, 105, 111, 0, - 112, 0, 108, 0, 0, 241, 0, 0, 0, 0, - 0, 99, 111, 0, 112, 0, 0, 0, 0, 0, - 0, 104, 0, 0, 0, 114, 0, 105, 0, -140, - 0, 0, 108, 0, 0, 0, 0, 0, 0, 114, - 0, 0, 111, 0, 112, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 114 -}; +#define YYPACT_NINF -703 #define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-755))) + (!!((Yystate) == (-703))) + +#define YYTABLE_NINF -676 #define yytable_value_is_error(Yytable_value) \ - YYID (0) + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int16 yypact[] = +{ + 362, -703, 2822, 4474, 57, 3018, -703, -703, -703, -703, + -703, -703, -703, -703, -118, -82, -78, -69, -61, -41, + -13, -30, -4, -703, -703, -18, -2, 1, 4682, -703, + -703, 23, 59, 73, 89, 133, -703, 141, 188, 199, + 2822, 2822, 2822, 2822, 2822, 1432, 585, 2822, 3762, -703, + 189, -703, -703, -703, -703, -703, -703, -703, 4704, 213, + -703, -20, -703, -703, 1983, 2722, 2722, -703, 1244, -703, + 2722, -703, -703, 62, -703, -703, -703, -703, 66, 48, + 959, -703, -703, -703, -703, -703, -703, 5378, 5378, -703, + 5378, 892, 5378, 160, -703, 5335, 225, 227, 233, 251, + 5378, 2255, 191, 269, 272, 5378, 5378, 263, 5263, 5378, + 5378, 2691, 5378, 5378, -703, 63, -703, -703, -703, 3269, + -703, -703, -703, -703, -703, -703, 2822, 4474, 2822, 2822, + 2822, 2822, 4474, 2822, 4474, 2822, 2822, 2822, -703, -703, + 278, 1244, 289, 1244, 1244, -703, 4474, 2822, 2822, 4474, + 4474, 1432, 2822, 2822, 79, 79, 79, 79, 79, -118, + -78, -69, -61, -41, -30, -18, -2, 2511, 2380, 2608, + 2625, 199, 309, -83, 3762, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, 1244, 310, 332, -703, -703, + 79, 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2822, + 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2822, + 2822, 2822, 2252, 2822, -703, -703, 62, 2822, -703, -703, + -703, 2722, -703, -703, -703, -703, -703, 322, 145, 62, + 62, 145, 145, 4033, 321, -703, 324, -703, -703, -703, + -703, 1115, 342, 27, 64, 87, -703, -703, -703, 5378, + -703, -703, -703, 5378, -703, -703, -703, 5231, 2349, -703, + 1244, 1244, 1244, 1244, -703, -703, 363, -703, -703, -703, + -703, -703, 2822, 3300, -703, 346, -703, 3376, -703, 1244, + 115, -703, -703, 1244, 300, 348, -703, 2943, 349, 4546, + 1244, -703, 1244, 350, 148, 370, -703, -703, -703, -703, + 900, 959, -703, 344, 381, -703, 351, 378, 383, 384, + 385, 396, 388, 399, 392, 397, 398, 2822, -703, 2822, + -703, -703, 413, 406, 407, 409, 425, 416, 3483, 417, + 418, 2822, 2822, -703, -703, -24, 585, 935, 3983, 1311, + 1311, 117, 117, 729, 729, -703, 3672, 4123, 4039, 1275, + 117, 117, 167, 167, 79, 79, 79, -703, -703, -36, + 1126, -703, 3504, 145, 441, 145, 145, 145, 145, 145, + 364, -703, 321, -703, 321, -703, 364, 364, -703, 145, + 4603, 4452, 145, 145, 435, 37, -703, 623, -703, 2822, + 1244, 436, -703, -703, -703, -703, 1115, -703, 509, -703, + -703, -703, 458, 466, 467, 470, 477, 4839, -703, 3443, + 4236, 295, 464, 2943, 148, -703, -703, 481, -703, 4474, + 468, 485, 471, -703, 20, -703, -703, -703, 2822, 4704, + 403, -703, -703, 474, -703, -703, 1244, -9, -703, -703, + -703, 1553, -703, -703, 529, -703, 491, -703, -703, -703, + -703, -703, -703, -703, 479, -703, 480, -703, -703, -703, + 3522, 482, 483, -703, -703, -703, 486, -703, -703, -703, + -703, 79, 3762, -703, 4308, 932, -703, -703, 2822, -703, + -703, -703, 364, 145, 364, 364, 364, 364, 364, 2822, + -58, 4704, 623, -703, 26, 35, 572, -703, 4380, 492, + 623, 623, 623, 623, 623, 623, -21, -703, -703, 484, + 3762, -703, -34, -703, 510, 4895, -703, 511, -703, 4951, + -703, 631, 633, 634, 637, -703, -703, 355, 523, -703, + -703, 1244, 2467, 1244, 516, 530, -703, 623, -703, -703, + 20, -703, -703, 529, -703, 528, 512, 1244, 2014, 4308, + 522, 529, 4308, 529, 3540, 403, 533, 403, 403, 403, + 403, 403, 95, -703, -703, 5007, -703, 520, -703, 210, + -703, -71, 546, 547, 537, 548, 549, 2366, 3707, 550, + 529, 529, 3133, 529, 529, 529, 529, -703, 138, 308, + -703, 1115, 2822, 2822, -703, -703, 2822, 2822, 539, 4625, + -703, -703, -703, -703, 543, 564, -703, 3762, 364, 544, + 552, 623, -21, 555, 556, 932, -703, -703, 623, 557, + 557, 557, 557, 557, 265, 2822, 2822, -703, -703, 558, + -703, 2822, -703, 4125, 568, 574, -703, -703, -703, -23, + 577, 579, 584, 5063, 41, -703, 582, 623, 587, 5309, + 4236, 44, 529, -703, 308, -703, 5378, -703, -703, -703, + -703, -703, -703, -703, 601, 586, 611, -703, -703, 4682, + -703, -703, 612, 605, 615, -703, 609, 2822, 2822, 2822, + 2822, 1432, 2822, 610, 78, -703, -703, 3804, -703, 189, + -703, 613, 529, 367, 614, -703, 308, -703, 273, 403, + 618, 618, 618, 618, 618, -703, 2822, -703, 4308, -703, + 1867, -703, -703, 1244, 2822, 2822, -703, -703, -703, -703, + -703, 2366, 619, 638, 3762, -703, -703, 529, 301, 301, + 748, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, 622, 621, -703, + -703, 301, 301, 301, 373, 766, -703, 2822, -703, 1553, + 645, -703, 510, 17, 80, 98, 142, 572, 4682, 62, + 369, -703, -703, 4308, -21, -703, 4308, 4308, -703, 557, + 629, 3762, 627, 3726, 4743, 4759, 4798, 1244, 426, -703, + 1244, -703, -703, -703, 4125, 5119, 767, 650, 769, 772, + 773, -703, 657, 4474, 44, 4474, -703, -703, -703, -703, + 2936, -703, -703, -703, 308, 660, -703, -703, 4474, 4474, + 4474, 647, 4474, 4474, 4474, 1432, 79, 79, 79, 79, + 654, 144, 79, -703, -703, 2133, 2822, 2822, 2822, 2822, + 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2822, + 2822, 2822, 2822, 2822, 2822, 2822, 2822, 2480, 2822, 572, + 382, 661, 572, 674, -703, -703, 618, 4308, 656, 662, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, -703, -703, -703, -703, -703, + -703, -703, -703, -703, -703, 659, -703, 663, 665, 667, + -703, 2594, 301, -703, -703, -703, -703, -703, 2014, 668, + 3707, 529, -703, -703, -703, -703, 932, 62, -703, -703, + 669, 670, 682, -703, 688, 689, 4308, -703, -703, 3147, + -703, 3147, -703, 3147, -703, -703, 3147, 3147, 3147, -703, + 5175, -703, -703, 154, -703, 175, 691, 176, -703, -703, + -703, -703, 694, 697, 705, 707, 699, 709, 2936, 2936, + 2936, 2936, 2936, 1432, 2936, 3935, -703, 720, -703, 529, + 706, 715, 717, 2822, 721, 719, 739, 730, 3575, 2822, + -703, -703, -703, 935, 3983, 1311, 1311, 117, 117, 729, + 729, -703, 3744, 4123, 4039, 1275, 117, 117, 167, 167, + 79, 79, 79, -703, -703, 196, 2034, 283, 733, -703, + 283, 529, 4308, 736, -703, 572, 1720, -703, -703, -703, + -703, 2366, 3762, 738, -703, -703, 753, -703, -703, -703, + 572, 572, 572, 741, -703, -703, -703, -703, -703, -703, + -703, 875, 760, 879, 764, 765, 884, 768, 4474, 4474, + 4474, 4474, 4474, 4474, 205, 205, 205, 205, 205, 749, + 198, 205, 2936, 2936, 2936, 2936, 2936, 2936, 2936, 2936, + 2936, 2936, 2936, 2936, 2936, 2936, 2936, 2936, 2936, 2936, + 2936, 2708, 2822, 529, -703, -703, 771, 774, 751, 775, + -703, 777, -703, -703, 79, 2822, -703, -703, -703, 4308, + -703, 763, 572, 283, -703, 761, 572, -703, 932, 932, + 932, 572, 770, -703, 785, -703, -703, 200, -703, 795, + 781, 807, 809, 802, 813, 2936, -703, 1567, 3965, 3088, + 3088, 462, 462, 762, 762, -703, 3893, 2266, 4139, 4168, + 686, 686, 205, 205, 205, -703, -703, 201, 3164, -703, + 2822, 2822, -703, 2822, 2822, 3762, 4308, 812, 572, 283, + -703, 283, 816, -703, -703, -703, 283, 837, 903, 956, + 847, -703, 832, 833, 834, -703, 836, 205, 2936, -703, + -703, 206, 245, 247, 248, 835, 572, 283, -703, -703, + 838, 841, -703, 2822, 2822, 2822, 2822, 3935, -703, -703, + -703, -703, 572, 932, 854, 855, 256, 257, 258, 262, + 932, -703, -703, -703, -703, -703, -703, -703, -703 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint16 yydefact[] = +{ + 0, 680, 0, 0, 0, 680, 5, 592, 588, 591, + 676, 677, 594, 595, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 590, 596, 0, 0, 0, 0, 598, + 597, 0, 0, 0, 0, 0, 589, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 680, 0, 3, 532, + 593, 261, 269, 343, 344, 346, 347, 328, 0, 0, + 358, 325, 357, 352, 349, 348, 351, 329, 0, 330, + 350, 360, 345, 680, 4, 263, 264, 265, 0, 314, + 0, 260, 340, 341, 342, 1, 20, 680, 680, 21, + 680, 680, 680, 0, 37, 680, 0, 0, 0, 0, + 680, 0, 0, 0, 0, 680, 680, 0, 680, 680, + 680, 0, 680, 680, 6, 0, 16, 7, 18, 0, + 14, 58, 15, 17, 62, 39, 680, 0, 680, 680, + 680, 680, 0, 680, 0, 680, 680, 680, 282, 287, + 0, 0, 553, 0, 0, 281, 0, 680, 680, 0, + 0, 0, 680, 680, 562, 560, 559, 561, 558, 261, + 343, 344, 346, 347, 358, 357, 352, 349, 348, 351, + 350, 345, 0, 0, 493, 664, 665, 666, 669, 667, + 671, 670, 668, 672, 658, 657, 0, 655, 660, 654, + 557, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 678, 679, 680, 0, 326, 327, + 359, 349, 354, 353, 356, 262, 355, 0, 680, 680, + 680, 680, 680, 680, 0, 290, 248, 680, 673, 674, + 675, 0, 316, 664, 665, 667, 292, 266, 294, 680, + 50, 49, 51, 680, 40, 45, 22, 680, 0, 43, + 0, 0, 0, 0, 48, 680, 0, 25, 24, 23, + 46, 42, 0, 0, 146, 0, 52, 0, 19, 0, + 0, 44, 47, 0, 289, 271, 280, 0, 0, 0, + 0, 12, 0, 0, 0, 288, 63, 273, 274, 275, + 314, 0, 270, 0, 492, 491, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 283, 680, + 285, 284, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 587, 659, 680, 680, 571, 572, 573, + 574, 575, 576, 579, 580, 586, 0, 568, 569, 570, + 577, 578, 566, 567, 563, 564, 565, 585, 584, 0, + 0, 291, 0, 680, 0, 680, 680, 680, 680, 680, + 253, 240, 0, 249, 0, 250, 252, 251, 179, 680, + 0, 0, 680, 680, 0, 180, 183, 680, 178, 680, + 322, 0, 319, 318, 313, 317, 0, 680, 680, 41, + 38, 680, 0, 0, 0, 0, 0, 680, 331, 0, + 680, 289, 271, 0, 0, 288, 71, 0, 337, 0, + 0, 54, 56, 80, 82, 289, 271, 65, 0, 0, + 680, 272, 680, 0, 361, 196, 0, 0, 60, 361, + 201, 0, 61, 59, 0, 278, 316, 276, 538, 552, + 544, 540, 542, 543, 0, 550, 0, 549, 539, 546, + 0, 0, 0, 545, 548, 551, 0, 555, 556, 547, + 541, 533, 494, 96, 680, 680, 95, 656, 0, 583, + 582, 268, 254, 680, 245, 241, 242, 244, 243, 680, + 0, 0, 680, 217, 0, 0, 680, 182, 0, 0, + 680, 680, 680, 680, 680, 680, 680, 230, 229, 0, + 490, 489, 323, 312, 267, 680, 297, 680, 296, 680, + 333, 0, 0, 0, 0, 335, 680, 0, 0, 158, + 159, 0, 0, 0, 0, 148, 149, 680, 157, 147, + 0, 73, 75, 0, 339, 0, 0, 0, 680, 680, + 0, 0, 680, 0, 0, 680, 0, 680, 680, 680, + 680, 680, 0, 221, 220, 680, 84, 0, 680, 0, + 8, 0, 0, 0, 0, 0, 0, 680, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 64, 680, 680, + 160, 0, 0, 0, 286, 554, 0, 0, 0, 0, + 98, 100, 97, 99, 0, 0, 175, 581, 246, 0, + 0, 680, 680, 0, 0, 680, 181, 184, 680, 235, + 231, 232, 234, 233, 0, 0, 680, 214, 194, 255, + 320, 0, 293, 0, 0, 299, 298, 336, 680, 0, + 0, 0, 0, 680, 0, 36, 151, 680, 153, 680, + 0, 680, 0, 72, 680, 338, 680, 55, 647, 643, + 646, 649, 650, 186, 0, 0, 0, 645, 651, 0, + 653, 652, 0, 0, 0, 644, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 218, 190, 219, 601, 648, + 185, 0, 0, 0, 0, 66, 680, 279, 0, 680, + 226, 222, 223, 225, 224, 90, 680, 13, 680, 197, + 362, 363, 361, 0, 680, 680, 199, 200, 202, 204, + 205, 680, 0, 208, 210, 207, 203, 0, 167, 163, + 0, 113, 114, 115, 116, 117, 118, 121, 122, 137, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 141, 140, 124, 123, 110, 112, 111, 119, + 120, 108, 109, 105, 106, 107, 104, 0, 0, 103, + 161, 164, 166, 165, 0, 0, 171, 680, 173, 0, + 0, 67, 277, 0, 0, 0, 0, 680, 0, 680, + 0, 361, 247, 680, 680, 215, 680, 680, 256, 236, + 239, 195, 0, 324, 671, 0, 670, 0, 0, 300, + 0, 302, 661, 680, 0, 680, 0, 0, 0, 0, + 0, 332, 0, 0, 680, 0, 142, 145, 143, 150, + 0, 155, 192, 74, 680, 0, 76, 53, 0, 0, + 0, 609, 0, 0, 0, 0, 617, 616, 615, 614, + 0, 0, 613, 57, 189, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 680, + 0, 0, 680, 0, 69, 92, 227, 680, 0, 0, + 365, 366, 370, 367, 374, 368, 369, 371, 372, 373, + 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 440, 421, 422, 423, + 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, + 434, 435, 436, 437, 438, 439, 441, 442, 443, 444, + 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, + 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, + 465, 680, 482, 483, 484, 475, 487, 471, 472, 470, + 477, 478, 466, 467, 468, 469, 476, 474, 481, 479, + 485, 480, 486, 473, 364, 0, 9, 0, 0, 0, + 206, 209, 168, 162, 139, 138, 170, 174, 680, 0, + 195, 0, 536, 535, 537, 534, 680, 680, 176, 101, + 0, 0, 0, 216, 0, 0, 680, 237, 321, 0, + 305, 0, 304, 0, 303, 663, 0, 0, 0, 662, + 680, 301, 334, 0, 26, 0, 0, 0, 35, 152, + 156, 154, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 193, 495, 0, 78, 0, + 0, 0, 0, 680, 0, 0, 0, 0, 0, 0, + 642, 188, 191, 626, 627, 628, 629, 630, 631, 634, + 635, 641, 0, 623, 624, 625, 632, 633, 621, 622, + 618, 619, 620, 640, 639, 0, 0, 81, 0, 86, + 83, 0, 680, 0, 228, 680, 0, 198, 11, 10, + 211, 680, 212, 0, 169, 68, 0, 177, 102, 599, + 680, 680, 680, 0, 311, 310, 309, 308, 307, 306, + 295, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 508, 506, 505, 507, 504, 0, + 0, 503, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 77, 608, 0, 0, 0, 0, + 607, 0, 611, 612, 602, 0, 638, 637, 88, 680, + 70, 0, 680, 85, 488, 0, 680, 361, 680, 680, + 680, 680, 0, 27, 0, 32, 34, 0, 29, 0, + 0, 0, 0, 0, 0, 0, 531, 517, 518, 519, + 520, 521, 522, 523, 524, 530, 0, 514, 515, 516, + 512, 513, 509, 510, 511, 529, 528, 0, 0, 79, + 0, 0, 610, 0, 0, 636, 680, 0, 680, 91, + 213, 172, 0, 259, 258, 257, 238, 0, 0, 0, + 0, 502, 0, 0, 0, 501, 0, 496, 0, 527, + 526, 0, 0, 0, 0, 0, 680, 93, 600, 28, + 0, 0, 30, 0, 0, 0, 0, 525, 605, 604, + 606, 603, 680, 680, 0, 0, 0, 0, 0, 0, + 680, 87, 33, 31, 499, 498, 500, 497, 89 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -703, -703, -222, -703, 279, -703, -703, 734, -703, -703, + -11, 450, -703, -99, -703, -703, -703, -33, -132, -703, + -703, -703, -87, -197, -703, -703, -703, 731, -703, -703, + -703, -703, -703, -442, -703, -703, 358, -703, -703, -703, + 361, 489, -516, -703, -512, -559, -467, -703, -15, -703, + 190, -541, -703, -377, -702, -703, -380, 161, -309, -206, + 85, -191, -42, -95, -579, -227, 16, -104, -703, -89, + -703, -703, -703, -703, 203, -73, -703, -356, -703, -703, + -14, -7, -703, -703, -703, -703, 14, 51, -703, -703, + -437, -703, 24, -703, -472, -125, -27, -260, 531, 277, + -703, -703, 687, -703, -698, 803, 811, -514, -1 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 4, 5, 569, 570, 116, 432, 117, 118, 257, + 119, 420, 421, 120, 121, 444, 553, 587, 695, 278, + 543, 652, 653, 833, 293, 549, 552, 294, 708, 1219, + 1276, 887, 1132, 475, 770, 827, 122, 275, 534, 535, + 536, 537, 588, 1028, 589, 605, 384, 385, 683, 684, + 831, 627, 438, 442, 722, 723, 386, 686, 562, 506, + 234, 235, 73, 415, 142, 296, 74, 75, 397, 76, + 398, 517, 634, 635, 809, 77, 78, 394, 390, 391, + 79, 80, 123, 526, 638, 124, 81, 82, 83, 84, + 567, 568, 710, 1014, 509, 303, 304, 1085, 174, 49, + 687, 688, 186, 187, 811, 812, 590, 50, 125 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int16 yytable[] = +{ + 6, 493, 574, 307, 308, 309, 310, 598, 312, 274, + 314, 315, 316, 644, 143, 297, 216, 609, 173, 1019, + 789, 144, 323, 324, 295, 361, 126, 329, 330, 778, + 298, 654, 550, 473, 689, 693, 218, 542, 373, 375, + 514, 696, 145, 407, 332, 189, 299, 214, 780, 215, + 416, 497, 572, 573, 615, 714, 798, 85, 238, 239, + 427, 172, 127, 333, 728, 729, 128, 771, 772, 773, + 774, 795, 236, 715, 227, 129, 250, 251, 228, 252, + 254, 255, 691, 130, 259, 694, 219, 489, 610, 264, + 841, 332, 854, 630, 270, 271, 631, 273, 276, 277, + -673, 281, 282, 131, 816, 300, 1050, 1052, 1054, 625, + 479, 199, 301, 835, 133, 222, 223, 224, 617, 229, + 474, 226, 132, 817, 626, 305, 135, 305, 305, 305, + 305, 134, 305, 302, 305, 305, 305, -674, 197, 198, + 834, 240, 136, 306, 332, 137, 305, 305, 311, 199, + 313, 305, 305, -673, 802, 883, -673, 364, 146, 551, + -675, 365, 322, 1032, 498, 325, 326, 327, 685, 297, + 599, 489, 613, 297, 830, 515, 880, 241, 295, 519, + 489, 614, 230, 297, 298, 359, 541, 822, 298, 626, + -674, 387, 237, -674, 461, 214, 231, 215, 298, 199, + 299, 232, 366, 147, 299, 855, 233, 332, 283, 1037, + 565, 1022, 781, -675, 299, 236, -675, 148, 222, 223, + 224, 226, 211, 212, 213, 332, 1033, 371, 236, 236, + 371, 371, 388, 149, 888, 782, 392, 1190, 259, 705, + 706, 889, 399, 418, 1034, 419, 698, 430, 700, 701, + 702, 703, 704, 1043, 206, 207, 208, 209, 210, 300, + 211, 212, 213, 300, 6, 367, 301, 775, 150, 332, + 301, 332, 222, 300, 439, 1015, 440, 836, 441, 368, + 301, 1161, 776, 777, 369, 151, 612, 302, 1035, 256, + 1100, 302, 395, 1087, 619, 620, 621, 622, 623, 624, + 1162, 302, 1163, 1166, 643, 1029, 208, 209, 210, 297, + 211, 212, 213, 370, 372, 374, 376, 377, 305, 884, + 267, 1164, 1167, 332, 298, 332, 1042, 1289, 332, 1044, + 1045, 651, 152, 332, 476, 189, 712, 713, 492, 387, + 299, 689, 1216, 153, 1246, 1036, 1290, 1299, 1200, 1201, + 1202, 1154, 1318, 1155, 1041, 1156, 600, 217, 1157, 1158, + 1159, 10, 371, 11, 371, 371, 371, 371, 371, 260, + 601, 261, 332, 602, 332, 332, 603, 262, 371, 175, + 176, 371, 371, 332, 332, 332, 508, 555, 511, 332, + 886, 1319, 604, 1320, 1321, 263, 6, 518, 268, 300, + 6, 269, 1334, 1335, 1336, 794, 301, 272, 1337, 539, + 626, 800, 799, 238, 239, 556, 815, 885, 706, 557, + 1133, -94, 317, -94, 538, -94, -94, 302, -94, 564, + -94, 6, 387, 319, 439, 545, 440, 1127, 779, 1225, + 1130, 824, 177, 178, 423, 776, 777, 395, 482, 611, + 484, 485, 486, 487, 488, 331, 387, 1088, 335, 336, + 558, 363, 179, 180, 490, 181, 389, 494, 495, -240, + 182, 396, 183, 388, 606, 685, 434, 1146, 435, 436, + 437, 410, 371, 1188, 1189, 1, 2, 3, 511, 408, + 448, 508, 424, 428, 1190, 476, 240, 449, 443, 508, + 508, 508, 508, 508, 508, 628, 387, 387, 332, 489, + 387, 776, 777, 881, 689, 1039, 636, 776, 777, 1026, + 1056, 1057, 1058, 559, 450, 6, 776, 777, 1128, 451, + 452, 453, 454, 48, 455, 456, 508, 560, 457, 238, + 239, 579, 561, 458, 459, 580, 538, 690, 388, 462, + 826, 388, 463, 464, 564, 465, 564, 564, 564, 564, + 564, 466, 467, 469, 470, 783, 784, 711, 608, 785, + 786, 154, 155, 156, 157, 158, 725, 654, 190, 1153, + 483, 496, 516, 513, 520, 143, 581, 606, 628, 1017, + 1018, 1060, 144, 521, 522, 175, 176, 523, 1038, 1195, + 1196, 1197, 1198, 1199, 524, 1200, 1201, 1202, 540, 544, + 508, 628, 547, 145, 606, 548, 546, 508, 566, 696, + 591, 582, 240, 592, 593, 511, 810, 596, 595, 473, + 597, 618, 629, 238, 239, 499, -315, 6, 273, 500, + 633, 639, 395, 640, 641, 837, 508, 642, 685, 583, + 832, 645, 649, 628, 851, 143, 655, 650, 177, 178, + 656, 692, 144, 584, 538, 1221, 387, 709, 585, 1283, + 1284, 1285, 699, 586, 716, 717, 719, 720, 179, 180, + 501, 181, 328, 145, 718, 787, 182, 790, 183, 727, + 791, 834, 792, 1223, 813, 628, 793, 850, 564, 796, + 797, 814, 626, -247, 818, 511, 819, 388, 1228, 1229, + 1230, 820, 823, 305, 305, 184, 240, 825, 1190, 185, + 725, 839, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 502, 360, 838, 840, 842, 362, 843, + 844, 387, 1277, 845, 387, 387, 853, 503, 1023, 879, + 882, 199, 504, 706, 1331, 1021, 1020, 505, 1024, 1025, + 1027, 1338, 1031, 1046, 143, 1047, 511, 1063, 1064, 1065, + 1279, 144, 1066, 1067, 1281, 1068, 476, 1089, 236, 1286, + 1282, 1093, 388, 628, 1190, 388, 388, 810, 810, 810, + 1099, 1131, 145, 409, 1134, 1129, 1137, 810, 1135, 1305, + 1138, 1139, 6, 387, 1140, 1148, 1144, 1149, 1174, 1175, + 1176, 1177, 1178, 832, 1181, 1197, 1198, 1199, 1150, 1200, + 1201, 1202, 1169, 628, 1151, 1152, 1307, 1165, 1168, 1069, + 1170, 1071, 1171, 1172, 1173, 387, 1147, 1203, 460, 188, + 1125, 1206, 1205, 1207, 1090, 1091, 1092, 1209, 1094, 1095, + 1096, 1097, 471, 472, 1323, 1210, 206, 207, 208, 209, + 210, 225, 211, 212, 213, 1211, 1212, 1218, 476, 1227, + 1330, 476, 1222, 247, 1226, 1232, 388, 1231, 1233, 1234, + 242, 248, 1235, 1236, 1237, 1245, 1238, 1272, 253, 1195, + 1196, 1197, 1198, 1199, 266, 1200, 1201, 1202, 1280, 1278, + 243, 244, 1288, 1310, 280, 1270, 1287, 1292, 1271, 1273, + 510, 1274, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, + 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, + 1265, 1291, 87, 1293, 318, 1294, 320, 321, 1295, 1296, + 88, 192, 193, 194, 195, 196, 197, 198, 1306, 554, + 90, 91, 92, 1308, 599, 1309, 1311, 199, 1208, 243, + 244, 249, 578, 177, 178, 1312, 1313, 1314, 1315, 100, + 1316, 1322, 1332, 1333, 1324, 1297, 387, 1325, 334, 105, + 711, 400, 1016, 245, 180, 106, 181, 657, 1145, 1220, + 109, 182, 1204, 183, 387, 600, 1269, 828, 414, 607, + 112, 829, 113, 1143, 1070, 1136, 1102, 1061, 0, 601, + 510, 647, 602, 477, 0, 603, 0, 690, 0, 241, + 0, 0, 177, 178, 0, 606, 236, 115, 1317, 0, + 0, 604, 810, 0, 810, 388, 810, 0, 0, 810, + 810, 810, 245, 180, 0, 181, 1180, 0, 0, 0, + 182, 402, 183, 403, 404, 405, 406, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 0, 417, 0, 0, 246, 422, 0, 0, 0, + 387, 0, 305, 431, 0, 433, 0, 0, 0, 1179, + 0, 0, 0, 445, 447, 0, 0, 1086, 724, 0, + 0, 446, 248, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 393, 0, 0, 0, + 0, 388, 0, 0, 476, 0, 0, 0, 0, 188, + 725, 191, 192, 193, 194, 195, 196, 197, 198, 476, + 476, 476, 0, 0, 0, 0, 801, 510, 199, 0, + 0, 0, 803, 0, 0, 0, 53, 0, 54, 55, + 56, 0, 0, 0, 1267, 0, 0, 387, 0, 0, + 0, 0, 0, 0, 1239, 1240, 1241, 1242, 1243, 1244, + 0, 0, 0, 512, 0, 63, 221, 0, 507, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 846, 847, + 848, 849, 0, 852, 0, 65, 66, 0, 388, 0, + 0, 476, 0, 0, 0, 476, 0, 606, 606, 606, + 476, 70, 0, 0, 387, 0, 72, 510, 0, 571, + 0, 563, 0, 1301, 1302, 0, 1303, 1304, 0, 0, + 0, 0, 724, 0, 175, 176, 0, 200, 201, 202, + 203, 204, 205, 206, 207, 208, 209, 210, 0, 211, + 212, 213, 0, 0, 480, 388, 0, 476, 0, 0, + 0, 0, 0, 0, 0, 0, 1326, 1327, 1328, 1329, + 0, 0, 193, 194, 195, 196, 197, 198, 0, 0, + 0, 0, 0, 507, 0, 476, 0, 199, 510, 0, + 1030, 507, 507, 507, 507, 507, 507, 177, 178, 0, + 0, 476, 606, 0, 0, 0, 0, 0, 0, 606, + 195, 196, 197, 198, 646, 0, 648, 179, 180, 0, + 181, 0, 0, 199, 0, 182, 0, 183, 507, 0, + 422, 0, 0, 0, 0, 1086, 1086, 1086, 1086, 1086, + 0, 1086, 0, 0, 0, 0, 563, 0, 563, 563, + 563, 563, 563, 0, 0, 0, 1098, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1103, 1104, 1105, + 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, + 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 0, 1126, + 204, 205, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 0, 507, 0, 0, 0, 0, 0, 0, 507, + 0, 0, 0, 0, 0, 7, 8, 9, 10, 0, + 11, 12, 13, 159, 0, 0, 204, 205, 206, 207, + 208, 209, 210, 0, 211, 212, 213, 0, 507, 1086, + 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, + 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 0, 15, + 52, 0, 0, 160, 0, 161, 162, 163, 57, 58, + 0, 20, 59, 0, 0, 164, 22, 0, 0, 61, + 0, 0, 0, 0, 23, 24, 165, 0, 0, 0, + 563, 0, 166, 167, 0, 0, 571, 0, 0, 0, + 0, 28, 1086, 29, 0, 30, 0, 0, 0, 0, + 31, 0, 168, 169, 34, 0, 0, 35, 67, 0, + 0, 0, 36, 0, 0, 37, 68, 69, 170, 0, + 0, 71, 1142, 171, 0, 0, 7, 8, 9, 10, + 0, 11, 12, 13, 14, 0, 40, 0, 0, 41, + 42, 43, 0, 0, 44, 1086, 45, 46, 0, 0, + 0, 47, 0, 1183, 1184, 1185, 1186, 1187, 1188, 1189, + 0, 0, 0, 1040, 0, 0, 0, 0, 0, 1190, + 15, 0, 0, 0, 16, 0, 17, 18, 19, 0, + 1055, 0, 20, 1059, 575, 576, 21, 22, 0, 0, + 0, 0, 0, 0, 0, 23, 24, 25, 0, 0, + 1214, 0, 0, 26, 27, 0, 0, 0, 0, 0, + 0, 0, 28, 0, 29, 0, 30, 0, 0, 0, + 0, 31, 0, 32, 33, 34, 0, 0, 35, 0, + 0, 0, 0, 36, 0, 0, 37, 0, 0, 38, + 0, 0, 724, 0, 39, 0, 0, 0, 0, 577, + 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, + 41, 42, 43, 0, 0, 44, 0, 45, 46, 1192, + 1193, 1194, 47, 0, 1195, 1196, 1197, 1198, 1199, 0, + 1200, 1201, 1202, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 890, 891, 892, 893, 894, 895, 896, + 897, 898, 899, 1268, 900, 901, 902, 903, 904, 905, + 906, 907, 908, 909, 910, 0, 1275, 0, 0, 0, + 0, 0, 911, 912, 913, 914, 915, 916, 917, 918, + 919, 920, 921, 922, 923, 924, 925, 926, 927, 0, + 0, 928, 929, 930, 931, 932, 933, 934, 935, 936, + 937, 938, 939, 940, 941, 942, 0, 943, 0, 944, + 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, + 955, 956, 0, 0, 0, 0, 0, 957, 958, 959, + 0, 960, 961, 962, 963, 964, 965, 966, 967, 968, + 969, 970, 971, 972, 973, 974, 975, 0, 976, 977, + 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, + 988, 989, 990, 0, 0, 0, 991, 992, 993, 994, + 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, + 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1224, 1012, 1013, + 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, + 0, 900, 901, 902, 903, 904, 905, 906, 907, 908, + 909, 910, 0, 0, 0, 0, 0, 0, 0, 911, + 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, + 922, 923, 924, 925, 926, 927, 0, 0, 928, 929, + 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, + 940, 941, 942, 0, 943, 0, 944, 945, 946, 947, + 948, 949, 950, 951, 952, 953, 954, 955, 956, 0, + 0, 0, 0, 0, 957, 958, 959, 0, 960, 961, + 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, + 972, 973, 974, 975, 0, 976, 977, 978, 979, 980, + 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, + 0, 0, 0, 991, 992, 993, 994, 995, 996, 997, + 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, + 1008, 1009, 1010, 1011, 0, 1012, 1013, 658, 659, 660, + 10, 0, 11, 661, 662, 51, 0, 0, 663, 0, + 0, 0, 0, 0, 53, 0, 54, 55, 56, 0, + 0, 0, 0, 0, 0, 0, 220, 0, 0, 191, + 192, 193, 194, 195, 196, 197, 198, 0, 0, 0, + 0, 664, 52, 63, 221, 53, 199, 54, 55, 56, + 57, 380, 0, 665, 59, 0, 0, 60, 666, 0, + 0, 61, 0, 65, 66, 0, 667, 668, 62, 0, + 0, 0, 0, 0, 63, 64, 0, 0, 0, 70, + 0, 0, 0, 669, 72, 670, 0, 671, 0, 0, + 0, 381, 672, 0, 65, 66, 673, 0, 0, 674, + 67, 0, 0, 0, 675, 0, 0, 676, 68, 69, + 70, 0, 0, 71, 0, 72, 658, 659, 660, 10, + 0, 11, 661, 662, 51, 0, 0, 1101, 677, 0, + 0, 678, 679, 0, 0, 0, 680, 0, 681, 0, + 0, 0, 0, 682, 0, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 0, 211, 212, 213, + 664, 52, 1217, 0, 53, 0, 54, 55, 56, 57, + 380, 0, 665, 59, 0, 0, 60, 666, 0, 0, + 61, 0, 0, 0, 0, 667, 668, 62, 0, 0, + 0, 0, 0, 63, 64, 0, 0, 0, 0, 0, + 0, 0, 669, 0, 670, 0, 671, 0, 0, 0, + 381, 672, 0, 65, 66, 673, 0, 0, 674, 67, + 0, 0, 0, 675, 0, 0, 676, 68, 69, 70, + 0, 0, 71, 0, 72, 7, 8, 9, 10, 0, + 11, 12, 13, 14, 0, 175, 176, 677, 0, 0, + 678, 679, 0, 0, 0, 680, 0, 681, 0, 0, + 0, 0, 682, 1184, 1185, 1186, 1187, 1188, 1189, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1190, 15, + 0, 0, 0, 16, 0, 17, 18, 19, 0, 0, + 0, 20, 0, 0, 0, 21, 22, 0, 0, 0, + 0, 0, 0, 0, 23, 24, 25, 0, 177, 178, + 0, 0, 26, 27, 0, 0, 0, 0, 0, 0, + 0, 28, 0, 29, 0, 30, 0, 0, 179, 180, + 31, 181, 32, 33, 34, 0, 182, 35, 183, 175, + 176, 0, 36, 0, 0, 37, 0, 0, 38, 7, + 8, 9, 10, 39, 11, 12, 13, 14, 0, 0, + 0, 265, 0, 0, 0, 0, 40, 0, 0, 41, + 42, 43, 0, 0, 44, 0, 45, 46, 358, 1193, + 1194, 47, 0, 1195, 1196, 1197, 1198, 1199, 0, 1200, + 1201, 1202, 0, 15, 0, 0, 0, 16, 0, 17, + 18, 19, 177, 178, 0, 20, 0, 0, 0, 21, + 22, 53, 0, 54, 55, 56, 0, 0, 23, 24, + 25, 0, 179, 180, 0, 181, 26, 27, 0, 0, + 182, 0, 183, 0, 0, 28, 0, 29, 0, 30, + 63, 221, 0, 0, 31, 0, 32, 33, 34, 0, + 0, 35, 0, 0, 0, 401, 36, 529, 530, 37, + 65, 66, 38, 7, 8, 9, 10, 39, 11, 12, + 13, 14, 721, 0, 0, 0, 70, 0, 0, 0, + 40, 72, 0, 41, 42, 43, 0, 0, 44, 0, + 45, 46, 0, 0, 0, 47, 0, 0, 53, 0, + 54, 55, 56, 0, 147, 0, 0, 15, 0, 0, + 60, 16, 0, 17, 18, 19, 0, 0, 0, 20, + 0, 62, 0, 21, 22, 0, 0, 63, 64, 0, + 0, 0, 23, 24, 25, 0, 0, 0, 0, 0, + 26, 27, 53, 0, 54, 55, 56, 65, 66, 28, + 0, 29, 0, 30, 220, 0, 0, 0, 31, 0, + 32, 33, 34, 70, 0, 35, 71, 0, 72, 0, + 36, 63, 221, 37, 0, 0, 38, 7, 8, 9, + 10, 39, 11, 12, 13, 14, 0, 0, 0, 0, + 0, 65, 66, 0, 40, 0, 0, 41, 42, 43, + 0, 0, 44, 0, 45, 46, 1124, 70, 0, 47, + 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 16, 0, 17, 18, 19, + 0, 0, 0, 20, 0, 137, 0, 21, 22, 53, + 0, 54, 55, 56, 0, 0, 23, 24, 25, 0, + 0, 0, 0, 0, 26, 27, 53, 0, 54, 55, + 56, 0, 0, 28, 0, 29, 0, 30, 63, 221, + 0, 0, 31, 0, 32, 33, 34, 0, 0, 35, + 0, 175, 176, 0, 36, 63, 221, 37, 65, 66, + 38, 7, 8, 9, 10, 39, 11, 12, 13, 14, + 1141, 0, 0, 0, 70, 65, 66, 0, 40, 72, + 0, 41, 42, 43, 0, 0, 44, 0, 45, 46, + 0, 70, 0, 47, 0, 0, 72, 0, 0, 0, + 0, 0, 148, 0, 0, 15, 0, 0, 0, 16, + 0, 17, 18, 19, 177, 178, 0, 20, 0, 152, + 0, 21, 22, 53, 0, 54, 55, 56, 0, 279, + 23, 24, 25, 0, 179, 180, 0, 181, 26, 27, + 0, 0, 182, 0, 183, 0, 0, 28, 0, 29, + 0, 30, 63, 221, 0, 0, 31, 0, 32, 33, + 34, 0, 0, 35, 0, 0, 0, 0, 36, 0, + 0, 37, 65, 66, 38, 7, 8, 9, 10, 39, + 11, 12, 13, 14, 0, 0, 0, 0, 70, 0, + 0, 0, 40, 72, 0, 41, 42, 43, 0, 0, + 44, 0, 45, 46, 1266, 0, 0, 47, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, + 0, 0, 0, 16, 0, 17, 18, 19, 0, 0, + 0, 20, 0, 0, 0, 21, 22, 0, 0, 0, + 0, 0, 0, 0, 23, 24, 25, 0, 0, 0, + 0, 0, 26, 27, 0, 0, 0, 0, 0, 0, + 0, 28, 0, 29, 0, 30, 0, 0, 0, 0, + 31, 0, 32, 33, 34, 0, 0, 35, 0, 0, + 0, 0, 36, 0, 0, 37, 0, 0, 38, 7, + 8, 9, 10, 39, 11, 12, 13, 0, 0, 0, + 0, 0, 0, 425, 426, 0, 40, 0, 0, 41, + 42, 43, 0, 0, 44, 0, 45, 46, 0, 0, + 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1072, 0, 0, 0, 0, 0, 0, + 0, 286, 0, 0, 53, 1073, 54, 55, 56, 57, + 1074, 0, 0, 288, 0, 0, 60, 0, 23, 24, + 61, 0, 0, 0, 0, 0, 0, 62, -2, 0, + 0, 0, 0, 63, 64, 0, 0, 29, 0, 30, + 0, 0, 0, 0, 1075, 0, 0, 0, 1076, 0, + 0, 1077, 0, 65, 66, 0, 36, 0, 0, 67, + 0, 0, 0, 0, 0, 0, 0, 290, 69, 70, + 0, 0, 71, 0, 72, 0, 0, 86, 87, 0, + 1078, 0, 0, 1079, 1080, 1081, 88, 0, 1082, 0, + 1083, 46, 0, 0, 89, 1084, 90, 91, 92, 93, + 0, 0, 0, 94, 0, 0, 0, 95, 0, 0, + 0, 96, 97, 98, 99, 100, 101, 1186, 1187, 1188, + 1189, 0, 102, 103, 104, 105, 0, 0, 0, 0, + 1190, 106, 107, 0, 0, 108, 109, 0, 0, 0, + 110, 0, 0, 0, 0, 111, 112, 0, 113, 730, + 0, 0, 0, 0, 0, 0, 114, 0, 731, 732, + 733, 734, 735, 736, 737, 738, 0, 175, 176, 0, + 0, 0, 0, 115, 0, 739, 0, 740, 741, 742, + 743, 744, 745, 746, 747, 748, 749, 750, 751, 191, + 192, 193, 194, 195, 196, 197, 198, 0, 0, 0, + 0, 0, 0, 0, 0, 752, 199, 0, 0, 0, + 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 177, 178, 753, 0, 0, 1195, 1196, 1197, 1198, 1199, + 0, 1200, 1201, 1202, 0, 0, 0, 0, 0, 0, + 179, 180, 0, 181, 0, 0, 0, 0, 182, 0, + 183, 0, 0, 67, 0, 0, 0, 0, 0, 0, + 754, 807, 69, 755, 0, 756, 757, 758, 759, 760, + 761, 762, 763, 764, 765, 766, 0, 767, 768, 284, + 285, 0, 769, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 0, 211, 212, 213, + 284, 285, 1300, 0, 0, 0, 0, 286, 0, 0, + 53, 0, 54, 55, 56, 57, 287, 0, 0, 288, + 0, 0, 60, 0, 0, 0, 61, 0, 0, 0, + 0, 0, 0, 62, 0, 0, 0, 0, 286, 63, + 64, 53, 0, 54, 55, 56, 57, 287, 0, 0, + 288, 289, 0, 60, 0, 0, 0, 61, 0, 65, + 66, 0, 0, 0, 62, 67, 0, 0, 0, 0, + 63, 64, 0, 290, 69, 70, 411, 412, 71, 0, + 72, 0, 289, 0, 0, 291, 0, 0, 0, 0, + 65, 66, 0, 0, 0, 0, 67, 0, 0, 0, + 0, 292, 0, 0, 290, 69, 70, 0, 0, 71, + 0, 72, 0, 0, 286, 0, 0, 53, 0, 54, + 55, 56, 57, 413, 0, 0, 288, 0, 0, 60, + 0, 0, 292, 61, 0, 0, 0, 0, 0, 0, + 62, 0, 0, 0, 0, 0, 63, 64, 191, 192, + 193, 194, 195, 196, 197, 198, 0, 0, 289, 0, + 0, 0, 0, 0, 0, 199, 65, 66, 0, 0, + 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, + 290, 69, 70, 0, 0, 71, 0, 72, 191, 192, + 193, 194, 195, 196, 197, 198, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 199, 0, 0, 292, 191, + 192, 193, 194, 195, 196, 197, 198, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 199, 191, 192, 193, + 194, 195, 196, 197, 198, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 199, 191, 192, 193, 194, 195, + 196, 197, 198, 0, 0, 0, 0, 0, 0, 0, + 527, 0, 199, 0, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 528, + 191, 192, 193, 194, 195, 196, 197, 198, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 199, 0, 0, + 0, 0, 0, 0, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 468, + 0, 0, 0, 0, 0, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 0, 211, 212, 213, + 481, 0, 0, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 0, 211, 212, 213, 594, 0, + 0, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 0, 211, 212, 213, 697, 191, 192, 193, + 194, 195, 196, 197, 198, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 199, 0, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 1213, 191, 192, 193, 194, 195, 196, 197, 198, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, + 0, 191, 192, 193, 194, 195, 196, 197, 198, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 199, 191, + 192, 193, 194, 195, 196, 197, 198, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 199, 191, 192, 193, + 194, 195, 196, 197, 198, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 199, 0, 0, 0, 0, 0, + 0, 478, 0, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 0, 211, 212, 213, 0, 856, + 857, 858, 859, 860, 861, 862, 863, 0, 0, 0, + 0, 0, 0, 0, 0, 726, 864, 0, 200, 201, + 202, 203, 204, 205, 206, 207, 208, 209, 210, 0, + 211, 212, 213, 1048, 0, 0, 0, 200, 201, 202, + 203, 204, 205, 206, 207, 208, 209, 210, 0, 211, + 212, 213, 0, 1215, 0, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 0, 211, 212, 213, + 0, 0, 0, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 0, 211, 212, 213, 1182, 1183, + 1184, 1185, 1186, 1187, 1188, 1189, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1190, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 865, 866, 867, 868, 869, + 870, 871, 872, 873, 874, 875, 0, 876, 877, 878, + 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1190, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1184, 1185, 1186, 1187, 1188, 1189, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1190, 0, 0, + 193, 194, 195, 196, 197, 198, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 199, 0, 0, 0, 0, + 0, 0, 1298, 0, 1191, 1192, 1193, 1194, 0, 0, + 1195, 1196, 1197, 1198, 1199, 0, 1200, 1201, 1202, 0, + 0, 0, 0, 0, 51, 0, 0, 378, 0, 379, + 0, 0, 0, 0, 0, 0, 193, 194, 195, 196, + 197, 198, 0, 0, 0, 0, 1191, 1192, 1193, 1194, + 0, 199, 1195, 1196, 1197, 1198, 1199, 0, 1200, 1201, + 1202, 52, 0, 0, 53, 0, 54, 55, 56, 57, + 380, 0, 0, 59, 0, 0, 60, 1192, 1193, 1194, + 61, 0, 1195, 1196, 1197, 1198, 1199, 62, 1200, 1201, + 1202, 0, 0, 63, 64, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 0, + 381, 0, 0, 65, 66, 175, 176, 0, 0, 67, + 193, 194, 195, 196, 197, 198, 0, 68, 69, 70, + 0, 0, 71, 0, 72, 199, 1184, 1185, 1186, 1187, + 1188, 1189, 0, 0, 0, 0, 0, 382, 0, 0, + 0, 1190, 383, 203, 204, 205, 206, 207, 208, 209, + 210, 57, 211, 212, 213, 1184, 1185, 1186, 1187, 1188, + 1189, 0, 0, 0, 0, 0, 0, 0, 177, 178, + 1190, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 179, 804, + 805, 806, 0, 0, 0, 0, 182, 0, 183, 0, + 0, 67, 0, 0, 0, 0, 0, 0, 0, 807, + 69, 0, 0, 808, 0, 0, 529, 530, 0, 0, + 0, 0, 0, 0, 0, 0, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 0, + 0, 0, 0, 1194, 0, 0, 1195, 1196, 1197, 1198, + 1199, 0, 1200, 1201, 1202, 0, 0, 53, 0, 54, + 55, 56, 531, 532, 0, 0, 0, 0, 0, 60, + 0, 0, 0, 0, 0, 1195, 1196, 1197, 1198, 1199, + 62, 1200, 1201, 1202, 0, 0, 63, 64, 0, 51, + 0, 0, 378, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 65, 66, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 533, 0, 70, 0, 0, 71, 52, 72, 0, 53, + 0, 54, 55, 56, 57, 380, 0, 0, 59, 0, + 0, 60, 0, 0, 0, 61, 0, 0, 0, 0, + 0, 0, 62, 0, 0, 0, 0, 0, 63, 64, + 0, 51, 0, 0, 616, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 381, 0, 0, 65, 66, + 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, + 0, 0, 68, 69, 70, 0, 0, 71, 52, 72, + 0, 53, 0, 54, 55, 56, 57, 380, 0, 0, + 59, 0, 0, 60, 0, 0, 0, 61, 0, 0, + 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, + 63, 64, 0, 51, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 381, 0, 0, + 65, 66, 0, 0, 0, 51, 67, 0, 0, 0, + 0, 0, 0, 0, 68, 69, 70, 0, 0, 71, + 52, 72, 0, 53, 0, 54, 55, 56, 57, 380, + 0, 0, 59, 0, 0, 60, 0, 0, 0, 61, + 0, 0, 52, 0, 0, 53, 62, 54, 55, 56, + 57, 58, 63, 64, 59, 0, 0, 60, 0, 0, + 0, 61, 0, 0, 0, 0, 0, 0, 62, 381, + 0, 0, 65, 66, 63, 64, 0, 51, 67, 0, + 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, + 0, 71, 0, 72, 65, 66, 0, 0, 0, 0, + 67, 0, 0, 0, 0, 0, 0, 0, 68, 69, + 70, 0, 0, 71, 52, 72, 0, 53, 0, 54, + 55, 56, 57, 429, 0, 0, 59, 0, 0, 60, + 0, 0, 0, 61, 51, 0, 0, 0, 0, 0, + 62, 0, 0, 0, 0, 0, 63, 64, 0, 0, + 0, 0, 0, 0, 0, 0, 138, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 65, 66, 0, 0, + 0, 52, 67, 0, 53, 0, 54, 55, 56, 57, + 68, 69, 70, 59, 0, 71, 60, 72, 0, 0, + 61, 0, 0, 139, 0, 0, 53, 62, 54, 55, + 56, 57, 788, 63, 64, 140, 0, 0, 60, 0, + 0, 0, 61, 138, 0, 0, 0, 0, 0, 62, + 491, 0, 0, 65, 66, 63, 64, 0, 0, 67, + 0, 0, 0, 0, 0, 51, 0, 68, 69, 70, + 0, 0, 71, 0, 72, 65, 66, 0, 0, 0, + 139, 67, 0, 53, 0, 54, 55, 56, 57, 141, + 69, 70, 140, 0, 71, 60, 72, 0, 0, 61, + 0, 0, 52, 175, 176, 53, 62, 54, 55, 56, + 57, 0, 63, 64, 59, 0, 0, 60, 0, 175, + 176, 61, 0, 0, 0, 0, 0, 0, 62, 0, + 0, 0, 65, 66, 63, 64, 0, 0, 67, 0, + 0, 0, 0, 0, 0, 0, 141, 69, 70, 57, + 0, 71, 0, 72, 65, 66, 0, 0, 175, 176, + 67, 0, 0, 0, 0, 57, 177, 178, 68, 69, + 70, 0, 0, 71, 0, 72, 0, 0, 0, 0, + 0, 0, 177, 178, 0, 0, 179, 180, 0, 181, + 0, 0, 0, 0, 182, 0, 183, 0, 0, 67, + 0, 0, 179, 180, 57, 181, 0, 807, 69, 0, + 182, 1049, 183, 0, 0, 67, 0, 0, 0, 0, + 0, 177, 178, 807, 69, 0, 0, 1051, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 87, + 0, 179, 180, 0, 181, 0, 0, 88, 0, 182, + 0, 183, 0, 0, 67, 89, 0, 90, 91, 92, + 93, 0, 807, 69, 94, 0, 1053, 0, 95, 0, + 0, 0, 96, 97, 98, 99, 100, 101, 0, 0, + 0, 0, 0, 102, 103, 104, 105, 0, 0, 0, + 0, 0, 106, 107, 86, 87, 108, 109, 0, 0, + 0, 110, 0, 88, 0, 0, 111, 112, 0, 113, + 0, 89, 0, 90, 91, 92, 93, 114, 0, 0, + 94, 0, 0, 0, 95, 0, 0, 0, 96, 97, + 98, 99, 100, 101, 115, 0, 525, 0, 0, 102, + 103, 104, 105, 0, 0, 0, 0, 0, 106, 107, + 86, 87, 108, 109, 0, 0, 0, 110, 0, 88, + 0, 0, 111, 112, 0, 113, 0, 89, 0, 90, + 91, 92, 93, 114, 0, 0, 94, 0, 0, 0, + 95, 0, 0, 0, 96, 97, 98, 99, 100, 101, + 115, 0, 632, 0, 0, 102, 103, 104, 105, 0, + 0, 0, 0, 0, 106, 107, 86, 87, 108, 109, + 0, 0, 0, 110, 0, 88, 0, 0, 111, 112, + 0, 113, 0, 89, 0, 90, 91, 92, 93, 114, + 0, 0, 94, 0, 0, 0, 95, 0, 0, 0, + 96, 97, 98, 99, 100, 101, 115, 0, 637, 0, + 0, 102, 103, 104, 105, 0, 0, 0, 0, 0, + 106, 107, 86, 87, 108, 109, 0, 0, 0, 110, + 0, 88, 0, 0, 111, 112, 0, 113, 0, 89, + 0, 90, 91, 92, 93, 114, 0, 0, 94, 0, + 0, 0, 95, 0, 0, 0, 96, 97, 98, 99, + 100, 101, 115, 0, 707, 0, 0, 102, 103, 104, + 105, 0, 0, 0, 0, 0, 106, 107, 86, 87, + 108, 109, 0, 0, 0, 110, 0, 88, 0, 0, + 111, 112, 0, 113, 0, 89, 0, 90, 91, 92, + 93, 114, 0, 0, 94, 0, 0, 0, 95, 0, + 0, 0, 96, 97, 98, 99, 100, 101, 115, 0, + 821, 0, 0, 102, 103, 104, 105, 0, 0, 0, + 0, 0, 106, 107, 86, 87, 108, 109, 0, 0, + 0, 110, 0, 88, 0, 0, 111, 112, 0, 113, + 0, 89, 0, 90, 91, 92, 93, 114, 0, 0, + 94, 0, 0, 0, 95, 0, 0, 0, 96, 97, + 98, 99, 100, 101, 115, 0, 1062, 0, 0, 102, + 103, 104, 105, 0, 0, 0, 0, 0, 106, 107, + 86, 87, 108, 109, 0, 0, 0, 110, 0, 88, + 0, 0, 111, 112, 0, 113, 0, 89, 0, 90, + 91, 92, 93, 114, 0, 0, 94, 0, 0, 0, + 95, 0, 0, 87, 96, 97, 98, 99, 100, 101, + 115, 88, 1160, 0, 0, 102, 103, 104, 105, 0, + 0, 90, 91, 92, 106, 107, 0, 0, 108, 109, + 0, 0, 249, 110, 0, 0, 0, 0, 111, 112, + 100, 113, 0, 0, 0, 0, 0, 0, 0, 87, + 105, 0, 0, 0, 0, 0, 106, 88, 0, 0, + 0, 109, 0, 0, 0, 0, 115, 90, 91, 92, + 111, 112, 0, 113, 0, 87, 0, 0, 249, 0, + 0, 0, 0, 88, 0, 0, 100, 0, -144, 0, + 0, 0, 0, 90, 91, 92, 105, 0, 115, 0, + 0, 0, 106, 0, 249, 0, 108, 109, 0, 0, + 0, 0, 100, 258, 0, 0, 111, 112, 87, 113, + 0, 0, 105, 0, 0, 0, 88, 0, 106, 0, + 0, 0, 0, 109, 0, 0, 90, 91, 92, 0, + 0, 0, 0, 112, 115, 113, 0, 249, 0, 0, + 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 105, 0, 0, 0, 0, + 115, 106, 0, 0, 0, 0, 109, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 112, 0, 113, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 115 +}; static const yytype_int16 yycheck[] = { - 1, 429, 107, 127, 128, 129, 130, 404, 132, 532, - 134, 135, 136, 210, 516, 464, 709, 58, 45, 542, - 118, 28, 146, 147, 221, 222, 256, 151, 152, 28, - 28, 372, 578, 387, 479, 537, 577, 588, 792, 793, - 794, 14, 6, 12, 8, 46, 12, 16, 118, 482, - 0, 10, 11, 118, 118, 601, 124, 490, 491, 492, - 493, 494, 495, 604, 544, 125, 546, 547, 548, 549, - 550, 14, 73, 45, 142, 540, 61, 62, 125, 10, - 11, 142, 125, 128, 144, 64, 65, 66, 57, 538, - 73, 70, 541, 526, 10, 11, 642, 144, 143, 133, - 486, 144, 268, 142, 569, 570, 657, 572, 573, 574, - 575, 118, 278, 125, 73, 128, 128, 640, 73, 118, - 118, 57, 32, 6, 125, 8, 127, 128, 129, 130, - 143, 132, 91, 134, 135, 136, 10, 11, 684, 143, - 144, 124, 73, 133, 127, 146, 147, 488, 142, 118, - 151, 152, 125, 32, 126, 143, 144, 73, 388, 131, - 91, 133, 392, 132, 125, 142, 264, 600, 137, 124, - 615, 137, 127, 145, 607, 91, 148, 149, 150, 206, - 144, 578, 125, 144, 225, 144, 310, 166, 167, 168, - 169, 125, 422, 124, 264, 142, 537, 12, 268, 264, - 264, 16, 635, 268, 268, 142, 142, 687, 278, 210, - 144, 133, 128, 278, 278, 680, 132, 91, 32, 220, - 221, 222, 223, 224, 225, 776, 580, 73, 229, 10, - 11, 141, 142, 143, 213, 142, 782, 403, 32, 280, - 142, 126, 57, 128, 142, 642, 142, 696, 125, 694, - 715, 143, 144, 127, 233, 256, 142, 264, 137, 138, - 139, 268, 141, 142, 143, 264, 264, 144, 133, 268, - 268, 278, 700, 32, 125, 821, 142, 125, 124, 278, - 278, 127, 1036, 142, 1038, 515, 1040, 684, 125, 1043, - 1044, 1045, 73, 144, 87, 88, 144, 90, 91, 92, - 10, 11, 95, 118, 10, 11, 99, 144, 142, 310, - 91, 104, 105, 127, 107, 108, 109, 132, 111, 112, - 765, 6, 137, 8, 142, 326, 327, 142, 142, 143, - 371, 372, 781, 403, 142, 784, 785, 142, 403, 403, - 842, 135, 136, 137, 138, 139, 127, 141, 142, 143, - 124, 779, 126, 354, 128, 356, 357, 358, 359, 360, - 142, 125, 124, 73, 126, 6, 128, 73, 142, 370, - 10, 11, 373, 374, 127, 125, 125, 378, 419, 380, - 144, 91, 141, 142, 143, 91, 124, 388, 389, 775, - 142, 392, 10, 11, 144, 144, 403, 627, 73, 400, - 142, 400, 127, 125, 403, 403, 127, 125, 387, 50, - 85, 125, 125, 88, 124, 127, 91, 58, 124, 420, - 125, 422, 144, 464, 821, 874, 144, 68, 69, 70, - 144, 144, 107, 73, 1127, 142, 143, 409, 79, 144, - 481, 142, 125, 125, 85, 143, 86, 488, 241, 143, - 144, 91, 245, 142, 95, 73, 142, 125, 124, 125, - 101, 144, 144, 464, 465, 106, 142, 143, 79, 80, - 142, 143, 473, 91, 144, 116, 144, 118, 479, 146, - 866, 482, 1023, 869, 137, 486, 121, 122, 123, 490, - 491, 492, 493, 494, 495, 496, 537, 538, 125, 143, - 541, 842, 143, 142, 143, 144, 507, 21, 22, 143, - 10, 11, 12, 1015, 515, 127, 16, 124, 32, 126, - 127, 128, 521, 124, 126, 526, 142, 124, 2, 126, - 133, 128, 637, 142, 143, 144, 537, 538, 142, 144, - 541, 125, 32, 544, 144, 546, 547, 548, 549, 550, - 144, 144, 1075, 144, 581, 582, 557, 57, 585, 586, - 124, 144, 126, 134, 128, 566, 40, 41, 42, 43, - 44, 801, 144, 47, 134, 144, 577, 578, 702, 703, - 777, 588, 144, 144, 1033, 92, 93, 94, 134, 588, - 588, 91, 144, 144, 1117, 144, 134, 10, 11, 600, - 601, 580, 144, 604, 144, 144, 607, 142, 143, 144, - 137, 143, 145, 144, 615, 622, 73, 125, 118, 124, - 142, 135, 136, 137, 138, 139, 627, 141, 142, 143, - 125, 125, 132, 126, 635, 146, 125, 137, 639, 638, - 142, 642, 669, 56, 142, 135, 136, 137, 138, 139, - 657, 141, 142, 143, 127, 696, 142, 142, 657, 657, - 73, 144, 142, 1186, 142, 57, 137, 146, 124, 1118, - 1211, 1212, 1213, 127, 1015, 10, 150, 10, 91, 10, - 291, 292, 126, 684, 134, 125, 687, 126, 146, 137, - 137, 104, 145, 694, 126, 696, 126, 669, 817, 112, - 113, 702, 703, 116, 32, 126, 32, 145, 709, 126, - 137, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 144, 207, 142, 1121, 124, 211, 142, 146, - 781, 142, 142, 784, 785, 73, 143, 143, 124, 128, - 1136, 1137, 1138, 1202, 125, 125, 1297, 85, 125, 128, - 88, 142, 1303, 91, 765, 133, 144, 378, 133, 776, - 133, 133, 144, 10, 775, 125, 777, 776, 776, 107, - 781, 782, 1210, 784, 785, 792, 793, 794, 142, 263, - 142, 144, 143, 10, 11, 802, 10, 11, 12, 145, - 801, 842, 16, 144, 146, 4, 125, 1256, 142, 420, - 811, 137, 138, 139, 146, 141, 142, 143, 10, 1205, - 821, 126, 10, 1209, 10, 126, 125, 1024, 1214, 142, - 144, 142, 125, 874, 308, 144, 146, 864, 810, 56, - 812, 145, 145, 57, 637, 145, 144, 144, 322, 323, - 146, 644, 144, 825, 826, 827, 73, 829, 830, 831, - 832, 145, 144, 144, 144, 866, 144, 46, 869, 142, - 133, 482, 1258, 874, 91, 133, 90, 91, 133, 490, - 491, 492, 493, 494, 495, 142, 133, 104, 144, 68, - 125, 134, 134, 134, 144, 112, 113, 1283, 134, 116, - 144, 80, 142, 124, 118, 144, 380, 10, 11, 10, - 1296, 144, 144, 126, 126, 526, 126, 144, 132, 142, - 142, 100, 125, 137, 144, 144, 142, 142, 142, 10, - 126, 110, 134, 544, 145, 546, 547, 548, 549, 550, - 144, 134, 142, 134, 418, 1064, 1065, 1066, 1067, 1068, - 144, 1070, 134, 56, 144, 1079, 145, 431, 142, 142, - 701, 140, 142, 142, 143, 19, 20, 21, 22, 144, - 73, 144, 249, 536, 1015, 1117, 1018, 978, 32, 1075, - 1186, 268, 637, 1015, 638, 521, 811, 842, 91, 600, - 802, 978, 1033, -1, 468, -1, 607, 327, -1, -1, - 179, 104, -1, -1, -1, 479, -1, -1, -1, 112, - 113, -1, -1, 116, 1015, 220, 221, 222, 223, 224, - -1, -1, 1023, 1024, 635, -1, -1, -1, -1, 1036, - -1, 1038, 1033, 1040, -1, -1, 1043, 1044, 1045, -1, - 10, 11, 1069, -1, -1, -1, 1165, 1166, 1167, 1168, - 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, - 1179, 1180, 1181, 1182, 1183, -1, -1, -1, -1, -1, - -1, 250, -1, 252, 253, 254, 687, 1118, 1079, 133, - 134, 135, 136, 137, 138, 139, 56, 141, 142, 143, - -1, 270, 566, -1, -1, 274, -1, 1069, -1, -1, - -1, -1, 281, 73, 283, -1, 1225, -1, -1, -1, - -1, -1, 291, 292, -1, -1, -1, 1118, -1, -1, - 1121, 91, -1, -1, -1, -1, 1127, -1, -1, -1, - 11, -1, -1, -1, 104, 1136, 1137, 1138, -1, -1, - 614, 615, 112, 113, -1, -1, 620, -1, 327, 354, - -1, 356, 357, 358, 359, 360, 1275, 1184, 10, 11, - 12, 1202, -1, -1, 16, 370, -1, -1, 373, 374, - 51, -1, 53, 54, 55, -1, -1, -1, -1, 1151, - 1152, 1153, 1154, 1155, 1156, -1, -1, -1, -1, -1, - -1, 665, 666, 667, 668, -1, 670, -1, -1, 80, - 81, 1202, 381, -1, 1205, 57, -1, -1, 1209, -1, - 1211, 1212, 1213, 1214, -1, 1256, -1, 98, 99, -1, - 694, -1, -1, 1250, 1251, -1, 1253, 1254, -1, -1, - -1, -1, -1, 114, -1, 709, -1, -1, 119, 91, - 16, 17, 18, 19, 20, 21, 22, 426, -1, -1, - -1, -1, -1, -1, -1, 1256, 32, 1258, -1, -1, - 1287, 1288, 1289, 1290, -1, -1, 118, -1, 473, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 132, -1, 1283, -1, -1, 137, -1, -1, -1, -1, - 142, 765, -1, 767, -1, 1296, 1297, 1064, 1065, 1066, - 1067, 1068, 1303, 1070, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 15, 16, 17, 18, 19, 20, - 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 32, -1, 15, 16, 17, 18, 19, 20, 21, - 22, 520, -1, 522, -1, -1, -1, -1, -1, -1, - 32, -1, -1, -1, 130, 131, 132, 536, 832, 135, - 136, 137, 138, 139, -1, 141, 142, 143, -1, 843, - 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, - 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, - -1, 865, -1, -1, -1, -1, -1, -1, 1165, 1166, - 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, - 1177, 1178, 1179, 1180, 1181, 1182, 1183, -1, -1, 3, - 4, 5, 6, -1, 8, 9, 10, 11, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, - 141, 142, 143, 125, -1, 146, -1, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 1225, 141, - 142, 143, 144, 47, 48, -1, -1, 51, -1, 53, - 54, 55, 56, 57, -1, 59, 60, -1, -1, 63, - 64, -1, -1, 67, -1, -1, -1, -1, 72, 73, - 74, -1, -1, -1, -1, -1, 80, 81, -1, -1, - -1, -1, -1, 87, -1, 89, -1, 91, 1275, -1, - -1, -1, 96, -1, 98, 99, 100, -1, -1, 103, - 104, -1, 701, -1, 108, -1, -1, 111, 112, 113, - 114, -1, -1, 117, 1008, 119, 3, 4, 5, 6, - -1, 8, 9, 10, 11, -1, -1, 14, 132, -1, - -1, 135, 136, 137, -1, -1, 140, -1, 142, 143, - -1, -1, -1, 147, -1, -1, -1, -1, 15, 16, - 17, 18, 19, 20, 21, 22, -1, -1, -1, -1, - 47, 48, -1, -1, 51, 32, 53, 54, 55, 56, - 57, -1, 59, 60, -1, -1, 63, 64, -1, 778, - 67, -1, -1, -1, -1, 72, 73, 74, -1, -1, - -1, 1085, -1, 80, 81, -1, 795, -1, -1, 798, - 87, -1, 89, -1, 91, -1, -1, -1, 95, 96, - -1, 98, 99, 100, -1, -1, 103, 104, -1, -1, - -1, 108, -1, -1, 111, 112, 113, 114, -1, -1, - 117, -1, 119, 1127, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 132, -1, -1, 135, 136, - -1, -1, -1, 140, -1, 142, -1, -1, -1, -1, - 147, -1, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, -1, 141, 142, 143, -1, -1, 146, - -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 1185, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, -1, 1198, -1, -1, -1, -1, -1, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, -1, -1, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, -1, 67, -1, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - -1, -1, -1, 85, 86, 87, -1, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, -1, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, -1, - -1, -1, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, -1, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, -1, -1, - -1, -1, -1, -1, -1, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, -1, -1, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, -1, - 67, -1, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, -1, -1, -1, 85, 86, - 87, -1, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, -1, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, -1, -1, -1, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, -1, 146, - 147, 3, 4, 5, 6, -1, 8, 9, 10, 11, - -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 15, 16, 17, 18, 19, 20, 21, - 22, -1, -1, -1, -1, 47, 48, -1, -1, 51, - 32, 53, 54, 55, 56, 57, -1, 59, 60, -1, - -1, 63, 64, -1, -1, 67, -1, -1, -1, -1, - 72, 73, 74, -1, -1, -1, -1, -1, 80, 81, - -1, -1, -1, -1, -1, 87, -1, 89, -1, 91, - -1, -1, -1, 95, 96, -1, 98, 99, 100, -1, - -1, 103, 104, -1, -1, -1, 108, -1, -1, 111, - 112, 113, 114, -1, -1, 117, -1, 119, 3, 4, - 5, 6, -1, 8, 9, 10, 11, -1, -1, -1, - 132, -1, -1, 135, 136, -1, -1, -1, 140, -1, - 142, -1, -1, -1, -1, 147, -1, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, -1, 141, - 142, 143, 47, -1, 146, -1, 51, -1, 53, 54, - 55, -1, -1, -1, 59, -1, 61, 62, 63, 64, - 51, -1, 53, 54, 55, -1, -1, 72, 73, 74, - -1, -1, 63, -1, -1, 80, 81, -1, -1, -1, - -1, -1, 87, -1, 89, -1, 91, -1, -1, 80, - 81, 96, -1, 98, 99, 100, -1, -1, 103, -1, - -1, -1, -1, 108, 10, 11, 111, 98, 99, 114, - 3, 4, 5, 6, 119, 8, 9, 10, 11, 124, - -1, -1, -1, 114, -1, -1, -1, 132, 119, -1, - 135, 136, 137, -1, -1, 140, -1, 142, 143, -1, - -1, -1, 147, -1, -1, 51, -1, 53, 54, 55, - -1, 142, -1, -1, 47, -1, -1, 63, 51, -1, - 53, 54, 55, -1, -1, -1, 59, -1, 74, -1, - 63, 64, -1, -1, 80, 81, -1, -1, -1, 72, - 73, 74, -1, -1, -1, -1, -1, 80, 81, -1, - -1, -1, 98, 99, 87, -1, 89, -1, 91, -1, - -1, -1, -1, 96, -1, 98, 99, 100, 114, -1, - 103, 117, -1, 119, -1, 108, -1, -1, 111, -1, - -1, 114, 3, 4, 5, 6, 119, 8, 9, 10, - 11, -1, -1, 51, -1, 53, 54, 55, -1, 132, - -1, -1, 135, 136, 137, -1, -1, 140, -1, 142, - 143, 144, -1, -1, 147, -1, -1, -1, -1, -1, - -1, -1, 80, 81, -1, -1, 47, -1, -1, -1, - 51, -1, 53, 54, 55, -1, -1, -1, 59, -1, - 98, 99, 63, 64, -1, -1, 10, 11, -1, -1, - -1, 72, 73, 74, -1, -1, 114, -1, -1, 80, - 81, 119, -1, -1, -1, -1, 87, -1, 89, -1, - 91, -1, -1, -1, -1, 96, -1, 98, 99, 100, - -1, -1, 103, -1, 142, -1, -1, 108, -1, -1, - 111, -1, 56, 114, 3, 4, 5, 6, 119, 8, - 9, 10, 11, 124, -1, -1, -1, -1, -1, 73, - -1, 132, -1, -1, 135, 136, 137, -1, -1, 140, - -1, 142, 143, -1, -1, -1, 147, 91, 92, 93, - 94, -1, -1, -1, -1, -1, -1, -1, 47, -1, - 104, -1, 51, -1, 53, 54, 55, -1, 112, 113, - 59, -1, 116, -1, 63, 64, 51, -1, 53, 54, - 55, -1, -1, 72, 73, 74, -1, -1, -1, -1, - -1, 80, 81, -1, -1, -1, -1, -1, 87, -1, - 89, -1, 91, -1, -1, 80, 81, 96, -1, 98, - 99, 100, -1, -1, 103, -1, -1, -1, -1, 108, - -1, -1, 111, 98, 99, 114, 3, 4, 5, 6, - 119, 8, 9, 10, 11, -1, -1, -1, -1, 114, - -1, -1, -1, 132, 119, -1, 135, 136, 137, -1, - -1, 140, -1, 142, 143, 144, -1, -1, 147, -1, - -1, 51, -1, 53, 54, 55, -1, 142, -1, -1, + 1, 381, 439, 128, 129, 130, 131, 474, 133, 108, + 135, 136, 137, 527, 28, 119, 58, 489, 45, 721, + 599, 28, 147, 148, 119, 216, 144, 152, 153, 588, + 119, 543, 12, 57, 548, 551, 56, 414, 229, 230, + 396, 553, 28, 265, 127, 46, 119, 6, 589, 8, + 277, 14, 61, 62, 496, 126, 615, 0, 10, 11, + 287, 45, 144, 146, 580, 581, 144, 583, 584, 585, + 586, 612, 73, 144, 12, 144, 87, 88, 16, 90, + 91, 92, 549, 144, 95, 552, 106, 145, 146, 100, + 669, 127, 14, 127, 105, 106, 130, 108, 109, 110, + 73, 112, 113, 144, 127, 119, 804, 805, 806, 130, + 146, 32, 119, 654, 144, 64, 65, 66, 498, 57, + 144, 70, 135, 146, 145, 126, 144, 128, 129, 130, + 131, 135, 133, 119, 135, 136, 137, 73, 21, 22, + 652, 93, 144, 127, 127, 144, 147, 148, 132, 32, + 134, 152, 153, 126, 626, 696, 129, 12, 135, 139, + 73, 16, 146, 146, 127, 149, 150, 151, 548, 273, + 32, 145, 146, 277, 130, 397, 692, 129, 273, 401, + 145, 146, 120, 287, 273, 212, 413, 146, 277, 145, + 126, 233, 126, 129, 319, 6, 134, 8, 287, 32, + 273, 139, 57, 144, 277, 127, 144, 127, 145, 788, + 432, 727, 589, 126, 287, 216, 129, 144, 167, 168, + 169, 170, 143, 144, 145, 127, 146, 228, 229, 230, + 231, 232, 233, 144, 706, 591, 237, 32, 249, 144, + 145, 708, 253, 128, 146, 130, 555, 289, 557, 558, + 559, 560, 561, 794, 137, 138, 139, 140, 141, 273, + 143, 144, 145, 277, 265, 120, 273, 129, 135, 127, + 277, 127, 221, 287, 126, 712, 128, 654, 130, 134, + 287, 127, 144, 145, 139, 144, 492, 273, 146, 129, + 146, 277, 241, 834, 500, 501, 502, 503, 504, 505, + 146, 287, 127, 127, 526, 777, 139, 140, 141, 413, + 143, 144, 145, 228, 229, 230, 231, 232, 319, 696, + 129, 146, 146, 127, 413, 127, 793, 127, 127, 796, + 797, 537, 144, 127, 335, 336, 126, 127, 380, 381, + 413, 855, 146, 144, 146, 787, 146, 146, 143, 144, + 145, 1049, 146, 1051, 791, 1053, 73, 144, 1056, 1057, + 1058, 6, 363, 8, 365, 366, 367, 368, 369, 144, + 87, 144, 127, 90, 127, 127, 93, 144, 379, 10, + 11, 382, 383, 127, 127, 127, 387, 429, 389, 127, + 699, 146, 109, 146, 146, 144, 397, 398, 129, 413, + 401, 129, 146, 146, 146, 611, 413, 144, 146, 410, + 145, 146, 618, 10, 11, 12, 638, 144, 145, 16, + 887, 126, 144, 128, 410, 130, 126, 413, 128, 430, + 130, 432, 474, 144, 126, 419, 128, 879, 130, 1141, + 882, 647, 73, 74, 144, 144, 145, 396, 363, 491, + 365, 366, 367, 368, 369, 146, 498, 834, 148, 127, + 57, 139, 93, 94, 379, 96, 145, 382, 383, 145, + 101, 129, 103, 474, 475, 855, 126, 1036, 128, 129, + 130, 135, 483, 21, 22, 123, 124, 125, 489, 126, + 146, 492, 144, 144, 32, 496, 93, 146, 128, 500, + 501, 502, 503, 504, 505, 506, 548, 549, 127, 145, + 552, 144, 145, 146, 1028, 146, 517, 144, 145, 146, + 94, 95, 96, 120, 146, 526, 144, 145, 146, 146, + 146, 146, 136, 2, 146, 136, 537, 134, 146, 10, + 11, 12, 139, 146, 146, 16, 532, 548, 549, 136, + 649, 552, 146, 146, 555, 146, 557, 558, 559, 560, + 561, 136, 146, 146, 146, 592, 593, 568, 483, 596, + 597, 40, 41, 42, 43, 44, 577, 1089, 47, 1046, + 139, 146, 73, 147, 126, 599, 57, 588, 589, 714, + 715, 813, 599, 127, 127, 10, 11, 127, 789, 137, + 138, 139, 140, 141, 127, 143, 144, 145, 144, 128, + 611, 612, 127, 599, 615, 144, 148, 618, 144, 1131, + 129, 92, 93, 144, 144, 626, 633, 144, 146, 57, + 144, 139, 148, 10, 11, 12, 126, 638, 649, 16, + 129, 10, 591, 10, 10, 656, 647, 10, 1028, 120, + 651, 128, 136, 654, 681, 669, 128, 127, 73, 74, + 148, 139, 669, 134, 650, 1132, 708, 147, 139, 1228, + 1229, 1230, 139, 144, 128, 128, 128, 128, 93, 94, + 57, 96, 151, 669, 147, 146, 101, 144, 103, 139, + 126, 1203, 148, 1135, 126, 696, 144, 681, 699, 144, + 144, 127, 145, 145, 127, 706, 127, 708, 1150, 1151, + 1152, 127, 130, 714, 715, 130, 93, 130, 32, 134, + 721, 135, 191, 192, 193, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 211, 120, 213, 144, 135, 135, 217, 144, + 135, 793, 1219, 144, 796, 797, 146, 134, 10, 146, + 146, 32, 139, 145, 1323, 127, 147, 144, 146, 148, + 4, 1330, 127, 144, 788, 148, 777, 10, 128, 10, + 1222, 788, 10, 10, 1226, 128, 787, 127, 789, 1231, + 1227, 144, 793, 794, 32, 796, 797, 804, 805, 806, + 146, 127, 788, 272, 148, 144, 147, 814, 146, 1276, + 147, 146, 813, 855, 147, 146, 148, 147, 1078, 1079, + 1080, 1081, 1082, 824, 1084, 139, 140, 141, 146, 143, + 144, 145, 135, 834, 146, 146, 1278, 146, 144, 823, + 135, 825, 135, 144, 135, 887, 1037, 127, 317, 46, + 877, 136, 146, 136, 838, 839, 840, 136, 842, 843, + 844, 845, 331, 332, 1306, 146, 137, 138, 139, 140, + 141, 68, 143, 144, 145, 136, 146, 144, 879, 126, + 1322, 882, 146, 80, 146, 10, 887, 146, 128, 10, + 79, 80, 128, 128, 10, 146, 128, 146, 6, 137, + 138, 139, 140, 141, 101, 143, 144, 145, 147, 146, + 10, 11, 127, 10, 111, 144, 146, 136, 144, 144, + 389, 144, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, + 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, + 1200, 146, 50, 136, 141, 136, 143, 144, 146, 136, + 58, 16, 17, 18, 19, 20, 21, 22, 146, 428, + 68, 69, 70, 147, 32, 128, 10, 32, 1093, 10, + 11, 79, 441, 73, 74, 128, 144, 144, 144, 87, + 144, 146, 128, 128, 146, 1245, 1028, 146, 185, 97, + 991, 257, 713, 93, 94, 103, 96, 547, 1031, 1131, + 108, 101, 1089, 103, 1046, 73, 1203, 649, 277, 478, + 118, 650, 120, 1028, 824, 991, 855, 814, -1, 87, + 489, 532, 90, 336, -1, 93, -1, 1028, -1, 129, + -1, -1, 73, 74, -1, 1036, 1037, 145, 1298, -1, + -1, 109, 1049, -1, 1051, 1046, 1053, -1, -1, 1056, + 1057, 1058, 93, 94, -1, 96, 1083, -1, -1, -1, + 101, 258, 103, 260, 261, 262, 263, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, -1, 143, 144, + 145, -1, 279, -1, -1, 126, 283, -1, -1, -1, + 1132, -1, 1093, 290, -1, 292, -1, -1, -1, 1083, + -1, -1, -1, 300, 301, -1, -1, 830, 577, -1, + -1, 300, 301, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, + -1, 1132, -1, -1, 1135, -1, -1, -1, -1, 336, + 1141, 15, 16, 17, 18, 19, 20, 21, 22, 1150, + 1151, 1152, -1, -1, -1, -1, 625, 626, 32, -1, + -1, -1, 631, -1, -1, -1, 51, -1, 53, 54, + 55, -1, -1, -1, 1201, -1, -1, 1219, -1, -1, + -1, -1, -1, -1, 1168, 1169, 1170, 1171, 1172, 1173, + -1, -1, -1, 390, -1, 80, 81, -1, 387, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 677, 678, + 679, 680, -1, 682, -1, 100, 101, -1, 1219, -1, + -1, 1222, -1, -1, -1, 1226, -1, 1228, 1229, 1230, + 1231, 116, -1, -1, 1276, -1, 121, 706, -1, 436, + -1, 430, -1, 1270, 1271, -1, 1273, 1274, -1, -1, + -1, -1, 721, -1, 10, 11, -1, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, -1, 143, + 144, 145, -1, -1, 148, 1276, -1, 1278, -1, -1, + -1, -1, -1, -1, -1, -1, 1313, 1314, 1315, 1316, + -1, -1, 17, 18, 19, 20, 21, 22, -1, -1, + -1, -1, -1, 492, -1, 1306, -1, 32, 777, -1, + 779, 500, 501, 502, 503, 504, 505, 73, 74, -1, + -1, 1322, 1323, -1, -1, -1, -1, -1, -1, 1330, + 19, 20, 21, 22, 531, -1, 533, 93, 94, -1, + 96, -1, -1, 32, -1, 101, -1, 103, 537, -1, + 547, -1, -1, -1, -1, 1078, 1079, 1080, 1081, 1082, + -1, 1084, -1, -1, -1, -1, 555, -1, 557, 558, + 559, 560, 561, -1, -1, -1, 845, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 856, 857, 858, + 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, + 869, 870, 871, 872, 873, 874, 875, 876, -1, 878, + 135, 136, 137, 138, 139, 140, 141, -1, 143, 144, + 145, -1, 611, -1, -1, -1, -1, -1, -1, 618, + -1, -1, -1, -1, -1, 3, 4, 5, 6, -1, + 8, 9, 10, 11, -1, -1, 135, 136, 137, 138, + 139, 140, 141, -1, 143, 144, 145, -1, 647, 1182, + 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, + 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, -1, 47, + 48, -1, -1, 51, -1, 53, 54, 55, 56, 57, + -1, 59, 60, -1, -1, 63, 64, -1, -1, 67, + -1, -1, -1, -1, 72, 73, 74, -1, -1, -1, + 699, -1, 80, 81, -1, -1, 713, -1, -1, -1, + -1, 89, 1245, 91, -1, 93, -1, -1, -1, -1, + 98, -1, 100, 101, 102, -1, -1, 105, 106, -1, + -1, -1, 110, -1, -1, 113, 114, 115, 116, -1, + -1, 119, 1021, 121, -1, -1, 3, 4, 5, 6, + -1, 8, 9, 10, 11, -1, 134, -1, -1, 137, + 138, 139, -1, -1, 142, 1298, 144, 145, -1, -1, + -1, 149, -1, 16, 17, 18, 19, 20, 21, 22, + -1, -1, -1, 790, -1, -1, -1, -1, -1, 32, 47, -1, -1, -1, 51, -1, 53, 54, 55, -1, - -1, -1, 59, -1, -1, -1, 63, 64, -1, -1, - 80, 81, -1, -1, -1, 72, 73, 74, -1, -1, - -1, -1, -1, 80, 81, -1, -1, -1, 98, 99, - 87, -1, 89, -1, 91, -1, -1, -1, -1, 96, - -1, 98, 99, 100, 114, -1, 103, -1, -1, 119, - -1, 108, -1, -1, 111, -1, -1, 114, 3, 4, - 5, 6, 119, 8, 9, 10, 11, 124, -1, -1, - -1, -1, 142, -1, -1, 132, -1, -1, 135, 136, - 137, -1, -1, 140, -1, 142, 143, -1, -1, -1, - 147, -1, -1, 51, -1, 53, 54, 55, -1, -1, - -1, -1, 47, -1, -1, 63, 51, -1, 53, 54, - 55, -1, -1, -1, 59, -1, -1, -1, 63, 64, - -1, -1, 80, 81, -1, -1, -1, 72, 73, 74, - -1, -1, -1, -1, -1, 80, 81, -1, -1, -1, - 98, 99, 87, -1, 89, -1, 91, -1, -1, -1, - -1, 96, -1, 98, 99, 100, 114, -1, 103, -1, - -1, 119, -1, 108, -1, -1, 111, -1, -1, 114, - 3, 4, 5, 6, 119, 8, 9, 10, 11, -1, - -1, 51, -1, 53, 54, 55, -1, 132, -1, -1, - 135, 136, 137, -1, -1, 140, -1, 142, 143, 144, - -1, -1, 147, -1, -1, -1, -1, -1, -1, -1, - 80, 81, -1, -1, 47, -1, -1, -1, 51, -1, - 53, 54, 55, -1, -1, -1, 59, -1, 98, 99, - 63, 64, -1, -1, -1, -1, -1, -1, -1, 72, - 73, 74, -1, -1, 114, -1, -1, 80, 81, 119, - -1, -1, -1, -1, 87, -1, 89, -1, 91, -1, - -1, -1, -1, 96, -1, 98, 99, 100, -1, -1, - 103, -1, -1, -1, -1, 108, 10, 11, 111, 21, - 22, 114, 3, 4, 5, 6, 119, 8, 9, 10, - 32, -1, -1, -1, -1, -1, -1, -1, -1, 132, - -1, -1, 135, 136, 137, -1, -1, 140, -1, 142, - 143, -1, -1, -1, 147, -1, -1, 51, -1, 53, - 54, 55, 56, 57, -1, -1, 47, -1, -1, 63, - -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, - 74, -1, -1, 64, -1, -1, 80, 81, -1, -1, - -1, 72, 73, -1, -1, -1, -1, -1, -1, 0, - -1, -1, -1, -1, 98, 99, -1, -1, 89, -1, - 91, -1, -1, -1, -1, 96, -1, -1, 112, 100, - 114, -1, 103, 117, -1, 119, -1, 108, -1, -1, - -1, -1, -1, 135, 136, 137, 138, 139, -1, 141, - 142, 143, -1, -1, -1, -1, -1, -1, 49, 50, - -1, 132, -1, -1, 135, 136, 137, 58, -1, 140, - -1, 142, 143, -1, -1, 66, 147, 68, 69, 70, - 71, -1, -1, -1, 75, -1, -1, -1, 79, -1, - -1, 82, 83, 84, 85, 86, -1, -1, -1, -1, - -1, 92, 93, 94, 95, -1, -1, -1, -1, -1, - 101, 102, -1, -1, 105, 106, -1, -1, -1, 110, - -1, -1, -1, -1, 115, 116, -1, 118, 6, -1, - -1, -1, -1, 10, 11, 126, -1, 15, 16, 17, - 18, 19, 20, 21, 22, -1, -1, -1, -1, -1, - -1, -1, 143, -1, 32, -1, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, -1, -1, - -1, 48, -1, -1, 51, -1, 53, 54, 55, 56, - 57, -1, -1, 60, 62, -1, 63, -1, -1, -1, - 67, -1, -1, -1, -1, -1, -1, 74, -1, -1, - -1, -1, -1, 80, 81, -1, -1, -1, -1, 87, - -1, -1, -1, 90, -1, -1, -1, -1, -1, -1, - -1, 98, 99, -1, -1, -1, -1, 104, -1, 10, - 11, -1, -1, -1, -1, 112, 113, 114, -1, -1, - 117, -1, 119, -1, -1, -1, -1, 125, -1, -1, - 128, -1, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 140, 142, 143, -1, 48, -1, 147, + 807, -1, 59, 810, 61, 62, 63, 64, -1, -1, + -1, -1, -1, -1, -1, 72, 73, 74, -1, -1, + 1099, -1, -1, 80, 81, -1, -1, -1, -1, -1, + -1, -1, 89, -1, 91, -1, 93, -1, -1, -1, + -1, 98, -1, 100, 101, 102, -1, -1, 105, -1, + -1, -1, -1, 110, -1, -1, 113, -1, -1, 116, + -1, -1, 1141, -1, 121, -1, -1, -1, -1, 126, + -1, -1, -1, -1, -1, -1, -1, 134, -1, -1, + 137, 138, 139, -1, -1, 142, -1, 144, 145, 132, + 133, 134, 149, -1, 137, 138, 139, 140, 141, -1, + 143, 144, 145, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 1202, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, -1, 1215, -1, -1, -1, + -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, -1, + -1, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, -1, 67, -1, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, -1, -1, -1, -1, -1, 87, 88, 89, + -1, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, -1, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, -1, -1, -1, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + -1, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, -1, -1, -1, -1, -1, -1, -1, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, -1, -1, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, -1, 67, -1, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, -1, + -1, -1, -1, -1, 87, 88, 89, -1, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, -1, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + -1, -1, -1, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, -1, 148, 149, 3, 4, 5, + 6, -1, 8, 9, 10, 11, -1, -1, 14, -1, + -1, -1, -1, -1, 51, -1, 53, 54, 55, -1, + -1, -1, -1, -1, -1, -1, 63, -1, -1, 15, + 16, 17, 18, 19, 20, 21, 22, -1, -1, -1, + -1, 47, 48, 80, 81, 51, 32, 53, 54, 55, + 56, 57, -1, 59, 60, -1, -1, 63, 64, -1, + -1, 67, -1, 100, 101, -1, 72, 73, 74, -1, + -1, -1, -1, -1, 80, 81, -1, -1, -1, 116, + -1, -1, -1, 89, 121, 91, -1, 93, -1, -1, + -1, 97, 98, -1, 100, 101, 102, -1, -1, 105, + 106, -1, -1, -1, 110, -1, -1, 113, 114, 115, + 116, -1, -1, 119, -1, 121, 3, 4, 5, 6, + -1, 8, 9, 10, 11, -1, -1, 14, 134, -1, + -1, 137, 138, -1, -1, -1, 142, -1, 144, -1, + -1, -1, -1, 149, -1, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, -1, 143, 144, 145, + 47, 48, 148, -1, 51, -1, 53, 54, 55, 56, + 57, -1, 59, 60, -1, -1, 63, 64, -1, -1, + 67, -1, -1, -1, -1, 72, 73, 74, -1, -1, + -1, -1, -1, 80, 81, -1, -1, -1, -1, -1, + -1, -1, 89, -1, 91, -1, 93, -1, -1, -1, + 97, 98, -1, 100, 101, 102, -1, -1, 105, 106, + -1, -1, -1, 110, -1, -1, 113, 114, 115, 116, + -1, -1, 119, -1, 121, 3, 4, 5, 6, -1, + 8, 9, 10, 11, -1, 10, 11, 134, -1, -1, + 137, 138, -1, -1, -1, 142, -1, 144, -1, -1, + -1, -1, 149, 17, 18, 19, 20, 21, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 32, 47, + -1, -1, -1, 51, -1, 53, 54, 55, -1, -1, + -1, 59, -1, -1, -1, 63, 64, -1, -1, -1, + -1, -1, -1, -1, 72, 73, 74, -1, 73, 74, + -1, -1, 80, 81, -1, -1, -1, -1, -1, -1, + -1, 89, -1, 91, -1, 93, -1, -1, 93, 94, + 98, 96, 100, 101, 102, -1, 101, 105, 103, 10, + 11, -1, 110, -1, -1, 113, -1, -1, 116, 3, + 4, 5, 6, 121, 8, 9, 10, 11, -1, -1, + -1, 126, -1, -1, -1, -1, 134, -1, -1, 137, + 138, 139, -1, -1, 142, -1, 144, 145, 146, 133, + 134, 149, -1, 137, 138, 139, 140, 141, -1, 143, + 144, 145, -1, 47, -1, -1, -1, 51, -1, 53, + 54, 55, 73, 74, -1, 59, -1, -1, -1, 63, + 64, 51, -1, 53, 54, 55, -1, -1, 72, 73, + 74, -1, 93, 94, -1, 96, 80, 81, -1, -1, + 101, -1, 103, -1, -1, 89, -1, 91, -1, 93, + 80, 81, -1, -1, 98, -1, 100, 101, 102, -1, + -1, 105, -1, -1, -1, 126, 110, 10, 11, 113, + 100, 101, 116, 3, 4, 5, 6, 121, 8, 9, + 10, 11, 126, -1, -1, -1, 116, -1, -1, -1, + 134, 121, -1, 137, 138, 139, -1, -1, 142, -1, + 144, 145, -1, -1, -1, 149, -1, -1, 51, -1, + 53, 54, 55, -1, 144, -1, -1, 47, -1, -1, + 63, 51, -1, 53, 54, 55, -1, -1, -1, 59, + -1, 74, -1, 63, 64, -1, -1, 80, 81, -1, + -1, -1, 72, 73, 74, -1, -1, -1, -1, -1, + 80, 81, 51, -1, 53, 54, 55, 100, 101, 89, + -1, 91, -1, 93, 63, -1, -1, -1, 98, -1, + 100, 101, 102, 116, -1, 105, 119, -1, 121, -1, + 110, 80, 81, 113, -1, -1, 116, 3, 4, 5, + 6, 121, 8, 9, 10, 11, -1, -1, -1, -1, + -1, 100, 101, -1, 134, -1, -1, 137, 138, 139, + -1, -1, 142, -1, 144, 145, 146, 116, -1, 149, + -1, -1, 121, -1, -1, -1, -1, -1, -1, -1, + -1, 47, -1, -1, -1, 51, -1, 53, 54, 55, + -1, -1, -1, 59, -1, 144, -1, 63, 64, 51, + -1, 53, 54, 55, -1, -1, 72, 73, 74, -1, + -1, -1, -1, -1, 80, 81, 51, -1, 53, 54, + 55, -1, -1, 89, -1, 91, -1, 93, 80, 81, + -1, -1, 98, -1, 100, 101, 102, -1, -1, 105, + -1, 10, 11, -1, 110, 80, 81, 113, 100, 101, + 116, 3, 4, 5, 6, 121, 8, 9, 10, 11, + 126, -1, -1, -1, 116, 100, 101, -1, 134, 121, + -1, 137, 138, 139, -1, -1, 142, -1, 144, 145, + -1, 116, -1, 149, -1, -1, 121, -1, -1, -1, + -1, -1, 144, -1, -1, 47, -1, -1, -1, 51, + -1, 53, 54, 55, 73, 74, -1, 59, -1, 144, + -1, 63, 64, 51, -1, 53, 54, 55, -1, 88, + 72, 73, 74, -1, 93, 94, -1, 96, 80, 81, + -1, -1, 101, -1, 103, -1, -1, 89, -1, 91, + -1, 93, 80, 81, -1, -1, 98, -1, 100, 101, + 102, -1, -1, 105, -1, -1, -1, -1, 110, -1, + -1, 113, 100, 101, 116, 3, 4, 5, 6, 121, + 8, 9, 10, 11, -1, -1, -1, -1, 116, -1, + -1, -1, 134, 121, -1, 137, 138, 139, -1, -1, + 142, -1, 144, 145, 146, -1, -1, 149, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 47, + -1, -1, -1, 51, -1, 53, 54, 55, -1, -1, + -1, 59, -1, -1, -1, 63, 64, -1, -1, -1, + -1, -1, -1, -1, 72, 73, 74, -1, -1, -1, + -1, -1, 80, 81, -1, -1, -1, -1, -1, -1, + -1, 89, -1, 91, -1, 93, -1, -1, -1, -1, + 98, -1, 100, 101, 102, -1, -1, 105, -1, -1, + -1, -1, 110, -1, -1, 113, -1, -1, 116, 3, + 4, 5, 6, 121, 8, 9, 10, -1, -1, -1, + -1, -1, -1, 10, 11, -1, 134, -1, -1, 137, + 138, 139, -1, -1, 142, -1, 144, 145, -1, -1, + -1, 149, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, + -1, 48, -1, -1, 51, 59, 53, 54, 55, 56, + 64, -1, -1, 60, -1, -1, 63, -1, 72, 73, + 67, -1, -1, -1, -1, -1, -1, 74, 0, -1, + -1, -1, -1, 80, 81, -1, -1, 91, -1, 93, + -1, -1, -1, -1, 98, -1, -1, -1, 102, -1, + -1, 105, -1, 100, 101, -1, 110, -1, -1, 106, + -1, -1, -1, -1, -1, -1, -1, 114, 115, 116, + -1, -1, 119, -1, 121, -1, -1, 49, 50, -1, + 134, -1, -1, 137, 138, 139, 58, -1, 142, -1, + 144, 145, -1, -1, 66, 149, 68, 69, 70, 71, + -1, -1, -1, 75, -1, -1, -1, 79, -1, -1, + -1, 83, 84, 85, 86, 87, 88, 19, 20, 21, + 22, -1, 94, 95, 96, 97, -1, -1, -1, -1, + 32, 103, 104, -1, -1, 107, 108, -1, -1, -1, + 112, -1, -1, -1, -1, 117, 118, -1, 120, 6, + -1, -1, -1, -1, -1, -1, 128, -1, 15, 16, + 17, 18, 19, 20, 21, 22, -1, 10, 11, -1, + -1, -1, -1, 145, -1, 32, -1, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 15, + 16, 17, 18, 19, 20, 21, 22, -1, -1, -1, + -1, -1, -1, -1, -1, 62, 32, -1, -1, -1, + -1, -1, -1, 56, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 73, 74, 89, -1, -1, 137, 138, 139, 140, 141, + -1, 143, 144, 145, -1, -1, -1, -1, -1, -1, + 93, 94, -1, 96, -1, -1, -1, -1, 101, -1, + 103, -1, -1, 106, -1, -1, -1, -1, -1, -1, + 127, 114, 115, 130, -1, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, -1, 144, 145, 10, + 11, -1, 149, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, -1, 143, 144, 145, + 10, 11, 148, -1, -1, -1, -1, 48, -1, -1, 51, -1, 53, 54, 55, 56, 57, -1, -1, 60, -1, -1, 63, -1, -1, -1, 67, -1, -1, -1, - -1, -1, -1, 74, -1, -1, -1, -1, -1, 80, - 81, 10, 11, 19, 20, 21, 22, -1, -1, 90, - -1, -1, -1, -1, -1, -1, 32, 98, 99, -1, - -1, -1, -1, 104, -1, -1, -1, -1, -1, -1, - -1, 112, 113, 114, -1, -1, 117, -1, 119, 48, - -1, -1, 51, 124, 53, 54, 55, 56, 57, -1, - -1, 60, -1, -1, 63, -1, -1, -1, 67, 140, - -1, -1, -1, -1, -1, 74, -1, -1, -1, -1, - -1, 80, 81, -1, -1, -1, -1, -1, -1, -1, - -1, 90, -1, -1, -1, -1, -1, -1, -1, 98, - 99, -1, -1, -1, -1, 104, -1, -1, -1, -1, - -1, -1, -1, 112, 113, 114, -1, -1, 117, -1, - 119, 15, 16, 17, 18, 19, 20, 21, 22, 135, - 136, 137, 138, 139, -1, 141, 142, 143, 32, -1, - -1, 140, 15, 16, 17, 18, 19, 20, 21, 22, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, - 15, 16, 17, 18, 19, 20, 21, 22, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 32, 15, 16, - 17, 18, 19, 20, 21, 22, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 32, 15, 16, 17, 18, - 19, 20, 21, 22, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 32, 15, 16, 17, 18, 19, 20, - 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 32, -1, -1, -1, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, -1, 141, 142, 143, - 144, -1, -1, -1, -1, -1, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, -1, 141, 142, - 143, 144, -1, -1, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, -1, 141, 142, 143, 144, - -1, -1, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, -1, 141, 142, 143, 144, -1, -1, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, -1, 141, 142, 143, 144, 127, -1, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, -1, - 141, 142, 143, 15, 16, 17, 18, 19, 20, 21, - 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 32, -1, 15, 16, 17, 18, 19, 20, 21, 22, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, - 15, 16, 17, 18, 19, 20, 21, 22, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 32, 15, 16, - 17, 18, 19, 20, 21, 22, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 32, 15, 16, 17, 18, - 19, 20, 21, 22, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 32, 15, 16, 17, 18, 19, 20, - 21, 22, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 32, -1, -1, 126, -1, -1, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, -1, 141, - 142, 143, 125, -1, -1, -1, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, -1, 141, 142, - 143, -1, 127, -1, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, -1, 141, 142, 143, -1, - -1, -1, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, -1, 141, 142, 143, -1, -1, -1, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, -1, 141, 142, 143, -1, 127, -1, 129, 130, - 131, 132, -1, -1, 135, 136, 137, 138, 139, -1, - 141, 142, 143, 15, 16, 17, 18, 19, 20, 21, - 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 32, 16, 17, 18, 19, 20, 21, 22, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, - -1, -1, 17, 18, 19, 20, 21, 22, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 32, 17, 18, - 19, 20, 21, 22, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, - 18, 19, 20, 21, 22, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 32, -1, 17, 18, 19, 20, - 21, 22, -1, -1, -1, -1, -1, 129, 130, 131, - 132, 32, -1, 135, 136, 137, 138, 139, -1, 141, - 142, 143, -1, -1, -1, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, -1, 141, 142, 143, 11, - -1, -1, 14, -1, 16, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, -1, 141, 142, 143, -1, - -1, -1, 131, 132, 133, 134, 135, 136, 137, 138, - 139, -1, 141, 142, 143, -1, 48, -1, -1, 51, - -1, 53, 54, 55, 56, 57, -1, -1, 60, -1, - -1, 63, 130, 131, 132, 67, -1, 135, 136, 137, - 138, 139, 74, 141, 142, 143, -1, -1, 80, 81, - -1, 132, 133, 134, 135, 136, 137, 138, 139, -1, - 141, 142, 143, 95, -1, -1, 98, 99, -1, -1, - -1, -1, 104, 17, 18, 19, 20, 21, 22, -1, - 112, 113, 114, -1, -1, 117, -1, 119, 32, 17, - 18, 19, 20, 21, 22, -1, -1, -1, -1, -1, - 132, -1, -1, -1, 32, 137, 17, 18, 19, 20, - 21, 22, -1, -1, -1, 17, 18, 19, 20, 21, - 22, 32, -1, -1, -1, -1, -1, -1, -1, -1, - 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 133, - 134, 135, 136, 137, 138, 139, -1, 141, 142, 143, - -1, -1, -1, 131, 132, 10, 11, 135, 136, 137, - 138, 139, -1, 141, 142, 143, -1, -1, -1, -1, - -1, 132, -1, -1, 135, 136, 137, 138, 139, -1, - 141, 142, 143, 135, 136, 137, 138, 139, -1, 141, - 142, 143, -1, 48, -1, -1, 51, -1, 53, 54, - 55, 56, -1, -1, -1, 60, -1, -1, 63, -1, - -1, -1, 67, -1, -1, -1, -1, -1, -1, 74, - -1, -1, -1, -1, -1, 80, 81, -1, 11, -1, - -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 98, 99, -1, -1, -1, -1, 104, - -1, -1, -1, -1, -1, -1, -1, 112, 113, 114, - -1, -1, 117, -1, 119, 48, -1, -1, 51, -1, - 53, 54, 55, 56, 57, -1, -1, 60, -1, -1, - 63, -1, -1, -1, 67, -1, -1, -1, -1, -1, - -1, 74, -1, -1, -1, -1, -1, 80, 81, -1, - 11, -1, -1, 14, -1, -1, 50, -1, -1, -1, - -1, -1, 95, -1, 58, 98, 99, -1, -1, -1, - -1, 104, -1, -1, 68, 69, 70, -1, -1, 112, - 113, 114, -1, -1, 117, 79, 119, 48, -1, -1, - 51, 85, 53, 54, 55, 56, 57, -1, -1, 60, - -1, 95, 63, -1, -1, -1, 67, 101, -1, -1, - -1, 105, 106, 74, -1, -1, -1, 11, -1, 80, - 81, -1, 116, -1, 118, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 95, -1, -1, 98, 99, 11, - -1, -1, -1, 104, -1, -1, -1, -1, -1, 143, - -1, 112, 113, 114, 48, -1, 117, 51, 119, 53, + -1, -1, -1, 74, -1, -1, -1, -1, 48, 80, + 81, 51, -1, 53, 54, 55, 56, 57, -1, -1, + 60, 92, -1, 63, -1, -1, -1, 67, -1, 100, + 101, -1, -1, -1, 74, 106, -1, -1, -1, -1, + 80, 81, -1, 114, 115, 116, 10, 11, 119, -1, + 121, -1, 92, -1, -1, 126, -1, -1, -1, -1, + 100, 101, -1, -1, -1, -1, 106, -1, -1, -1, + -1, 142, -1, -1, 114, 115, 116, -1, -1, 119, + -1, 121, -1, -1, 48, -1, -1, 51, -1, 53, 54, 55, 56, 57, -1, -1, 60, -1, -1, 63, - -1, -1, -1, 67, -1, -1, 48, -1, -1, 51, - 74, 53, 54, 55, 56, 57, 80, 81, 60, -1, - -1, 63, -1, -1, -1, 67, -1, -1, -1, -1, - -1, 95, 74, -1, 98, 99, 11, -1, 80, 81, - 104, -1, -1, -1, -1, -1, -1, -1, 112, 113, - 114, -1, -1, 117, -1, 119, 98, 99, -1, -1, - -1, -1, 104, -1, -1, -1, -1, -1, -1, -1, - 112, 113, 114, 48, -1, 117, 51, 119, 53, 54, - 55, 56, 57, -1, -1, 60, -1, -1, 63, -1, - -1, 11, 67, -1, -1, -1, -1, -1, -1, 74, - -1, -1, -1, -1, -1, 80, 81, -1, -1, -1, - -1, -1, -1, 11, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 98, 99, -1, -1, -1, 48, 104, - -1, 51, -1, 53, 54, 55, 56, 112, 113, 114, - 60, -1, 117, 63, 119, -1, -1, 67, -1, -1, - 48, -1, -1, 51, 74, 53, 54, 55, 56, 57, - 80, 81, 60, -1, -1, 63, -1, -1, 11, 67, - -1, -1, -1, -1, -1, 95, 74, -1, 98, 99, - -1, -1, 80, 81, 104, -1, -1, -1, -1, -1, - 11, -1, 112, 113, 114, -1, -1, 117, -1, 119, - 98, 99, -1, -1, -1, 48, 104, -1, 51, -1, - 53, 54, 55, 56, 112, 113, 114, 60, -1, 117, - 63, 119, -1, -1, 67, -1, -1, 48, -1, -1, - 51, 74, 53, 54, 55, 56, -1, 80, 81, 60, - -1, -1, 63, -1, -1, -1, 67, -1, -1, -1, - -1, -1, -1, 74, -1, 98, 99, -1, -1, 80, - 81, 104, -1, -1, -1, -1, -1, -1, -1, 112, - 113, 114, -1, -1, 117, -1, 119, 98, 99, -1, - 49, 50, -1, 104, -1, -1, -1, -1, -1, 58, - -1, 112, 113, 114, -1, -1, 117, 66, 119, 68, - 69, 70, 71, -1, -1, -1, 75, -1, -1, -1, - 79, -1, -1, 82, 83, 84, 85, 86, -1, -1, - -1, -1, -1, 92, 93, 94, 95, -1, -1, -1, - -1, -1, 101, 102, 49, 50, 105, 106, -1, -1, - -1, 110, -1, 58, -1, -1, 115, 116, -1, 118, - -1, 66, -1, 68, 69, 70, 71, 126, -1, -1, - 75, -1, -1, -1, 79, -1, -1, 82, 83, 84, - 85, 86, -1, -1, 143, -1, 145, 92, 93, 94, - 95, -1, -1, -1, -1, -1, 101, 102, 49, 50, - 105, 106, -1, -1, -1, 110, -1, 58, -1, -1, - 115, 116, -1, 118, -1, 66, -1, 68, 69, 70, - 71, 126, -1, -1, 75, -1, -1, -1, 79, -1, - -1, 82, 83, 84, 85, 86, -1, -1, 143, -1, - 145, 92, 93, 94, 95, -1, -1, -1, -1, -1, - 101, 102, 49, 50, 105, 106, -1, -1, -1, 110, - -1, 58, -1, -1, 115, 116, -1, 118, -1, 66, - -1, 68, 69, 70, 71, 126, -1, -1, 75, -1, - -1, -1, 79, -1, -1, 82, 83, 84, 85, 86, - -1, -1, 143, -1, 145, 92, 93, 94, 95, -1, - -1, -1, -1, -1, 101, 102, 49, 50, 105, 106, - -1, -1, -1, 110, -1, 58, -1, -1, 115, 116, - -1, 118, -1, 66, -1, 68, 69, 70, 71, 126, - -1, -1, 75, -1, -1, -1, 79, -1, -1, 82, - 83, 84, 85, 86, -1, -1, 143, -1, 145, 92, - 93, 94, 95, -1, -1, -1, -1, -1, 101, 102, - 49, 50, 105, 106, -1, -1, -1, 110, -1, 58, - -1, -1, 115, 116, -1, 118, -1, 66, -1, 68, - 69, 70, 71, 126, -1, -1, 75, -1, -1, -1, - 79, -1, -1, 82, 83, 84, 85, 86, -1, -1, - 143, -1, 145, 92, 93, 94, 95, -1, -1, -1, - -1, -1, 101, 102, 49, 50, 105, 106, -1, -1, - -1, 110, -1, 58, -1, -1, 115, 116, -1, 118, - -1, 66, -1, 68, 69, 70, 71, 126, -1, -1, - 75, -1, -1, -1, 79, -1, -1, 82, 83, 84, - 85, 86, -1, -1, 143, -1, 145, 92, 93, 94, - 95, -1, -1, -1, -1, -1, 101, 102, 49, 50, - 105, 106, -1, -1, -1, 110, -1, 58, -1, -1, - 115, 116, -1, 118, -1, 66, -1, 68, 69, 70, - 71, 126, -1, -1, 75, -1, -1, -1, 79, -1, - -1, 82, 83, 84, 85, 86, -1, -1, 143, -1, - 145, 92, 93, 94, 95, -1, -1, -1, -1, -1, - 101, 102, 50, -1, 105, 106, -1, -1, -1, 110, - 58, -1, -1, -1, 115, 116, 50, 118, -1, -1, - 68, 69, 70, -1, 58, -1, -1, -1, -1, -1, - -1, 79, -1, -1, 68, 69, 70, 85, 86, -1, - -1, -1, 143, -1, -1, 79, 50, 95, -1, -1, - -1, 85, -1, 101, 58, -1, -1, -1, 106, -1, - -1, 95, -1, -1, 68, 69, 70, 101, 116, -1, - 118, -1, 106, -1, -1, 79, -1, -1, -1, -1, - -1, 85, 116, -1, 118, -1, -1, -1, -1, -1, - -1, 95, -1, -1, -1, 143, -1, 101, -1, 133, - -1, -1, 106, -1, -1, -1, -1, -1, -1, 143, - -1, -1, 116, -1, 118, -1, -1, -1, -1, -1, + -1, -1, 142, 67, -1, -1, -1, -1, -1, -1, + 74, -1, -1, -1, -1, -1, 80, 81, 15, 16, + 17, 18, 19, 20, 21, 22, -1, -1, 92, -1, + -1, -1, -1, -1, -1, 32, 100, 101, -1, -1, + -1, -1, 106, -1, -1, -1, -1, -1, -1, -1, + 114, 115, 116, -1, -1, 119, -1, 121, 15, 16, + 17, 18, 19, 20, 21, 22, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 32, -1, -1, 142, 15, + 16, 17, 18, 19, 20, 21, 22, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 32, 15, 16, 17, + 18, 19, 20, 21, 22, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 32, 15, 16, 17, 18, 19, + 20, 21, 22, -1, -1, -1, -1, -1, -1, -1, + 127, -1, 32, -1, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, -1, 143, 144, 145, 146, + 15, 16, 17, 18, 19, 20, 21, 22, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, + -1, -1, -1, -1, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, -1, 143, 144, 145, 146, + -1, -1, -1, -1, -1, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, -1, 143, 144, 145, + 146, -1, -1, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, -1, 143, 144, 145, 146, -1, + -1, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, -1, 143, 144, 145, 146, 15, 16, 17, + 18, 19, 20, 21, 22, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 32, -1, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, -1, 143, 144, + 145, 146, 15, 16, 17, 18, 19, 20, 21, 22, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, + -1, 15, 16, 17, 18, 19, 20, 21, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 32, 15, + 16, 17, 18, 19, 20, 21, 22, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 32, 15, 16, 17, + 18, 19, 20, 21, 22, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, + -1, 129, -1, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, -1, 143, 144, 145, -1, 15, + 16, 17, 18, 19, 20, 21, 22, -1, -1, -1, + -1, -1, -1, -1, -1, 128, 32, -1, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, -1, + 143, 144, 145, 127, -1, -1, -1, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, -1, 143, + 144, 145, -1, 129, -1, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, -1, 143, 144, 145, + -1, -1, -1, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, -1, 143, 144, 145, 15, 16, + 17, 18, 19, 20, 21, 22, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, -1, 143, 144, 145, + 15, 16, 17, 18, 19, 20, 21, 22, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 143 + -1, -1, 17, 18, 19, 20, 21, 22, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, + 17, 18, 19, 20, 21, 22, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, + -1, -1, 129, -1, 131, 132, 133, 134, -1, -1, + 137, 138, 139, 140, 141, -1, 143, 144, 145, -1, + -1, -1, -1, -1, 11, -1, -1, 14, -1, 16, + -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, + 21, 22, -1, -1, -1, -1, 131, 132, 133, 134, + -1, 32, 137, 138, 139, 140, 141, -1, 143, 144, + 145, 48, -1, -1, 51, -1, 53, 54, 55, 56, + 57, -1, -1, 60, -1, -1, 63, 132, 133, 134, + 67, -1, 137, 138, 139, 140, 141, 74, 143, 144, + 145, -1, -1, 80, 81, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, -1, 143, 144, 145, -1, + 97, -1, -1, 100, 101, 10, 11, -1, -1, 106, + 17, 18, 19, 20, 21, 22, -1, 114, 115, 116, + -1, -1, 119, -1, 121, 32, 17, 18, 19, 20, + 21, 22, -1, -1, -1, -1, -1, 134, -1, -1, + -1, 32, 139, 134, 135, 136, 137, 138, 139, 140, + 141, 56, 143, 144, 145, 17, 18, 19, 20, 21, + 22, -1, -1, -1, -1, -1, -1, -1, 73, 74, + 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 93, 94, + 95, 96, -1, -1, -1, -1, 101, -1, 103, -1, + -1, 106, -1, -1, -1, -1, -1, -1, -1, 114, + 115, -1, -1, 118, -1, -1, 10, 11, -1, -1, + -1, -1, -1, -1, -1, -1, 133, 134, 135, 136, + 137, 138, 139, 140, 141, -1, 143, 144, 145, -1, + -1, -1, -1, 134, -1, -1, 137, 138, 139, 140, + 141, -1, 143, 144, 145, -1, -1, 51, -1, 53, + 54, 55, 56, 57, -1, -1, -1, -1, -1, 63, + -1, -1, -1, -1, -1, 137, 138, 139, 140, 141, + 74, 143, 144, 145, -1, -1, 80, 81, -1, 11, + -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 100, 101, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 114, -1, 116, -1, -1, 119, 48, 121, -1, 51, + -1, 53, 54, 55, 56, 57, -1, -1, 60, -1, + -1, 63, -1, -1, -1, 67, -1, -1, -1, -1, + -1, -1, 74, -1, -1, -1, -1, -1, 80, 81, + -1, 11, -1, -1, 14, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 97, -1, -1, 100, 101, + -1, -1, -1, -1, 106, -1, -1, -1, -1, -1, + -1, -1, 114, 115, 116, -1, -1, 119, 48, 121, + -1, 51, -1, 53, 54, 55, 56, 57, -1, -1, + 60, -1, -1, 63, -1, -1, -1, 67, -1, -1, + -1, -1, -1, -1, 74, -1, -1, -1, -1, -1, + 80, 81, -1, 11, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 97, -1, -1, + 100, 101, -1, -1, -1, 11, 106, -1, -1, -1, + -1, -1, -1, -1, 114, 115, 116, -1, -1, 119, + 48, 121, -1, 51, -1, 53, 54, 55, 56, 57, + -1, -1, 60, -1, -1, 63, -1, -1, -1, 67, + -1, -1, 48, -1, -1, 51, 74, 53, 54, 55, + 56, 57, 80, 81, 60, -1, -1, 63, -1, -1, + -1, 67, -1, -1, -1, -1, -1, -1, 74, 97, + -1, -1, 100, 101, 80, 81, -1, 11, 106, -1, + -1, -1, -1, -1, -1, -1, 114, 115, 116, -1, + -1, 119, -1, 121, 100, 101, -1, -1, -1, -1, + 106, -1, -1, -1, -1, -1, -1, -1, 114, 115, + 116, -1, -1, 119, 48, 121, -1, 51, -1, 53, + 54, 55, 56, 57, -1, -1, 60, -1, -1, 63, + -1, -1, -1, 67, 11, -1, -1, -1, -1, -1, + 74, -1, -1, -1, -1, -1, 80, 81, -1, -1, + -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 100, 101, -1, -1, + -1, 48, 106, -1, 51, -1, 53, 54, 55, 56, + 114, 115, 116, 60, -1, 119, 63, 121, -1, -1, + 67, -1, -1, 48, -1, -1, 51, 74, 53, 54, + 55, 56, 57, 80, 81, 60, -1, -1, 63, -1, + -1, -1, 67, 11, -1, -1, -1, -1, -1, 74, + 97, -1, -1, 100, 101, 80, 81, -1, -1, 106, + -1, -1, -1, -1, -1, 11, -1, 114, 115, 116, + -1, -1, 119, -1, 121, 100, 101, -1, -1, -1, + 48, 106, -1, 51, -1, 53, 54, 55, 56, 114, + 115, 116, 60, -1, 119, 63, 121, -1, -1, 67, + -1, -1, 48, 10, 11, 51, 74, 53, 54, 55, + 56, -1, 80, 81, 60, -1, -1, 63, -1, 10, + 11, 67, -1, -1, -1, -1, -1, -1, 74, -1, + -1, -1, 100, 101, 80, 81, -1, -1, 106, -1, + -1, -1, -1, -1, -1, -1, 114, 115, 116, 56, + -1, 119, -1, 121, 100, 101, -1, -1, 10, 11, + 106, -1, -1, -1, -1, 56, 73, 74, 114, 115, + 116, -1, -1, 119, -1, 121, -1, -1, -1, -1, + -1, -1, 73, 74, -1, -1, 93, 94, -1, 96, + -1, -1, -1, -1, 101, -1, 103, -1, -1, 106, + -1, -1, 93, 94, 56, 96, -1, 114, 115, -1, + 101, 118, 103, -1, -1, 106, -1, -1, -1, -1, + -1, 73, 74, 114, 115, -1, -1, 118, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 49, 50, + -1, 93, 94, -1, 96, -1, -1, 58, -1, 101, + -1, 103, -1, -1, 106, 66, -1, 68, 69, 70, + 71, -1, 114, 115, 75, -1, 118, -1, 79, -1, + -1, -1, 83, 84, 85, 86, 87, 88, -1, -1, + -1, -1, -1, 94, 95, 96, 97, -1, -1, -1, + -1, -1, 103, 104, 49, 50, 107, 108, -1, -1, + -1, 112, -1, 58, -1, -1, 117, 118, -1, 120, + -1, 66, -1, 68, 69, 70, 71, 128, -1, -1, + 75, -1, -1, -1, 79, -1, -1, -1, 83, 84, + 85, 86, 87, 88, 145, -1, 147, -1, -1, 94, + 95, 96, 97, -1, -1, -1, -1, -1, 103, 104, + 49, 50, 107, 108, -1, -1, -1, 112, -1, 58, + -1, -1, 117, 118, -1, 120, -1, 66, -1, 68, + 69, 70, 71, 128, -1, -1, 75, -1, -1, -1, + 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, + 145, -1, 147, -1, -1, 94, 95, 96, 97, -1, + -1, -1, -1, -1, 103, 104, 49, 50, 107, 108, + -1, -1, -1, 112, -1, 58, -1, -1, 117, 118, + -1, 120, -1, 66, -1, 68, 69, 70, 71, 128, + -1, -1, 75, -1, -1, -1, 79, -1, -1, -1, + 83, 84, 85, 86, 87, 88, 145, -1, 147, -1, + -1, 94, 95, 96, 97, -1, -1, -1, -1, -1, + 103, 104, 49, 50, 107, 108, -1, -1, -1, 112, + -1, 58, -1, -1, 117, 118, -1, 120, -1, 66, + -1, 68, 69, 70, 71, 128, -1, -1, 75, -1, + -1, -1, 79, -1, -1, -1, 83, 84, 85, 86, + 87, 88, 145, -1, 147, -1, -1, 94, 95, 96, + 97, -1, -1, -1, -1, -1, 103, 104, 49, 50, + 107, 108, -1, -1, -1, 112, -1, 58, -1, -1, + 117, 118, -1, 120, -1, 66, -1, 68, 69, 70, + 71, 128, -1, -1, 75, -1, -1, -1, 79, -1, + -1, -1, 83, 84, 85, 86, 87, 88, 145, -1, + 147, -1, -1, 94, 95, 96, 97, -1, -1, -1, + -1, -1, 103, 104, 49, 50, 107, 108, -1, -1, + -1, 112, -1, 58, -1, -1, 117, 118, -1, 120, + -1, 66, -1, 68, 69, 70, 71, 128, -1, -1, + 75, -1, -1, -1, 79, -1, -1, -1, 83, 84, + 85, 86, 87, 88, 145, -1, 147, -1, -1, 94, + 95, 96, 97, -1, -1, -1, -1, -1, 103, 104, + 49, 50, 107, 108, -1, -1, -1, 112, -1, 58, + -1, -1, 117, 118, -1, 120, -1, 66, -1, 68, + 69, 70, 71, 128, -1, -1, 75, -1, -1, -1, + 79, -1, -1, 50, 83, 84, 85, 86, 87, 88, + 145, 58, 147, -1, -1, 94, 95, 96, 97, -1, + -1, 68, 69, 70, 103, 104, -1, -1, 107, 108, + -1, -1, 79, 112, -1, -1, -1, -1, 117, 118, + 87, 120, -1, -1, -1, -1, -1, -1, -1, 50, + 97, -1, -1, -1, -1, -1, 103, 58, -1, -1, + -1, 108, -1, -1, -1, -1, 145, 68, 69, 70, + 117, 118, -1, 120, -1, 50, -1, -1, 79, -1, + -1, -1, -1, 58, -1, -1, 87, -1, 135, -1, + -1, -1, -1, 68, 69, 70, 97, -1, 145, -1, + -1, -1, 103, -1, 79, -1, 107, 108, -1, -1, + -1, -1, 87, 88, -1, -1, 117, 118, 50, 120, + -1, -1, 97, -1, -1, -1, 58, -1, 103, -1, + -1, -1, -1, 108, -1, -1, 68, 69, 70, -1, + -1, -1, -1, 118, 145, 120, -1, 79, -1, -1, + -1, -1, -1, -1, -1, 87, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 97, -1, -1, -1, -1, + 145, 103, -1, -1, -1, -1, 108, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 118, -1, 120, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 145 }; -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ static const yytype_uint16 yystos[] = { - 0, 121, 122, 123, 149, 150, 256, 3, 4, 5, + 0, 123, 124, 125, 151, 152, 258, 3, 4, 5, 6, 8, 9, 10, 11, 47, 51, 53, 54, 55, - 59, 63, 64, 72, 73, 74, 80, 81, 87, 89, - 91, 96, 98, 99, 100, 103, 108, 111, 114, 119, - 132, 135, 136, 137, 140, 142, 143, 147, 246, 247, - 255, 11, 48, 51, 53, 54, 55, 56, 57, 60, - 63, 67, 74, 80, 81, 98, 99, 104, 112, 113, - 114, 117, 119, 210, 214, 215, 217, 223, 224, 228, - 229, 234, 235, 236, 237, 0, 49, 50, 58, 66, - 68, 69, 70, 71, 75, 79, 82, 83, 84, 85, - 86, 92, 93, 94, 95, 101, 102, 105, 106, 110, - 115, 116, 118, 126, 143, 153, 155, 156, 158, 161, - 162, 184, 230, 233, 256, 142, 142, 142, 142, 142, - 142, 133, 142, 133, 142, 142, 142, 11, 48, 60, - 112, 212, 228, 229, 234, 133, 142, 142, 142, 133, - 142, 142, 142, 246, 246, 246, 246, 246, 11, 51, - 53, 54, 55, 63, 74, 80, 81, 98, 99, 114, - 119, 214, 244, 246, 10, 11, 73, 91, 128, 132, - 250, 251, 253, 256, 246, 15, 16, 17, 18, 19, - 20, 21, 22, 32, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 141, 142, 143, 6, 8, - 210, 142, 63, 81, 235, 235, 235, 253, 235, 12, - 16, 57, 118, 132, 137, 142, 208, 209, 256, 124, - 10, 11, 91, 127, 254, 10, 11, 91, 124, 253, - 254, 79, 158, 158, 158, 6, 158, 158, 127, 157, - 86, 158, 142, 142, 142, 158, 124, 253, 127, 127, - 127, 158, 158, 142, 158, 161, 185, 158, 158, 167, - 86, 253, 158, 158, 143, 10, 11, 48, 57, 60, - 90, 112, 124, 140, 172, 175, 211, 213, 215, 217, - 223, 228, 229, 234, 243, 244, 256, 214, 243, 243, - 243, 243, 214, 243, 214, 243, 243, 243, 142, 253, - 142, 253, 253, 214, 243, 243, 214, 214, 214, 246, - 243, 243, 144, 125, 144, 253, 146, 125, 246, 246, - 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 246, 246, 246, 246, 246, 246, 246, 144, - 244, 246, 209, 246, 137, 12, 16, 57, 118, 132, - 137, 208, 256, 208, 209, 208, 209, 208, 208, 14, - 16, 57, 95, 132, 137, 194, 195, 204, 210, 256, - 143, 226, 227, 256, 11, 225, 235, 127, 216, 218, - 158, 155, 124, 253, 253, 253, 253, 150, 124, 246, - 133, 10, 11, 57, 175, 211, 213, 253, 126, 128, - 159, 160, 253, 142, 142, 10, 11, 213, 142, 57, - 210, 253, 154, 253, 124, 126, 127, 128, 200, 124, - 126, 128, 201, 126, 163, 253, 254, 253, 144, 144, - 144, 144, 144, 144, 134, 144, 134, 144, 144, 144, - 246, 243, 134, 144, 144, 144, 134, 144, 144, 144, - 144, 246, 246, 57, 142, 181, 256, 250, 127, 144, - 146, 144, 208, 137, 208, 208, 208, 208, 208, 143, - 208, 95, 210, 204, 208, 208, 144, 14, 125, 12, - 16, 57, 118, 132, 137, 142, 207, 254, 256, 242, - 246, 256, 253, 145, 225, 150, 73, 219, 256, 150, - 124, 125, 125, 125, 145, 231, 125, 144, 10, 11, - 56, 57, 112, 186, 187, 188, 189, 234, 256, 142, - 213, 201, 168, 126, 214, 146, 125, 142, 173, 12, - 137, 174, 164, 246, 210, 12, 16, 57, 118, 132, - 137, 206, 254, 256, 150, 142, 238, 239, 151, 152, - 253, 61, 62, 238, 61, 62, 124, 246, 12, 16, - 57, 90, 118, 132, 137, 142, 165, 190, 192, 254, - 127, 142, 142, 144, 144, 142, 142, 194, 32, 73, - 85, 88, 91, 107, 193, 256, 246, 208, 242, 144, - 210, 207, 144, 144, 181, 14, 204, 137, 207, 207, - 207, 207, 207, 207, 128, 143, 199, 256, 146, 125, - 128, 145, 127, 220, 221, 256, 145, 232, 10, 10, - 10, 150, 255, 126, 253, 189, 253, 134, 125, 207, - 169, 170, 192, 126, 146, 159, 3, 4, 5, 9, - 10, 14, 47, 59, 64, 72, 73, 87, 89, 91, - 96, 100, 103, 108, 111, 132, 135, 136, 140, 142, - 147, 196, 197, 204, 205, 248, 249, 255, 256, 194, - 137, 190, 194, 166, 192, 144, 206, 137, 206, 206, - 206, 206, 206, 142, 143, 145, 176, 145, 240, 256, - 124, 125, 124, 142, 126, 126, 145, 126, 126, 124, - 202, 203, 246, 256, 126, 137, 190, 190, 6, 15, - 16, 17, 18, 19, 20, 21, 22, 32, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 62, 87, 125, 128, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 142, 143, 147, 182, 190, - 190, 190, 190, 127, 142, 143, 193, 128, 199, 201, - 225, 244, 244, 244, 244, 144, 57, 212, 142, 124, - 146, 142, 207, 199, 142, 142, 193, 207, 144, 246, - 242, 246, 92, 93, 94, 112, 116, 222, 229, 252, - 253, 124, 125, 150, 125, 144, 125, 125, 145, 144, - 128, 207, 128, 161, 183, 184, 188, 128, 198, 256, - 171, 192, 199, 201, 158, 142, 133, 133, 212, 133, - 142, 133, 142, 246, 246, 246, 246, 214, 244, 246, - 144, 14, 125, 15, 16, 17, 18, 19, 20, 21, - 22, 32, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 141, 142, 143, 144, 190, 144, 144, - 199, 201, 142, 206, 179, 242, 194, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 32, 33, + 59, 63, 64, 72, 73, 74, 80, 81, 89, 91, + 93, 98, 100, 101, 102, 105, 110, 113, 116, 121, + 134, 137, 138, 139, 142, 144, 145, 149, 248, 249, + 257, 11, 48, 51, 53, 54, 55, 56, 57, 60, + 63, 67, 74, 80, 81, 100, 101, 106, 114, 115, + 116, 119, 121, 212, 216, 217, 219, 225, 226, 230, + 231, 236, 237, 238, 239, 0, 49, 50, 58, 66, + 68, 69, 70, 71, 75, 79, 83, 84, 85, 86, + 87, 88, 94, 95, 96, 97, 103, 104, 107, 108, + 112, 117, 118, 120, 128, 145, 155, 157, 158, 160, + 163, 164, 186, 232, 235, 258, 144, 144, 144, 144, + 144, 144, 135, 144, 135, 144, 144, 144, 11, 48, + 60, 114, 214, 230, 231, 236, 135, 144, 144, 144, + 135, 144, 144, 144, 248, 248, 248, 248, 248, 11, + 51, 53, 54, 55, 63, 74, 80, 81, 100, 101, + 116, 121, 216, 246, 248, 10, 11, 73, 74, 93, + 94, 96, 101, 103, 130, 134, 252, 253, 255, 258, + 248, 15, 16, 17, 18, 19, 20, 21, 22, 32, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 143, 144, 145, 6, 8, 212, 144, 56, 106, + 63, 81, 237, 237, 237, 255, 237, 12, 16, 57, + 120, 134, 139, 144, 210, 211, 258, 126, 10, 11, + 93, 129, 256, 10, 11, 93, 126, 255, 256, 79, + 160, 160, 160, 6, 160, 160, 129, 159, 88, 160, + 144, 144, 144, 144, 160, 126, 255, 129, 129, 129, + 160, 160, 144, 160, 163, 187, 160, 160, 169, 88, + 255, 160, 160, 145, 10, 11, 48, 57, 60, 92, + 114, 126, 142, 174, 177, 213, 215, 217, 219, 225, + 230, 231, 236, 245, 246, 258, 216, 245, 245, 245, + 245, 216, 245, 216, 245, 245, 245, 144, 255, 144, + 255, 255, 216, 245, 245, 216, 216, 216, 248, 245, + 245, 146, 127, 146, 255, 148, 127, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 146, 246, + 248, 211, 248, 139, 12, 16, 57, 120, 134, 139, + 210, 258, 210, 211, 210, 211, 210, 210, 14, 16, + 57, 97, 134, 139, 196, 197, 206, 212, 258, 145, + 228, 229, 258, 11, 227, 237, 129, 218, 220, 160, + 157, 126, 255, 255, 255, 255, 255, 152, 126, 248, + 135, 10, 11, 57, 177, 213, 215, 255, 128, 130, + 161, 162, 255, 144, 144, 10, 11, 215, 144, 57, + 212, 255, 156, 255, 126, 128, 129, 130, 202, 126, + 128, 130, 203, 128, 165, 255, 256, 255, 146, 146, + 146, 146, 146, 146, 136, 146, 136, 146, 146, 146, + 248, 245, 136, 146, 146, 146, 136, 146, 146, 146, + 146, 248, 248, 57, 144, 183, 258, 252, 129, 146, + 148, 146, 210, 139, 210, 210, 210, 210, 210, 145, + 210, 97, 212, 206, 210, 210, 146, 14, 127, 12, + 16, 57, 120, 134, 139, 144, 209, 256, 258, 244, + 248, 258, 255, 147, 227, 152, 73, 221, 258, 152, + 126, 127, 127, 127, 127, 147, 233, 127, 146, 10, + 11, 56, 57, 114, 188, 189, 190, 191, 236, 258, + 144, 215, 203, 170, 128, 216, 148, 127, 144, 175, + 12, 139, 176, 166, 248, 212, 12, 16, 57, 120, + 134, 139, 208, 256, 258, 152, 144, 240, 241, 153, + 154, 255, 61, 62, 240, 61, 62, 126, 248, 12, + 16, 57, 92, 120, 134, 139, 144, 167, 192, 194, + 256, 129, 144, 144, 146, 146, 144, 144, 196, 32, + 73, 87, 90, 93, 109, 195, 258, 248, 210, 244, + 146, 212, 209, 146, 146, 183, 14, 206, 139, 209, + 209, 209, 209, 209, 209, 130, 145, 201, 258, 148, + 127, 130, 147, 129, 222, 223, 258, 147, 234, 10, + 10, 10, 10, 152, 257, 128, 255, 191, 255, 136, + 127, 209, 171, 172, 194, 128, 148, 161, 3, 4, + 5, 9, 10, 14, 47, 59, 64, 72, 73, 89, + 91, 93, 98, 102, 105, 110, 113, 134, 137, 138, + 142, 144, 149, 198, 199, 206, 207, 250, 251, 257, + 258, 196, 139, 192, 196, 168, 194, 146, 208, 139, + 208, 208, 208, 208, 208, 144, 145, 147, 178, 147, + 242, 258, 126, 127, 126, 144, 128, 128, 147, 128, + 128, 126, 204, 205, 248, 258, 128, 139, 192, 192, + 6, 15, 16, 17, 18, 19, 20, 21, 22, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 67, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 85, 86, 87, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 146, - 147, 241, 238, 152, 243, 243, 202, 145, 125, 190, - 10, 144, 146, 144, 4, 191, 242, 246, 125, 144, - 144, 144, 144, 181, 212, 209, 144, 253, 238, 194, - 199, 194, 194, 142, 146, 125, 116, 252, 116, 252, - 116, 252, 253, 92, 93, 94, 253, 150, 222, 145, - 10, 126, 10, 10, 126, 214, 198, 214, 47, 59, - 64, 96, 100, 103, 132, 135, 136, 137, 140, 142, - 147, 245, 247, 199, 201, 125, 214, 214, 214, 142, - 214, 214, 214, 214, 246, 144, 144, 14, 205, 246, - 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 144, 244, 246, 181, 144, 142, 181, 125, 180, 194, - 146, 144, 240, 145, 145, 144, 145, 124, 246, 196, - 146, 165, 193, 209, 144, 145, 144, 144, 144, 194, - 252, 252, 252, 252, 252, 252, 145, 144, 125, 144, - 144, 142, 133, 133, 133, 142, 133, 245, 245, 245, - 245, 245, 214, 244, 245, 15, 16, 17, 18, 19, - 20, 21, 22, 32, 129, 130, 131, 132, 135, 136, - 137, 138, 139, 141, 142, 143, 125, 170, 144, 134, - 134, 243, 134, 144, 134, 144, 144, 246, 127, 144, - 146, 142, 177, 166, 194, 144, 181, 145, 202, 144, - 124, 181, 181, 181, 144, 126, 10, 126, 126, 214, - 214, 214, 214, 214, 214, 144, 144, 245, 245, 245, - 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, - 245, 245, 245, 245, 245, 245, 144, 244, 246, 171, - 142, 142, 144, 142, 142, 246, 178, 194, 144, 181, - 145, 181, 238, 193, 193, 193, 181, 125, 144, 134, - 134, 134, 144, 134, 245, 127, 144, 146, 244, 244, - 244, 244, 194, 144, 181, 145, 10, 142, 142, 142, - 142, 245, 144, 144, 144, 144, 144, 181, 144, 244, - 244, 244, 244, 181, 193, 126, 144, 144, 144, 144, - 193 + 44, 45, 62, 89, 127, 130, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 144, 145, 149, + 184, 192, 192, 192, 192, 129, 144, 145, 195, 130, + 201, 203, 227, 246, 246, 246, 246, 146, 57, 214, + 144, 126, 148, 144, 209, 201, 144, 144, 195, 209, + 146, 248, 244, 248, 94, 95, 96, 114, 118, 224, + 231, 254, 255, 126, 127, 152, 127, 146, 127, 127, + 127, 147, 146, 130, 209, 130, 163, 185, 186, 190, + 130, 200, 258, 173, 194, 201, 203, 160, 144, 135, + 135, 214, 135, 144, 135, 144, 248, 248, 248, 248, + 216, 246, 248, 146, 14, 127, 15, 16, 17, 18, + 19, 20, 21, 22, 32, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 143, 144, 145, 146, + 192, 146, 146, 201, 203, 144, 208, 181, 244, 196, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 67, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 87, 88, 89, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 148, 149, 243, 240, 154, 245, 245, 204, + 147, 127, 192, 10, 146, 148, 146, 4, 193, 244, + 248, 127, 146, 146, 146, 146, 183, 214, 211, 146, + 255, 240, 196, 201, 196, 196, 144, 148, 127, 118, + 254, 118, 254, 118, 254, 255, 94, 95, 96, 255, + 152, 224, 147, 10, 128, 10, 10, 10, 128, 216, + 200, 216, 47, 59, 64, 98, 102, 105, 134, 137, + 138, 139, 142, 144, 149, 247, 249, 201, 203, 127, + 216, 216, 216, 144, 216, 216, 216, 216, 248, 146, + 146, 14, 207, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 146, 246, 248, 183, 146, 144, + 183, 127, 182, 196, 148, 146, 242, 147, 147, 146, + 147, 126, 248, 198, 148, 167, 195, 211, 146, 147, + 146, 146, 146, 196, 254, 254, 254, 254, 254, 254, + 147, 127, 146, 127, 146, 146, 127, 146, 144, 135, + 135, 135, 144, 135, 247, 247, 247, 247, 247, 216, + 246, 247, 15, 16, 17, 18, 19, 20, 21, 22, + 32, 131, 132, 133, 134, 137, 138, 139, 140, 141, + 143, 144, 145, 127, 172, 146, 136, 136, 245, 136, + 146, 136, 146, 146, 248, 129, 146, 148, 144, 179, + 168, 196, 146, 183, 147, 204, 146, 126, 183, 183, + 183, 146, 10, 128, 10, 128, 128, 10, 128, 216, + 216, 216, 216, 216, 216, 146, 146, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 146, 246, 248, 173, + 144, 144, 146, 144, 144, 248, 180, 196, 146, 183, + 147, 183, 240, 195, 195, 195, 183, 146, 127, 127, + 146, 146, 136, 136, 136, 146, 136, 247, 129, 146, + 148, 246, 246, 246, 246, 196, 146, 183, 147, 128, + 10, 10, 128, 144, 144, 144, 144, 247, 146, 146, + 146, 146, 146, 183, 146, 146, 246, 246, 246, 246, + 183, 195, 128, 128, 146, 146, 146, 146, 195 }; -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint16 yyr1[] = +{ + 0, 150, 151, 151, 151, 152, 152, 152, 153, 153, + 154, 154, 156, 155, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 159, 158, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 161, 161, 162, 162, 163, 163, + 163, 163, 163, 165, 164, 166, 164, 167, 167, 168, + 168, 170, 169, 171, 169, 169, 172, 172, 173, 173, + 175, 174, 176, 174, 178, 177, 179, 177, 180, 177, + 181, 177, 182, 177, 177, 183, 183, 183, 183, 183, + 183, 183, 183, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 185, 185, 187, 186, 186, 188, 188, 189, + 189, 190, 190, 190, 190, 190, 190, 191, 191, 191, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 193, 192, 194, 194, 195, 195, 195, 196, 196, + 196, 196, 196, 197, 197, 198, 198, 198, 198, 198, + 199, 199, 200, 200, 201, 201, 202, 202, 202, 202, + 202, 203, 203, 203, 203, 203, 203, 204, 204, 204, + 205, 205, 205, 205, 206, 206, 206, 206, 207, 207, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 209, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 210, 210, 210, 210, 210, 210, 210, 210, 211, 211, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 214, 214, 214, 214, 214, 214, 214, 215, 215, + 216, 216, 218, 217, 220, 219, 221, 221, 222, 222, + 223, 223, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 225, 226, 226, 226, 226, 227, 227, 228, + 228, 228, 229, 229, 229, 230, 230, 230, 231, 231, + 231, 233, 232, 234, 232, 232, 232, 235, 235, 235, + 236, 236, 236, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 237, 237, 237, 238, 238, 238, + 239, 241, 240, 242, 242, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 244, + 244, 245, 245, 246, 246, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 249, 249, + 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, + 249, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 251, 251, 251, 251, 251, 251, 251, + 251, 251, 251, 251, 252, 252, 252, 253, 253, 253, + 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 256, 256, 256, 257, 257, 257, 257, + 258 +}; -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 2, 2, 2, 1, 2, 2, 1, 3, + 4, 4, 0, 5, 1, 1, 1, 1, 1, 2, + 1, 1, 2, 2, 2, 2, 7, 9, 11, 9, + 11, 13, 9, 13, 9, 7, 5, 0, 3, 1, + 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 6, 1, 3, 1, 4, 1, 3, + 3, 3, 1, 0, 4, 0, 5, 2, 4, 2, + 4, 0, 4, 0, 5, 3, 2, 4, 2, 4, + 0, 6, 0, 6, 0, 7, 0, 11, 0, 12, + 0, 8, 0, 9, 1, 1, 1, 2, 2, 2, + 2, 4, 5, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 1, 1, 1, 1, 0, 6, 2, 1, 1, 1, + 3, 2, 4, 2, 4, 3, 4, 1, 1, 1, + 1, 2, 3, 2, 2, 2, 2, 2, 3, 4, + 3, 0, 6, 2, 3, 1, 3, 4, 1, 1, + 1, 3, 2, 1, 3, 1, 1, 1, 3, 2, + 1, 3, 1, 2, 1, 2, 1, 3, 5, 3, + 3, 1, 3, 3, 3, 3, 4, 1, 1, 2, + 1, 3, 3, 5, 3, 4, 5, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 3, 4, 1, + 1, 2, 2, 2, 2, 2, 3, 4, 7, 3, + 1, 2, 2, 2, 2, 2, 3, 4, 1, 2, + 2, 2, 2, 2, 3, 4, 5, 9, 9, 9, + 1, 1, 2, 1, 1, 1, 2, 4, 4, 1, + 1, 1, 2, 1, 1, 1, 2, 4, 2, 4, + 1, 1, 1, 2, 2, 2, 4, 1, 1, 1, + 2, 3, 0, 5, 0, 8, 1, 1, 1, 1, + 2, 3, 1, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 4, 3, 1, 4, 2, 1, 1, 1, + 3, 5, 1, 2, 4, 1, 2, 2, 1, 1, + 1, 0, 6, 0, 7, 4, 5, 3, 5, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, + 1, 0, 2, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, + 1, 1, 1, 1, 3, 1, 4, 7, 7, 7, + 7, 4, 4, 2, 2, 2, 2, 2, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 5, 4, 4, 3, 3, + 3, 3, 1, 4, 7, 7, 7, 7, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 2, 5, 4, 4, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 5, 4, 4, 3, 3, 3, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, + 11, 1, 4, 7, 7, 7, 7, 4, 4, 2, + 5, 4, 4, 2, 2, 2, 2, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, + 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, + 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 0 +}; -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. However, - YYFAIL appears to be in use. Nevertheless, it is formally deprecated - in Bison 2.4.2's NEWS entry, where a plan to phase it out is - discussed. */ +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab -#define YYFAIL goto yyerrlab -#if defined YYFAIL - /* This is here to suppress warnings from the GCC cpp's - -Wunused-macros. Normally we don't worry about that warning, but - some users do, and we want to make it easy for users to remove - YYFAIL uses, which will produce warnings from Bison 2.5. */ -#endif #define YYRECOVERING() (!!yyerrstatus) @@ -3043,13 +2802,13 @@ do \ else \ { \ yyerror (&yylloc, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (YYID (0)) + YYERROR; \ + } \ +while (0) /* Error token number */ -#define YYTERROR 1 -#define YYERRCODE 256 +#define YYTERROR 1 +#define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. @@ -3059,7 +2818,7 @@ while (YYID (0)) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ - if (YYID (N)) \ + if (N) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ @@ -3073,12 +2832,27 @@ while (YYID (0)) (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ - while (YYID (0)) + while (0) #endif #define YYRHSLOC(Rhs, K) ((Rhs)[K]) +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + + /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ @@ -3088,36 +2862,28 @@ while (YYID (0)) /* Print *YYLOCP on YYO. Private, do not rely on its existence. */ -__attribute__((__unused__)) -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +YY_ATTRIBUTE_UNUSED static unsigned yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) -#else -static unsigned -yy_location_print_ (yyo, yylocp) - FILE *yyo; - YYLTYPE const * const yylocp; -#endif { unsigned res = 0; int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; if (0 <= yylocp->first_line) { - res += fprintf (yyo, "%d", yylocp->first_line); + res += YYFPRINTF (yyo, "%d", yylocp->first_line); if (0 <= yylocp->first_column) - res += fprintf (yyo, ".%d", yylocp->first_column); + res += YYFPRINTF (yyo, ".%d", yylocp->first_column); } if (0 <= yylocp->last_line) { if (yylocp->first_line < yylocp->last_line) { - res += fprintf (yyo, "-%d", yylocp->last_line); + res += YYFPRINTF (yyo, "-%d", yylocp->last_line); if (0 <= end_col) - res += fprintf (yyo, ".%d", end_col); + res += YYFPRINTF (yyo, ".%d", end_col); } else if (0 <= end_col && yylocp->first_column < end_col) - res += fprintf (yyo, "-%d", end_col); + res += YYFPRINTF (yyo, "-%d", end_col); } return res; } @@ -3131,73 +2897,35 @@ yy_location_print_ (yyo, yylocp) #endif -/* YYLEX -- calling `yylex' with the right arguments. */ -#ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) -#else -# define YYLEX yylex (&yylval, &yylloc) -#endif - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (YYID (0)) - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value, Location); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (YYID (0)) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, Location); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) -#else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; - YYLTYPE const * const yylocationp; -#endif { FILE *yyo = yyoutput; YYUSE (yyo); + YYUSE (yylocationp); if (!yyvaluep) return; - YYUSE (yylocationp); # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); # endif - switch (yytype) - { - default: - break; - } + YYUSE (yytype); } @@ -3205,23 +2933,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp) | Print this symbol on YYOUTPUT. | `--------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) -#else -static void -yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; - YYLTYPE const * const yylocationp; -#endif { - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); YY_LOCATION_PRINT (yyoutput, *yylocationp); YYFPRINTF (yyoutput, ": "); @@ -3234,16 +2950,8 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp) | TOP (included). | `------------------------------------------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -#else -static void -yy_stack_print (yybottom, yytop) - yytype_int16 *yybottom; - yytype_int16 *yytop; -#endif { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) @@ -3254,50 +2962,42 @@ yy_stack_print (yybottom, yytop) YYFPRINTF (stderr, "\n"); } -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule) -#else -static void -yy_reduce_print (yyvsp, yylsp, yyrule) - YYSTYPE *yyvsp; - YYLTYPE *yylsp; - int yyrule; -#endif +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule) { + unsigned long int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; - unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); + yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], - &(yyvsp[(yyi + 1) - (yynrhs)]) - , &(yylsp[(yyi + 1) - (yynrhs)]) ); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , &(yylsp[(yyi + 1) - (yynrhs)]) ); YYFPRINTF (stderr, "\n"); } } -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyvsp, yylsp, Rule); \ -} while (YYID (0)) +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, yylsp, Rule); \ +} while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ @@ -3311,7 +3011,7 @@ int yydebug; /* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH +#ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif @@ -3334,15 +3034,8 @@ int yydebug; # define yystrlen strlen # else /* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) @@ -3358,16 +3051,8 @@ yystrlen (yystr) # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif { char *yyd = yydest; const char *yys = yysrc; @@ -3397,27 +3082,27 @@ yytnamerr (char *yyres, const char *yystr) char const *yyp = yystr; for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } do_not_strip_quotes: ; } @@ -3440,11 +3125,11 @@ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { - YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); YYSIZE_T yysize = yysize0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ - const char *yyformat = YY_NULL; + const char *yyformat = YY_NULLPTR; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per @@ -3452,10 +3137,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, int yycount = 0; /* There are many possibilities here to consider: - - Assume YYFAIL is not used. It's too flawed to consider. See - - for details. YYERROR is fine as it does not invoke this - function. - If this state is a consistent state with a default action, then the only way this function was invoked is if the default action is an error action. In that case, don't check for expected @@ -3505,7 +3186,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, } yyarg[yycount++] = yytname[yyx]; { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; @@ -3572,33 +3253,18 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, | Release the memory associated to this symbol. | `-----------------------------------------------*/ -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) -#else -static void -yydestruct (yymsg, yytype, yyvaluep, yylocationp) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; - YYLTYPE *yylocationp; -#endif { YYUSE (yyvaluep); YYUSE (yylocationp); - if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - switch (yytype) - { - - default: - break; - } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -3608,66 +3274,27 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp) | yyparse. | `----------*/ -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) int yyparse (void) -#else -int -yyparse () - -#endif -#endif { /* The lookahead symbol. */ int yychar; -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") -#else +/* The semantic value of the lookahead symbol. */ /* Default value used for initialization, for pacifying older GCCs or non-GCC compilers. */ -static YYSTYPE yyval_default; -# define YY_INITIAL_VALUE(Value) = Value -#endif +YY_INITIAL_VALUE (static YYSTYPE yyval_default;) +YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); + +/* Location data for the lookahead symbol. */ static YYLTYPE yyloc_default # if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL = { 1, 1, 1, 1 } # endif ; -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); - -/* Location data for the lookahead symbol. */ YYLTYPE yylloc = yyloc_default; - /* Number of syntax errors so far. */ int yynerrs; @@ -3676,9 +3303,9 @@ YYLTYPE yylloc = yyloc_default; int yyerrstatus; /* The stacks and their tools: - `yyss': related to states. - `yyvs': related to semantic values. - `yyls': related to locations. + 'yyss': related to states. + 'yyvs': related to semantic values. + 'yyls': related to locations. Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ @@ -3757,26 +3384,26 @@ YYLTYPE yylloc = yyloc_default; #ifdef yyoverflow { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - YYLTYPE *yyls1 = yyls; + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yyls1, yysize * sizeof (*yylsp), - &yystacksize); + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); - yyls = yyls1; - yyss = yyss1; - yyvs = yyvs1; + yyls = yyls1; + yyss = yyss1; + yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE @@ -3784,23 +3411,23 @@ YYLTYPE yylloc = yyloc_default; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; + goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; + yystacksize = YYMAXDEPTH; { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); - YYSTACK_RELOCATE (yyls_alloc, yyls); + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); + YYSTACK_RELOCATE (yyls_alloc, yyls); # undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ @@ -3810,10 +3437,10 @@ YYLTYPE yylloc = yyloc_default; yylsp = yyls + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) - YYABORT; + YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); @@ -3842,7 +3469,7 @@ yybackup: if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; + yychar = yylex (&yylval, &yylloc); } if (yychar <= YYEOF) @@ -3907,7 +3534,7 @@ yyreduce: yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. + '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison @@ -3922,57 +3549,56 @@ yyreduce: switch (yyn) { case 3: -/* Line 1792 of yacc.c */ -#line 423 "dtool/src/cppparser/cppBison.yxx" +#line 426 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - current_expr = (yyvsp[(2) - (2)].u.expr); + current_expr = (yyvsp[0].u.expr); } +#line 3557 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 4: -/* Line 1792 of yacc.c */ -#line 427 "dtool/src/cppparser/cppBison.yxx" +#line 430 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - current_type = (yyvsp[(2) - (2)].u.type); + current_type = (yyvsp[0].u.type); } +#line 3565 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 10: -/* Line 1792 of yacc.c */ -#line 445 "dtool/src/cppparser/cppBison.yxx" +#line 448 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - delete (yyvsp[(3) - (4)].u.expr); + delete (yyvsp[-1].u.expr); } +#line 3573 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 11: -/* Line 1792 of yacc.c */ -#line 449 "dtool/src/cppparser/cppBison.yxx" +#line 452 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - delete (yyvsp[(3) - (4)].u.expr); + delete (yyvsp[-1].u.expr); } +#line 3581 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 12: -/* Line 1792 of yacc.c */ -#line 461 "dtool/src/cppparser/cppBison.yxx" +#line 464 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { push_storage_class((current_storage_class & ~CPPInstance::SC_c_binding) | - ((yyvsp[(1) - (2)].u.integer) & CPPInstance::SC_c_binding)); + ((yyvsp[-1].u.integer) & CPPInstance::SC_c_binding)); } +#line 3590 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 13: -/* Line 1792 of yacc.c */ -#line 466 "dtool/src/cppparser/cppBison.yxx" +#line 469 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { pop_storage_class(); } +#line 3598 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 21: -/* Line 1792 of yacc.c */ -#line 480 "dtool/src/cppparser/cppBison.yxx" + case 20: +#line 482 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { if (publish_nest_level != 0) { yyerror("Unclosed __begin_publish", publish_loc); @@ -3981,36 +3607,36 @@ yyreduce: } publish_previous = current_scope->get_current_vis(); - publish_loc = (yylsp[(1) - (1)]); + publish_loc = (yylsp[0]); publish_nest_level++; current_scope->set_current_vis(V_published); } +#line 3615 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 22: -/* Line 1792 of yacc.c */ -#line 493 "dtool/src/cppparser/cppBison.yxx" + case 21: +#line 495 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { if (publish_nest_level != 1) { - yyerror("Unmatched __end_publish", (yylsp[(1) - (1)])); + yyerror("Unmatched __end_publish", (yylsp[0])); } else { current_scope->set_current_vis(publish_previous); } publish_nest_level = 0; } +#line 3628 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 23: -/* Line 1792 of yacc.c */ -#line 502 "dtool/src/cppparser/cppBison.yxx" + case 22: +#line 504 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { current_scope->set_current_vis(V_published); } +#line 3636 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 24: -/* Line 1792 of yacc.c */ -#line 506 "dtool/src/cppparser/cppBison.yxx" + case 23: +#line 508 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { if (publish_nest_level > 0) { current_scope->set_current_vis(V_published); @@ -4018,621 +3644,749 @@ yyreduce: current_scope->set_current_vis(V_public); } } +#line 3648 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 25: -/* Line 1792 of yacc.c */ -#line 514 "dtool/src/cppparser/cppBison.yxx" + case 24: +#line 516 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { current_scope->set_current_vis(V_protected); } +#line 3656 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 26: -/* Line 1792 of yacc.c */ -#line 518 "dtool/src/cppparser/cppBison.yxx" + case 25: +#line 520 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { current_scope->set_current_vis(V_private); } +#line 3664 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 26: +#line 524 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + + CPPDeclaration *getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); + } + + CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-4].u.identifier), getter->as_function_group(), NULL, current_scope, (yylsp[-6]).file); + current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-6])); +} +#line 3679 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 27: -/* Line 1792 of yacc.c */ -#line 522 "dtool/src/cppparser/cppBison.yxx" +#line 535 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - - CPPDeclaration *getter = (yyvsp[(5) - (7)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPDeclaration *getter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[(5) - (7)].u.identifier)->get_fully_scoped_name(), (yylsp[(5) - (7)])); - } - - CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[(3) - (7)].u.identifier), getter->as_function_group(), NULL, current_scope, (yylsp[(1) - (7)]).file); - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[(1) - (7)])); -} - break; - - case 28: -/* Line 1792 of yacc.c */ -#line 533 "dtool/src/cppparser/cppBison.yxx" - { - CPPDeclaration *getter = (yyvsp[(5) - (9)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[(5) - (9)].u.identifier)->get_fully_scoped_name(), (yylsp[(5) - (9)])); + yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); } else { - CPPDeclaration *setter = (yyvsp[(7) - (9)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPDeclaration *setter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); CPPFunctionGroup *setter_func = NULL; if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + (yyvsp[(7) - (9)].u.identifier)->get_fully_scoped_name(), (yylsp[(7) - (9)])); + yyerror("Reference to non-existent or invalid setter: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); } else { setter_func = setter->as_function_group(); } - CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[(3) - (9)].u.identifier), getter->as_function_group(), - setter_func, current_scope, (yylsp[(1) - (9)]).file); - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[(1) - (9)])); + CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-6].u.identifier), getter->as_function_group(), + setter_func, current_scope, (yylsp[-8]).file); + current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-8])); } } +#line 3704 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 28: +#line 556 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPDeclaration *getter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-6].u.identifier)->get_fully_scoped_name(), (yylsp[-6])); + + } else { + CPPDeclaration *setter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPFunctionGroup *setter_func = NULL; + + if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid setter: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); + } else { + setter_func = setter->as_function_group(); + } + + CPPDeclaration *deleter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + if (deleter == (CPPDeclaration *)NULL || deleter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("reference to non-existent or invalid delete method: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); + deleter = NULL; + } + + CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-8].u.identifier), getter->as_function_group(), + setter_func, current_scope, (yylsp[-10]).file); + if (deleter) { + make_property->_del_function = deleter->as_function_group(); + } + current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-10])); + } +} +#line 3738 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 29: -/* Line 1792 of yacc.c */ -#line 554 "dtool/src/cppparser/cppBison.yxx" +#line 586 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPDeclaration *hasser = (yyvsp[(5) - (9)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (hasser == (CPPDeclaration *)NULL || hasser->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid has-function: " + (yyvsp[(5) - (9)].u.identifier)->get_fully_scoped_name(), (yylsp[(5) - (9)])); + CPPDeclaration *length_getter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("reference to non-existent or invalid length method: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); + length_getter = NULL; } - CPPDeclaration *getter = (yyvsp[(7) - (9)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPDeclaration *getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[(7) - (9)].u.identifier)->get_fully_scoped_name(), (yylsp[(7) - (9)])); + yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); + } + + CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-6].u.identifier), getter->as_function_group(), NULL, current_scope, (yylsp[-8]).file); + make_property->_length_function = length_getter->as_function_group(); + current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-8])); +} +#line 3759 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 30: +#line 603 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPDeclaration *length_getter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("reference to non-existent or invalid length method: " + (yyvsp[-6].u.identifier)->get_fully_scoped_name(), (yylsp[-6])); + length_getter = NULL; + } + + CPPDeclaration *getter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); + + } else { + CPPDeclaration *setter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPFunctionGroup *setter_func = NULL; + + if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid setter: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); + } else { + setter_func = setter->as_function_group(); + } + + CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-8].u.identifier), getter->as_function_group(), + setter_func, current_scope, (yylsp[-10]).file); + make_property->_length_function = length_getter->as_function_group(); + current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-10])); + } +} +#line 3791 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 31: +#line 631 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPDeclaration *length_getter = (yyvsp[-8].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("reference to non-existent or invalid length method: " + (yyvsp[-8].u.identifier)->get_fully_scoped_name(), (yylsp[-8])); + length_getter = NULL; + } + + CPPDeclaration *getter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-6].u.identifier)->get_fully_scoped_name(), (yylsp[-6])); + + } else { + CPPDeclaration *setter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPFunctionGroup *setter_func = NULL; + + if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid setter: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); + } else { + setter_func = setter->as_function_group(); + } + + CPPDeclaration *deleter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + if (deleter == (CPPDeclaration *)NULL || deleter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("reference to non-existent or invalid delete method: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); + deleter = NULL; + } + + CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-10].u.identifier), getter->as_function_group(), + setter_func, current_scope, (yylsp[-12]).file); + make_property->_length_function = length_getter->as_function_group(); + if (deleter) { + make_property->_del_function = deleter->as_function_group(); + } + current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-12])); + } +} +#line 3832 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 32: +#line 668 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPDeclaration *hasser = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + if (hasser == (CPPDeclaration *)NULL || hasser->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid has-function: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); + } + + CPPDeclaration *getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); } if (hasser && getter) { CPPMakeProperty *make_property; - make_property = new CPPMakeProperty((yyvsp[(3) - (9)].u.identifier), + make_property = new CPPMakeProperty((yyvsp[-6].u.identifier), hasser->as_function_group(), getter->as_function_group(), NULL, NULL, - current_scope, (yylsp[(1) - (9)]).file); - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[(1) - (9)])); + current_scope, (yylsp[-8]).file); + current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-8])); } } +#line 3858 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 30: -/* Line 1792 of yacc.c */ -#line 576 "dtool/src/cppparser/cppBison.yxx" + case 33: +#line 690 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPDeclaration *hasser = (yyvsp[(5) - (13)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPDeclaration *hasser = (yyvsp[-8].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (hasser == (CPPDeclaration *)NULL || hasser->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid has-function: " + (yyvsp[(5) - (13)].u.identifier)->get_fully_scoped_name(), (yylsp[(5) - (13)])); + yyerror("Reference to non-existent or invalid has-function: " + (yyvsp[-8].u.identifier)->get_fully_scoped_name(), (yylsp[-8])); } - CPPDeclaration *getter = (yyvsp[(7) - (13)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPDeclaration *getter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[(7) - (13)].u.identifier)->get_fully_scoped_name(), (yylsp[(7) - (13)])); + yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-6].u.identifier)->get_fully_scoped_name(), (yylsp[-6])); } - CPPDeclaration *setter = (yyvsp[(9) - (13)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPDeclaration *setter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + (yyvsp[(9) - (13)].u.identifier)->get_fully_scoped_name(), (yylsp[(9) - (13)])); + yyerror("Reference to non-existent or invalid setter: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); } - CPPDeclaration *clearer = (yyvsp[(11) - (13)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPDeclaration *clearer = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (clearer == (CPPDeclaration *)NULL || clearer->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid clear-function: " + (yyvsp[(11) - (13)].u.identifier)->get_fully_scoped_name(), (yylsp[(11) - (13)])); + yyerror("Reference to non-existent or invalid clear-function: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); } if (hasser && getter && setter && clearer) { CPPMakeProperty *make_property; - make_property = new CPPMakeProperty((yyvsp[(3) - (13)].u.identifier), + make_property = new CPPMakeProperty((yyvsp[-10].u.identifier), hasser->as_function_group(), getter->as_function_group(), setter->as_function_group(), clearer->as_function_group(), - current_scope, (yylsp[(1) - (13)]).file); - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[(1) - (13)])); + current_scope, (yylsp[-12]).file); + current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-12])); } } +#line 3895 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 31: -/* Line 1792 of yacc.c */ -#line 609 "dtool/src/cppparser/cppBison.yxx" + case 34: +#line 723 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPDeclaration *length_getter = (yyvsp[(5) - (9)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPDeclaration *length_getter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + (yyvsp[(5) - (9)].u.identifier)->get_fully_scoped_name(), (yylsp[(5) - (9)])); + yyerror("reference to non-existent or invalid length method: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); length_getter = NULL; } - CPPDeclaration *element_getter = (yyvsp[(7) - (9)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + CPPDeclaration *element_getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (element_getter == (CPPDeclaration *)NULL || element_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid element method: " + (yyvsp[(7) - (9)].u.identifier)->get_fully_scoped_name(), (yylsp[(5) - (9)])); + yyerror("reference to non-existent or invalid element method: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); element_getter = NULL; } if (length_getter != (CPPDeclaration *)NULL && element_getter != (CPPDeclaration *)NULL) { - CPPMakeSeq *make_seq = new CPPMakeSeq((yyvsp[(3) - (9)].u.identifier), + CPPMakeSeq *make_seq = new CPPMakeSeq((yyvsp[-6].u.identifier), length_getter->as_function_group(), element_getter->as_function_group(), - current_scope, (yylsp[(1) - (9)]).file); - current_scope->add_declaration(make_seq, global_scope, current_lexer, (yylsp[(1) - (9)])); + current_scope, (yylsp[-8]).file); + current_scope->add_declaration(make_seq, global_scope, current_lexer, (yylsp[-8])); } } +#line 3921 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 32: -/* Line 1792 of yacc.c */ -#line 631 "dtool/src/cppparser/cppBison.yxx" + case 35: +#line 745 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPExpression::Result result = (yyvsp[(3) - (7)].u.expr)->evaluate(); + CPPExpression::Result result = (yyvsp[-4].u.expr)->evaluate(); if (result._type == CPPExpression::RT_error) { - yywarning("static_assert requires a constant expression", (yylsp[(3) - (7)])); + yywarning("static_assert requires a constant expression", (yylsp[-4])); } else if (!result.as_boolean()) { stringstream str; - str << *(yyvsp[(5) - (7)].u.expr); - yywarning("static_assert failed: " + str.str(), (yylsp[(3) - (7)])); + str << *(yyvsp[-2].u.expr); + yywarning("static_assert failed: " + str.str(), (yylsp[-4])); } } +#line 3936 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 33: -/* Line 1792 of yacc.c */ -#line 642 "dtool/src/cppparser/cppBison.yxx" + case 36: +#line 756 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { // This alternative version of static_assert was introduced in C++17. - CPPExpression::Result result = (yyvsp[(3) - (5)].u.expr)->evaluate(); + CPPExpression::Result result = (yyvsp[-2].u.expr)->evaluate(); if (result._type == CPPExpression::RT_error) { - yywarning("static_assert requires a constant expression", (yylsp[(3) - (5)])); + yywarning("static_assert requires a constant expression", (yylsp[-2])); } else if (!result.as_boolean()) { - yywarning("static_assert failed", (yylsp[(3) - (5)])); + yywarning("static_assert failed", (yylsp[-2])); } } +#line 3950 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 34: -/* Line 1792 of yacc.c */ -#line 655 "dtool/src/cppparser/cppBison.yxx" + case 37: +#line 769 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("temp"), V_public); push_scope(new_scope); } +#line 3960 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 35: -/* Line 1792 of yacc.c */ -#line 661 "dtool/src/cppparser/cppBison.yxx" + case 38: +#line 775 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { delete current_scope; pop_scope(); } - break; - - case 36: -/* Line 1792 of yacc.c */ -#line 670 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.integer) = 0; -} - break; - - case 37: -/* Line 1792 of yacc.c */ -#line 674 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_extern; -} - break; - - case 38: -/* Line 1792 of yacc.c */ -#line 678 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.integer) = (yyvsp[(3) - (3)].u.integer) | (int)CPPInstance::SC_extern; - if ((yyvsp[(2) - (3)].str) == "C") { - (yyval.u.integer) |= (int)CPPInstance::SC_c_binding; - } else if ((yyvsp[(2) - (3)].str) == "C++") { - (yyval.u.integer) &= ~(int)CPPInstance::SC_c_binding; - } else { - yywarning("Ignoring unknown linkage type \"" + (yyvsp[(2) - (3)].str) + "\"", (yylsp[(2) - (3)])); - } -} +#line 3969 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 39: -/* Line 1792 of yacc.c */ -#line 689 "dtool/src/cppparser/cppBison.yxx" +#line 784 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_static; + (yyval.u.integer) = 0; } +#line 3977 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 40: -/* Line 1792 of yacc.c */ -#line 693 "dtool/src/cppparser/cppBison.yxx" +#line 788 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_inline; + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_extern; } +#line 3985 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 41: -/* Line 1792 of yacc.c */ -#line 697 "dtool/src/cppparser/cppBison.yxx" +#line 792 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_virtual; + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_extern; + if ((yyvsp[-1].str) == "C") { + (yyval.u.integer) |= (int)CPPInstance::SC_c_binding; + } else if ((yyvsp[-1].str) == "C++") { + (yyval.u.integer) &= ~(int)CPPInstance::SC_c_binding; + } else { + yywarning("Ignoring unknown linkage type \"" + (yyvsp[-1].str) + "\"", (yylsp[-1])); + } } +#line 4000 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 42: -/* Line 1792 of yacc.c */ -#line 701 "dtool/src/cppparser/cppBison.yxx" +#line 803 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_explicit; + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_static; } +#line 4008 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 43: -/* Line 1792 of yacc.c */ -#line 705 "dtool/src/cppparser/cppBison.yxx" +#line 807 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_register; + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_inline; } +#line 4016 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 44: -/* Line 1792 of yacc.c */ -#line 709 "dtool/src/cppparser/cppBison.yxx" +#line 811 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_volatile; + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_virtual; } +#line 4024 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 45: -/* Line 1792 of yacc.c */ -#line 713 "dtool/src/cppparser/cppBison.yxx" +#line 815 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_mutable; + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_explicit; } +#line 4032 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 46: -/* Line 1792 of yacc.c */ -#line 717 "dtool/src/cppparser/cppBison.yxx" +#line 819 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_constexpr; + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_register; } +#line 4040 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 47: -/* Line 1792 of yacc.c */ -#line 721 "dtool/src/cppparser/cppBison.yxx" +#line 823 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_blocking; + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_volatile; } +#line 4048 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 48: -/* Line 1792 of yacc.c */ -#line 725 "dtool/src/cppparser/cppBison.yxx" +#line 827 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_extension; + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_mutable; } +#line 4056 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 49: -/* Line 1792 of yacc.c */ -#line 729 "dtool/src/cppparser/cppBison.yxx" +#line 831 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (yyvsp[(2) - (2)].u.integer) | (int)CPPInstance::SC_thread_local; + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_constexpr; } +#line 4064 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 50: -/* Line 1792 of yacc.c */ -#line 733 "dtool/src/cppparser/cppBison.yxx" +#line 835 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - // Ignore attribute specifiers for now. - (yyval.u.integer) = (yyvsp[(6) - (6)].u.integer); + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_blocking; } +#line 4072 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 55: -/* Line 1792 of yacc.c */ -#line 751 "dtool/src/cppparser/cppBison.yxx" + case 51: +#line 839 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_extension; +} +#line 4080 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 52: +#line 843 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_thread_local; +} +#line 4088 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 53: +#line 847 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + // Ignore attribute specifiers for now. + (yyval.u.integer) = (yyvsp[0].u.integer); +} +#line 4097 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 58: +#line 865 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { /* multiple_var_declaration adds itself to the scope. */ } +#line 4105 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 56: -/* Line 1792 of yacc.c */ -#line 755 "dtool/src/cppparser/cppBison.yxx" + case 59: +#line 869 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { // We don't really care about the storage class here. In fact, it's // not actually legal to define a class or struct using a particular // storage class, but we require it just to help yacc out in its // parsing. - current_scope->add_declaration((yyvsp[(2) - (3)].u.decl), global_scope, current_lexer, (yylsp[(2) - (3)])); -} - break; - - case 57: -/* Line 1792 of yacc.c */ -#line 764 "dtool/src/cppparser/cppBison.yxx" - { - if ((yyvsp[(2) - (3)].u.instance) != (CPPInstance *)NULL) { - (yyvsp[(2) - (3)].u.instance)->_storage_class |= (current_storage_class | (yyvsp[(1) - (3)].u.integer)); - current_scope->add_declaration((yyvsp[(2) - (3)].u.instance), global_scope, current_lexer, (yylsp[(2) - (3)])); - (yyvsp[(2) - (3)].u.instance)->set_initializer((yyvsp[(3) - (3)].u.expr)); - } -} - break; - - case 58: -/* Line 1792 of yacc.c */ -#line 772 "dtool/src/cppparser/cppBison.yxx" - { - if ((yyvsp[(2) - (3)].u.instance) != (CPPInstance *)NULL) { - (yyvsp[(2) - (3)].u.instance)->_storage_class |= (current_storage_class | (yyvsp[(1) - (3)].u.integer)); - current_scope->add_declaration((yyvsp[(2) - (3)].u.instance), global_scope, current_lexer, (yylsp[(2) - (3)])); - (yyvsp[(2) - (3)].u.instance)->set_initializer((yyvsp[(3) - (3)].u.expr)); - } -} - break; - - case 59: -/* Line 1792 of yacc.c */ -#line 783 "dtool/src/cppparser/cppBison.yxx" - { - // We don't need to push/pop type, because we can't nest - // multiple_var_declarations. - if ((yyvsp[(2) - (2)].u.decl)->as_type_declaration()) { - current_type = (yyvsp[(2) - (2)].u.decl)->as_type_declaration()->_type; - } else { - current_type = (yyvsp[(2) - (2)].u.decl)->as_type(); - } - push_storage_class((yyvsp[(1) - (2)].u.integer)); + current_scope->add_declaration((yyvsp[-1].u.decl), global_scope, current_lexer, (yylsp[-1])); } +#line 4118 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 60: -/* Line 1792 of yacc.c */ -#line 794 "dtool/src/cppparser/cppBison.yxx" +#line 878 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - pop_storage_class(); + if ((yyvsp[-1].u.instance) != (CPPInstance *)NULL) { + (yyvsp[-1].u.instance)->_storage_class |= (current_storage_class | (yyvsp[-2].u.integer)); + current_scope->add_declaration((yyvsp[-1].u.instance), global_scope, current_lexer, (yylsp[-1])); + (yyvsp[-1].u.instance)->set_initializer((yyvsp[0].u.expr)); + } } +#line 4130 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 61: -/* Line 1792 of yacc.c */ -#line 798 "dtool/src/cppparser/cppBison.yxx" +#line 886 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - // We don't need to push/pop type, because we can't nest - // multiple_var_declarations. - if ((yyvsp[(3) - (3)].u.decl)->as_type_declaration()) { - current_type = (yyvsp[(3) - (3)].u.decl)->as_type_declaration()->_type; - } else { - current_type = (yyvsp[(3) - (3)].u.decl)->as_type(); + if ((yyvsp[-1].u.instance) != (CPPInstance *)NULL) { + (yyvsp[-1].u.instance)->_storage_class |= (current_storage_class | (yyvsp[-2].u.integer)); + current_scope->add_declaration((yyvsp[-1].u.instance), global_scope, current_lexer, (yylsp[-1])); + (yyvsp[-1].u.instance)->set_initializer((yyvsp[0].u.expr)); } - push_storage_class((yyvsp[(1) - (3)].u.integer)); -} - break; - - case 62: -/* Line 1792 of yacc.c */ -#line 809 "dtool/src/cppparser/cppBison.yxx" - { - pop_storage_class(); } +#line 4142 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 63: -/* Line 1792 of yacc.c */ -#line 820 "dtool/src/cppparser/cppBison.yxx" +#line 898 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPInstance *inst = new CPPInstance(current_type, (yyvsp[(1) - (2)].u.inst_ident), - current_storage_class, - (yylsp[(1) - (2)]).file); - inst->set_initializer((yyvsp[(2) - (2)].u.expr)); - current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[(1) - (2)])); + // We don't need to push/pop type, because we can't nest + // multiple_var_declarations. + if ((yyvsp[0].u.decl)->as_type_declaration()) { + current_type = (yyvsp[0].u.decl)->as_type_declaration()->_type; + } else { + current_type = (yyvsp[0].u.decl)->as_type(); + } + push_storage_class((yyvsp[-1].u.integer)); } +#line 4157 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 64: -/* Line 1792 of yacc.c */ -#line 828 "dtool/src/cppparser/cppBison.yxx" +#line 909 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPInstance *inst = new CPPInstance(current_type, (yyvsp[(1) - (4)].u.inst_ident), - current_storage_class, - (yylsp[(1) - (4)]).file); - inst->set_initializer((yyvsp[(2) - (4)].u.expr)); - current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[(1) - (4)])); + pop_storage_class(); } +#line 4165 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 65: -/* Line 1792 of yacc.c */ -#line 839 "dtool/src/cppparser/cppBison.yxx" +#line 913 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyvsp[(1) - (2)].u.inst_ident)->add_modifier(IIT_const); - CPPInstance *inst = new CPPInstance(current_type, (yyvsp[(1) - (2)].u.inst_ident), - current_storage_class, - (yylsp[(1) - (2)]).file); - inst->set_initializer((yyvsp[(2) - (2)].u.expr)); - current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[(1) - (2)])); + // We don't need to push/pop type, because we can't nest + // multiple_var_declarations. + if ((yyvsp[0].u.decl)->as_type_declaration()) { + current_type = (yyvsp[0].u.decl)->as_type_declaration()->_type; + } else { + current_type = (yyvsp[0].u.decl)->as_type(); + } + push_storage_class((yyvsp[-2].u.integer)); } +#line 4180 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 66: -/* Line 1792 of yacc.c */ -#line 848 "dtool/src/cppparser/cppBison.yxx" +#line 924 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyvsp[(1) - (4)].u.inst_ident)->add_modifier(IIT_const); - CPPInstance *inst = new CPPInstance(current_type, (yyvsp[(1) - (4)].u.inst_ident), - current_storage_class, - (yylsp[(1) - (4)]).file); - inst->set_initializer((yyvsp[(2) - (4)].u.expr)); - current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[(1) - (4)])); + pop_storage_class(); } +#line 4188 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 67: -/* Line 1792 of yacc.c */ -#line 861 "dtool/src/cppparser/cppBison.yxx" +#line 935 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - // We don't need to push/pop type, because we can't nest - // multiple_var_declarations. - if ((yyvsp[(2) - (2)].u.decl)->as_type_declaration()) { - current_type = (yyvsp[(2) - (2)].u.decl)->as_type_declaration()->_type; - } else { - current_type = (yyvsp[(2) - (2)].u.decl)->as_type(); - } - push_storage_class((yyvsp[(1) - (2)].u.integer)); + CPPInstance *inst = new CPPInstance(current_type, (yyvsp[-1].u.inst_ident), + current_storage_class, + (yylsp[-1]).file); + inst->set_initializer((yyvsp[0].u.expr)); + current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[-1])); } +#line 4200 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 68: -/* Line 1792 of yacc.c */ -#line 872 "dtool/src/cppparser/cppBison.yxx" +#line 943 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - pop_storage_class(); + CPPInstance *inst = new CPPInstance(current_type, (yyvsp[-3].u.inst_ident), + current_storage_class, + (yylsp[-3]).file); + inst->set_initializer((yyvsp[-2].u.expr)); + current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[-3])); } +#line 4212 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 69: -/* Line 1792 of yacc.c */ -#line 876 "dtool/src/cppparser/cppBison.yxx" +#line 954 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - // We don't need to push/pop type, because we can't nest - // multiple_var_declarations. - if ((yyvsp[(3) - (3)].u.decl)->as_type_declaration()) { - current_type = (yyvsp[(3) - (3)].u.decl)->as_type_declaration()->_type; - } else { - current_type = (yyvsp[(3) - (3)].u.decl)->as_type(); - } - push_storage_class((yyvsp[(1) - (3)].u.integer)); + (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); + CPPInstance *inst = new CPPInstance(current_type, (yyvsp[-1].u.inst_ident), + current_storage_class, + (yylsp[-1]).file); + inst->set_initializer((yyvsp[0].u.expr)); + current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[-1])); } +#line 4225 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 70: -/* Line 1792 of yacc.c */ -#line 887 "dtool/src/cppparser/cppBison.yxx" +#line 963 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - pop_storage_class(); + (yyvsp[-3].u.inst_ident)->add_modifier(IIT_const); + CPPInstance *inst = new CPPInstance(current_type, (yyvsp[-3].u.inst_ident), + current_storage_class, + (yylsp[-3]).file); + inst->set_initializer((yyvsp[-2].u.expr)); + current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[-3])); } +#line 4238 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 71: -/* Line 1792 of yacc.c */ -#line 891 "dtool/src/cppparser/cppBison.yxx" +#line 976 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - if ((yyvsp[(2) - (3)].u.instance) != (CPPDeclaration *)NULL) { - CPPInstance *inst = (yyvsp[(2) - (3)].u.instance)->as_instance(); - if (inst != (CPPInstance *)NULL) { - inst->_storage_class |= (current_storage_class | (yyvsp[(1) - (3)].u.integer)); - current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[(2) - (3)])); - CPPTypedefType *typedef_type = new CPPTypedefType(inst->_type, inst->_ident, current_scope); - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[(2) - (3)])); - } + // We don't need to push/pop type, because we can't nest + // multiple_var_declarations. + if ((yyvsp[0].u.decl)->as_type_declaration()) { + current_type = (yyvsp[0].u.decl)->as_type_declaration()->_type; + } else { + current_type = (yyvsp[0].u.decl)->as_type(); } + push_storage_class((yyvsp[-1].u.integer)); } +#line 4253 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 72: -/* Line 1792 of yacc.c */ -#line 906 "dtool/src/cppparser/cppBison.yxx" +#line 987 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *target_type = current_type; - CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[(1) - (2)].u.inst_ident), current_scope, (yylsp[(1) - (2)]).file); - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[(1) - (2)])); + pop_storage_class(); } +#line 4261 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 73: -/* Line 1792 of yacc.c */ -#line 912 "dtool/src/cppparser/cppBison.yxx" +#line 991 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *target_type = current_type; - CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[(1) - (4)].u.inst_ident), current_scope, (yylsp[(1) - (4)]).file); - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[(1) - (4)])); + // We don't need to push/pop type, because we can't nest + // multiple_var_declarations. + if ((yyvsp[0].u.decl)->as_type_declaration()) { + current_type = (yyvsp[0].u.decl)->as_type_declaration()->_type; + } else { + current_type = (yyvsp[0].u.decl)->as_type(); + } + push_storage_class((yyvsp[-2].u.integer)); } +#line 4276 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 74: -/* Line 1792 of yacc.c */ -#line 921 "dtool/src/cppparser/cppBison.yxx" +#line 1002 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyvsp[(1) - (2)].u.inst_ident)->add_modifier(IIT_const); - CPPType *target_type = current_type; - CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[(1) - (2)].u.inst_ident), current_scope, (yylsp[(1) - (2)]).file); - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[(1) - (2)])); + pop_storage_class(); } +#line 4284 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 75: -/* Line 1792 of yacc.c */ -#line 928 "dtool/src/cppparser/cppBison.yxx" +#line 1006 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyvsp[(1) - (4)].u.inst_ident)->add_modifier(IIT_const); - CPPType *target_type = current_type; - CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[(1) - (4)].u.inst_ident), current_scope, (yylsp[(1) - (4)]).file); - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[(1) - (4)])); + if ((yyvsp[-1].u.instance) != (CPPDeclaration *)NULL) { + CPPInstance *inst = (yyvsp[-1].u.instance)->as_instance(); + if (inst != (CPPInstance *)NULL) { + inst->_storage_class |= (current_storage_class | (yyvsp[-2].u.integer)); + current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[-1])); + CPPTypedefType *typedef_type = new CPPTypedefType(inst->_type, inst->_ident, current_scope); + current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-1])); + } + } } +#line 4300 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 76: -/* Line 1792 of yacc.c */ -#line 940 "dtool/src/cppparser/cppBison.yxx" +#line 1021 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - push_scope((yyvsp[(1) - (2)].u.identifier)->get_scope(current_scope, global_scope)); + CPPType *target_type = current_type; + CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[-1].u.inst_ident), current_scope, (yylsp[-1]).file); + current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-1])); } +#line 4310 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 77: -/* Line 1792 of yacc.c */ -#line 944 "dtool/src/cppparser/cppBison.yxx" +#line 1027 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *type; - if ((yyvsp[(1) - (6)].u.identifier)->get_simple_name() == current_scope->get_simple_name() || - (yyvsp[(1) - (6)].u.identifier)->get_simple_name() == string("~") + current_scope->get_simple_name()) { - // This is a constructor, and has no return. - type = new CPPSimpleType(CPPSimpleType::T_void); - } else { - // This isn't a constructor, so it has an implicit return type of - // int. - yywarning("function has no return type, assuming int", (yylsp[(1) - (6)])); - type = new CPPSimpleType(CPPSimpleType::T_int); - } - pop_scope(); - - CPPInstanceIdentifier *ii = new CPPInstanceIdentifier((yyvsp[(1) - (6)].u.identifier)); - ii->add_func_modifier((yyvsp[(4) - (6)].u.param_list), (yyvsp[(6) - (6)].u.integer)); - - (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[(1) - (6)]).file); + CPPType *target_type = current_type; + CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[-3].u.inst_ident), current_scope, (yylsp[-3]).file); + current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-3])); } +#line 4320 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 78: -/* Line 1792 of yacc.c */ -#line 964 "dtool/src/cppparser/cppBison.yxx" +#line 1036 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - push_scope((yyvsp[(1) - (2)].u.identifier)->get_scope(current_scope, global_scope)); + (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); + CPPType *target_type = current_type; + CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[-1].u.inst_ident), current_scope, (yylsp[-1]).file); + current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-1])); } +#line 4331 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 79: -/* Line 1792 of yacc.c */ -#line 968 "dtool/src/cppparser/cppBison.yxx" +#line 1043 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyvsp[-3].u.inst_ident)->add_modifier(IIT_const); + CPPType *target_type = current_type; + CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[-3].u.inst_ident), current_scope, (yylsp[-3]).file); + current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-3])); +} +#line 4342 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 80: +#line 1055 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + push_scope((yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope)); +} +#line 4350 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 81: +#line 1059 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPType *type; + if ((yyvsp[-5].u.identifier)->get_simple_name() == current_scope->get_simple_name() || + (yyvsp[-5].u.identifier)->get_simple_name() == string("~") + current_scope->get_simple_name()) { + // This is a constructor, and has no return. + type = new CPPSimpleType(CPPSimpleType::T_void); + } else { + // This isn't a constructor, so it has an implicit return type of + // int. + yywarning("function has no return type, assuming int", (yylsp[-5])); + type = new CPPSimpleType(CPPSimpleType::T_int); + } + pop_scope(); + + CPPInstanceIdentifier *ii = new CPPInstanceIdentifier((yyvsp[-5].u.identifier)); + ii->add_func_modifier((yyvsp[-2].u.param_list), (yyvsp[0].u.integer)); + + (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-5]).file); +} +#line 4374 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 82: +#line 1079 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + push_scope((yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope)); +} +#line 4382 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 83: +#line 1083 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { pop_scope(); CPPType *type; - if ((yyvsp[(1) - (6)].u.identifier)->get_simple_name() == current_scope->get_simple_name()) { + if ((yyvsp[-5].u.identifier)->get_simple_name() == current_scope->get_simple_name()) { // This is a constructor, and has no return. type = new CPPSimpleType(CPPSimpleType::T_void); } else { @@ -4641,111 +4395,111 @@ yyreduce: type = new CPPSimpleType(CPPSimpleType::T_int); } - CPPInstanceIdentifier *ii = new CPPInstanceIdentifier((yyvsp[(1) - (6)].u.identifier)); - ii->add_func_modifier((yyvsp[(4) - (6)].u.param_list), (yyvsp[(6) - (6)].u.integer)); + CPPInstanceIdentifier *ii = new CPPInstanceIdentifier((yyvsp[-5].u.identifier)); + ii->add_func_modifier((yyvsp[-2].u.param_list), (yyvsp[0].u.integer)); - (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[(1) - (6)]).file); + (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-5]).file); } +#line 4404 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 80: -/* Line 1792 of yacc.c */ -#line 991 "dtool/src/cppparser/cppBison.yxx" + case 84: +#line 1106 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - push_scope((yyvsp[(2) - (3)].u.identifier)->get_scope(current_scope, global_scope)); + push_scope((yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope)); } +#line 4412 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 81: -/* Line 1792 of yacc.c */ -#line 995 "dtool/src/cppparser/cppBison.yxx" + case 85: +#line 1110 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { pop_scope(); - if ((yyvsp[(2) - (7)].u.identifier)->is_scoped()) { - yyerror("Invalid destructor name: ~" + (yyvsp[(2) - (7)].u.identifier)->get_fully_scoped_name(), (yylsp[(2) - (7)])); + if ((yyvsp[-5].u.identifier)->is_scoped()) { + yyerror("Invalid destructor name: ~" + (yyvsp[-5].u.identifier)->get_fully_scoped_name(), (yylsp[-5])); } else { CPPIdentifier *ident = - new CPPIdentifier("~" + (yyvsp[(2) - (7)].u.identifier)->get_simple_name(), (yylsp[(2) - (7)])); - delete (yyvsp[(2) - (7)].u.identifier); + new CPPIdentifier("~" + (yyvsp[-5].u.identifier)->get_simple_name(), (yylsp[-5])); + delete (yyvsp[-5].u.identifier); CPPType *type; type = new CPPSimpleType(CPPSimpleType::T_void); CPPInstanceIdentifier *ii = new CPPInstanceIdentifier(ident); - ii->add_func_modifier((yyvsp[(5) - (7)].u.param_list), (yyvsp[(7) - (7)].u.integer)); + ii->add_func_modifier((yyvsp[-2].u.param_list), (yyvsp[0].u.integer)); - (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[(2) - (7)]).file); + (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-5]).file); } } - break; - - case 82: -/* Line 1792 of yacc.c */ -#line 1021 "dtool/src/cppparser/cppBison.yxx" - { - push_scope((yyvsp[(4) - (6)].u.inst_ident)->get_scope(current_scope, global_scope)); -} - break; - - case 83: -/* Line 1792 of yacc.c */ -#line 1025 "dtool/src/cppparser/cppBison.yxx" - { - pop_scope(); - CPPType *type = (yyvsp[(1) - (11)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type == NULL) { - yyerror(string("internal error resolving type ") + (yyvsp[(1) - (11)].u.identifier)->get_fully_scoped_name(), (yylsp[(1) - (11)])); - } - assert(type != NULL); - - CPPInstanceIdentifier *ii = (yyvsp[(4) - (11)].u.inst_ident); - ii->add_modifier(IIT_pointer); - ii->add_func_modifier((yyvsp[(8) - (11)].u.param_list), (yyvsp[(10) - (11)].u.integer)); - (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[(1) - (11)]).file); -} - break; - - case 84: -/* Line 1792 of yacc.c */ -#line 1039 "dtool/src/cppparser/cppBison.yxx" - { - push_scope((yyvsp[(5) - (7)].u.inst_ident)->get_scope(current_scope, global_scope)); -} - break; - - case 85: -/* Line 1792 of yacc.c */ -#line 1043 "dtool/src/cppparser/cppBison.yxx" - { - pop_scope(); - CPPType *type = (yyvsp[(1) - (12)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type == NULL) { - yyerror(string("internal error resolving type ") + (yyvsp[(1) - (12)].u.identifier)->get_fully_scoped_name(), (yylsp[(1) - (12)])); - } - assert(type != NULL); - - CPPInstanceIdentifier *ii = (yyvsp[(5) - (12)].u.inst_ident); - ii->add_scoped_pointer_modifier((yyvsp[(3) - (12)].u.identifier)); - ii->add_func_modifier((yyvsp[(9) - (12)].u.param_list), (yyvsp[(11) - (12)].u.integer)); - (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[(1) - (12)]).file); -} +#line 4435 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 86: -/* Line 1792 of yacc.c */ -#line 1059 "dtool/src/cppparser/cppBison.yxx" +#line 1136 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - if ((yyvsp[(1) - (4)].u.identifier) != NULL) { - push_scope((yyvsp[(1) - (4)].u.identifier)->get_scope(current_scope, global_scope)); - } + push_scope((yyvsp[-2].u.inst_ident)->get_scope(current_scope, global_scope)); } +#line 4443 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 87: -/* Line 1792 of yacc.c */ -#line 1065 "dtool/src/cppparser/cppBison.yxx" +#line 1140 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - if ((yyvsp[(1) - (8)].u.identifier) != NULL) { + pop_scope(); + CPPType *type = (yyvsp[-10].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + if (type == NULL) { + yyerror(string("internal error resolving type ") + (yyvsp[-10].u.identifier)->get_fully_scoped_name(), (yylsp[-10])); + } + assert(type != NULL); + + CPPInstanceIdentifier *ii = (yyvsp[-7].u.inst_ident); + ii->add_modifier(IIT_pointer); + ii->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer)); + (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-10]).file); +} +#line 4461 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 88: +#line 1154 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + push_scope((yyvsp[-2].u.inst_ident)->get_scope(current_scope, global_scope)); +} +#line 4469 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 89: +#line 1158 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + pop_scope(); + CPPType *type = (yyvsp[-11].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + if (type == NULL) { + yyerror(string("internal error resolving type ") + (yyvsp[-11].u.identifier)->get_fully_scoped_name(), (yylsp[-11])); + } + assert(type != NULL); + + CPPInstanceIdentifier *ii = (yyvsp[-7].u.inst_ident); + ii->add_scoped_pointer_modifier((yyvsp[-9].u.identifier)); + ii->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer)); + (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-11]).file); +} +#line 4487 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 90: +#line 1174 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + if ((yyvsp[-3].u.identifier) != NULL) { + push_scope((yyvsp[-3].u.identifier)->get_scope(current_scope, global_scope)); + } +} +#line 4497 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 91: +#line 1180 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + if ((yyvsp[-7].u.identifier) != NULL) { pop_scope(); } @@ -4758,3861 +4512,3917 @@ yyreduce: // We give typecast operators the name "operator typecast ", // where is a simple name of the type to be typecast. Use // the method's return type to determine the full type description. - string name = "operator typecast " + (yyvsp[(2) - (8)].u.type)->get_simple_name(); - CPPIdentifier *ident = (yyvsp[(1) - (8)].u.identifier); + string name = "operator typecast " + (yyvsp[-6].u.type)->get_simple_name(); + CPPIdentifier *ident = (yyvsp[-7].u.identifier); if (ident == NULL) { - ident = new CPPIdentifier(name, (yylsp[(2) - (8)])); + ident = new CPPIdentifier(name, (yylsp[-6])); } else { ident->add_name(name); } (yyval.u.instance) = CPPInstance::make_typecast_function - (new CPPInstance((yyvsp[(2) - (8)].u.type), (yyvsp[(3) - (8)].u.inst_ident), 0, (yylsp[(3) - (8)]).file), ident, (yyvsp[(6) - (8)].u.param_list), (yyvsp[(8) - (8)].u.integer)); + (new CPPInstance((yyvsp[-6].u.type), (yyvsp[-5].u.inst_ident), 0, (yylsp[-5]).file), ident, (yyvsp[-2].u.param_list), (yyvsp[0].u.integer)); } +#line 4526 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 88: -/* Line 1792 of yacc.c */ -#line 1090 "dtool/src/cppparser/cppBison.yxx" + case 92: +#line 1205 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - if ((yyvsp[(1) - (5)].u.identifier) != NULL) { - push_scope((yyvsp[(1) - (5)].u.identifier)->get_scope(current_scope, global_scope)); + if ((yyvsp[-4].u.identifier) != NULL) { + push_scope((yyvsp[-4].u.identifier)->get_scope(current_scope, global_scope)); } } +#line 4536 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 89: -/* Line 1792 of yacc.c */ -#line 1096 "dtool/src/cppparser/cppBison.yxx" + case 93: +#line 1211 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - if ((yyvsp[(1) - (9)].u.identifier) != NULL) { + if ((yyvsp[-8].u.identifier) != NULL) { pop_scope(); } - CPPIdentifier *ident = (yyvsp[(1) - (9)].u.identifier); + CPPIdentifier *ident = (yyvsp[-8].u.identifier); if (ident == NULL) { - ident = new CPPIdentifier("operator typecast", (yylsp[(4) - (9)])); + ident = new CPPIdentifier("operator typecast", (yylsp[-5])); } else { ident->add_name("operator typecast"); } - (yyvsp[(4) - (9)].u.inst_ident)->add_modifier(IIT_const); + (yyvsp[-5].u.inst_ident)->add_modifier(IIT_const); (yyval.u.instance) = CPPInstance::make_typecast_function - (new CPPInstance((yyvsp[(3) - (9)].u.type), (yyvsp[(4) - (9)].u.inst_ident), 0, (yylsp[(4) - (9)]).file), ident, (yyvsp[(7) - (9)].u.param_list), (yyvsp[(9) - (9)].u.integer)); + (new CPPInstance((yyvsp[-6].u.type), (yyvsp[-5].u.inst_ident), 0, (yylsp[-5]).file), ident, (yyvsp[-2].u.param_list), (yyvsp[0].u.integer)); } +#line 4556 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 90: -/* Line 1792 of yacc.c */ -#line 1116 "dtool/src/cppparser/cppBison.yxx" + case 94: +#line 1231 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { CPPDeclaration *decl = - (yyvsp[(1) - (1)].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); + (yyvsp[0].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (decl != (CPPDeclaration *)NULL) { (yyval.u.instance) = decl->as_instance(); } else { (yyval.u.instance) = (CPPInstance *)NULL; } } - break; - - case 91: -/* Line 1792 of yacc.c */ -#line 1129 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.integer) = 0; -} - break; - - case 92: -/* Line 1792 of yacc.c */ -#line 1133 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.integer) = (int)CPPFunctionType::F_const_method; -} - break; - - case 93: -/* Line 1792 of yacc.c */ -#line 1137 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.integer) = (int)CPPFunctionType::F_noexcept; -} - break; - - case 94: -/* Line 1792 of yacc.c */ -#line 1141 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.integer) = (int)CPPFunctionType::F_final; -} +#line 4570 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 95: -/* Line 1792 of yacc.c */ -#line 1145 "dtool/src/cppparser/cppBison.yxx" +#line 1244 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.integer) = (int)CPPFunctionType::F_override; + (yyval.u.integer) = 0; } +#line 4578 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 96: -/* Line 1792 of yacc.c */ -#line 1149 "dtool/src/cppparser/cppBison.yxx" +#line 1248 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.integer) = (int)CPPFunctionType::F_const_method; +} +#line 4586 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 97: +#line 1252 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.integer) = (int)CPPFunctionType::F_noexcept; +} +#line 4594 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 98: +#line 1256 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.integer) = (int)CPPFunctionType::F_final; +} +#line 4602 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 99: +#line 1260 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.integer) = (int)CPPFunctionType::F_override; +} +#line 4610 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 100: +#line 1264 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { // Used for lambdas, currently ignored. (yyval.u.integer) = 0; } - break; - - case 97: -/* Line 1792 of yacc.c */ -#line 1154 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.integer) = (yyvsp[(1) - (4)].u.integer); -} - break; - - case 98: -/* Line 1792 of yacc.c */ -#line 1158 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.integer) = (yyvsp[(1) - (5)].u.integer); -} - break; - - case 99: -/* Line 1792 of yacc.c */ -#line 1169 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.str) = "!"; -} - break; - - case 100: -/* Line 1792 of yacc.c */ -#line 1173 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.str) = "~"; -} +#line 4619 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 101: -/* Line 1792 of yacc.c */ -#line 1177 "dtool/src/cppparser/cppBison.yxx" +#line 1269 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "*"; + (yyval.u.integer) = (yyvsp[-3].u.integer); } +#line 4627 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 102: -/* Line 1792 of yacc.c */ -#line 1181 "dtool/src/cppparser/cppBison.yxx" +#line 1273 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "/"; + (yyval.u.integer) = (yyvsp[-4].u.integer); } +#line 4635 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 103: -/* Line 1792 of yacc.c */ -#line 1185 "dtool/src/cppparser/cppBison.yxx" +#line 1284 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "%"; + (yyval.str) = "!"; } +#line 4643 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 104: -/* Line 1792 of yacc.c */ -#line 1189 "dtool/src/cppparser/cppBison.yxx" +#line 1288 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "+"; + (yyval.str) = "~"; } +#line 4651 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 105: -/* Line 1792 of yacc.c */ -#line 1193 "dtool/src/cppparser/cppBison.yxx" +#line 1292 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "-"; + (yyval.str) = "*"; } +#line 4659 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 106: -/* Line 1792 of yacc.c */ -#line 1197 "dtool/src/cppparser/cppBison.yxx" +#line 1296 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "|"; + (yyval.str) = "/"; } +#line 4667 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 107: -/* Line 1792 of yacc.c */ -#line 1201 "dtool/src/cppparser/cppBison.yxx" +#line 1300 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "&"; + (yyval.str) = "%"; } +#line 4675 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 108: -/* Line 1792 of yacc.c */ -#line 1205 "dtool/src/cppparser/cppBison.yxx" +#line 1304 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "^"; + (yyval.str) = "+"; } +#line 4683 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 109: -/* Line 1792 of yacc.c */ -#line 1209 "dtool/src/cppparser/cppBison.yxx" +#line 1308 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "||"; + (yyval.str) = "-"; } +#line 4691 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 110: -/* Line 1792 of yacc.c */ -#line 1213 "dtool/src/cppparser/cppBison.yxx" +#line 1312 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "&&"; + (yyval.str) = "|"; } +#line 4699 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 111: -/* Line 1792 of yacc.c */ -#line 1217 "dtool/src/cppparser/cppBison.yxx" +#line 1316 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "=="; + (yyval.str) = "&"; } +#line 4707 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 112: -/* Line 1792 of yacc.c */ -#line 1221 "dtool/src/cppparser/cppBison.yxx" +#line 1320 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "!="; + (yyval.str) = "^"; } +#line 4715 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 113: -/* Line 1792 of yacc.c */ -#line 1225 "dtool/src/cppparser/cppBison.yxx" +#line 1324 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "<="; + (yyval.str) = "||"; } +#line 4723 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 114: -/* Line 1792 of yacc.c */ -#line 1229 "dtool/src/cppparser/cppBison.yxx" +#line 1328 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = ">="; + (yyval.str) = "&&"; } +#line 4731 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 115: -/* Line 1792 of yacc.c */ -#line 1233 "dtool/src/cppparser/cppBison.yxx" +#line 1332 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "<"; + (yyval.str) = "=="; } +#line 4739 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 116: -/* Line 1792 of yacc.c */ -#line 1237 "dtool/src/cppparser/cppBison.yxx" +#line 1336 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = ">"; + (yyval.str) = "!="; } +#line 4747 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 117: -/* Line 1792 of yacc.c */ -#line 1241 "dtool/src/cppparser/cppBison.yxx" +#line 1340 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "<<"; + (yyval.str) = "<="; } +#line 4755 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 118: -/* Line 1792 of yacc.c */ -#line 1245 "dtool/src/cppparser/cppBison.yxx" +#line 1344 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = ">>"; + (yyval.str) = ">="; } +#line 4763 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 119: -/* Line 1792 of yacc.c */ -#line 1249 "dtool/src/cppparser/cppBison.yxx" +#line 1348 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "="; + (yyval.str) = "<"; } +#line 4771 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 120: -/* Line 1792 of yacc.c */ -#line 1253 "dtool/src/cppparser/cppBison.yxx" +#line 1352 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = ","; + (yyval.str) = ">"; } +#line 4779 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 121: -/* Line 1792 of yacc.c */ -#line 1257 "dtool/src/cppparser/cppBison.yxx" +#line 1356 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "++"; + (yyval.str) = "<<"; } +#line 4787 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 122: -/* Line 1792 of yacc.c */ -#line 1261 "dtool/src/cppparser/cppBison.yxx" +#line 1360 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "--"; + (yyval.str) = ">>"; } +#line 4795 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 123: -/* Line 1792 of yacc.c */ -#line 1265 "dtool/src/cppparser/cppBison.yxx" +#line 1364 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "*="; + (yyval.str) = "="; } +#line 4803 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 124: -/* Line 1792 of yacc.c */ -#line 1269 "dtool/src/cppparser/cppBison.yxx" +#line 1368 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "/="; + (yyval.str) = ","; } +#line 4811 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 125: -/* Line 1792 of yacc.c */ -#line 1273 "dtool/src/cppparser/cppBison.yxx" +#line 1372 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "%="; + (yyval.str) = "++"; } +#line 4819 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 126: -/* Line 1792 of yacc.c */ -#line 1277 "dtool/src/cppparser/cppBison.yxx" +#line 1376 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "+="; + (yyval.str) = "--"; } +#line 4827 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 127: -/* Line 1792 of yacc.c */ -#line 1281 "dtool/src/cppparser/cppBison.yxx" +#line 1380 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "-="; + (yyval.str) = "*="; } +#line 4835 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 128: -/* Line 1792 of yacc.c */ -#line 1285 "dtool/src/cppparser/cppBison.yxx" +#line 1384 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "|="; + (yyval.str) = "/="; } +#line 4843 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 129: -/* Line 1792 of yacc.c */ -#line 1289 "dtool/src/cppparser/cppBison.yxx" +#line 1388 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "&="; + (yyval.str) = "%="; } +#line 4851 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 130: -/* Line 1792 of yacc.c */ -#line 1293 "dtool/src/cppparser/cppBison.yxx" +#line 1392 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "^="; + (yyval.str) = "+="; } +#line 4859 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 131: -/* Line 1792 of yacc.c */ -#line 1297 "dtool/src/cppparser/cppBison.yxx" +#line 1396 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "<<="; + (yyval.str) = "-="; } +#line 4867 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 132: -/* Line 1792 of yacc.c */ -#line 1301 "dtool/src/cppparser/cppBison.yxx" +#line 1400 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = ">>="; + (yyval.str) = "|="; } +#line 4875 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 133: -/* Line 1792 of yacc.c */ -#line 1305 "dtool/src/cppparser/cppBison.yxx" +#line 1404 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "->"; + (yyval.str) = "&="; } +#line 4883 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 134: -/* Line 1792 of yacc.c */ -#line 1309 "dtool/src/cppparser/cppBison.yxx" +#line 1408 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "[]"; + (yyval.str) = "^="; } +#line 4891 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 135: -/* Line 1792 of yacc.c */ -#line 1313 "dtool/src/cppparser/cppBison.yxx" +#line 1412 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "()"; + (yyval.str) = "<<="; } +#line 4899 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 136: -/* Line 1792 of yacc.c */ -#line 1317 "dtool/src/cppparser/cppBison.yxx" +#line 1416 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "new"; + (yyval.str) = ">>="; } +#line 4907 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 137: -/* Line 1792 of yacc.c */ -#line 1321 "dtool/src/cppparser/cppBison.yxx" +#line 1420 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.str) = "delete"; + (yyval.str) = "->"; } +#line 4915 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 138: +#line 1424 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.str) = "[]"; +} +#line 4923 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 139: +#line 1428 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.str) = "()"; +} +#line 4931 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 140: -/* Line 1792 of yacc.c */ -#line 1333 "dtool/src/cppparser/cppBison.yxx" +#line 1432 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - push_scope(new CPPTemplateScope(current_scope)); + (yyval.str) = "new"; } +#line 4939 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 141: -/* Line 1792 of yacc.c */ -#line 1337 "dtool/src/cppparser/cppBison.yxx" +#line 1436 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - pop_scope(); + (yyval.str) = "delete"; } +#line 4947 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 144: +#line 1448 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + push_scope(new CPPTemplateScope(current_scope)); +} +#line 4955 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 145: -/* Line 1792 of yacc.c */ -#line 1350 "dtool/src/cppparser/cppBison.yxx" +#line 1452 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPTemplateScope *ts = current_scope->as_template_scope(); - assert(ts != NULL); - ts->add_template_parameter((yyvsp[(1) - (1)].u.decl)); -} - break; - - case 146: -/* Line 1792 of yacc.c */ -#line 1356 "dtool/src/cppparser/cppBison.yxx" - { - CPPTemplateScope *ts = current_scope->as_template_scope(); - assert(ts != NULL); - ts->add_template_parameter((yyvsp[(3) - (3)].u.decl)); -} - break; - - case 147: -/* Line 1792 of yacc.c */ -#line 1365 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[(2) - (2)].u.identifier))); -} - break; - - case 148: -/* Line 1792 of yacc.c */ -#line 1369 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[(2) - (4)].u.identifier), (yyvsp[(4) - (4)].u.type))); + pop_scope(); } +#line 4963 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 149: -/* Line 1792 of yacc.c */ -#line 1373 "dtool/src/cppparser/cppBison.yxx" +#line 1465 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[(2) - (2)].u.identifier))); + CPPTemplateScope *ts = current_scope->as_template_scope(); + assert(ts != NULL); + ts->add_template_parameter((yyvsp[0].u.decl)); } +#line 4973 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 150: -/* Line 1792 of yacc.c */ -#line 1377 "dtool/src/cppparser/cppBison.yxx" +#line 1471 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[(2) - (4)].u.identifier), (yyvsp[(4) - (4)].u.type))); + CPPTemplateScope *ts = current_scope->as_template_scope(); + assert(ts != NULL); + ts->add_template_parameter((yyvsp[0].u.decl)); } +#line 4983 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 151: -/* Line 1792 of yacc.c */ -#line 1381 "dtool/src/cppparser/cppBison.yxx" +#line 1480 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPInstance *inst = new CPPInstance((yyvsp[(1) - (3)].u.type), (yyvsp[(2) - (3)].u.inst_ident), 0, (yylsp[(2) - (3)]).file); - inst->set_initializer((yyvsp[(3) - (3)].u.expr)); - (yyval.u.decl) = inst; + (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[0].u.identifier))); } +#line 4991 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 152: -/* Line 1792 of yacc.c */ -#line 1387 "dtool/src/cppparser/cppBison.yxx" +#line 1484 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyvsp[(3) - (4)].u.inst_ident)->add_modifier(IIT_const); - CPPInstance *inst = new CPPInstance((yyvsp[(2) - (4)].u.type), (yyvsp[(3) - (4)].u.inst_ident), 0, (yylsp[(3) - (4)]).file); - inst->set_initializer((yyvsp[(4) - (4)].u.expr)); - (yyval.u.decl) = inst; + (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[-2].u.identifier), (yyvsp[0].u.type))); } +#line 4999 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 153: -/* Line 1792 of yacc.c */ -#line 1397 "dtool/src/cppparser/cppBison.yxx" +#line 1488 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = CPPType::new_type((yyvsp[(1) - (1)].u.simple_type)); + (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[0].u.identifier))); } +#line 5007 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 154: -/* Line 1792 of yacc.c */ -#line 1401 "dtool/src/cppparser/cppBison.yxx" +#line 1492 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - yywarning("Not a type: " + (yyvsp[(1) - (1)].u.identifier)->get_fully_scoped_name(), (yylsp[(1) - (1)])); - (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown)); + (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[-2].u.identifier), (yyvsp[0].u.type))); } +#line 5015 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 155: -/* Line 1792 of yacc.c */ -#line 1406 "dtool/src/cppparser/cppBison.yxx" +#line 1496 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = (yyvsp[(1) - (1)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if ((yyval.u.type) == NULL) { - yyerror(string("internal error resolving type ") + (yyvsp[(1) - (1)].u.identifier)->get_fully_scoped_name(), (yylsp[(1) - (1)])); - } - assert((yyval.u.type) != NULL); + CPPInstance *inst = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); + inst->set_initializer((yyvsp[0].u.expr)); + (yyval.u.decl) = inst; } +#line 5025 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 156: -/* Line 1792 of yacc.c */ -#line 1418 "dtool/src/cppparser/cppBison.yxx" +#line 1502 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[(1) - (1)].u.identifier)); + (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); + CPPInstance *inst = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); + inst->set_initializer((yyvsp[0].u.expr)); + (yyval.u.decl) = inst; } +#line 5036 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 157: -/* Line 1792 of yacc.c */ -#line 1422 "dtool/src/cppparser/cppBison.yxx" +#line 1512 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); +} +#line 5044 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 158: +#line 1516 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + yywarning("Not a type: " + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); + (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown)); +} +#line 5053 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 159: +#line 1521 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + if ((yyval.u.type) == NULL) { + yyerror(string("internal error resolving type ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); + } + assert((yyval.u.type) != NULL); +} +#line 5065 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 160: +#line 1533 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[0].u.identifier)); +} +#line 5073 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 161: +#line 1537 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { // For an operator function. We implement this simply by building a // ficticious name for the function; in other respects it's just // like a regular function. - CPPIdentifier *ident = (yyvsp[(1) - (2)].u.identifier); + CPPIdentifier *ident = (yyvsp[-1].u.identifier); if (ident == NULL) { - ident = new CPPIdentifier("operator "+(yyvsp[(2) - (2)].str), (yylsp[(2) - (2)])); + ident = new CPPIdentifier("operator "+(yyvsp[0].str), (yylsp[0])); } else { - ident->_names.push_back("operator "+(yyvsp[(2) - (2)].str)); + ident->_names.push_back("operator "+(yyvsp[0].str)); } (yyval.u.inst_ident) = new CPPInstanceIdentifier(ident); } - break; - - case 158: -/* Line 1792 of yacc.c */ -#line 1436 "dtool/src/cppparser/cppBison.yxx" - { - // A C++11 literal operator. - if (!(yyvsp[(2) - (3)].str).empty()) { - yyerror("expected empty string", (yylsp[(2) - (3)])); - } - CPPIdentifier *ident = (yyvsp[(1) - (3)].u.identifier); - if (ident == NULL) { - ident = new CPPIdentifier("operator \"\" "+(yyvsp[(3) - (3)].u.identifier)->get_simple_name(), (yylsp[(3) - (3)])); - } else { - ident->_names.push_back("operator \"\" "+(yyvsp[(3) - (3)].u.identifier)->get_simple_name()); - } - - (yyval.u.inst_ident) = new CPPInstanceIdentifier(ident); -} - break; - - case 159: -/* Line 1792 of yacc.c */ -#line 1451 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_const); -} - break; - - case 160: -/* Line 1792 of yacc.c */ -#line 1456 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_volatile); -} - break; - - case 161: -/* Line 1792 of yacc.c */ -#line 1461 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer); -} +#line 5091 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 162: -/* Line 1792 of yacc.c */ -#line 1466 "dtool/src/cppparser/cppBison.yxx" +#line 1551 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference); + // A C++11 literal operator. + if (!(yyvsp[-1].str).empty()) { + yyerror("expected empty string", (yylsp[-1])); + } + CPPIdentifier *ident = (yyvsp[-2].u.identifier); + if (ident == NULL) { + ident = new CPPIdentifier("operator \"\" "+(yyvsp[0].u.identifier)->get_simple_name(), (yylsp[0])); + } else { + ident->_names.push_back("operator \"\" "+(yyvsp[0].u.identifier)->get_simple_name()); + } + + (yyval.u.inst_ident) = new CPPInstanceIdentifier(ident); } +#line 5110 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 163: -/* Line 1792 of yacc.c */ -#line 1471 "dtool/src/cppparser/cppBison.yxx" +#line 1566 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_const); } +#line 5119 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 164: -/* Line 1792 of yacc.c */ -#line 1476 "dtool/src/cppparser/cppBison.yxx" +#line 1571 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(3) - (3)].u.inst_ident); - (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[(1) - (3)].u.identifier)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_volatile); } +#line 5128 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 165: -/* Line 1792 of yacc.c */ -#line 1481 "dtool/src/cppparser/cppBison.yxx" +#line 1576 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(1) - (4)].u.inst_ident); - (yyval.u.inst_ident)->add_array_modifier((yyvsp[(3) - (4)].u.expr)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_pointer); } +#line 5137 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 166: -/* Line 1792 of yacc.c */ -#line 1486 "dtool/src/cppparser/cppBison.yxx" +#line 1581 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (3)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_paren); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_reference); } +#line 5146 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 167: -/* Line 1792 of yacc.c */ -#line 1491 "dtool/src/cppparser/cppBison.yxx" +#line 1586 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - push_scope((yyvsp[(1) - (2)].u.inst_ident)->get_scope(current_scope, global_scope)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); } +#line 5155 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 168: -/* Line 1792 of yacc.c */ -#line 1495 "dtool/src/cppparser/cppBison.yxx" +#line 1591 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - pop_scope(); - (yyval.u.inst_ident) = (yyvsp[(1) - (6)].u.inst_ident); - if ((yyvsp[(4) - (6)].u.param_list)->is_parameter_expr() && (yyvsp[(6) - (6)].u.integer) == 0) { - // Oops, this must have been an instance declaration with a - // parameter list, not a function prototype. - (yyval.u.inst_ident)->add_initializer_modifier((yyvsp[(4) - (6)].u.param_list)); - - } else { - // This was (probably) a function prototype. - (yyval.u.inst_ident)->add_func_modifier((yyvsp[(4) - (6)].u.param_list), (yyvsp[(6) - (6)].u.integer)); - } + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-2].u.identifier)); } +#line 5164 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 169: -/* Line 1792 of yacc.c */ -#line 1513 "dtool/src/cppparser/cppBison.yxx" +#line 1596 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.inst_ident) = (yyvsp[-3].u.inst_ident); + (yyval.u.inst_ident)->add_array_modifier((yyvsp[-1].u.expr)); +} +#line 5173 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 170: +#line 1601 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.inst_ident) = (yyvsp[-1].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_paren); +} +#line 5182 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 171: +#line 1606 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + push_scope((yyvsp[-1].u.inst_ident)->get_scope(current_scope, global_scope)); +} +#line 5190 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 172: +#line 1610 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + pop_scope(); + (yyval.u.inst_ident) = (yyvsp[-5].u.inst_ident); + if ((yyvsp[-2].u.param_list)->is_parameter_expr() && (yyvsp[0].u.integer) == 0) { + // Oops, this must have been an instance declaration with a + // parameter list, not a function prototype. + (yyval.u.inst_ident)->add_initializer_modifier((yyvsp[-2].u.param_list)); + + } else { + // This was (probably) a function prototype. + (yyval.u.inst_ident)->add_func_modifier((yyvsp[-2].u.param_list), (yyvsp[0].u.integer)); + } +} +#line 5208 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 173: +#line 1628 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { // This is handled a bit awkwardly right now. Ideally it'd be wrapped // up in the instance_identifier rule, but then more needs to happen in // order to avoid shift/reduce conflicts. - if ((yyvsp[(2) - (2)].u.type) != NULL) { - (yyvsp[(1) - (2)].u.inst_ident)->add_trailing_return_type((yyvsp[(2) - (2)].u.type)); + if ((yyvsp[0].u.type) != NULL) { + (yyvsp[-1].u.inst_ident)->add_trailing_return_type((yyvsp[0].u.type)); } - (yyval.u.inst_ident) = (yyvsp[(1) - (2)].u.inst_ident); -} - break; - - case 170: -/* Line 1792 of yacc.c */ -#line 1523 "dtool/src/cppparser/cppBison.yxx" - { - // Bitfield definition. - (yyvsp[(1) - (3)].u.inst_ident)->_bit_width = (yyvsp[(3) - (3)].u.integer); - (yyval.u.inst_ident) = (yyvsp[(1) - (3)].u.inst_ident); -} - break; - - case 171: -/* Line 1792 of yacc.c */ -#line 1533 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.type) = NULL; -} - break; - - case 172: -/* Line 1792 of yacc.c */ -#line 1537 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.type) = (yyvsp[(3) - (3)].u.inst_ident)->unroll_type((yyvsp[(2) - (3)].u.type)); -} - break; - - case 173: -/* Line 1792 of yacc.c */ -#line 1541 "dtool/src/cppparser/cppBison.yxx" - { - (yyvsp[(4) - (4)].u.inst_ident)->add_modifier(IIT_const); - (yyval.u.type) = (yyvsp[(4) - (4)].u.inst_ident)->unroll_type((yyvsp[(3) - (4)].u.type)); + (yyval.u.inst_ident) = (yyvsp[-1].u.inst_ident); } +#line 5222 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 174: -/* Line 1792 of yacc.c */ -#line 1550 "dtool/src/cppparser/cppBison.yxx" +#line 1638 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = new CPPParameterList; + // Bitfield definition. + (yyvsp[-2].u.inst_ident)->_bit_width = (yyvsp[0].u.integer); + (yyval.u.inst_ident) = (yyvsp[-2].u.inst_ident); } +#line 5232 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 175: -/* Line 1792 of yacc.c */ -#line 1554 "dtool/src/cppparser/cppBison.yxx" +#line 1648 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = new CPPParameterList; - (yyval.u.param_list)->_includes_ellipsis = true; + (yyval.u.type) = NULL; } +#line 5240 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 176: -/* Line 1792 of yacc.c */ -#line 1559 "dtool/src/cppparser/cppBison.yxx" +#line 1652 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = (yyvsp[(1) - (1)].u.param_list); + (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); } +#line 5248 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 177: -/* Line 1792 of yacc.c */ -#line 1563 "dtool/src/cppparser/cppBison.yxx" +#line 1656 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = (yyvsp[(1) - (3)].u.param_list); - (yyval.u.param_list)->_includes_ellipsis = true; + (yyvsp[0].u.inst_ident)->add_modifier(IIT_const); + (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); } +#line 5257 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 178: -/* Line 1792 of yacc.c */ -#line 1568 "dtool/src/cppparser/cppBison.yxx" +#line 1665 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = (yyvsp[(1) - (2)].u.param_list); - (yyval.u.param_list)->_includes_ellipsis = true; + (yyval.u.param_list) = new CPPParameterList; } +#line 5265 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 179: -/* Line 1792 of yacc.c */ -#line 1576 "dtool/src/cppparser/cppBison.yxx" +#line 1669 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.param_list) = new CPPParameterList; - (yyval.u.param_list)->_parameters.push_back((yyvsp[(1) - (1)].u.instance)); + (yyval.u.param_list)->_includes_ellipsis = true; } +#line 5274 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 180: -/* Line 1792 of yacc.c */ -#line 1581 "dtool/src/cppparser/cppBison.yxx" +#line 1674 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = (yyvsp[(1) - (3)].u.param_list); - (yyval.u.param_list)->_parameters.push_back((yyvsp[(3) - (3)].u.instance)); + (yyval.u.param_list) = (yyvsp[0].u.param_list); } +#line 5282 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 181: -/* Line 1792 of yacc.c */ -#line 1589 "dtool/src/cppparser/cppBison.yxx" +#line 1678 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = new CPPParameterList; + (yyval.u.param_list) = (yyvsp[-2].u.param_list); + (yyval.u.param_list)->_includes_ellipsis = true; } +#line 5291 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 182: -/* Line 1792 of yacc.c */ -#line 1593 "dtool/src/cppparser/cppBison.yxx" +#line 1683 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = new CPPParameterList; + (yyval.u.param_list) = (yyvsp[-1].u.param_list); (yyval.u.param_list)->_includes_ellipsis = true; } +#line 5300 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 183: -/* Line 1792 of yacc.c */ -#line 1598 "dtool/src/cppparser/cppBison.yxx" +#line 1691 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = (yyvsp[(1) - (1)].u.param_list); + (yyval.u.param_list) = new CPPParameterList; + (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); } +#line 5309 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 184: -/* Line 1792 of yacc.c */ -#line 1602 "dtool/src/cppparser/cppBison.yxx" +#line 1696 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = (yyvsp[(1) - (3)].u.param_list); - (yyval.u.param_list)->_includes_ellipsis = true; + (yyval.u.param_list) = (yyvsp[-2].u.param_list); + (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); } +#line 5318 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 185: -/* Line 1792 of yacc.c */ -#line 1607 "dtool/src/cppparser/cppBison.yxx" +#line 1704 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = (yyvsp[(1) - (2)].u.param_list); - (yyval.u.param_list)->_includes_ellipsis = true; + (yyval.u.param_list) = new CPPParameterList; } +#line 5326 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 186: -/* Line 1792 of yacc.c */ -#line 1615 "dtool/src/cppparser/cppBison.yxx" +#line 1708 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.param_list) = new CPPParameterList; - (yyval.u.param_list)->_parameters.push_back((yyvsp[(1) - (1)].u.instance)); + (yyval.u.param_list)->_includes_ellipsis = true; } +#line 5335 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 187: -/* Line 1792 of yacc.c */ -#line 1620 "dtool/src/cppparser/cppBison.yxx" +#line 1713 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.param_list) = (yyvsp[(1) - (3)].u.param_list); - (yyval.u.param_list)->_parameters.push_back((yyvsp[(3) - (3)].u.instance)); + (yyval.u.param_list) = (yyvsp[0].u.param_list); } +#line 5343 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 188: -/* Line 1792 of yacc.c */ -#line 1628 "dtool/src/cppparser/cppBison.yxx" +#line 1717 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (CPPExpression *)NULL; + (yyval.u.param_list) = (yyvsp[-2].u.param_list); + (yyval.u.param_list)->_includes_ellipsis = true; } +#line 5352 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 189: -/* Line 1792 of yacc.c */ -#line 1632 "dtool/src/cppparser/cppBison.yxx" +#line 1722 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (yyvsp[(2) - (2)].u.expr); + (yyval.u.param_list) = (yyvsp[-1].u.param_list); + (yyval.u.param_list)->_includes_ellipsis = true; } +#line 5361 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 190: -/* Line 1792 of yacc.c */ -#line 1639 "dtool/src/cppparser/cppBison.yxx" +#line 1730 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (CPPExpression *)NULL; + (yyval.u.param_list) = new CPPParameterList; + (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); } +#line 5370 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 191: -/* Line 1792 of yacc.c */ -#line 1643 "dtool/src/cppparser/cppBison.yxx" +#line 1735 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (yyvsp[(2) - (2)].u.expr); + (yyval.u.param_list) = (yyvsp[-2].u.param_list); + (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); } +#line 5379 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 192: -/* Line 1792 of yacc.c */ -#line 1650 "dtool/src/cppparser/cppBison.yxx" +#line 1743 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.expr) = (CPPExpression *)NULL; } +#line 5387 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 193: -/* Line 1792 of yacc.c */ -#line 1654 "dtool/src/cppparser/cppBison.yxx" +#line 1747 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (CPPExpression *)NULL; + (yyval.u.expr) = (yyvsp[0].u.expr); } +#line 5395 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 194: -/* Line 1792 of yacc.c */ -#line 1658 "dtool/src/cppparser/cppBison.yxx" +#line 1754 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.expr) = (CPPExpression *)NULL; } +#line 5403 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 195: -/* Line 1792 of yacc.c */ -#line 1662 "dtool/src/cppparser/cppBison.yxx" +#line 1758 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::get_default()); + (yyval.u.expr) = (yyvsp[0].u.expr); } +#line 5411 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 196: -/* Line 1792 of yacc.c */ -#line 1666 "dtool/src/cppparser/cppBison.yxx" +#line 1765 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::get_delete()); + (yyval.u.expr) = (CPPExpression *)NULL; } +#line 5419 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 197: -/* Line 1792 of yacc.c */ -#line 1673 "dtool/src/cppparser/cppBison.yxx" +#line 1769 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.expr) = (CPPExpression *)NULL; } +#line 5427 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 198: -/* Line 1792 of yacc.c */ -#line 1677 "dtool/src/cppparser/cppBison.yxx" +#line 1773 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.expr) = (CPPExpression *)NULL; } +#line 5435 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 199: -/* Line 1792 of yacc.c */ -#line 1681 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = (yyvsp[(2) - (3)].u.expr); -} - break; - - case 200: -/* Line 1792 of yacc.c */ -#line 1685 "dtool/src/cppparser/cppBison.yxx" +#line 1777 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.expr) = new CPPExpression(CPPExpression::get_default()); } +#line 5443 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 201: -/* Line 1792 of yacc.c */ -#line 1689 "dtool/src/cppparser/cppBison.yxx" + case 200: +#line 1781 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.expr) = new CPPExpression(CPPExpression::get_delete()); } +#line 5451 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 202: -/* Line 1792 of yacc.c */ -#line 1693 "dtool/src/cppparser/cppBison.yxx" + case 201: +#line 1788 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.expr) = (CPPExpression *)NULL; } +#line 5459 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 202: +#line 1792 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = (CPPExpression *)NULL; +} +#line 5467 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 203: +#line 1796 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = (yyvsp[-1].u.expr); +} +#line 5475 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 204: +#line 1800 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::get_default()); +} +#line 5483 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 205: +#line 1804 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::get_delete()); +} +#line 5491 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 206: -/* Line 1792 of yacc.c */ -#line 1706 "dtool/src/cppparser/cppBison.yxx" +#line 1808 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { + (yyval.u.expr) = (CPPExpression *)NULL; } +#line 5499 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 210: -/* Line 1792 of yacc.c */ -#line 1715 "dtool/src/cppparser/cppBison.yxx" +#line 1821 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.instance) = new CPPInstance((yyvsp[(1) - (3)].u.type), (yyvsp[(2) - (3)].u.inst_ident), 0, (yylsp[(2) - (3)]).file); - (yyval.u.instance)->set_initializer((yyvsp[(3) - (3)].u.expr)); -} - break; - - case 211: -/* Line 1792 of yacc.c */ -#line 1720 "dtool/src/cppparser/cppBison.yxx" - { - (yyvsp[(3) - (4)].u.inst_ident)->add_modifier(IIT_const); - (yyval.u.instance) = new CPPInstance((yyvsp[(2) - (4)].u.type), (yyvsp[(3) - (4)].u.inst_ident), 0, (yylsp[(3) - (4)]).file); - (yyval.u.instance)->set_initializer((yyvsp[(4) - (4)].u.expr)); -} - break; - - case 212: -/* Line 1792 of yacc.c */ -#line 1726 "dtool/src/cppparser/cppBison.yxx" - { - (yyvsp[(4) - (5)].u.inst_ident)->add_modifier(IIT_const); - (yyval.u.instance) = new CPPInstance((yyvsp[(3) - (5)].u.type), (yyvsp[(4) - (5)].u.inst_ident), 0, (yylsp[(3) - (5)]).file); - (yyval.u.instance)->set_initializer((yyvsp[(5) - (5)].u.expr)); -} - break; - - case 213: -/* Line 1792 of yacc.c */ -#line 1732 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.instance) = (yyvsp[(2) - (2)].u.instance); } +#line 5506 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 214: -/* Line 1792 of yacc.c */ -#line 1743 "dtool/src/cppparser/cppBison.yxx" +#line 1830 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.instance) = (yyvsp[(1) - (1)].u.instance); + (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); + (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); } +#line 5515 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 215: -/* Line 1792 of yacc.c */ -#line 1747 "dtool/src/cppparser/cppBison.yxx" +#line 1835 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); + (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); + (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); +} +#line 5525 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 216: +#line 1841 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); + (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-2]).file); + (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); +} +#line 5535 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 217: +#line 1847 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.instance) = (yyvsp[0].u.instance); +} +#line 5543 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 218: +#line 1858 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.instance) = (yyvsp[0].u.instance); +} +#line 5551 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 219: +#line 1862 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_parameter)); (yyval.u.instance) = new CPPInstance(type, "expr"); - (yyval.u.instance)->set_initializer((yyvsp[(1) - (1)].u.expr)); -} - break; - - case 216: -/* Line 1792 of yacc.c */ -#line 1757 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.inst_ident) = new CPPInstanceIdentifier((CPPIdentifier *)NULL); -} - break; - - case 217: -/* Line 1792 of yacc.c */ -#line 1761 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[(1) - (1)].u.identifier)); -} - break; - - case 218: -/* Line 1792 of yacc.c */ -#line 1765 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_const); -} - break; - - case 219: -/* Line 1792 of yacc.c */ -#line 1770 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_volatile); + (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); } +#line 5562 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 220: -/* Line 1792 of yacc.c */ -#line 1775 "dtool/src/cppparser/cppBison.yxx" +#line 1872 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer); + (yyval.u.inst_ident) = new CPPInstanceIdentifier((CPPIdentifier *)NULL); } +#line 5570 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 221: -/* Line 1792 of yacc.c */ -#line 1780 "dtool/src/cppparser/cppBison.yxx" +#line 1876 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference); + (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[0].u.identifier)); } +#line 5578 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 222: -/* Line 1792 of yacc.c */ -#line 1785 "dtool/src/cppparser/cppBison.yxx" +#line 1880 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_const); } +#line 5587 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 223: -/* Line 1792 of yacc.c */ -#line 1790 "dtool/src/cppparser/cppBison.yxx" +#line 1885 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(3) - (3)].u.inst_ident); - (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[(1) - (3)].u.identifier)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_volatile); } +#line 5596 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 224: -/* Line 1792 of yacc.c */ -#line 1795 "dtool/src/cppparser/cppBison.yxx" +#line 1890 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(1) - (4)].u.inst_ident); - (yyval.u.inst_ident)->add_array_modifier((yyvsp[(3) - (4)].u.expr)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_pointer); } +#line 5605 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 225: -/* Line 1792 of yacc.c */ -#line 1803 "dtool/src/cppparser/cppBison.yxx" +#line 1895 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = new CPPInstanceIdentifier((CPPIdentifier *)NULL); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_reference); } +#line 5614 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 226: -/* Line 1792 of yacc.c */ -#line 1807 "dtool/src/cppparser/cppBison.yxx" +#line 1900 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[(1) - (1)].u.identifier)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); } +#line 5623 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 227: -/* Line 1792 of yacc.c */ -#line 1811 "dtool/src/cppparser/cppBison.yxx" +#line 1905 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_const); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-2].u.identifier)); } +#line 5632 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 228: -/* Line 1792 of yacc.c */ -#line 1816 "dtool/src/cppparser/cppBison.yxx" +#line 1910 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_volatile); + (yyval.u.inst_ident) = (yyvsp[-3].u.inst_ident); + (yyval.u.inst_ident)->add_array_modifier((yyvsp[-1].u.expr)); } +#line 5641 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 229: -/* Line 1792 of yacc.c */ -#line 1821 "dtool/src/cppparser/cppBison.yxx" +#line 1918 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer); + (yyval.u.inst_ident) = new CPPInstanceIdentifier((CPPIdentifier *)NULL); } +#line 5649 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 230: -/* Line 1792 of yacc.c */ -#line 1826 "dtool/src/cppparser/cppBison.yxx" +#line 1922 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference); + (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[0].u.identifier)); } +#line 5657 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 231: -/* Line 1792 of yacc.c */ -#line 1831 "dtool/src/cppparser/cppBison.yxx" +#line 1926 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_const); } +#line 5666 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 232: -/* Line 1792 of yacc.c */ -#line 1836 "dtool/src/cppparser/cppBison.yxx" +#line 1931 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(3) - (3)].u.inst_ident); - (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[(1) - (3)].u.identifier)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_volatile); } +#line 5675 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 233: -/* Line 1792 of yacc.c */ -#line 1841 "dtool/src/cppparser/cppBison.yxx" +#line 1936 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(1) - (4)].u.inst_ident); - (yyval.u.inst_ident)->add_array_modifier((yyvsp[(3) - (4)].u.expr)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_pointer); } +#line 5684 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 234: -/* Line 1792 of yacc.c */ -#line 1846 "dtool/src/cppparser/cppBison.yxx" +#line 1941 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (7)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_paren); - (yyval.u.inst_ident)->add_func_modifier((yyvsp[(5) - (7)].u.param_list), (yyvsp[(7) - (7)].u.integer)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_reference); } +#line 5693 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 235: -/* Line 1792 of yacc.c */ -#line 1852 "dtool/src/cppparser/cppBison.yxx" +#line 1946 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (3)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_paren); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); } +#line 5702 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 236: -/* Line 1792 of yacc.c */ -#line 1860 "dtool/src/cppparser/cppBison.yxx" +#line 1951 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = new CPPInstanceIdentifier((CPPIdentifier *)NULL); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-2].u.identifier)); } +#line 5711 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 237: -/* Line 1792 of yacc.c */ -#line 1864 "dtool/src/cppparser/cppBison.yxx" +#line 1956 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_const); + (yyval.u.inst_ident) = (yyvsp[-3].u.inst_ident); + (yyval.u.inst_ident)->add_array_modifier((yyvsp[-1].u.expr)); } +#line 5720 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 238: -/* Line 1792 of yacc.c */ -#line 1869 "dtool/src/cppparser/cppBison.yxx" +#line 1961 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_volatile); + (yyval.u.inst_ident) = (yyvsp[-5].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_paren); + (yyval.u.inst_ident)->add_func_modifier((yyvsp[-2].u.param_list), (yyvsp[0].u.integer)); } +#line 5730 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 239: -/* Line 1792 of yacc.c */ -#line 1874 "dtool/src/cppparser/cppBison.yxx" +#line 1967 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer); + (yyval.u.inst_ident) = (yyvsp[-1].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_paren); } +#line 5739 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 240: -/* Line 1792 of yacc.c */ -#line 1879 "dtool/src/cppparser/cppBison.yxx" +#line 1975 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference); + (yyval.u.inst_ident) = new CPPInstanceIdentifier((CPPIdentifier *)NULL); } +#line 5747 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 241: -/* Line 1792 of yacc.c */ -#line 1884 "dtool/src/cppparser/cppBison.yxx" +#line 1979 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_const); } +#line 5756 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 242: -/* Line 1792 of yacc.c */ -#line 1889 "dtool/src/cppparser/cppBison.yxx" +#line 1984 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(3) - (3)].u.inst_ident); - (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[(1) - (3)].u.identifier)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_volatile); } +#line 5765 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 243: -/* Line 1792 of yacc.c */ -#line 1894 "dtool/src/cppparser/cppBison.yxx" +#line 1989 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(1) - (4)].u.inst_ident); - (yyval.u.inst_ident)->add_array_modifier((yyvsp[(3) - (4)].u.expr)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_pointer); } +#line 5774 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 244: -/* Line 1792 of yacc.c */ -#line 1902 "dtool/src/cppparser/cppBison.yxx" +#line 1994 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = new CPPInstanceIdentifier((CPPIdentifier *)NULL); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_reference); } +#line 5783 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 245: -/* Line 1792 of yacc.c */ -#line 1906 "dtool/src/cppparser/cppBison.yxx" +#line 1999 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_const); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); } +#line 5792 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 246: -/* Line 1792 of yacc.c */ -#line 1911 "dtool/src/cppparser/cppBison.yxx" +#line 2004 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_volatile); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-2].u.identifier)); } +#line 5801 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 247: -/* Line 1792 of yacc.c */ -#line 1916 "dtool/src/cppparser/cppBison.yxx" +#line 2009 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer); + (yyval.u.inst_ident) = (yyvsp[-3].u.inst_ident); + (yyval.u.inst_ident)->add_array_modifier((yyvsp[-1].u.expr)); } +#line 5810 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 248: -/* Line 1792 of yacc.c */ -#line 1921 "dtool/src/cppparser/cppBison.yxx" +#line 2017 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference); + (yyval.u.inst_ident) = new CPPInstanceIdentifier((CPPIdentifier *)NULL); } +#line 5818 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 249: -/* Line 1792 of yacc.c */ -#line 1926 "dtool/src/cppparser/cppBison.yxx" +#line 2021 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(2) - (2)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_const); } +#line 5827 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 250: -/* Line 1792 of yacc.c */ -#line 1931 "dtool/src/cppparser/cppBison.yxx" +#line 2026 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(3) - (3)].u.inst_ident); - (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[(1) - (3)].u.identifier)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_volatile); } +#line 5836 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 251: -/* Line 1792 of yacc.c */ -#line 1936 "dtool/src/cppparser/cppBison.yxx" +#line 2031 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(1) - (4)].u.inst_ident); - (yyval.u.inst_ident)->add_array_modifier((yyvsp[(3) - (4)].u.expr)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_pointer); } +#line 5845 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 252: -/* Line 1792 of yacc.c */ -#line 1941 "dtool/src/cppparser/cppBison.yxx" +#line 2036 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = new CPPInstanceIdentifier((CPPIdentifier *)NULL); - (yyval.u.inst_ident)->add_modifier(IIT_paren); - (yyval.u.inst_ident)->add_func_modifier((yyvsp[(2) - (5)].u.param_list), (yyvsp[(4) - (5)].u.integer), (yyvsp[(5) - (5)].u.type)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_reference); } +#line 5854 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 253: -/* Line 1792 of yacc.c */ -#line 1947 "dtool/src/cppparser/cppBison.yxx" +#line 2041 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(3) - (9)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer); - (yyval.u.inst_ident)->add_modifier(IIT_paren); - (yyval.u.inst_ident)->add_func_modifier((yyvsp[(6) - (9)].u.param_list), (yyvsp[(8) - (9)].u.integer), (yyvsp[(9) - (9)].u.type)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); } +#line 5863 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 254: -/* Line 1792 of yacc.c */ -#line 1954 "dtool/src/cppparser/cppBison.yxx" +#line 2046 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(3) - (9)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference); - (yyval.u.inst_ident)->add_modifier(IIT_paren); - (yyval.u.inst_ident)->add_func_modifier((yyvsp[(6) - (9)].u.param_list), (yyvsp[(8) - (9)].u.integer), (yyvsp[(9) - (9)].u.type)); + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-2].u.identifier)); } +#line 5872 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 255: -/* Line 1792 of yacc.c */ -#line 1961 "dtool/src/cppparser/cppBison.yxx" +#line 2051 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.inst_ident) = (yyvsp[(3) - (9)].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); - (yyval.u.inst_ident)->add_modifier(IIT_paren); - (yyval.u.inst_ident)->add_func_modifier((yyvsp[(6) - (9)].u.param_list), (yyvsp[(8) - (9)].u.integer), (yyvsp[(9) - (9)].u.type)); + (yyval.u.inst_ident) = (yyvsp[-3].u.inst_ident); + (yyval.u.inst_ident)->add_array_modifier((yyvsp[-1].u.expr)); } +#line 5881 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 256: -/* Line 1792 of yacc.c */ -#line 1971 "dtool/src/cppparser/cppBison.yxx" +#line 2056 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = CPPType::new_type((yyvsp[(1) - (1)].u.simple_type)); + (yyval.u.inst_ident) = new CPPInstanceIdentifier((CPPIdentifier *)NULL); + (yyval.u.inst_ident)->add_modifier(IIT_paren); + (yyval.u.inst_ident)->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), (yyvsp[0].u.type)); } +#line 5891 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 257: -/* Line 1792 of yacc.c */ -#line 1975 "dtool/src/cppparser/cppBison.yxx" +#line 2062 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = (yyvsp[(1) - (1)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if ((yyval.u.type) == NULL) { - yyerror(string("internal error resolving type ") + (yyvsp[(1) - (1)].u.identifier)->get_fully_scoped_name(), (yylsp[(1) - (1)])); - } - assert((yyval.u.type) != NULL); + (yyval.u.inst_ident) = (yyvsp[-6].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_pointer); + (yyval.u.inst_ident)->add_modifier(IIT_paren); + (yyval.u.inst_ident)->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), (yyvsp[0].u.type)); } +#line 5902 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 258: -/* Line 1792 of yacc.c */ -#line 1983 "dtool/src/cppparser/cppBison.yxx" +#line 2069 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[(2) - (2)].u.identifier))); + (yyval.u.inst_ident) = (yyvsp[-6].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_reference); + (yyval.u.inst_ident)->add_modifier(IIT_paren); + (yyval.u.inst_ident)->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), (yyvsp[0].u.type)); } +#line 5913 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 259: -/* Line 1792 of yacc.c */ -#line 1987 "dtool/src/cppparser/cppBison.yxx" +#line 2076 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = CPPType::new_type((yyvsp[(1) - (1)].u.struct_type)); + (yyval.u.inst_ident) = (yyvsp[-6].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference); + (yyval.u.inst_ident)->add_modifier(IIT_paren); + (yyval.u.inst_ident)->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), (yyvsp[0].u.type)); } +#line 5924 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 260: -/* Line 1792 of yacc.c */ -#line 1991 "dtool/src/cppparser/cppBison.yxx" +#line 2086 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = CPPType::new_type((yyvsp[(1) - (1)].u.struct_type)); + (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); } +#line 5932 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 261: -/* Line 1792 of yacc.c */ -#line 1995 "dtool/src/cppparser/cppBison.yxx" +#line 2090 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = CPPType::new_type((yyvsp[(1) - (1)].u.enum_type)); -} - break; - - case 262: -/* Line 1792 of yacc.c */ -#line 1999 "dtool/src/cppparser/cppBison.yxx" - { - CPPType *type = (yyvsp[(2) - (2)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != NULL) { - (yyval.u.type) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[(1) - (2)].u.extension_enum), (yyvsp[(2) - (2)].u.identifier), current_scope, (yylsp[(1) - (2)]).file)) - ->as_extension_type(); - CPPScope *scope = (yyvsp[(2) - (2)].u.identifier)->get_scope(current_scope, global_scope); - if (scope != NULL) { - scope->define_extension_type(et); - } - (yyval.u.type) = et; - } -} - break; - - case 263: -/* Line 1792 of yacc.c */ -#line 2015 "dtool/src/cppparser/cppBison.yxx" - { - CPPType *type = (yyvsp[(2) - (4)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != NULL) { - (yyval.u.type) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[(1) - (4)].u.extension_enum), (yyvsp[(2) - (4)].u.identifier), current_scope, (yylsp[(1) - (4)]).file)) - ->as_extension_type(); - CPPScope *scope = (yyvsp[(2) - (4)].u.identifier)->get_scope(current_scope, global_scope); - if (scope != NULL) { - scope->define_extension_type(et); - } - (yyval.u.type) = et; - } -} - break; - - case 264: -/* Line 1792 of yacc.c */ -#line 2031 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.type) = (yyvsp[(3) - (4)].u.expr)->determine_type(); - if ((yyval.u.type) == (CPPType *)NULL) { - stringstream str; - str << *(yyvsp[(3) - (4)].u.expr); - yyerror("could not determine type of " + str.str(), (yylsp[(3) - (4)])); - } -} - break; - - case 265: -/* Line 1792 of yacc.c */ -#line 2040 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} - break; - - case 266: -/* Line 1792 of yacc.c */ -#line 2047 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.decl) = CPPType::new_type((yyvsp[(1) - (1)].u.simple_type)); -} - break; - - case 267: -/* Line 1792 of yacc.c */ -#line 2051 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.decl) = (yyvsp[(1) - (1)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if ((yyval.u.decl) == NULL) { - yyerror(string("internal error resolving type ") + (yyvsp[(1) - (1)].u.identifier)->get_fully_scoped_name(), (yylsp[(1) - (1)])); - } - assert((yyval.u.decl) != NULL); -} - break; - - case 268: -/* Line 1792 of yacc.c */ -#line 2059 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.decl) = CPPType::new_type(new CPPTBDType((yyvsp[(2) - (2)].u.identifier))); -} - break; - - case 269: -/* Line 1792 of yacc.c */ -#line 2063 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.decl) = CPPType::new_type((yyvsp[(1) - (1)].u.struct_type)); -} - break; - - case 270: -/* Line 1792 of yacc.c */ -#line 2067 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.decl) = new CPPTypeDeclaration(CPPType::new_type((yyvsp[(1) - (1)].u.struct_type))); -} - break; - - case 271: -/* Line 1792 of yacc.c */ -#line 2071 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.decl) = new CPPTypeDeclaration(CPPType::new_type((yyvsp[(1) - (1)].u.enum_type))); -} - break; - - case 272: -/* Line 1792 of yacc.c */ -#line 2075 "dtool/src/cppparser/cppBison.yxx" - { - CPPType *type = (yyvsp[(2) - (2)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != NULL) { - (yyval.u.decl) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[(1) - (2)].u.extension_enum), (yyvsp[(2) - (2)].u.identifier), current_scope, (yylsp[(1) - (2)]).file)) - ->as_extension_type(); - CPPScope *scope = (yyvsp[(2) - (2)].u.identifier)->get_scope(current_scope, global_scope); - if (scope != NULL) { - scope->define_extension_type(et); - } - (yyval.u.decl) = et; - } -} - break; - - case 273: -/* Line 1792 of yacc.c */ -#line 2091 "dtool/src/cppparser/cppBison.yxx" - { - CPPType *type = (yyvsp[(2) - (4)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != NULL) { - (yyval.u.decl) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[(1) - (4)].u.extension_enum), (yyvsp[(2) - (4)].u.identifier), current_scope, (yylsp[(1) - (4)]).file)) - ->as_extension_type(); - CPPScope *scope = (yyvsp[(2) - (4)].u.identifier)->get_scope(current_scope, global_scope); - if (scope != NULL) { - scope->define_extension_type(et); - } - (yyval.u.decl) = et; - } -} - break; - - case 274: -/* Line 1792 of yacc.c */ -#line 2107 "dtool/src/cppparser/cppBison.yxx" - { - yywarning(string("C++ does not permit forward declaration of untyped enum ") + (yyvsp[(2) - (2)].u.identifier)->get_fully_scoped_name(), (yylsp[(1) - (2)])); - - CPPType *type = (yyvsp[(2) - (2)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != NULL) { - (yyval.u.decl) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[(1) - (2)].u.extension_enum), (yyvsp[(2) - (2)].u.identifier), current_scope, (yylsp[(1) - (2)]).file)) - ->as_extension_type(); - CPPScope *scope = (yyvsp[(2) - (2)].u.identifier)->get_scope(current_scope, global_scope); - if (scope != NULL) { - scope->define_extension_type(et); - } - (yyval.u.decl) = et; - } -} - break; - - case 275: -/* Line 1792 of yacc.c */ -#line 2125 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.decl) = (yyvsp[(3) - (4)].u.expr)->determine_type(); - if ((yyval.u.decl) == (CPPType *)NULL) { - stringstream str; - str << *(yyvsp[(3) - (4)].u.expr); - yyerror("could not determine type of " + str.str(), (yylsp[(3) - (4)])); - } -} - break; - - case 276: -/* Line 1792 of yacc.c */ -#line 2134 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} - break; - - case 277: -/* Line 1792 of yacc.c */ -#line 2141 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.type) = CPPType::new_type((yyvsp[(1) - (1)].u.simple_type)); -} - break; - - case 278: -/* Line 1792 of yacc.c */ -#line 2145 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.type) = (yyvsp[(1) - (1)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if ((yyval.u.type) == NULL) { - yyerror(string("internal error resolving type ") + (yyvsp[(1) - (1)].u.identifier)->get_fully_scoped_name(), (yylsp[(1) - (1)])); + yyerror(string("internal error resolving type ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); } assert((yyval.u.type) != NULL); } +#line 5944 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 279: -/* Line 1792 of yacc.c */ -#line 2153 "dtool/src/cppparser/cppBison.yxx" + case 262: +#line 2098 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[(2) - (2)].u.identifier))); + (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); } +#line 5952 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 280: -/* Line 1792 of yacc.c */ -#line 2157 "dtool/src/cppparser/cppBison.yxx" + case 263: +#line 2102 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *type = (yyvsp[(2) - (2)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + (yyval.u.type) = CPPType::new_type((yyvsp[0].u.struct_type)); +} +#line 5960 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 264: +#line 2106 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.type) = CPPType::new_type((yyvsp[0].u.struct_type)); +} +#line 5968 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 265: +#line 2110 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.type) = CPPType::new_type((yyvsp[0].u.enum_type)); +} +#line 5976 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 266: +#line 2114 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if (type != NULL) { (yyval.u.type) = type; } else { CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[(1) - (2)].u.extension_enum), (yyvsp[(2) - (2)].u.identifier), current_scope, (yylsp[(1) - (2)]).file)) + CPPType::new_type(new CPPExtensionType((yyvsp[-1].u.extension_enum), (yyvsp[0].u.identifier), current_scope, (yylsp[-1]).file)) ->as_extension_type(); - CPPScope *scope = (yyvsp[(2) - (2)].u.identifier)->get_scope(current_scope, global_scope); + CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope); if (scope != NULL) { scope->define_extension_type(et); } (yyval.u.type) = et; } } +#line 5996 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 281: -/* Line 1792 of yacc.c */ -#line 2173 "dtool/src/cppparser/cppBison.yxx" + case 267: +#line 2130 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *type = (yyvsp[(2) - (2)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + CPPType *type = (yyvsp[-2].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if (type != NULL) { (yyval.u.type) = type; } else { CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[(1) - (2)].u.extension_enum), (yyvsp[(2) - (2)].u.identifier), current_scope, (yylsp[(1) - (2)]).file)) + CPPType::new_type(new CPPExtensionType((yyvsp[-3].u.extension_enum), (yyvsp[-2].u.identifier), current_scope, (yylsp[-3]).file)) ->as_extension_type(); - CPPScope *scope = (yyvsp[(2) - (2)].u.identifier)->get_scope(current_scope, global_scope); + CPPScope *scope = (yyvsp[-2].u.identifier)->get_scope(current_scope, global_scope); if (scope != NULL) { scope->define_extension_type(et); } (yyval.u.type) = et; } } +#line 6016 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 282: -/* Line 1792 of yacc.c */ -#line 2189 "dtool/src/cppparser/cppBison.yxx" + case 268: +#line 2146 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = (yyvsp[(3) - (4)].u.expr)->determine_type(); + (yyval.u.type) = (yyvsp[-1].u.expr)->determine_type(); if ((yyval.u.type) == (CPPType *)NULL) { stringstream str; - str << *(yyvsp[(3) - (4)].u.expr); - yyerror("could not determine type of " + str.str(), (yylsp[(3) - (4)])); + str << *(yyvsp[-1].u.expr); + yyerror("could not determine type of " + str.str(), (yylsp[-1])); } } +#line 6029 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 283: -/* Line 1792 of yacc.c */ -#line 2198 "dtool/src/cppparser/cppBison.yxx" + case 269: +#line 2155 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); } +#line 6037 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 270: +#line 2162 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.decl) = CPPType::new_type((yyvsp[0].u.simple_type)); +} +#line 6045 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 271: +#line 2166 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.decl) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + if ((yyval.u.decl) == NULL) { + yyerror(string("internal error resolving type ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); + } + assert((yyval.u.decl) != NULL); +} +#line 6057 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 272: +#line 2174 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.decl) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); +} +#line 6065 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 273: +#line 2178 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.decl) = CPPType::new_type((yyvsp[0].u.struct_type)); +} +#line 6073 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 274: +#line 2182 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.decl) = new CPPTypeDeclaration(CPPType::new_type((yyvsp[0].u.struct_type))); +} +#line 6081 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 275: +#line 2186 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.decl) = new CPPTypeDeclaration(CPPType::new_type((yyvsp[0].u.enum_type))); +} +#line 6089 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 276: +#line 2190 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + if (type != NULL) { + (yyval.u.decl) = type; + } else { + CPPExtensionType *et = + CPPType::new_type(new CPPExtensionType((yyvsp[-1].u.extension_enum), (yyvsp[0].u.identifier), current_scope, (yylsp[-1]).file)) + ->as_extension_type(); + CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope); + if (scope != NULL) { + scope->define_extension_type(et); + } + (yyval.u.decl) = et; + } +} +#line 6109 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 277: +#line 2206 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPType *type = (yyvsp[-2].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + if (type != NULL) { + (yyval.u.decl) = type; + } else { + CPPExtensionType *et = + CPPType::new_type(new CPPExtensionType((yyvsp[-3].u.extension_enum), (yyvsp[-2].u.identifier), current_scope, (yylsp[-3]).file)) + ->as_extension_type(); + CPPScope *scope = (yyvsp[-2].u.identifier)->get_scope(current_scope, global_scope); + if (scope != NULL) { + scope->define_extension_type(et); + } + (yyval.u.decl) = et; + } +} +#line 6129 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 278: +#line 2222 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + yywarning(string("C++ does not permit forward declaration of untyped enum ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[-1])); + + CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + if (type != NULL) { + (yyval.u.decl) = type; + } else { + CPPExtensionType *et = + CPPType::new_type(new CPPExtensionType((yyvsp[-1].u.extension_enum), (yyvsp[0].u.identifier), current_scope, (yylsp[-1]).file)) + ->as_extension_type(); + CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope); + if (scope != NULL) { + scope->define_extension_type(et); + } + (yyval.u.decl) = et; + } +} +#line 6151 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 279: +#line 2240 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.decl) = (yyvsp[-1].u.expr)->determine_type(); + if ((yyval.u.decl) == (CPPType *)NULL) { + stringstream str; + str << *(yyvsp[-1].u.expr); + yyerror("could not determine type of " + str.str(), (yylsp[-1])); + } +} +#line 6164 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 280: +#line 2249 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); +} +#line 6172 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 281: +#line 2256 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); +} +#line 6180 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 282: +#line 2260 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + if ((yyval.u.type) == NULL) { + yyerror(string("internal error resolving type ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); + } + assert((yyval.u.type) != NULL); +} +#line 6192 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 283: +#line 2268 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); +} +#line 6200 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 284: -/* Line 1792 of yacc.c */ -#line 2205 "dtool/src/cppparser/cppBison.yxx" +#line 2272 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.decl) = (yyvsp[(1) - (1)].u.decl); + CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + if (type != NULL) { + (yyval.u.type) = type; + } else { + CPPExtensionType *et = + CPPType::new_type(new CPPExtensionType((yyvsp[-1].u.extension_enum), (yyvsp[0].u.identifier), current_scope, (yylsp[-1]).file)) + ->as_extension_type(); + CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope); + if (scope != NULL) { + scope->define_extension_type(et); + } + (yyval.u.type) = et; + } } +#line 6220 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 285: -/* Line 1792 of yacc.c */ -#line 2209 "dtool/src/cppparser/cppBison.yxx" +#line 2288 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - yyerror(string("unknown type '") + (yyvsp[(1) - (1)].u.identifier)->get_fully_scoped_name() + "'", (yylsp[(1) - (1)])); - - (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown)); + CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + if (type != NULL) { + (yyval.u.type) = type; + } else { + CPPExtensionType *et = + CPPType::new_type(new CPPExtensionType((yyvsp[-1].u.extension_enum), (yyvsp[0].u.identifier), current_scope, (yylsp[-1]).file)) + ->as_extension_type(); + CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope); + if (scope != NULL) { + scope->define_extension_type(et); + } + (yyval.u.type) = et; + } } +#line 6240 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 286: -/* Line 1792 of yacc.c */ -#line 2217 "dtool/src/cppparser/cppBison.yxx" +#line 2304 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = (yyvsp[(2) - (2)].u.inst_ident)->unroll_type((yyvsp[(1) - (2)].u.type)); + (yyval.u.type) = (yyvsp[-1].u.expr)->determine_type(); + if ((yyval.u.type) == (CPPType *)NULL) { + stringstream str; + str << *(yyvsp[-1].u.expr); + yyerror("could not determine type of " + str.str(), (yylsp[-1])); + } } +#line 6253 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 287: -/* Line 1792 of yacc.c */ -#line 2221 "dtool/src/cppparser/cppBison.yxx" +#line 2313 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyvsp[(3) - (3)].u.inst_ident)->add_modifier(IIT_const); - (yyval.u.type) = (yyvsp[(3) - (3)].u.inst_ident)->unroll_type((yyvsp[(2) - (3)].u.type)); + (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); } +#line 6261 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 288: -/* Line 1792 of yacc.c */ -#line 2229 "dtool/src/cppparser/cppBison.yxx" +#line 2320 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.decl) = (yyvsp[0].u.decl); +} +#line 6269 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 289: +#line 2324 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + yyerror(string("unknown type '") + (yyvsp[0].u.identifier)->get_fully_scoped_name() + "'", (yylsp[0])); + + (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown)); +} +#line 6279 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 290: +#line 2332 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); +} +#line 6287 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 291: +#line 2336 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyvsp[0].u.inst_ident)->add_modifier(IIT_const); + (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); +} +#line 6296 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 292: +#line 2344 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { CPPVisibility starting_vis = - ((yyvsp[(1) - (2)].u.extension_enum) == CPPExtensionType::T_class) ? V_private : V_public; + ((yyvsp[-1].u.extension_enum) == CPPExtensionType::T_class) ? V_private : V_public; CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("anon"), starting_vis); - CPPStructType *st = new CPPStructType((yyvsp[(1) - (2)].u.extension_enum), NULL, current_scope, - new_scope, (yylsp[(1) - (2)]).file); + CPPStructType *st = new CPPStructType((yyvsp[-1].u.extension_enum), NULL, current_scope, + new_scope, (yylsp[-1]).file); new_scope->set_struct_type(st); push_scope(new_scope); push_struct(st); } +#line 6314 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 289: -/* Line 1792 of yacc.c */ -#line 2243 "dtool/src/cppparser/cppBison.yxx" + case 293: +#line 2358 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.struct_type) = current_struct; current_struct->_incomplete = false; pop_struct(); pop_scope(); } +#line 6325 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 290: -/* Line 1792 of yacc.c */ -#line 2253 "dtool/src/cppparser/cppBison.yxx" + case 294: +#line 2368 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { CPPVisibility starting_vis = - ((yyvsp[(1) - (2)].u.extension_enum) == CPPExtensionType::T_class) ? V_private : V_public; + ((yyvsp[-1].u.extension_enum) == CPPExtensionType::T_class) ? V_private : V_public; - CPPScope *scope = (yyvsp[(2) - (2)].u.identifier)->get_scope(current_scope, global_scope, current_lexer); + CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope, current_lexer); if (scope == NULL) { scope = current_scope; } - CPPScope *new_scope = new CPPScope(scope, (yyvsp[(2) - (2)].u.identifier)->_names.back(), + CPPScope *new_scope = new CPPScope(scope, (yyvsp[0].u.identifier)->_names.back(), starting_vis); - CPPStructType *st = new CPPStructType((yyvsp[(1) - (2)].u.extension_enum), (yyvsp[(2) - (2)].u.identifier), current_scope, - new_scope, (yylsp[(1) - (2)]).file); + CPPStructType *st = new CPPStructType((yyvsp[-1].u.extension_enum), (yyvsp[0].u.identifier), current_scope, + new_scope, (yylsp[-1]).file); new_scope->set_struct_type(st); current_scope->define_extension_type(st); push_scope(new_scope); push_struct(st); } +#line 6349 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 291: -/* Line 1792 of yacc.c */ -#line 2273 "dtool/src/cppparser/cppBison.yxx" + case 295: +#line 2388 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.struct_type) = current_struct; current_struct->_incomplete = false; pop_struct(); pop_scope(); } +#line 6360 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 293: -/* Line 1792 of yacc.c */ -#line 2284 "dtool/src/cppparser/cppBison.yxx" + case 297: +#line 2399 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { current_struct->_final = true; } - break; - - case 298: -/* Line 1792 of yacc.c */ -#line 2301 "dtool/src/cppparser/cppBison.yxx" - { - current_struct->append_derivation((yyvsp[(1) - (1)].u.type), V_unknown, false); -} - break; - - case 299: -/* Line 1792 of yacc.c */ -#line 2305 "dtool/src/cppparser/cppBison.yxx" - { - current_struct->append_derivation((yyvsp[(2) - (2)].u.type), V_public, false); -} - break; - - case 300: -/* Line 1792 of yacc.c */ -#line 2309 "dtool/src/cppparser/cppBison.yxx" - { - current_struct->append_derivation((yyvsp[(2) - (2)].u.type), V_protected, false); -} - break; - - case 301: -/* Line 1792 of yacc.c */ -#line 2313 "dtool/src/cppparser/cppBison.yxx" - { - current_struct->append_derivation((yyvsp[(2) - (2)].u.type), V_private, false); -} +#line 6368 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 302: -/* Line 1792 of yacc.c */ -#line 2317 "dtool/src/cppparser/cppBison.yxx" +#line 2416 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - current_struct->append_derivation((yyvsp[(3) - (3)].u.type), V_public, true); + current_struct->append_derivation((yyvsp[0].u.type), V_unknown, false); } +#line 6376 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 303: -/* Line 1792 of yacc.c */ -#line 2321 "dtool/src/cppparser/cppBison.yxx" +#line 2420 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - current_struct->append_derivation((yyvsp[(3) - (3)].u.type), V_protected, true); + current_struct->append_derivation((yyvsp[0].u.type), V_public, false); } +#line 6384 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 304: -/* Line 1792 of yacc.c */ -#line 2325 "dtool/src/cppparser/cppBison.yxx" +#line 2424 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - current_struct->append_derivation((yyvsp[(3) - (3)].u.type), V_private, true); + current_struct->append_derivation((yyvsp[0].u.type), V_protected, false); } +#line 6392 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 305: -/* Line 1792 of yacc.c */ -#line 2329 "dtool/src/cppparser/cppBison.yxx" +#line 2428 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - current_struct->append_derivation((yyvsp[(3) - (3)].u.type), V_public, true); + current_struct->append_derivation((yyvsp[0].u.type), V_private, false); } +#line 6400 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 306: -/* Line 1792 of yacc.c */ -#line 2333 "dtool/src/cppparser/cppBison.yxx" +#line 2432 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - current_struct->append_derivation((yyvsp[(3) - (3)].u.type), V_protected, true); + current_struct->append_derivation((yyvsp[0].u.type), V_public, true); } +#line 6408 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 307: -/* Line 1792 of yacc.c */ -#line 2337 "dtool/src/cppparser/cppBison.yxx" +#line 2436 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - current_struct->append_derivation((yyvsp[(3) - (3)].u.type), V_private, true); + current_struct->append_derivation((yyvsp[0].u.type), V_protected, true); } +#line 6416 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 308: -/* Line 1792 of yacc.c */ -#line 2344 "dtool/src/cppparser/cppBison.yxx" +#line 2440 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + current_struct->append_derivation((yyvsp[0].u.type), V_private, true); +} +#line 6424 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 309: +#line 2444 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + current_struct->append_derivation((yyvsp[0].u.type), V_public, true); +} +#line 6432 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 310: +#line 2448 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + current_struct->append_derivation((yyvsp[0].u.type), V_protected, true); +} +#line 6440 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 311: +#line 2452 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + current_struct->append_derivation((yyvsp[0].u.type), V_private, true); +} +#line 6448 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 312: +#line 2459 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.enum_type) = current_enum; current_enum = NULL; } - break; - - case 309: -/* Line 1792 of yacc.c */ -#line 2352 "dtool/src/cppparser/cppBison.yxx" - { - current_enum = new CPPEnumType((yyvsp[(2) - (4)].u.identifier), (yyvsp[(4) - (4)].u.type), current_scope, (yylsp[(1) - (4)]).file); -} - break; - - case 310: -/* Line 1792 of yacc.c */ -#line 2356 "dtool/src/cppparser/cppBison.yxx" - { - current_enum = new CPPEnumType((yyvsp[(2) - (2)].u.identifier), current_scope, (yylsp[(1) - (2)]).file); -} - break; - - case 311: -/* Line 1792 of yacc.c */ -#line 2360 "dtool/src/cppparser/cppBison.yxx" - { - current_enum = new CPPEnumType(NULL, (yyvsp[(3) - (3)].u.type), current_scope, (yylsp[(1) - (3)]).file); -} - break; - - case 312: -/* Line 1792 of yacc.c */ -#line 2364 "dtool/src/cppparser/cppBison.yxx" - { - current_enum = new CPPEnumType(NULL, current_scope, (yylsp[(1) - (1)]).file); -} +#line 6457 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 313: -/* Line 1792 of yacc.c */ -#line 2371 "dtool/src/cppparser/cppBison.yxx" +#line 2467 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = CPPType::new_type((yyvsp[(1) - (1)].u.simple_type)); + current_enum = new CPPEnumType((yyvsp[-2].u.extension_enum), NULL, (yyvsp[0].u.type), current_scope, NULL, (yylsp[-2]).file); } +#line 6465 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 314: -/* Line 1792 of yacc.c */ -#line 2375 "dtool/src/cppparser/cppBison.yxx" +#line 2471 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = (yyvsp[(1) - (1)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + current_enum = new CPPEnumType((yyvsp[0].u.extension_enum), NULL, current_scope, NULL, (yylsp[0]).file); } +#line 6473 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 315: +#line 2475 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPScope *new_scope = new CPPScope(current_scope, (yyvsp[-2].u.identifier)->_names.back(), V_public); + current_enum = new CPPEnumType((yyvsp[-3].u.extension_enum), (yyvsp[-2].u.identifier), (yyvsp[0].u.type), current_scope, new_scope, (yylsp[-3]).file); +} +#line 6482 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 316: -/* Line 1792 of yacc.c */ -#line 2383 "dtool/src/cppparser/cppBison.yxx" +#line 2480 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - assert(current_enum != NULL); - CPPInstance *inst = current_enum->add_element((yyvsp[(2) - (3)].u.identifier)->get_simple_name()); - current_scope->add_enum_value(inst, current_lexer, (yylsp[(2) - (3)])); + CPPScope *new_scope = new CPPScope(current_scope, (yyvsp[0].u.identifier)->_names.back(), V_public); + current_enum = new CPPEnumType((yyvsp[-1].u.extension_enum), (yyvsp[0].u.identifier), current_scope, new_scope, (yylsp[-1]).file); } +#line 6491 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 317: -/* Line 1792 of yacc.c */ -#line 2389 "dtool/src/cppparser/cppBison.yxx" +#line 2488 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - assert(current_enum != NULL); - CPPInstance *inst = current_enum->add_element((yyvsp[(2) - (5)].u.identifier)->get_simple_name(), (yyvsp[(4) - (5)].u.expr)); - current_scope->add_enum_value(inst, current_lexer, (yylsp[(2) - (5)])); + (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); } +#line 6499 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 319: -/* Line 1792 of yacc.c */ -#line 2398 "dtool/src/cppparser/cppBison.yxx" + case 318: +#line 2492 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - assert(current_enum != NULL); - CPPInstance *inst = current_enum->add_element((yyvsp[(2) - (2)].u.identifier)->get_simple_name()); - current_scope->add_enum_value(inst, current_lexer, (yylsp[(2) - (2)])); + (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); } +#line 6507 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 320: -/* Line 1792 of yacc.c */ -#line 2404 "dtool/src/cppparser/cppBison.yxx" +#line 2500 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { assert(current_enum != NULL); - CPPInstance *inst = current_enum->add_element((yyvsp[(2) - (4)].u.identifier)->get_simple_name(), (yyvsp[(4) - (4)].u.expr)); - current_scope->add_enum_value(inst, current_lexer, (yylsp[(2) - (4)])); + current_enum->add_element((yyvsp[-1].u.identifier)->get_simple_name(), NULL, current_lexer, (yylsp[-1])); } +#line 6516 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 321: -/* Line 1792 of yacc.c */ -#line 2413 "dtool/src/cppparser/cppBison.yxx" +#line 2505 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.extension_enum) = CPPExtensionType::T_enum; -} - break; - - case 322: -/* Line 1792 of yacc.c */ -#line 2420 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.extension_enum) = CPPExtensionType::T_class; + assert(current_enum != NULL); + current_enum->add_element((yyvsp[-3].u.identifier)->get_simple_name(), (yyvsp[-1].u.expr), current_lexer, (yylsp[-3])); } +#line 6525 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 323: -/* Line 1792 of yacc.c */ -#line 2424 "dtool/src/cppparser/cppBison.yxx" +#line 2513 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.extension_enum) = CPPExtensionType::T_struct; + assert(current_enum != NULL); + current_enum->add_element((yyvsp[0].u.identifier)->get_simple_name(), NULL, current_lexer, (yylsp[0])); } +#line 6534 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 324: -/* Line 1792 of yacc.c */ -#line 2428 "dtool/src/cppparser/cppBison.yxx" +#line 2518 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.extension_enum) = CPPExtensionType::T_union; + assert(current_enum != NULL); + current_enum->add_element((yyvsp[-2].u.identifier)->get_simple_name(), (yyvsp[0].u.expr), current_lexer, (yylsp[-2])); } +#line 6543 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 325: -/* Line 1792 of yacc.c */ -#line 2435 "dtool/src/cppparser/cppBison.yxx" +#line 2526 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPScope *scope = (yyvsp[(2) - (3)].u.identifier)->find_scope(current_scope, global_scope, current_lexer); - if (scope == NULL) { - // This must be a new namespace declaration. - CPPScope *parent_scope = - (yyvsp[(2) - (3)].u.identifier)->get_scope(current_scope, global_scope, current_lexer); - if (parent_scope == NULL) { - parent_scope = current_scope; - } - scope = new CPPScope(parent_scope, (yyvsp[(2) - (3)].u.identifier)->_names.back(), V_public); - } - - CPPNamespace *nspace = new CPPNamespace((yyvsp[(2) - (3)].u.identifier), scope, (yylsp[(1) - (3)]).file); - current_scope->add_declaration(nspace, global_scope, current_lexer, (yylsp[(1) - (3)])); - current_scope->define_namespace(nspace); - push_scope(scope); + (yyval.u.extension_enum) = CPPExtensionType::T_enum; } +#line 6551 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 326: -/* Line 1792 of yacc.c */ -#line 2453 "dtool/src/cppparser/cppBison.yxx" +#line 2530 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - pop_scope(); + (yyval.u.extension_enum) = CPPExtensionType::T_enum_class; } +#line 6559 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 327: -/* Line 1792 of yacc.c */ -#line 2457 "dtool/src/cppparser/cppBison.yxx" +#line 2534 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPScope *scope = (yyvsp[(3) - (4)].u.identifier)->find_scope(current_scope, global_scope, current_lexer); - if (scope == NULL) { - // This must be a new namespace declaration. - CPPScope *parent_scope = - (yyvsp[(3) - (4)].u.identifier)->get_scope(current_scope, global_scope, current_lexer); - if (parent_scope == NULL) { - parent_scope = current_scope; - } - scope = new CPPScope(parent_scope, (yyvsp[(3) - (4)].u.identifier)->_names.back(), V_public); - } - - CPPNamespace *nspace = new CPPNamespace((yyvsp[(3) - (4)].u.identifier), scope, (yylsp[(2) - (4)]).file); - nspace->_is_inline = true; - current_scope->add_declaration(nspace, global_scope, current_lexer, (yylsp[(2) - (4)])); - current_scope->define_namespace(nspace); - push_scope(scope); + (yyval.u.extension_enum) = CPPExtensionType::T_enum_struct; } +#line 6567 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 328: -/* Line 1792 of yacc.c */ -#line 2476 "dtool/src/cppparser/cppBison.yxx" +#line 2541 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - pop_scope(); + (yyval.u.extension_enum) = CPPExtensionType::T_class; } +#line 6575 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 329: +#line 2545 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.extension_enum) = CPPExtensionType::T_struct; +} +#line 6583 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 330: +#line 2549 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.extension_enum) = CPPExtensionType::T_union; +} +#line 6591 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 331: -/* Line 1792 of yacc.c */ -#line 2485 "dtool/src/cppparser/cppBison.yxx" +#line 2556 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPUsing *using_decl = new CPPUsing((yyvsp[(2) - (3)].u.identifier), false, (yylsp[(1) - (3)]).file); - current_scope->add_declaration(using_decl, global_scope, current_lexer, (yylsp[(1) - (3)])); - current_scope->add_using(using_decl, global_scope, current_lexer); + CPPScope *scope = (yyvsp[-1].u.identifier)->find_scope(current_scope, global_scope, current_lexer); + if (scope == NULL) { + // This must be a new namespace declaration. + CPPScope *parent_scope = + (yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope, current_lexer); + if (parent_scope == NULL) { + parent_scope = current_scope; + } + scope = new CPPScope(parent_scope, (yyvsp[-1].u.identifier)->_names.back(), V_public); + } + + CPPNamespace *nspace = new CPPNamespace((yyvsp[-1].u.identifier), scope, (yylsp[-2]).file); + current_scope->add_declaration(nspace, global_scope, current_lexer, (yylsp[-2])); + current_scope->define_namespace(nspace); + push_scope(scope); } +#line 6613 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 332: -/* Line 1792 of yacc.c */ -#line 2491 "dtool/src/cppparser/cppBison.yxx" +#line 2574 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - // This is really just an alternative way to declare a typedef. - CPPTypedefType *typedef_type = new CPPTypedefType((yyvsp[(4) - (5)].u.type), (yyvsp[(2) - (5)].u.identifier), current_scope); - typedef_type->_using = true; - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[(1) - (5)])); + pop_scope(); } +#line 6621 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 333: -/* Line 1792 of yacc.c */ -#line 2498 "dtool/src/cppparser/cppBison.yxx" +#line 2578 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPUsing *using_decl = new CPPUsing((yyvsp[(3) - (4)].u.identifier), true, (yylsp[(1) - (4)]).file); - current_scope->add_declaration(using_decl, global_scope, current_lexer, (yylsp[(1) - (4)])); - current_scope->add_using(using_decl, global_scope, current_lexer); + CPPScope *scope = (yyvsp[-1].u.identifier)->find_scope(current_scope, global_scope, current_lexer); + if (scope == NULL) { + // This must be a new namespace declaration. + CPPScope *parent_scope = + (yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope, current_lexer); + if (parent_scope == NULL) { + parent_scope = current_scope; + } + scope = new CPPScope(parent_scope, (yyvsp[-1].u.identifier)->_names.back(), V_public); + } + + CPPNamespace *nspace = new CPPNamespace((yyvsp[-1].u.identifier), scope, (yylsp[-2]).file); + nspace->_is_inline = true; + current_scope->add_declaration(nspace, global_scope, current_lexer, (yylsp[-2])); + current_scope->define_namespace(nspace); + push_scope(scope); } +#line 6644 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 334: +#line 2597 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + pop_scope(); +} +#line 6652 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 337: -/* Line 1792 of yacc.c */ -#line 2513 "dtool/src/cppparser/cppBison.yxx" +#line 2606 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_bool); + CPPUsing *using_decl = new CPPUsing((yyvsp[-1].u.identifier), false, (yylsp[-2]).file); + current_scope->add_declaration(using_decl, global_scope, current_lexer, (yylsp[-2])); + current_scope->add_using(using_decl, global_scope, current_lexer); } +#line 6662 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 338: -/* Line 1792 of yacc.c */ -#line 2517 "dtool/src/cppparser/cppBison.yxx" +#line 2612 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char); + // This is really just an alternative way to declare a typedef. + CPPTypedefType *typedef_type = new CPPTypedefType((yyvsp[-1].u.type), (yyvsp[-3].u.identifier), current_scope); + typedef_type->_using = true; + current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-4])); } +#line 6673 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 339: -/* Line 1792 of yacc.c */ -#line 2521 "dtool/src/cppparser/cppBison.yxx" +#line 2619 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPUsing *using_decl = new CPPUsing((yyvsp[-1].u.identifier), true, (yylsp[-3]).file); + current_scope->add_declaration(using_decl, global_scope, current_lexer, (yylsp[-3])); + current_scope->add_using(using_decl, global_scope, current_lexer); +} +#line 6683 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 343: +#line 2634 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_bool); +} +#line 6691 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 344: +#line 2638 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char); +} +#line 6699 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 345: +#line 2642 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_wchar_t); } +#line 6707 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 340: -/* Line 1792 of yacc.c */ -#line 2525 "dtool/src/cppparser/cppBison.yxx" + case 346: +#line 2646 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char16_t); } +#line 6715 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 341: -/* Line 1792 of yacc.c */ -#line 2529 "dtool/src/cppparser/cppBison.yxx" + case 347: +#line 2650 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char32_t); } +#line 6723 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 342: -/* Line 1792 of yacc.c */ -#line 2533 "dtool/src/cppparser/cppBison.yxx" + case 348: +#line 2654 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_short); } +#line 6732 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 343: -/* Line 1792 of yacc.c */ -#line 2538 "dtool/src/cppparser/cppBison.yxx" + case 349: +#line 2659 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_long); } +#line 6741 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 344: -/* Line 1792 of yacc.c */ -#line 2543 "dtool/src/cppparser/cppBison.yxx" + case 350: +#line 2664 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_unsigned); } +#line 6750 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 345: -/* Line 1792 of yacc.c */ -#line 2548 "dtool/src/cppparser/cppBison.yxx" + case 351: +#line 2669 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_signed); } +#line 6759 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 346: -/* Line 1792 of yacc.c */ -#line 2553 "dtool/src/cppparser/cppBison.yxx" + case 352: +#line 2674 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int); } +#line 6767 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 347: -/* Line 1792 of yacc.c */ -#line 2557 "dtool/src/cppparser/cppBison.yxx" + case 353: +#line 2678 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.simple_type) = (yyvsp[(2) - (2)].u.simple_type); + (yyval.u.simple_type) = (yyvsp[0].u.simple_type); (yyval.u.simple_type)->_flags |= CPPSimpleType::F_short; } +#line 6776 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 348: -/* Line 1792 of yacc.c */ -#line 2562 "dtool/src/cppparser/cppBison.yxx" + case 354: +#line 2683 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.simple_type) = (yyvsp[(2) - (2)].u.simple_type); + (yyval.u.simple_type) = (yyvsp[0].u.simple_type); if ((yyval.u.simple_type)->_flags & CPPSimpleType::F_long) { (yyval.u.simple_type)->_flags |= CPPSimpleType::F_longlong; } else { (yyval.u.simple_type)->_flags |= CPPSimpleType::F_long; } } +#line 6789 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 349: -/* Line 1792 of yacc.c */ -#line 2571 "dtool/src/cppparser/cppBison.yxx" + case 355: +#line 2692 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.simple_type) = (yyvsp[(2) - (2)].u.simple_type); + (yyval.u.simple_type) = (yyvsp[0].u.simple_type); (yyval.u.simple_type)->_flags |= CPPSimpleType::F_unsigned; } +#line 6798 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 350: -/* Line 1792 of yacc.c */ -#line 2576 "dtool/src/cppparser/cppBison.yxx" + case 356: +#line 2697 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.simple_type) = (yyvsp[(2) - (2)].u.simple_type); + (yyval.u.simple_type) = (yyvsp[0].u.simple_type); (yyval.u.simple_type)->_flags |= CPPSimpleType::F_signed; } +#line 6807 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 351: -/* Line 1792 of yacc.c */ -#line 2584 "dtool/src/cppparser/cppBison.yxx" + case 357: +#line 2705 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_float); } +#line 6815 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 352: -/* Line 1792 of yacc.c */ -#line 2588 "dtool/src/cppparser/cppBison.yxx" + case 358: +#line 2709 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_double); } +#line 6823 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 353: -/* Line 1792 of yacc.c */ -#line 2592 "dtool/src/cppparser/cppBison.yxx" + case 359: +#line 2713 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_double, CPPSimpleType::F_long); } +#line 6832 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 354: -/* Line 1792 of yacc.c */ -#line 2600 "dtool/src/cppparser/cppBison.yxx" + case 360: +#line 2721 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_void); } +#line 6840 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 355: -/* Line 1792 of yacc.c */ -#line 2609 "dtool/src/cppparser/cppBison.yxx" + case 361: +#line 2730 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { current_lexer->_resolve_identifiers = false; } +#line 6848 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 356: -/* Line 1792 of yacc.c */ -#line 2613 "dtool/src/cppparser/cppBison.yxx" + case 362: +#line 2734 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { current_lexer->_resolve_identifiers = true; } +#line 6856 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 459: -/* Line 1792 of yacc.c */ -#line 2654 "dtool/src/cppparser/cppBison.yxx" + case 465: +#line 2775 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { } - break; - - case 483: -/* Line 1792 of yacc.c */ -#line 2663 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = (CPPExpression *)NULL; -} - break; - - case 484: -/* Line 1792 of yacc.c */ -#line 2667 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = (yyvsp[(1) - (1)].u.expr); -} - break; - - case 485: -/* Line 1792 of yacc.c */ -#line 2674 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = (CPPExpression *)NULL; -} - break; - - case 486: -/* Line 1792 of yacc.c */ -#line 2678 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = (yyvsp[(1) - (1)].u.expr); -} - break; - - case 487: -/* Line 1792 of yacc.c */ -#line 2685 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = (yyvsp[(1) - (1)].u.expr); -} - break; - - case 488: -/* Line 1792 of yacc.c */ -#line 2689 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(',', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} +#line 6863 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 489: -/* Line 1792 of yacc.c */ -#line 2696 "dtool/src/cppparser/cppBison.yxx" +#line 2784 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (yyvsp[(1) - (1)].u.expr); + (yyval.u.expr) = (CPPExpression *)NULL; } +#line 6871 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 490: -/* Line 1792 of yacc.c */ -#line 2700 "dtool/src/cppparser/cppBison.yxx" +#line 2788 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(2) - (4)].u.type), (yyvsp[(4) - (4)].u.expr))); + (yyval.u.expr) = (yyvsp[0].u.expr); } +#line 6879 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 491: -/* Line 1792 of yacc.c */ -#line 2704 "dtool/src/cppparser/cppBison.yxx" +#line 2795 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_static_cast)); + (yyval.u.expr) = (CPPExpression *)NULL; } +#line 6887 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 492: -/* Line 1792 of yacc.c */ -#line 2708 "dtool/src/cppparser/cppBison.yxx" +#line 2799 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_dynamic_cast)); + (yyval.u.expr) = (yyvsp[0].u.expr); } +#line 6895 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 493: -/* Line 1792 of yacc.c */ -#line 2712 "dtool/src/cppparser/cppBison.yxx" +#line 2806 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_const_cast)); + (yyval.u.expr) = (yyvsp[0].u.expr); } +#line 6903 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 494: -/* Line 1792 of yacc.c */ -#line 2716 "dtool/src/cppparser/cppBison.yxx" +#line 2810 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_reinterpret_cast)); + (yyval.u.expr) = new CPPExpression(',', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 6911 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 495: -/* Line 1792 of yacc.c */ -#line 2720 "dtool/src/cppparser/cppBison.yxx" +#line 2817 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[(3) - (4)].u.type))); + (yyval.u.expr) = (yyvsp[0].u.expr); } +#line 6919 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 496: -/* Line 1792 of yacc.c */ -#line 2724 "dtool/src/cppparser/cppBison.yxx" +#line 2821 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[(3) - (4)].u.type))); + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-2].u.type), (yyvsp[0].u.expr))); } +#line 6927 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 497: -/* Line 1792 of yacc.c */ -#line 2728 "dtool/src/cppparser/cppBison.yxx" +#line 2825 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[(2) - (2)].u.expr)); + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_static_cast)); } +#line 6935 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 498: -/* Line 1792 of yacc.c */ -#line 2732 "dtool/src/cppparser/cppBison.yxx" +#line 2829 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[(2) - (2)].u.expr)); + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_dynamic_cast)); } +#line 6943 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 499: -/* Line 1792 of yacc.c */ -#line 2736 "dtool/src/cppparser/cppBison.yxx" +#line 2833 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[(2) - (2)].u.expr)); + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_const_cast)); } +#line 6951 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 500: -/* Line 1792 of yacc.c */ -#line 2740 "dtool/src/cppparser/cppBison.yxx" +#line 2837 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[(2) - (2)].u.expr)); + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_reinterpret_cast)); } +#line 6959 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 501: -/* Line 1792 of yacc.c */ -#line 2744 "dtool/src/cppparser/cppBison.yxx" +#line 2841 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_STAR, (yyvsp[(2) - (2)].u.expr)); + (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[-1].u.type))); } +#line 6967 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 502: -/* Line 1792 of yacc.c */ -#line 2748 "dtool/src/cppparser/cppBison.yxx" +#line 2845 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[(2) - (2)].u.expr)); + (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[-1].u.type))); } +#line 6975 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 503: -/* Line 1792 of yacc.c */ -#line 2752 "dtool/src/cppparser/cppBison.yxx" +#line 2849 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('*', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[0].u.expr)); } +#line 6983 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 504: -/* Line 1792 of yacc.c */ -#line 2756 "dtool/src/cppparser/cppBison.yxx" +#line 2853 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('/', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[0].u.expr)); } +#line 6991 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 505: -/* Line 1792 of yacc.c */ -#line 2760 "dtool/src/cppparser/cppBison.yxx" +#line 2857 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('%', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[0].u.expr)); } +#line 6999 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 506: -/* Line 1792 of yacc.c */ -#line 2764 "dtool/src/cppparser/cppBison.yxx" +#line 2861 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('+', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[0].u.expr)); } +#line 7007 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 507: -/* Line 1792 of yacc.c */ -#line 2768 "dtool/src/cppparser/cppBison.yxx" +#line 2865 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('-', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_STAR, (yyvsp[0].u.expr)); } +#line 7015 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 508: -/* Line 1792 of yacc.c */ -#line 2772 "dtool/src/cppparser/cppBison.yxx" +#line 2869 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('|', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[0].u.expr)); } +#line 7023 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 509: -/* Line 1792 of yacc.c */ -#line 2776 "dtool/src/cppparser/cppBison.yxx" +#line 2873 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('^', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('*', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7031 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 510: -/* Line 1792 of yacc.c */ -#line 2780 "dtool/src/cppparser/cppBison.yxx" +#line 2877 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('&', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('/', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7039 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 511: -/* Line 1792 of yacc.c */ -#line 2784 "dtool/src/cppparser/cppBison.yxx" +#line 2881 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('%', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7047 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 512: -/* Line 1792 of yacc.c */ -#line 2788 "dtool/src/cppparser/cppBison.yxx" +#line 2885 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('+', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7055 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 513: -/* Line 1792 of yacc.c */ -#line 2792 "dtool/src/cppparser/cppBison.yxx" +#line 2889 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('-', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7063 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 514: -/* Line 1792 of yacc.c */ -#line 2796 "dtool/src/cppparser/cppBison.yxx" +#line 2893 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('|', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7071 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 515: -/* Line 1792 of yacc.c */ -#line 2800 "dtool/src/cppparser/cppBison.yxx" +#line 2897 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('^', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7079 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 516: -/* Line 1792 of yacc.c */ -#line 2804 "dtool/src/cppparser/cppBison.yxx" +#line 2901 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('&', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7087 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 517: -/* Line 1792 of yacc.c */ -#line 2808 "dtool/src/cppparser/cppBison.yxx" +#line 2905 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7095 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 518: -/* Line 1792 of yacc.c */ -#line 2812 "dtool/src/cppparser/cppBison.yxx" +#line 2909 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7103 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 519: -/* Line 1792 of yacc.c */ -#line 2816 "dtool/src/cppparser/cppBison.yxx" +#line 2913 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('?', (yyvsp[(1) - (5)].u.expr), (yyvsp[(3) - (5)].u.expr), (yyvsp[(5) - (5)].u.expr)); + (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7111 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 520: -/* Line 1792 of yacc.c */ -#line 2820 "dtool/src/cppparser/cppBison.yxx" +#line 2917 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('[', (yyvsp[(1) - (4)].u.expr), (yyvsp[(3) - (4)].u.expr)); + (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7119 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 521: -/* Line 1792 of yacc.c */ -#line 2824 "dtool/src/cppparser/cppBison.yxx" +#line 2921 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('f', (yyvsp[(1) - (4)].u.expr), (yyvsp[(3) - (4)].u.expr)); + (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7127 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 522: -/* Line 1792 of yacc.c */ -#line 2828 "dtool/src/cppparser/cppBison.yxx" +#line 2925 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('f', (yyvsp[(1) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7135 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 523: -/* Line 1792 of yacc.c */ -#line 2832 "dtool/src/cppparser/cppBison.yxx" +#line 2929 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('.', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7143 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 524: -/* Line 1792 of yacc.c */ -#line 2836 "dtool/src/cppparser/cppBison.yxx" +#line 2933 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7151 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 525: -/* Line 1792 of yacc.c */ -#line 2840 "dtool/src/cppparser/cppBison.yxx" +#line 2937 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (yyvsp[(2) - (3)].u.expr); + (yyval.u.expr) = new CPPExpression('?', (yyvsp[-4].u.expr), (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7159 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 526: -/* Line 1792 of yacc.c */ -#line 2848 "dtool/src/cppparser/cppBison.yxx" +#line 2941 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (yyvsp[(1) - (1)].u.expr); + (yyval.u.expr) = new CPPExpression('[', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); } +#line 7167 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 527: -/* Line 1792 of yacc.c */ -#line 2852 "dtool/src/cppparser/cppBison.yxx" +#line 2945 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(2) - (4)].u.type), (yyvsp[(4) - (4)].u.expr))); + (yyval.u.expr) = new CPPExpression('f', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); } +#line 7175 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 528: -/* Line 1792 of yacc.c */ -#line 2856 "dtool/src/cppparser/cppBison.yxx" +#line 2949 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_static_cast)); + (yyval.u.expr) = new CPPExpression('f', (yyvsp[-2].u.expr)); } +#line 7183 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 529: -/* Line 1792 of yacc.c */ -#line 2860 "dtool/src/cppparser/cppBison.yxx" +#line 2953 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_dynamic_cast)); + (yyval.u.expr) = new CPPExpression('.', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7191 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 530: -/* Line 1792 of yacc.c */ -#line 2864 "dtool/src/cppparser/cppBison.yxx" +#line 2957 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_const_cast)); + (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7199 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 531: -/* Line 1792 of yacc.c */ -#line 2868 "dtool/src/cppparser/cppBison.yxx" +#line 2961 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_reinterpret_cast)); + (yyval.u.expr) = (yyvsp[-1].u.expr); } +#line 7207 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 532: -/* Line 1792 of yacc.c */ -#line 2872 "dtool/src/cppparser/cppBison.yxx" +#line 2969 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - // A constructor call. - CPPType *type = (yyvsp[(1) - (4)].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type == NULL) { - yyerror(string("internal error resolving type ") + (yyvsp[(1) - (4)].u.identifier)->get_fully_scoped_name(), (yylsp[(1) - (4)])); - } - assert(type != NULL); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); + (yyval.u.expr) = (yyvsp[0].u.expr); } +#line 7215 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 533: -/* Line 1792 of yacc.c */ -#line 2882 "dtool/src/cppparser/cppBison.yxx" +#line 2973 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-2].u.type), (yyvsp[0].u.expr))); } +#line 7223 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 534: -/* Line 1792 of yacc.c */ -#line 2888 "dtool/src/cppparser/cppBison.yxx" +#line 2977 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_static_cast)); } +#line 7231 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 535: -/* Line 1792 of yacc.c */ -#line 2894 "dtool/src/cppparser/cppBison.yxx" +#line 2981 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_wchar_t)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_dynamic_cast)); } +#line 7239 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 536: -/* Line 1792 of yacc.c */ -#line 2900 "dtool/src/cppparser/cppBison.yxx" +#line 2985 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char16_t)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_const_cast)); } +#line 7247 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 537: -/* Line 1792 of yacc.c */ -#line 2906 "dtool/src/cppparser/cppBison.yxx" +#line 2989 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char32_t)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_reinterpret_cast)); } +#line 7255 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 538: -/* Line 1792 of yacc.c */ -#line 2912 "dtool/src/cppparser/cppBison.yxx" +#line 2993 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); + // A constructor call. + CPPType *type = (yyvsp[-3].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); + if (type == NULL) { + yyerror(string("internal error resolving type ") + (yyvsp[-3].u.identifier)->get_fully_scoped_name(), (yylsp[-3])); + } + assert(type != NULL); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } +#line 7269 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 539: -/* Line 1792 of yacc.c */ -#line 2918 "dtool/src/cppparser/cppBison.yxx" +#line 3003 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPType *type = + CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int)); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); +} +#line 7279 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 540: +#line 3009 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPType *type = + CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char)); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); +} +#line 7289 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 541: +#line 3015 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPType *type = + CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_wchar_t)); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); +} +#line 7299 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 542: +#line 3021 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPType *type = + CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char16_t)); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); +} +#line 7309 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 543: +#line 3027 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPType *type = + CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char32_t)); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); +} +#line 7319 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 544: +#line 3033 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPType *type = + CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool)); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); +} +#line 7329 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 545: +#line 3039 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_short)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } +#line 7340 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 540: -/* Line 1792 of yacc.c */ -#line 2925 "dtool/src/cppparser/cppBison.yxx" + case 546: +#line 3046 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_long)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } +#line 7351 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 541: -/* Line 1792 of yacc.c */ -#line 2932 "dtool/src/cppparser/cppBison.yxx" + case 547: +#line 3053 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_unsigned)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } +#line 7362 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 542: -/* Line 1792 of yacc.c */ -#line 2939 "dtool/src/cppparser/cppBison.yxx" + case 548: +#line 3060 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_signed)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); -} - break; - - case 543: -/* Line 1792 of yacc.c */ -#line 2946 "dtool/src/cppparser/cppBison.yxx" - { - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_float)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); -} - break; - - case 544: -/* Line 1792 of yacc.c */ -#line 2952 "dtool/src/cppparser/cppBison.yxx" - { - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[(3) - (4)].u.expr))); -} - break; - - case 545: -/* Line 1792 of yacc.c */ -#line 2958 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[(3) - (4)].u.type))); -} - break; - - case 546: -/* Line 1792 of yacc.c */ -#line 2962 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[(3) - (4)].u.type))); -} - break; - - case 547: -/* Line 1792 of yacc.c */ -#line 2966 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[(2) - (2)].u.type))); -} - break; - - case 548: -/* Line 1792 of yacc.c */ -#line 2970 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[(2) - (5)].u.type), (yyvsp[(4) - (5)].u.expr))); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } +#line 7373 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 549: -/* Line 1792 of yacc.c */ -#line 2974 "dtool/src/cppparser/cppBison.yxx" +#line 3067 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", (yylsp[(1) - (4)])); - } - (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[(3) - (4)].u.type), std_type_info)); + CPPType *type = + CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_float)); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } +#line 7383 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 550: -/* Line 1792 of yacc.c */ -#line 2985 "dtool/src/cppparser/cppBison.yxx" +#line 3073 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", (yylsp[(1) - (4)])); - } - (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[(3) - (4)].u.expr), std_type_info)); + CPPType *type = + CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double)); + (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } +#line 7393 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 551: -/* Line 1792 of yacc.c */ -#line 2996 "dtool/src/cppparser/cppBison.yxx" +#line 3079 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[(2) - (2)].u.expr)); + (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[-1].u.type))); } +#line 7401 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 552: -/* Line 1792 of yacc.c */ -#line 3000 "dtool/src/cppparser/cppBison.yxx" +#line 3083 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[(2) - (2)].u.expr)); + (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[-1].u.type))); } +#line 7409 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 553: -/* Line 1792 of yacc.c */ -#line 3004 "dtool/src/cppparser/cppBison.yxx" +#line 3087 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[(2) - (2)].u.expr)); + (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[0].u.type))); } +#line 7417 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 554: -/* Line 1792 of yacc.c */ -#line 3008 "dtool/src/cppparser/cppBison.yxx" +#line 3091 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[(2) - (2)].u.expr)); + (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[-3].u.type), (yyvsp[-1].u.expr))); } +#line 7425 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 555: -/* Line 1792 of yacc.c */ -#line 3012 "dtool/src/cppparser/cppBison.yxx" +#line 3095 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_STAR, (yyvsp[(2) - (2)].u.expr)); + CPPIdentifier ident(""); + ident.add_name("std"); + ident.add_name("type_info"); + CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); + if (!std_type_info) { + yywarning("cannot use typeid before including ", (yylsp[-3])); + } + (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.type), std_type_info)); } +#line 7440 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 556: -/* Line 1792 of yacc.c */ -#line 3016 "dtool/src/cppparser/cppBison.yxx" +#line 3106 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[(2) - (2)].u.expr)); + CPPIdentifier ident(""); + ident.add_name("std"); + ident.add_name("type_info"); + CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); + if (!std_type_info) { + yywarning("cannot use typeid before including ", (yylsp[-3])); + } + (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.expr), std_type_info)); } +#line 7455 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 557: -/* Line 1792 of yacc.c */ -#line 3020 "dtool/src/cppparser/cppBison.yxx" +#line 3117 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('*', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[0].u.expr)); } +#line 7463 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 558: -/* Line 1792 of yacc.c */ -#line 3024 "dtool/src/cppparser/cppBison.yxx" +#line 3121 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('/', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[0].u.expr)); } +#line 7471 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 559: -/* Line 1792 of yacc.c */ -#line 3028 "dtool/src/cppparser/cppBison.yxx" +#line 3125 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('%', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[0].u.expr)); } +#line 7479 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 560: -/* Line 1792 of yacc.c */ -#line 3032 "dtool/src/cppparser/cppBison.yxx" +#line 3129 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('+', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[0].u.expr)); } +#line 7487 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 561: -/* Line 1792 of yacc.c */ -#line 3036 "dtool/src/cppparser/cppBison.yxx" +#line 3133 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('-', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_STAR, (yyvsp[0].u.expr)); } +#line 7495 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 562: -/* Line 1792 of yacc.c */ -#line 3040 "dtool/src/cppparser/cppBison.yxx" +#line 3137 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('|', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[0].u.expr)); } +#line 7503 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 563: -/* Line 1792 of yacc.c */ -#line 3044 "dtool/src/cppparser/cppBison.yxx" +#line 3141 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('^', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('*', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7511 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 564: -/* Line 1792 of yacc.c */ -#line 3048 "dtool/src/cppparser/cppBison.yxx" +#line 3145 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('&', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('/', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7519 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 565: -/* Line 1792 of yacc.c */ -#line 3052 "dtool/src/cppparser/cppBison.yxx" +#line 3149 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('%', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7527 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 566: -/* Line 1792 of yacc.c */ -#line 3056 "dtool/src/cppparser/cppBison.yxx" +#line 3153 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('+', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7535 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 567: -/* Line 1792 of yacc.c */ -#line 3060 "dtool/src/cppparser/cppBison.yxx" +#line 3157 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('-', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7543 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 568: -/* Line 1792 of yacc.c */ -#line 3064 "dtool/src/cppparser/cppBison.yxx" +#line 3161 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('|', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7551 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 569: -/* Line 1792 of yacc.c */ -#line 3068 "dtool/src/cppparser/cppBison.yxx" +#line 3165 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('^', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7559 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 570: -/* Line 1792 of yacc.c */ -#line 3072 "dtool/src/cppparser/cppBison.yxx" +#line 3169 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('&', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7567 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 571: -/* Line 1792 of yacc.c */ -#line 3076 "dtool/src/cppparser/cppBison.yxx" +#line 3173 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('<', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7575 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 572: -/* Line 1792 of yacc.c */ -#line 3080 "dtool/src/cppparser/cppBison.yxx" +#line 3177 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('>', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7583 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 573: -/* Line 1792 of yacc.c */ -#line 3084 "dtool/src/cppparser/cppBison.yxx" +#line 3181 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7591 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 574: -/* Line 1792 of yacc.c */ -#line 3088 "dtool/src/cppparser/cppBison.yxx" +#line 3185 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7599 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 575: -/* Line 1792 of yacc.c */ -#line 3092 "dtool/src/cppparser/cppBison.yxx" +#line 3189 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('?', (yyvsp[(1) - (5)].u.expr), (yyvsp[(3) - (5)].u.expr), (yyvsp[(5) - (5)].u.expr)); + (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7607 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 576: -/* Line 1792 of yacc.c */ -#line 3096 "dtool/src/cppparser/cppBison.yxx" +#line 3193 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('[', (yyvsp[(1) - (4)].u.expr), (yyvsp[(3) - (4)].u.expr)); + (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7615 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 577: -/* Line 1792 of yacc.c */ -#line 3100 "dtool/src/cppparser/cppBison.yxx" +#line 3197 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('f', (yyvsp[(1) - (4)].u.expr), (yyvsp[(3) - (4)].u.expr)); + (yyval.u.expr) = new CPPExpression('<', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7623 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 578: -/* Line 1792 of yacc.c */ -#line 3104 "dtool/src/cppparser/cppBison.yxx" +#line 3201 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('f', (yyvsp[(1) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression('>', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7631 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 579: -/* Line 1792 of yacc.c */ -#line 3108 "dtool/src/cppparser/cppBison.yxx" +#line 3205 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression('.', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7639 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 580: -/* Line 1792 of yacc.c */ -#line 3112 "dtool/src/cppparser/cppBison.yxx" +#line 3209 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); + (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7647 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 581: -/* Line 1792 of yacc.c */ -#line 3116 "dtool/src/cppparser/cppBison.yxx" +#line 3213 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (yyvsp[(2) - (3)].u.expr); + (yyval.u.expr) = new CPPExpression('?', (yyvsp[-4].u.expr), (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7655 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 582: -/* Line 1792 of yacc.c */ -#line 3123 "dtool/src/cppparser/cppBison.yxx" +#line 3217 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression((yyvsp[(1) - (1)].u.integer)); + (yyval.u.expr) = new CPPExpression('[', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); } +#line 7663 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 583: -/* Line 1792 of yacc.c */ -#line 3127 "dtool/src/cppparser/cppBison.yxx" +#line 3221 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(true); + (yyval.u.expr) = new CPPExpression('f', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); } +#line 7671 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 584: -/* Line 1792 of yacc.c */ -#line 3131 "dtool/src/cppparser/cppBison.yxx" +#line 3225 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression(false); + (yyval.u.expr) = new CPPExpression('f', (yyvsp[-2].u.expr)); } +#line 7679 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 585: -/* Line 1792 of yacc.c */ -#line 3135 "dtool/src/cppparser/cppBison.yxx" +#line 3229 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression((yyvsp[(1) - (1)].u.integer)); + (yyval.u.expr) = new CPPExpression('.', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7687 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 586: -/* Line 1792 of yacc.c */ -#line 3139 "dtool/src/cppparser/cppBison.yxx" +#line 3233 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression((yyvsp[(1) - (1)].u.real)); + (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } +#line 7695 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 587: -/* Line 1792 of yacc.c */ -#line 3143 "dtool/src/cppparser/cppBison.yxx" +#line 3237 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (yyvsp[(1) - (1)].u.expr); + (yyval.u.expr) = (yyvsp[-1].u.expr); } +#line 7703 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 588: -/* Line 1792 of yacc.c */ -#line 3147 "dtool/src/cppparser/cppBison.yxx" +#line 3244 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (yyvsp[(1) - (1)].u.expr); + (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); } +#line 7711 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 589: -/* Line 1792 of yacc.c */ -#line 3151 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression((yyvsp[(1) - (1)].u.identifier), current_scope, global_scope, current_lexer); -} - break; - - case 590: -/* Line 1792 of yacc.c */ -#line 3155 "dtool/src/cppparser/cppBison.yxx" - { - // A variable named "final". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("final", (yylsp[(1) - (1)])); - (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); -} - break; - - case 591: -/* Line 1792 of yacc.c */ -#line 3161 "dtool/src/cppparser/cppBison.yxx" - { - // A variable named "override". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("override", (yylsp[(1) - (1)])); - (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); -} - break; - - case 592: -/* Line 1792 of yacc.c */ -#line 3167 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::get_nullptr()); -} - break; - - case 593: -/* Line 1792 of yacc.c */ -#line 3171 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = NULL; -} - break; - - case 594: -/* Line 1792 of yacc.c */ -#line 3175 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = NULL; -} - break; - - case 595: -/* Line 1792 of yacc.c */ -#line 3189 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = (yyvsp[(1) - (1)].u.expr); -} - break; - - case 596: -/* Line 1792 of yacc.c */ -#line 3193 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(2) - (4)].u.type), (yyvsp[(4) - (4)].u.expr))); -} - break; - - case 597: -/* Line 1792 of yacc.c */ -#line 3197 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_static_cast)); -} - break; - - case 598: -/* Line 1792 of yacc.c */ -#line 3201 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_dynamic_cast)); -} - break; - - case 599: -/* Line 1792 of yacc.c */ -#line 3205 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_const_cast)); -} - break; - - case 600: -/* Line 1792 of yacc.c */ -#line 3209 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[(3) - (7)].u.type), (yyvsp[(6) - (7)].u.expr), CPPExpression::T_reinterpret_cast)); -} - break; - - case 601: -/* Line 1792 of yacc.c */ -#line 3213 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[(3) - (4)].u.type))); -} - break; - - case 602: -/* Line 1792 of yacc.c */ -#line 3217 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[(3) - (4)].u.type))); -} - break; - - case 603: -/* Line 1792 of yacc.c */ -#line 3221 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[(2) - (2)].u.type))); -} - break; - - case 604: -/* Line 1792 of yacc.c */ -#line 3225 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[(2) - (5)].u.type), (yyvsp[(4) - (5)].u.expr))); -} - break; - - case 605: -/* Line 1792 of yacc.c */ -#line 3229 "dtool/src/cppparser/cppBison.yxx" - { - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", (yylsp[(1) - (4)])); - } - (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[(3) - (4)].u.type), std_type_info)); -} - break; - - case 606: -/* Line 1792 of yacc.c */ -#line 3240 "dtool/src/cppparser/cppBison.yxx" - { - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", (yylsp[(1) - (4)])); - } - (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[(3) - (4)].u.expr), std_type_info)); -} - break; - - case 607: -/* Line 1792 of yacc.c */ -#line 3251 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[(2) - (2)].u.expr)); -} - break; - - case 608: -/* Line 1792 of yacc.c */ -#line 3255 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[(2) - (2)].u.expr)); -} - break; - - case 609: -/* Line 1792 of yacc.c */ -#line 3259 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[(2) - (2)].u.expr)); -} - break; - - case 610: -/* Line 1792 of yacc.c */ -#line 3263 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[(2) - (2)].u.expr)); -} - break; - - case 611: -/* Line 1792 of yacc.c */ -#line 3267 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[(2) - (2)].u.expr)); -} - break; - - case 612: -/* Line 1792 of yacc.c */ -#line 3271 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('*', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 613: -/* Line 1792 of yacc.c */ -#line 3275 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('/', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 614: -/* Line 1792 of yacc.c */ -#line 3279 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('%', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 615: -/* Line 1792 of yacc.c */ -#line 3283 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('+', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 616: -/* Line 1792 of yacc.c */ -#line 3287 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('-', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 617: -/* Line 1792 of yacc.c */ -#line 3291 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('|', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 618: -/* Line 1792 of yacc.c */ -#line 3295 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('^', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 619: -/* Line 1792 of yacc.c */ -#line 3299 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('&', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 620: -/* Line 1792 of yacc.c */ -#line 3303 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 621: -/* Line 1792 of yacc.c */ -#line 3307 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 622: -/* Line 1792 of yacc.c */ -#line 3311 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 623: -/* Line 1792 of yacc.c */ -#line 3315 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 624: -/* Line 1792 of yacc.c */ -#line 3319 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 625: -/* Line 1792 of yacc.c */ -#line 3323 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 626: -/* Line 1792 of yacc.c */ -#line 3327 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('<', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 627: -/* Line 1792 of yacc.c */ -#line 3331 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('>', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 628: -/* Line 1792 of yacc.c */ -#line 3335 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 629: -/* Line 1792 of yacc.c */ -#line 3339 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 630: -/* Line 1792 of yacc.c */ -#line 3343 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('?', (yyvsp[(1) - (5)].u.expr), (yyvsp[(3) - (5)].u.expr), (yyvsp[(5) - (5)].u.expr)); -} - break; - - case 631: -/* Line 1792 of yacc.c */ -#line 3347 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('[', (yyvsp[(1) - (4)].u.expr), (yyvsp[(3) - (4)].u.expr)); -} - break; - - case 632: -/* Line 1792 of yacc.c */ -#line 3351 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('f', (yyvsp[(1) - (4)].u.expr), (yyvsp[(3) - (4)].u.expr)); -} - break; - - case 633: -/* Line 1792 of yacc.c */ -#line 3355 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('f', (yyvsp[(1) - (3)].u.expr)); -} - break; - - case 634: -/* Line 1792 of yacc.c */ -#line 3359 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression('.', (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 635: -/* Line 1792 of yacc.c */ -#line 3363 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[(1) - (3)].u.expr), (yyvsp[(3) - (3)].u.expr)); -} - break; - - case 636: -/* Line 1792 of yacc.c */ -#line 3367 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = (yyvsp[(2) - (3)].u.expr); -} - break; - - case 637: -/* Line 1792 of yacc.c */ -#line 3374 "dtool/src/cppparser/cppBison.yxx" - { - (yyval.u.expr) = new CPPExpression((yyvsp[(1) - (1)].u.integer)); -} - break; - - case 638: -/* Line 1792 of yacc.c */ -#line 3378 "dtool/src/cppparser/cppBison.yxx" +#line 3248 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.expr) = new CPPExpression(true); } +#line 7719 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 639: -/* Line 1792 of yacc.c */ -#line 3382 "dtool/src/cppparser/cppBison.yxx" + case 590: +#line 3252 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.expr) = new CPPExpression(false); } +#line 7727 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 640: -/* Line 1792 of yacc.c */ -#line 3386 "dtool/src/cppparser/cppBison.yxx" + case 591: +#line 3256 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression((yyvsp[(1) - (1)].u.integer)); + (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); } +#line 7735 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 641: -/* Line 1792 of yacc.c */ -#line 3390 "dtool/src/cppparser/cppBison.yxx" + case 592: +#line 3260 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression((yyvsp[(1) - (1)].u.real)); + (yyval.u.expr) = new CPPExpression((yyvsp[0].u.real)); } +#line 7743 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 642: -/* Line 1792 of yacc.c */ -#line 3394 "dtool/src/cppparser/cppBison.yxx" + case 593: +#line 3264 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (yyvsp[(1) - (1)].u.expr); + (yyval.u.expr) = (yyvsp[0].u.expr); } +#line 7751 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 643: -/* Line 1792 of yacc.c */ -#line 3398 "dtool/src/cppparser/cppBison.yxx" + case 594: +#line 3268 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (yyvsp[(1) - (1)].u.expr); + (yyval.u.expr) = (yyvsp[0].u.expr); } +#line 7759 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 644: -/* Line 1792 of yacc.c */ -#line 3402 "dtool/src/cppparser/cppBison.yxx" + case 595: +#line 3272 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression((yyvsp[(1) - (1)].u.identifier), current_scope, global_scope, current_lexer); + (yyval.u.expr) = new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer); } +#line 7767 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 645: -/* Line 1792 of yacc.c */ -#line 3406 "dtool/src/cppparser/cppBison.yxx" + case 596: +#line 3276 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { // A variable named "final". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("final", (yylsp[(1) - (1)])); + CPPIdentifier *ident = new CPPIdentifier("final", (yylsp[0])); (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); } +#line 7777 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 646: -/* Line 1792 of yacc.c */ -#line 3412 "dtool/src/cppparser/cppBison.yxx" + case 597: +#line 3282 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { // A variable named "override". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("override", (yylsp[(1) - (1)])); + CPPIdentifier *ident = new CPPIdentifier("override", (yylsp[0])); (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); } +#line 7787 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 647: -/* Line 1792 of yacc.c */ -#line 3418 "dtool/src/cppparser/cppBison.yxx" + case 598: +#line 3288 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { (yyval.u.expr) = new CPPExpression(CPPExpression::get_nullptr()); } +#line 7795 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 655: -/* Line 1792 of yacc.c */ -#line 3439 "dtool/src/cppparser/cppBison.yxx" + case 599: +#line 3292 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *type = (yyvsp[(1) - (1)].u.identifier)->find_type(current_scope, global_scope, true); - if (type == NULL) { - type = CPPType::new_type(new CPPTBDType((yyvsp[(1) - (1)].u.identifier))); + (yyval.u.expr) = NULL; +} +#line 7803 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 600: +#line 3296 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = NULL; +} +#line 7811 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 601: +#line 3310 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = (yyvsp[0].u.expr); +} +#line 7819 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 602: +#line 3314 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-2].u.type), (yyvsp[0].u.expr))); +} +#line 7827 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 603: +#line 3318 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_static_cast)); +} +#line 7835 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 604: +#line 3322 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_dynamic_cast)); +} +#line 7843 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 605: +#line 3326 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_const_cast)); +} +#line 7851 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 606: +#line 3330 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_reinterpret_cast)); +} +#line 7859 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 607: +#line 3334 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[-1].u.type))); +} +#line 7867 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 608: +#line 3338 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[-1].u.type))); +} +#line 7875 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 609: +#line 3342 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[0].u.type))); +} +#line 7883 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 610: +#line 3346 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[-3].u.type), (yyvsp[-1].u.expr))); +} +#line 7891 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 611: +#line 3350 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + CPPIdentifier ident(""); + ident.add_name("std"); + ident.add_name("type_info"); + CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); + if (!std_type_info) { + yywarning("cannot use typeid before including ", (yylsp[-3])); } - (yyval.u.type) = type; + (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.type), std_type_info)); } +#line 7906 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 656: -/* Line 1792 of yacc.c */ -#line 3447 "dtool/src/cppparser/cppBison.yxx" + case 612: +#line 3361 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - CPPType *type = (yyvsp[(2) - (2)].u.identifier)->find_type(current_scope, global_scope, true, current_lexer); - if (type == NULL) { - type = CPPType::new_type(new CPPTBDType((yyvsp[(2) - (2)].u.identifier))); + CPPIdentifier ident(""); + ident.add_name("std"); + ident.add_name("type_info"); + CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); + if (!std_type_info) { + yywarning("cannot use typeid before including ", (yylsp[-3])); } - (yyval.u.type) = type; + (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.expr), std_type_info)); } +#line 7921 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 657: -/* Line 1792 of yacc.c */ -#line 3455 "dtool/src/cppparser/cppBison.yxx" + case 613: +#line 3372 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[(2) - (2)].u.identifier))); + (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[0].u.expr)); } +#line 7929 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 658: -/* Line 1792 of yacc.c */ -#line 3483 "dtool/src/cppparser/cppBison.yxx" + case 614: +#line 3376 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.identifier) = (yyvsp[(1) - (1)].u.identifier); + (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[0].u.expr)); } +#line 7937 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 659: -/* Line 1792 of yacc.c */ -#line 3487 "dtool/src/cppparser/cppBison.yxx" + case 615: +#line 3380 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.identifier) = (yyvsp[(1) - (1)].u.identifier); + (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[0].u.expr)); } +#line 7945 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; - case 660: -/* Line 1792 of yacc.c */ -#line 3491 "dtool/src/cppparser/cppBison.yxx" + case 616: +#line 3384 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.identifier) = new CPPIdentifier("final", (yylsp[(1) - (1)])); + (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[0].u.expr)); } +#line 7953 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 617: +#line 3388 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[0].u.expr)); +} +#line 7961 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 618: +#line 3392 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('*', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 7969 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 619: +#line 3396 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('/', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 7977 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 620: +#line 3400 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('%', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 7985 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 621: +#line 3404 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('+', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 7993 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 622: +#line 3408 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('-', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8001 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 623: +#line 3412 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('|', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8009 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 624: +#line 3416 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('^', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8017 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 625: +#line 3420 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('&', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8025 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 626: +#line 3424 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8033 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 627: +#line 3428 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8041 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 628: +#line 3432 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8049 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 629: +#line 3436 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8057 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 630: +#line 3440 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8065 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 631: +#line 3444 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8073 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 632: +#line 3448 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('<', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8081 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 633: +#line 3452 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('>', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8089 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 634: +#line 3456 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8097 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 635: +#line 3460 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8105 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 636: +#line 3464 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('?', (yyvsp[-4].u.expr), (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8113 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 637: +#line 3468 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('[', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); +} +#line 8121 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 638: +#line 3472 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('f', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); +} +#line 8129 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 639: +#line 3476 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('f', (yyvsp[-2].u.expr)); +} +#line 8137 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 640: +#line 3480 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression('.', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8145 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 641: +#line 3484 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); +} +#line 8153 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 642: +#line 3488 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = (yyvsp[-1].u.expr); +} +#line 8161 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 643: +#line 3495 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); +} +#line 8169 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 644: +#line 3499 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(true); +} +#line 8177 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 645: +#line 3503 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(false); +} +#line 8185 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 646: +#line 3507 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); +} +#line 8193 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 647: +#line 3511 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression((yyvsp[0].u.real)); +} +#line 8201 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 648: +#line 3515 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = (yyvsp[0].u.expr); +} +#line 8209 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 649: +#line 3519 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = (yyvsp[0].u.expr); +} +#line 8217 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 650: +#line 3523 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer); +} +#line 8225 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 651: +#line 3527 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + // A variable named "final". C++11 explicitly permits this. + CPPIdentifier *ident = new CPPIdentifier("final", (yylsp[0])); + (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); +} +#line 8235 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 652: +#line 3533 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + // A variable named "override". C++11 explicitly permits this. + CPPIdentifier *ident = new CPPIdentifier("override", (yylsp[0])); + (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); +} +#line 8245 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 653: +#line 3539 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression(CPPExpression::get_nullptr()); +} +#line 8253 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 661: -/* Line 1792 of yacc.c */ -#line 3495 "dtool/src/cppparser/cppBison.yxx" +#line 3560 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.identifier) = new CPPIdentifier("override", (yylsp[(1) - (1)])); + CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, true); + if (type == NULL) { + type = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); + } + (yyval.u.type) = type; } +#line 8265 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 662: -/* Line 1792 of yacc.c */ -#line 3506 "dtool/src/cppparser/cppBison.yxx" +#line 3568 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.identifier) = (yyvsp[(1) - (1)].u.identifier); + CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, true, current_lexer); + if (type == NULL) { + type = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); + } + (yyval.u.type) = type; } +#line 8277 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 663: -/* Line 1792 of yacc.c */ -#line 3510 "dtool/src/cppparser/cppBison.yxx" +#line 3576 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.identifier) = (yyvsp[(1) - (1)].u.identifier); + (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); } +#line 8285 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 664: -/* Line 1792 of yacc.c */ -#line 3514 "dtool/src/cppparser/cppBison.yxx" +#line 3604 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.identifier) = new CPPIdentifier("override", (yylsp[(1) - (1)])); + (yyval.u.identifier) = (yyvsp[0].u.identifier); } +#line 8293 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 665: -/* Line 1792 of yacc.c */ -#line 3522 "dtool/src/cppparser/cppBison.yxx" +#line 3608 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = new CPPExpression((yyvsp[(1) - (1)].str)); + (yyval.u.identifier) = (yyvsp[0].u.identifier); } +#line 8301 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 666: -/* Line 1792 of yacc.c */ -#line 3526 "dtool/src/cppparser/cppBison.yxx" +#line 3612 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - (yyval.u.expr) = (yyvsp[(1) - (1)].u.expr); + (yyval.u.identifier) = new CPPIdentifier("final", (yylsp[0])); } +#line 8309 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 667: -/* Line 1792 of yacc.c */ -#line 3530 "dtool/src/cppparser/cppBison.yxx" +#line 3616 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { - // The right string takes on the literal type of the left. - (yyval.u.expr) = (yyvsp[(1) - (2)].u.expr); - (yyval.u.expr)->_str += (yyvsp[(2) - (2)].str); + (yyval.u.identifier) = new CPPIdentifier("override", (yylsp[0])); } +#line 8317 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; case 668: -/* Line 1792 of yacc.c */ -#line 3536 "dtool/src/cppparser/cppBison.yxx" +#line 3620 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + // This is not a keyword in Python, so it is useful to be able to use this + // in MAKE_PROPERTY definitions, etc. + (yyval.u.identifier) = new CPPIdentifier("signed", (yylsp[0])); +} +#line 8327 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 669: +#line 3626 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.identifier) = new CPPIdentifier("float", (yylsp[0])); +} +#line 8335 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 670: +#line 3630 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.identifier) = new CPPIdentifier("public", (yylsp[0])); +} +#line 8343 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 671: +#line 3634 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.identifier) = new CPPIdentifier("private", (yylsp[0])); +} +#line 8351 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 672: +#line 3638 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.identifier) = new CPPIdentifier("static", (yylsp[0])); +} +#line 8359 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 673: +#line 3649 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.identifier) = (yyvsp[0].u.identifier); +} +#line 8367 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 674: +#line 3653 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.identifier) = (yyvsp[0].u.identifier); +} +#line 8375 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 675: +#line 3657 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.identifier) = new CPPIdentifier("override", (yylsp[0])); +} +#line 8383 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 676: +#line 3665 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = new CPPExpression((yyvsp[0].str)); +} +#line 8391 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 677: +#line 3669 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + (yyval.u.expr) = (yyvsp[0].u.expr); +} +#line 8399 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 678: +#line 3673 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ + { + // The right string takes on the literal type of the left. + (yyval.u.expr) = (yyvsp[-1].u.expr); + (yyval.u.expr)->_str += (yyvsp[0].str); +} +#line 8409 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ + break; + + case 679: +#line 3679 "dtool/src/cppparser/cppBison.yxx" /* yacc.c:1646 */ { // We have to check that the two literal types match up. - (yyval.u.expr) = (yyvsp[(1) - (2)].u.expr); - if ((yyvsp[(2) - (2)].u.expr)->_type != CPPExpression::T_string && (yyvsp[(2) - (2)].u.expr)->_type != (yyvsp[(1) - (2)].u.expr)->_type) { + (yyval.u.expr) = (yyvsp[-1].u.expr); + if ((yyvsp[0].u.expr)->_type != CPPExpression::T_string && (yyvsp[0].u.expr)->_type != (yyvsp[-1].u.expr)->_type) { yywarning("cannot concatenate two string literals of different types", (yyloc)); } - (yyval.u.expr)->_str += (yyvsp[(2) - (2)].u.expr)->_str; + (yyval.u.expr)->_str += (yyvsp[0].u.expr)->_str; } +#line 8422 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ break; -/* Line 1792 of yacc.c */ -#line 8616 "built/tmp/cppBison.yxx.c" +#line 8426 "built/tmp/cppBison.yxx.c" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -8635,7 +8445,7 @@ yyreduce: *++yyvsp = yyval; *++yylsp = yyloc; - /* Now `shift' the result of the reduction. Determine what state + /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ @@ -8650,9 +8460,9 @@ yyreduce: goto yynewstate; -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ @@ -8703,20 +8513,20 @@ yyerrlab: if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an - error, discard it. */ + error, discard it. */ if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } else - { - yydestruct ("Error: discarding", - yytoken, &yylval, &yylloc); - yychar = YYEMPTY; - } + { + yydestruct ("Error: discarding", + yytoken, &yylval, &yylloc); + yychar = YYEMPTY; + } } /* Else will try to reuse lookahead token after shifting the error @@ -8736,7 +8546,7 @@ yyerrorlab: goto yyerrorlab; yyerror_range[1] = yylsp[1-yylen]; - /* Do not reclaim the symbols of the rule which action triggered + /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; @@ -8749,29 +8559,29 @@ yyerrorlab: | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ + yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (!yypact_value_is_default (yyn)) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) - YYABORT; + YYABORT; yyerror_range[1] = *yylsp; yydestruct ("Error: popping", - yystos[yystate], yyvsp, yylsp); + yystos[yystate], yyvsp, yylsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); @@ -8827,14 +8637,14 @@ yyreturn: yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc); } - /* Do not reclaim the symbols of the rule which action triggered + /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, yylsp); + yystos[*yyssp], yyvsp, yylsp); YYPOPSTACK (1); } #ifndef yyoverflow @@ -8845,8 +8655,5 @@ yyreturn: if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif - /* Make sure YYID is used. */ - return YYID (yyresult); + return yyresult; } - - diff --git a/dtool/src/cppparser/cppBison.h.prebuilt b/dtool/src/cppparser/cppBison.h.prebuilt index c7784f5edf..412b128300 100644 --- a/dtool/src/cppparser/cppBison.h.prebuilt +++ b/dtool/src/cppparser/cppBison.h.prebuilt @@ -1,19 +1,19 @@ -/* A Bison parser, made by GNU Bison 2.7. */ +/* A Bison parser, made by GNU Bison 3.0.4. */ /* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. - + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -26,13 +26,13 @@ special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. - + This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ #ifndef YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED # define YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED -/* Enabling traces. */ +/* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif @@ -40,134 +40,135 @@ extern int cppyydebug; #endif -/* Tokens. */ +/* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - REAL = 258, - INTEGER = 259, - CHAR_TOK = 260, - SIMPLE_STRING = 261, - SIMPLE_IDENTIFIER = 262, - STRING_LITERAL = 263, - CUSTOM_LITERAL = 264, - IDENTIFIER = 265, - TYPENAME_IDENTIFIER = 266, - SCOPING = 267, - TYPEDEFNAME = 268, - ELLIPSIS = 269, - OROR = 270, - ANDAND = 271, - EQCOMPARE = 272, - NECOMPARE = 273, - LECOMPARE = 274, - GECOMPARE = 275, - LSHIFT = 276, - RSHIFT = 277, - POINTSAT_STAR = 278, - DOT_STAR = 279, - UNARY = 280, - UNARY_NOT = 281, - UNARY_NEGATE = 282, - UNARY_MINUS = 283, - UNARY_PLUS = 284, - UNARY_STAR = 285, - UNARY_REF = 286, - POINTSAT = 287, - SCOPE = 288, - PLUSPLUS = 289, - MINUSMINUS = 290, - TIMESEQUAL = 291, - DIVIDEEQUAL = 292, - MODEQUAL = 293, - PLUSEQUAL = 294, - MINUSEQUAL = 295, - OREQUAL = 296, - ANDEQUAL = 297, - XOREQUAL = 298, - LSHIFTEQUAL = 299, - RSHIFTEQUAL = 300, - KW_ALIGNAS = 301, - KW_ALIGNOF = 302, - KW_AUTO = 303, - KW_BEGIN_PUBLISH = 304, - KW_BLOCKING = 305, - KW_BOOL = 306, - KW_CATCH = 307, - KW_CHAR = 308, - KW_CHAR16_T = 309, - KW_CHAR32_T = 310, - KW_CLASS = 311, - KW_CONST = 312, - KW_CONSTEXPR = 313, - KW_CONST_CAST = 314, - KW_DECLTYPE = 315, - KW_DEFAULT = 316, - KW_DELETE = 317, - KW_DOUBLE = 318, - KW_DYNAMIC_CAST = 319, - KW_ELSE = 320, - KW_END_PUBLISH = 321, - KW_ENUM = 322, - KW_EXTENSION = 323, - KW_EXTERN = 324, - KW_EXPLICIT = 325, - KW_PUBLISHED = 326, - KW_FALSE = 327, - KW_FINAL = 328, - KW_FLOAT = 329, - KW_FRIEND = 330, - KW_FOR = 331, - KW_GOTO = 332, - KW_IF = 333, - KW_INLINE = 334, - KW_INT = 335, - KW_LONG = 336, - KW_MAKE_PROPERTY = 337, - KW_MAKE_PROPERTY2 = 338, - KW_MAKE_SEQ = 339, - KW_MUTABLE = 340, - KW_NAMESPACE = 341, - KW_NEW = 342, - KW_NOEXCEPT = 343, - KW_NULLPTR = 344, - KW_OPERATOR = 345, - KW_OVERRIDE = 346, - KW_PRIVATE = 347, - KW_PROTECTED = 348, - KW_PUBLIC = 349, - KW_REGISTER = 350, - KW_REINTERPRET_CAST = 351, - KW_RETURN = 352, - KW_SHORT = 353, - KW_SIGNED = 354, - KW_SIZEOF = 355, - KW_STATIC = 356, - KW_STATIC_ASSERT = 357, - KW_STATIC_CAST = 358, - KW_STRUCT = 359, - KW_TEMPLATE = 360, - KW_THREAD_LOCAL = 361, - KW_THROW = 362, - KW_TRUE = 363, - KW_TRY = 364, - KW_TYPEDEF = 365, - KW_TYPEID = 366, - KW_TYPENAME = 367, - KW_UNION = 368, - KW_UNSIGNED = 369, - KW_USING = 370, - KW_VIRTUAL = 371, - KW_VOID = 372, - KW_VOLATILE = 373, - KW_WCHAR_T = 374, - KW_WHILE = 375, - START_CPP = 376, - START_CONST_EXPR = 377, - START_TYPE = 378 - }; + enum yytokentype + { + REAL = 258, + INTEGER = 259, + CHAR_TOK = 260, + SIMPLE_STRING = 261, + SIMPLE_IDENTIFIER = 262, + STRING_LITERAL = 263, + CUSTOM_LITERAL = 264, + IDENTIFIER = 265, + TYPENAME_IDENTIFIER = 266, + SCOPING = 267, + TYPEDEFNAME = 268, + ELLIPSIS = 269, + OROR = 270, + ANDAND = 271, + EQCOMPARE = 272, + NECOMPARE = 273, + LECOMPARE = 274, + GECOMPARE = 275, + LSHIFT = 276, + RSHIFT = 277, + POINTSAT_STAR = 278, + DOT_STAR = 279, + UNARY = 280, + UNARY_NOT = 281, + UNARY_NEGATE = 282, + UNARY_MINUS = 283, + UNARY_PLUS = 284, + UNARY_STAR = 285, + UNARY_REF = 286, + POINTSAT = 287, + SCOPE = 288, + PLUSPLUS = 289, + MINUSMINUS = 290, + TIMESEQUAL = 291, + DIVIDEEQUAL = 292, + MODEQUAL = 293, + PLUSEQUAL = 294, + MINUSEQUAL = 295, + OREQUAL = 296, + ANDEQUAL = 297, + XOREQUAL = 298, + LSHIFTEQUAL = 299, + RSHIFTEQUAL = 300, + KW_ALIGNAS = 301, + KW_ALIGNOF = 302, + KW_AUTO = 303, + KW_BEGIN_PUBLISH = 304, + KW_BLOCKING = 305, + KW_BOOL = 306, + KW_CATCH = 307, + KW_CHAR = 308, + KW_CHAR16_T = 309, + KW_CHAR32_T = 310, + KW_CLASS = 311, + KW_CONST = 312, + KW_CONSTEXPR = 313, + KW_CONST_CAST = 314, + KW_DECLTYPE = 315, + KW_DEFAULT = 316, + KW_DELETE = 317, + KW_DOUBLE = 318, + KW_DYNAMIC_CAST = 319, + KW_ELSE = 320, + KW_END_PUBLISH = 321, + KW_ENUM = 322, + KW_EXTENSION = 323, + KW_EXTERN = 324, + KW_EXPLICIT = 325, + KW_PUBLISHED = 326, + KW_FALSE = 327, + KW_FINAL = 328, + KW_FLOAT = 329, + KW_FRIEND = 330, + KW_FOR = 331, + KW_GOTO = 332, + KW_IF = 333, + KW_INLINE = 334, + KW_INT = 335, + KW_LONG = 336, + KW_MAKE_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 + }; #endif /* Tokens. */ #define REAL 258 @@ -249,83 +250,69 @@ extern int cppyydebug; #define KW_INLINE 334 #define KW_INT 335 #define KW_LONG 336 -#define KW_MAKE_PROPERTY 337 -#define KW_MAKE_PROPERTY2 338 -#define KW_MAKE_SEQ 339 -#define KW_MUTABLE 340 -#define KW_NAMESPACE 341 -#define KW_NEW 342 -#define KW_NOEXCEPT 343 -#define KW_NULLPTR 344 -#define KW_OPERATOR 345 -#define KW_OVERRIDE 346 -#define KW_PRIVATE 347 -#define KW_PROTECTED 348 -#define KW_PUBLIC 349 -#define KW_REGISTER 350 -#define KW_REINTERPRET_CAST 351 -#define KW_RETURN 352 -#define KW_SHORT 353 -#define KW_SIGNED 354 -#define KW_SIZEOF 355 -#define KW_STATIC 356 -#define KW_STATIC_ASSERT 357 -#define KW_STATIC_CAST 358 -#define KW_STRUCT 359 -#define KW_TEMPLATE 360 -#define KW_THREAD_LOCAL 361 -#define KW_THROW 362 -#define KW_TRUE 363 -#define KW_TRY 364 -#define KW_TYPEDEF 365 -#define KW_TYPEID 366 -#define KW_TYPENAME 367 -#define KW_UNION 368 -#define KW_UNSIGNED 369 -#define KW_USING 370 -#define KW_VIRTUAL 371 -#define KW_VOID 372 -#define KW_VOLATILE 373 -#define KW_WCHAR_T 374 -#define KW_WHILE 375 -#define START_CPP 376 -#define START_CONST_EXPR 377 -#define START_TYPE 378 +#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 +/* Value type. */ - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - +/* Location type. */ #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE +typedef struct YYLTYPE YYLTYPE; +struct YYLTYPE { int first_line; int first_column; int last_line; int last_column; -} YYLTYPE; -# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +}; # define YYLTYPE_IS_DECLARED 1 # define YYLTYPE_IS_TRIVIAL 1 #endif -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int cppyyparse (void *YYPARSE_PARAM); -#else -int cppyyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus + int cppyyparse (void); -#else -int cppyyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ #endif /* !YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED */ diff --git a/dtool/src/cppparser/cppBison.yxx b/dtool/src/cppparser/cppBison.yxx index b9a64f90fc..b8600975b8 100644 --- a/dtool/src/cppparser/cppBison.yxx +++ b/dtool/src/cppparser/cppBison.yxx @@ -284,9 +284,11 @@ pop_struct() { %token KW_INLINE %token KW_INT %token KW_LONG +%token KW_MAKE_MAP_PROPERTY %token KW_MAKE_PROPERTY %token KW_MAKE_PROPERTY2 %token KW_MAKE_SEQ +%token KW_MAKE_SEQ_PROPERTY %token KW_MUTABLE %token KW_NAMESPACE %token KW_NEW @@ -474,7 +476,6 @@ declaration: | template_declaration | extern_c | namespace_declaration - | using_declaration | friend_declaration | KW_TYPEDEF typedef_declaration | KW_BEGIN_PUBLISH @@ -550,6 +551,118 @@ declaration: setter_func, current_scope, @1.file); current_scope->add_declaration(make_property, global_scope, current_lexer, @1); } +} + | KW_MAKE_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' +{ + CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer); + if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @5); + + } else { + CPPDeclaration *setter = $7->find_symbol(current_scope, global_scope, current_lexer); + CPPFunctionGroup *setter_func = NULL; + + if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid setter: " + $7->get_fully_scoped_name(), @7); + } else { + setter_func = setter->as_function_group(); + } + + CPPDeclaration *deleter = $9->find_symbol(current_scope, global_scope, current_lexer); + if (deleter == (CPPDeclaration *)NULL || deleter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("reference to non-existent or invalid delete method: " + $9->get_fully_scoped_name(), @9); + deleter = NULL; + } + + CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(), + setter_func, current_scope, @1.file); + if (deleter) { + make_property->_del_function = deleter->as_function_group(); + } + current_scope->add_declaration(make_property, global_scope, current_lexer, @1); + } +} + | KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' +{ + CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer); + if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5); + length_getter = NULL; + } + + CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); + if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); + } + + CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(), NULL, current_scope, @1.file); + make_property->_length_function = length_getter->as_function_group(); + current_scope->add_declaration(make_property, global_scope, current_lexer, @1); +} + | KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' +{ + CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer); + if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5); + length_getter = NULL; + } + + CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); + if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); + + } else { + CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer); + CPPFunctionGroup *setter_func = NULL; + + if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9); + } else { + setter_func = setter->as_function_group(); + } + + CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(), + setter_func, current_scope, @1.file); + make_property->_length_function = length_getter->as_function_group(); + current_scope->add_declaration(make_property, global_scope, current_lexer, @1); + } +} + | KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' +{ + CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer); + if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5); + length_getter = NULL; + } + + CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); + if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); + + } else { + CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer); + CPPFunctionGroup *setter_func = NULL; + + if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9); + } else { + setter_func = setter->as_function_group(); + } + + CPPDeclaration *deleter = $11->find_symbol(current_scope, global_scope, current_lexer); + if (deleter == (CPPDeclaration *)NULL || deleter->get_subtype() != CPPDeclaration::ST_function_group) { + yyerror("reference to non-existent or invalid delete method: " + $11->get_fully_scoped_name(), @11); + deleter = NULL; + } + + CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(), + setter_func, current_scope, @1.file); + make_property->_length_function = length_getter->as_function_group(); + if (deleter) { + make_property->_del_function = deleter->as_function_group(); + } + current_scope->add_declaration(make_property, global_scope, current_lexer, @1); + } } | KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' { @@ -777,6 +890,7 @@ type_like_declaration: $2->set_initializer($3); } } + | using_declaration ; multiple_var_declaration: @@ -2349,21 +2463,23 @@ enum: ; enum_decl: - enum_keyword name_no_final ':' enum_element_type + enum_keyword ':' enum_element_type { - current_enum = new CPPEnumType($2, $4, current_scope, @1.file); -} - | enum_keyword name_no_final -{ - current_enum = new CPPEnumType($2, current_scope, @1.file); -} - | enum_keyword ':' enum_element_type -{ - current_enum = new CPPEnumType(NULL, $3, current_scope, @1.file); + current_enum = new CPPEnumType($1, NULL, $3, current_scope, NULL, @1.file); } | enum_keyword { - current_enum = new CPPEnumType(NULL, current_scope, @1.file); + current_enum = new CPPEnumType($1, NULL, current_scope, NULL, @1.file); +} + | enum_keyword name_no_final ':' enum_element_type +{ + CPPScope *new_scope = new CPPScope(current_scope, $2->_names.back(), V_public); + current_enum = new CPPEnumType($1, $2, $4, current_scope, new_scope, @1.file); +} + | enum_keyword name_no_final +{ + CPPScope *new_scope = new CPPScope(current_scope, $2->_names.back(), V_public); + current_enum = new CPPEnumType($1, $2, current_scope, new_scope, @1.file); } ; @@ -2383,14 +2499,12 @@ enum_body_trailing_comma: | enum_body_trailing_comma name ',' { assert(current_enum != NULL); - CPPInstance *inst = current_enum->add_element($2->get_simple_name()); - current_scope->add_enum_value(inst, current_lexer, @2); + current_enum->add_element($2->get_simple_name(), NULL, current_lexer, @2); } | enum_body_trailing_comma name '=' const_expr ',' { assert(current_enum != NULL); - CPPInstance *inst = current_enum->add_element($2->get_simple_name(), $4); - current_scope->add_enum_value(inst, current_lexer, @2); + current_enum->add_element($2->get_simple_name(), $4, current_lexer, @2); }; enum_body: @@ -2398,14 +2512,12 @@ enum_body: | enum_body_trailing_comma name { assert(current_enum != NULL); - CPPInstance *inst = current_enum->add_element($2->get_simple_name()); - current_scope->add_enum_value(inst, current_lexer, @2); + current_enum->add_element($2->get_simple_name(), NULL, current_lexer, @2); } | enum_body_trailing_comma name '=' const_expr { assert(current_enum != NULL); - CPPInstance *inst = current_enum->add_element($2->get_simple_name(), $4); - current_scope->add_enum_value(inst, current_lexer, @2); + current_enum->add_element($2->get_simple_name(), $4, current_lexer, @2); } ; @@ -2413,6 +2525,14 @@ enum_keyword: KW_ENUM { $$ = CPPExtensionType::T_enum; +} + | KW_ENUM KW_CLASS +{ + $$ = CPPExtensionType::T_enum_class; +} + | KW_ENUM KW_STRUCT +{ + $$ = CPPExtensionType::T_enum_struct; } ; @@ -3495,6 +3615,28 @@ name: | KW_OVERRIDE { $$ = new CPPIdentifier("override", @1); +} + | KW_SIGNED +{ + // This is not a keyword in Python, so it is useful to be able to use this + // in MAKE_PROPERTY definitions, etc. + $$ = new CPPIdentifier("signed", @1); +} + | KW_FLOAT +{ + $$ = new CPPIdentifier("float", @1); +} + | KW_PUBLIC +{ + $$ = new CPPIdentifier("public", @1); +} + | KW_PRIVATE +{ + $$ = new CPPIdentifier("private", @1); +} + | KW_STATIC +{ + $$ = new CPPIdentifier("static", @1); } ; diff --git a/dtool/src/cppparser/cppEnumType.cxx b/dtool/src/cppparser/cppEnumType.cxx index bee8ec2f5b..927488585d 100644 --- a/dtool/src/cppparser/cppEnumType.cxx +++ b/dtool/src/cppparser/cppEnumType.cxx @@ -22,42 +22,53 @@ #include "indent.h" /** - * Creates an untyped, unscoped enum. + * Creates an untyped enum. */ CPPEnumType:: -CPPEnumType(CPPIdentifier *ident, CPPScope *current_scope, - const CPPFile &file) : - CPPExtensionType(T_enum, ident, current_scope, file), - _parent_scope(current_scope), +CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope, + CPPScope *scope, const CPPFile &file) : + CPPExtensionType(type, ident, current_scope, file), + _scope(scope), _element_type(NULL), _last_value(NULL) { + _parent_scope = (type == T_enum) ? current_scope : scope; + if (ident != NULL) { ident->_native_scope = current_scope; } } /** - * Creates a typed but unscoped enum. + * Creates a typed enum. */ CPPEnumType:: -CPPEnumType(CPPIdentifier *ident, CPPType *element_type, - CPPScope *current_scope, const CPPFile &file) : - CPPExtensionType(T_enum, ident, current_scope, file), - _parent_scope(current_scope), +CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type, + CPPScope *current_scope, CPPScope *scope, const CPPFile &file) : + CPPExtensionType(type, ident, current_scope, file), + _scope(scope), _element_type(element_type), _last_value(NULL) { + _parent_scope = (type == T_enum) ? current_scope : scope; if (ident != NULL) { ident->_native_scope = current_scope; } } +/** + * Returns true if this is a scoped enum. + */ +bool CPPEnumType:: +is_scoped() const { + return (_type != T_enum); +} + /** * Returns the integral type used to store enum values. */ CPPType *CPPEnumType:: -get_element_type() { +get_underlying_type() { if (_element_type == NULL) { // This enum is untyped. Use a suitable default, ie. 'int'. In the // future, we might want to check whether it fits in an int. @@ -78,11 +89,18 @@ get_element_type() { * */ CPPInstance *CPPEnumType:: -add_element(const string &name, CPPExpression *value) { +add_element(const string &name, CPPExpression *value, CPPPreprocessor *preprocessor, const cppyyltype &pos) { CPPIdentifier *ident = new CPPIdentifier(name); ident->_native_scope = _parent_scope; - CPPInstance *inst = new CPPInstance(get_element_type(), ident); + CPPInstance *inst; + if (_type == T_enum) { + // Weakly typed enum. + inst = new CPPInstance(get_underlying_type(), ident); + } else { + // C++11-style strongly typed enum. + inst = new CPPInstance(this, ident); + } inst->_storage_class |= CPPInstance::SC_constexpr; _elements.push_back(inst); @@ -104,6 +122,41 @@ add_element(const string &name, CPPExpression *value) { } inst->_initializer = value; _last_value = value; + + if (preprocessor != (CPPPreprocessor *)NULL) { + // Same-line comment? + CPPCommentBlock *comment = + preprocessor->get_comment_on(pos.first_line, pos.file); + + if (comment == (CPPCommentBlock *)NULL) { + // Nope. Check for a comment before this line. + comment = + preprocessor->get_comment_before(pos.first_line, pos.file); + + if (comment != NULL) { + // This is a bit of a hack, but it prevents us from picking up a same- + // line comment from the previous line. + if (comment->_line_number != pos.first_line - 1 || + comment->_col_number <= pos.first_column) { + + inst->_leading_comment = comment; + } + } + } else { + inst->_leading_comment = comment; + } + } + + // Add the value to the enum scope (as per C++11), assuming it's not anonymous. + if (_scope != NULL) { + _scope->add_enum_value(inst); + } + + // Now add it to the containing scope as well if it's not an "enum class". + if (!is_scoped() && _parent_scope != NULL) { + _parent_scope->add_enum_value(inst); + } + return inst; } diff --git a/dtool/src/cppparser/cppEnumType.h b/dtool/src/cppparser/cppEnumType.h index 85143d664b..c22742203c 100644 --- a/dtool/src/cppparser/cppEnumType.h +++ b/dtool/src/cppparser/cppEnumType.h @@ -30,15 +30,16 @@ class CPPScope; */ class CPPEnumType : public CPPExtensionType { public: - CPPEnumType(CPPIdentifier *ident, CPPScope *current_scope, - const CPPFile &file); - CPPEnumType(CPPIdentifier *ident, CPPType *element_type, - CPPScope *current_scope, const CPPFile &file); + CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope, + CPPScope *scope, const CPPFile &file); + CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type, + CPPScope *current_scope, CPPScope *scope, const CPPFile &file); - CPPType *get_element_type(); + bool is_scoped() const; + CPPType *get_underlying_type(); - CPPInstance *add_element(const string &name, - CPPExpression *value = (CPPExpression *)NULL); + CPPInstance *add_element(const string &name, CPPExpression *value, + CPPPreprocessor *preprocessor, const cppyyltype &pos); virtual bool is_incomplete() const; @@ -54,6 +55,7 @@ public: virtual CPPEnumType *as_enum_type(); CPPScope *_parent_scope; + CPPScope *_scope; CPPType *_element_type; typedef vector Elements; diff --git a/dtool/src/cppparser/cppExpression.cxx b/dtool/src/cppparser/cppExpression.cxx index 8456c402f5..7ef5ec85fb 100644 --- a/dtool/src/cppparser/cppExpression.cxx +++ b/dtool/src/cppparser/cppExpression.cxx @@ -949,7 +949,7 @@ determine_type() const { case CPPDeclaration::ST_enum: // Convert into integral type. - return t1->as_enum_type()->get_element_type(); + return t1->as_enum_type()->get_underlying_type(); case CPPDeclaration::ST_simple: { diff --git a/dtool/src/cppparser/cppExtensionType.cxx b/dtool/src/cppparser/cppExtensionType.cxx index 9e9aeb4c71..36bdd307fe 100644 --- a/dtool/src/cppparser/cppExtensionType.cxx +++ b/dtool/src/cppparser/cppExtensionType.cxx @@ -229,6 +229,12 @@ operator << (ostream &out, CPPExtensionType::Type type) { case CPPExtensionType::T_union: return out << "union"; + case CPPExtensionType::T_enum_class: + return out << "enum class"; + + case CPPExtensionType::T_enum_struct: + return out << "enum struct"; + default: return out << "***invalid extension type***"; } diff --git a/dtool/src/cppparser/cppExtensionType.h b/dtool/src/cppparser/cppExtensionType.h index 801809f753..e60aeb9f21 100644 --- a/dtool/src/cppparser/cppExtensionType.h +++ b/dtool/src/cppparser/cppExtensionType.h @@ -34,6 +34,8 @@ public: T_class, T_struct, T_union, + T_enum_class, + T_enum_struct, }; CPPExtensionType(Type type, CPPIdentifier *ident, CPPScope *current_scope, diff --git a/dtool/src/cppparser/cppMakeProperty.cxx b/dtool/src/cppparser/cppMakeProperty.cxx index 78ea191092..c65fcf93b6 100644 --- a/dtool/src/cppparser/cppMakeProperty.cxx +++ b/dtool/src/cppparser/cppMakeProperty.cxx @@ -23,10 +23,12 @@ CPPMakeProperty(CPPIdentifier *ident, CPPScope *current_scope, const CPPFile &file) : CPPDeclaration(file), _ident(ident), + _length_function(NULL), _has_function(NULL), _get_function(getter), _set_function(setter), - _clear_function(NULL) + _clear_function(NULL), + _del_function(NULL) { _ident->_native_scope = current_scope; } @@ -41,10 +43,12 @@ CPPMakeProperty(CPPIdentifier *ident, CPPScope *current_scope, const CPPFile &file) : CPPDeclaration(file), _ident(ident), + _length_function(NULL), _has_function(hasser), _get_function(getter), _set_function(setter), - _clear_function(clearer) + _clear_function(clearer), + _del_function(NULL) { _ident->_native_scope = current_scope; } @@ -78,7 +82,11 @@ get_fully_scoped_name() const { */ void CPPMakeProperty:: output(ostream &out, int indent_level, CPPScope *scope, bool complete) const { - out << "__make_property"; + if (_length_function != NULL) { + out << "__make_seq_property"; + } else { + out << "__make_property"; + } if (_has_function != NULL) { out.put('2'); @@ -86,6 +94,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const { out << "(" << _ident->get_local_name(scope); + if (_length_function != NULL) { + out << ", " << _length_function->_name; + } + if (_has_function != NULL) { out << ", " << _has_function->_name; } @@ -100,6 +112,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const { out << ", " << _clear_function->_name; } + if (_del_function != NULL) { + out << ", " << _del_function->_name; + } + out << ");"; } diff --git a/dtool/src/cppparser/cppMakeProperty.h b/dtool/src/cppparser/cppMakeProperty.h index 40308e4b14..44a1a5671a 100644 --- a/dtool/src/cppparser/cppMakeProperty.h +++ b/dtool/src/cppparser/cppMakeProperty.h @@ -46,10 +46,14 @@ public: virtual CPPMakeProperty *as_make_property(); CPPIdentifier *_ident; + // If length_function is not NULL, this is actually a sequence property, + // and the other functions take an additional index argument. + CPPFunctionGroup *_length_function; CPPFunctionGroup *_has_function; CPPFunctionGroup *_get_function; CPPFunctionGroup *_set_function; CPPFunctionGroup *_clear_function; + CPPFunctionGroup *_del_function; }; #endif diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx index 6b382161db..24116a240a 100644 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ b/dtool/src/cppparser/cppPreprocessor.cxx @@ -2458,9 +2458,11 @@ check_keyword(const string &name) { if (name == "__inline__") return KW_INLINE; if (name == "int") return KW_INT; if (name == "long") return KW_LONG; + if (name == "__make_map_property") return KW_MAKE_MAP_PROPERTY; if (name == "__make_property") return KW_MAKE_PROPERTY; if (name == "__make_property2") return KW_MAKE_PROPERTY2; if (name == "__make_seq") return KW_MAKE_SEQ; + if (name == "__make_seq_property") return KW_MAKE_SEQ_PROPERTY; if (name == "mutable") return KW_MUTABLE; if (name == "namespace") return KW_NAMESPACE; if (name == "noexcept") return KW_NOEXCEPT; diff --git a/dtool/src/cppparser/cppScope.cxx b/dtool/src/cppparser/cppScope.cxx index 158c3884d2..e61b42f19e 100644 --- a/dtool/src/cppparser/cppScope.cxx +++ b/dtool/src/cppparser/cppScope.cxx @@ -124,40 +124,75 @@ add_declaration(CPPDeclaration *decl, CPPScope *global_scope, * */ void CPPScope:: -add_enum_value(CPPInstance *inst, CPPPreprocessor *preprocessor, - const cppyyltype &pos) { +add_enum_value(CPPInstance *inst) { inst->_vis = _current_vis; - if (inst->_leading_comment == (CPPCommentBlock *)NULL) { - // Same-line comment? - CPPCommentBlock *comment = - preprocessor->get_comment_on(pos.first_line, pos.file); - - if (comment == (CPPCommentBlock *)NULL) { - // Nope. Check for a comment before this line. - comment = - preprocessor->get_comment_before(pos.first_line, pos.file); - - if (comment != NULL) { - // This is a bit of a hack, but it prevents us from picking up a same- - // line comment from the previous line. - if (comment->_line_number != pos.first_line - 1 || - comment->_col_number <= pos.first_column) { - - inst->_leading_comment = comment; - } - } - } else { - inst->_leading_comment = comment; - } - } - string name = inst->get_simple_name(); if (!name.empty()) { _enum_values[name] = inst; } } +/** + * + */ +void CPPScope:: +define_typedef_type(CPPTypedefType *type, CPPPreprocessor *error_sink) { + string name = type->get_simple_name(); + + pair result = + _types.insert(Types::value_type(name, type)); + + if (!result.second) { + CPPType *other_type = result.first->second; + CPPTypedefType *other_td = other_type->as_typedef_type(); + + // We don't do redefinitions of typedefs. But we don't complain as long + // as this is actually a typedef to the previous definition. + if (other_type != type->_type && + (other_td == NULL || !other_td->_type->is_equivalent(*type->_type))) { + + if (error_sink != NULL) { + ostringstream errstr; + type->output(errstr, 0, NULL, false); + errstr << " has conflicting declaration as "; + other_type->output(errstr, 0, NULL, true); + error_sink->error(errstr.str(), type->_ident->_loc); + error_sink->error("previous definition is here", + other_td->_ident->_loc); + } + } + } else { + _types[name] = type; + } + + // This might be a templated "using" definition. + if (type->is_template()) { + CPPTemplateScope *scope = type->get_template_scope(); + if (scope->_parameters._parameters.size() == 0) { + return; + } + + string simple_name = type->get_simple_name(); + + pair result = + _templates.insert(Templates::value_type(simple_name, type)); + + if (!result.second) { + // The template was not inserted because we already had a template + // definition with the given name. If the previous definition was + // incomplete, replace it. + CPPDeclaration *old_templ = (*result.first).second; + CPPType *old_templ_type = old_templ->as_type(); + if (old_templ_type == NULL || old_templ_type->is_incomplete()) { + // The previous template definition was incomplete, maybe a forward + // reference; replace it with the good one. + (*result.first).second = type; + } + } + } +} + /** * */ @@ -183,6 +218,8 @@ define_extension_type(CPPExtensionType *type, CPPPreprocessor *error_sink) { break; case CPPExtensionType::T_enum: + case CPPExtensionType::T_enum_struct: + case CPPExtensionType::T_enum_class: _enums[name] = type; break; } @@ -606,6 +643,11 @@ find_scope(const string &name, bool recurse) const { if (st != NULL) { return st->_scope; } + + CPPEnumType *et = type->as_enum_type(); + if (et != NULL) { + return et->_scope; + } } Using::const_iterator ui; @@ -645,11 +687,16 @@ find_scope(const string &name, CPPDeclaration::SubstDecl &subst, } CPPStructType *st = type->as_struct_type(); - if (st == NULL) { - return NULL; + if (st != NULL) { + return st->_scope; } - return st->_scope; + CPPEnumType *et = type->as_enum_type(); + if (et != NULL) { + return et->_scope; + } + + return NULL; } /** @@ -1048,39 +1095,12 @@ handle_declaration(CPPDeclaration *decl, CPPScope *global_scope, CPPPreprocessor *error_sink) { CPPTypedefType *def = decl->as_typedef_type(); if (def != NULL) { - string name = def->get_simple_name(); - - pair result = - _types.insert(Types::value_type(name, def)); - - if (!result.second) { - CPPType *other_type = result.first->second; - CPPTypedefType *other_td = other_type->as_typedef_type(); - - // We don't do redefinitions of typedefs. But we don't complain as long - // as this is actually a typedef to the previous definition. - if (other_type != def->_type && - (other_td == NULL || !other_td->_type->is_equivalent(*def->_type))) { - - if (error_sink != NULL) { - ostringstream errstr; - def->output(errstr, 0, NULL, false); - errstr << " has conflicting declaration as "; - other_type->output(errstr, 0, NULL, true); - error_sink->error(errstr.str(), def->_ident->_loc); - error_sink->error("previous definition is here", - other_td->_ident->_loc); - } - } - } else { - _types[name] = def; - } + define_typedef_type(def, error_sink); CPPExtensionType *et = def->_type->as_extension_type(); if (et != NULL) { define_extension_type(et, error_sink); } - return; } diff --git a/dtool/src/cppparser/cppScope.h b/dtool/src/cppparser/cppScope.h index 7941a9afb1..75eaa53c6a 100644 --- a/dtool/src/cppparser/cppScope.h +++ b/dtool/src/cppparser/cppScope.h @@ -61,9 +61,9 @@ public: virtual void add_declaration(CPPDeclaration *decl, CPPScope *global_scope, CPPPreprocessor *preprocessor, const cppyyltype &pos); - virtual void add_enum_value(CPPInstance *inst, - CPPPreprocessor *preprocessor, - const cppyyltype &pos); + virtual void add_enum_value(CPPInstance *inst); + virtual void define_typedef_type(CPPTypedefType *type, + CPPPreprocessor *error_sink = NULL); virtual void define_extension_type(CPPExtensionType *type, CPPPreprocessor *error_sink = NULL); virtual void define_namespace(CPPNamespace *scope); diff --git a/dtool/src/cppparser/cppStructType.cxx b/dtool/src/cppparser/cppStructType.cxx index f1f610c191..49eee9c436 100644 --- a/dtool/src/cppparser/cppStructType.cxx +++ b/dtool/src/cppparser/cppStructType.cxx @@ -674,7 +674,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst, // If the struct name didn't have an explicit template reference // before, now it does. - if (!_ident->_names.empty() && !_ident->_names.back().has_templ()) { + if (_ident != NULL && !_ident->_names.empty() && !_ident->_names.back().has_templ()) { if (rep->is_template()) { rep->_template_scope = (CPPTemplateScope *)NULL; CPPNameComponent nc(get_simple_name()); diff --git a/dtool/src/cppparser/cppTemplateScope.cxx b/dtool/src/cppparser/cppTemplateScope.cxx index baa36a5619..50618b026d 100644 --- a/dtool/src/cppparser/cppTemplateScope.cxx +++ b/dtool/src/cppparser/cppTemplateScope.cxx @@ -43,11 +43,20 @@ add_declaration(CPPDeclaration *decl, CPPScope *global_scope, * */ void CPPTemplateScope:: -add_enum_value(CPPInstance *inst, CPPPreprocessor *preprocessor, - const cppyyltype &pos) { +add_enum_value(CPPInstance *inst) { inst->_template_scope = this; assert(_parent_scope != NULL); - _parent_scope->add_enum_value(inst, preprocessor, pos); + _parent_scope->add_enum_value(inst); +} + +/** + * + */ +void CPPTemplateScope:: +define_typedef_type(CPPTypedefType *type, CPPPreprocessor *error_sink) { + type->_template_scope = this; + assert(_parent_scope != NULL); + _parent_scope->define_typedef_type(type, error_sink); } /** diff --git a/dtool/src/cppparser/cppTemplateScope.h b/dtool/src/cppparser/cppTemplateScope.h index 7ce48f34f3..91235ff0fe 100644 --- a/dtool/src/cppparser/cppTemplateScope.h +++ b/dtool/src/cppparser/cppTemplateScope.h @@ -33,9 +33,9 @@ public: virtual void add_declaration(CPPDeclaration *decl, CPPScope *global_scope, CPPPreprocessor *preprocessor, const cppyyltype &pos); - virtual void add_enum_value(CPPInstance *inst, - CPPPreprocessor *preprocessor, - const cppyyltype &pos); + virtual void add_enum_value(CPPInstance *inst); + virtual void define_typedef_type(CPPTypedefType *type, + CPPPreprocessor *error_sink = NULL); virtual void define_extension_type(CPPExtensionType *type, CPPPreprocessor *error_sink = NULL); virtual void define_namespace(CPPNamespace *scope); diff --git a/dtool/src/cppparser/cppTypedefType.cxx b/dtool/src/cppparser/cppTypedefType.cxx index c86e684420..7f3443f600 100644 --- a/dtool/src/cppparser/cppTypedefType.cxx +++ b/dtool/src/cppparser/cppTypedefType.cxx @@ -193,6 +193,17 @@ is_fully_specified() const { _type->is_fully_specified(); } +/** + * + */ +CPPDeclaration *CPPTypedefType:: +instantiate(const CPPTemplateParameterList *actual_params, + CPPScope *current_scope, CPPScope *global_scope, + CPPPreprocessor *error_sink) const { + + return _type->instantiate(actual_params, current_scope, global_scope, error_sink); +} + /** * */ @@ -320,6 +331,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const { if (complete) { if (_using) { // It was declared using the "using" keyword. + if (is_template()) { + get_template_scope()->_parameters.write_formal(out, scope); + indent(out, indent_level); + } out << "using " << name << " = "; _type->output(out, 0, scope, false); } else { diff --git a/dtool/src/cppparser/cppTypedefType.h b/dtool/src/cppparser/cppTypedefType.h index 921c802383..2eae58cc68 100644 --- a/dtool/src/cppparser/cppTypedefType.h +++ b/dtool/src/cppparser/cppTypedefType.h @@ -21,7 +21,9 @@ class CPPIdentifier; class CPPInstanceIdentifier; /** - * + * A type alias created by a C++ typedef or using declaration. These aren't + * officially supposed to be types in themselves, but we represent them as + * such so that we can preserve typedef names in the generated code. */ class CPPTypedefType : public CPPType { public: @@ -46,6 +48,11 @@ public: virtual bool is_fully_specified() const; + virtual CPPDeclaration * + instantiate(const CPPTemplateParameterList *actual_params, + CPPScope *current_scope, CPPScope *global_scope, + CPPPreprocessor *error_sink = NULL) const; + virtual CPPDeclaration *substitute_decl(SubstDecl &subst, CPPScope *current_scope, CPPScope *global_scope); diff --git a/dtool/src/dtoolbase/addHash.I b/dtool/src/dtoolbase/addHash.I index ddc1c737fb..57084af72c 100644 --- a/dtool/src/dtoolbase/addHash.I +++ b/dtool/src/dtoolbase/addHash.I @@ -15,8 +15,8 @@ * Adds a linear sequence of uint32 words to the hash. */ INLINE size_t AddHash:: -add_hash(size_t start, const PN_uint32 *words, size_t num_words) { - return (size_t)hashword(words, num_words, (PN_uint32)start); +add_hash(size_t start, const uint32_t *words, size_t num_words) { + return (size_t)hashword(words, num_words, (uint32_t)start); } /** @@ -24,7 +24,7 @@ add_hash(size_t start, const PN_uint32 *words, size_t num_words) { */ INLINE size_t AddHash:: add_hash(size_t start, const PN_float32 *floats, size_t num_floats) { - return add_hash(start, (const PN_uint32 *)floats, num_floats); + return add_hash(start, (const uint32_t *)floats, num_floats); } /** @@ -32,5 +32,5 @@ add_hash(size_t start, const PN_float32 *floats, size_t num_floats) { */ INLINE size_t AddHash:: add_hash(size_t start, const PN_float64 *floats, size_t num_floats) { - return add_hash(start, (const PN_uint32 *)floats, num_floats * 2); + return add_hash(start, (const uint32_t *)floats, num_floats * 2); } diff --git a/dtool/src/dtoolbase/addHash.cxx b/dtool/src/dtoolbase/addHash.cxx index fd3717960d..5d7698b726 100644 --- a/dtool/src/dtoolbase/addHash.cxx +++ b/dtool/src/dtoolbase/addHash.cxx @@ -17,33 +17,33 @@ * Adds a linear sequence of bytes to the hash. */ size_t AddHash:: -add_hash(size_t start, const PN_uint8 *bytes, size_t num_bytes) { +add_hash(size_t start, const uint8_t *bytes, size_t num_bytes) { size_t num_words = num_bytes >> 2; size_t remaining_bytes = num_bytes - (num_words << 2); - size_t hash = (size_t)hashword((const PN_uint32 *)bytes, num_words, (PN_uint32)start); + size_t hash = (size_t)hashword((const uint32_t *)bytes, num_words, (uint32_t)start); switch (remaining_bytes) { case 3: { - PN_uint32 remaining; + uint32_t remaining; remaining = (bytes[num_bytes - 3] << 16) | (bytes[num_bytes - 2] << 8) | (bytes[num_bytes - 1]); - hash = (size_t)hashword(&remaining, 1, (PN_uint32)hash); + hash = (size_t)hashword(&remaining, 1, (uint32_t)hash); } break; case 2: { - PN_uint32 remaining; + uint32_t remaining; remaining = (bytes[num_bytes - 2] << 8) | (bytes[num_bytes - 1]); - hash = (size_t)hashword(&remaining, 1, (PN_uint32)hash); + hash = (size_t)hashword(&remaining, 1, (uint32_t)hash); } break; case 1: { - PN_uint32 remaining; + uint32_t remaining; remaining = (bytes[num_bytes - 1]); - hash = (size_t)hashword(&remaining, 1, (PN_uint32)hash); + hash = (size_t)hashword(&remaining, 1, (uint32_t)hash); } break; diff --git a/dtool/src/dtoolbase/addHash.h b/dtool/src/dtoolbase/addHash.h index fba194b688..11fabf77ce 100644 --- a/dtool/src/dtoolbase/addHash.h +++ b/dtool/src/dtoolbase/addHash.h @@ -25,8 +25,8 @@ */ class EXPCL_DTOOL AddHash { public: - INLINE static size_t add_hash(size_t start, const PN_uint32 *words, size_t num_words); - static size_t add_hash(size_t start, const PN_uint8 *bytes, size_t num_bytes); + INLINE static size_t add_hash(size_t start, const uint32_t *words, size_t num_words); + static size_t add_hash(size_t start, const uint8_t *bytes, size_t num_bytes); INLINE static size_t add_hash(size_t start, const PN_float32 *floats, size_t num_floats); INLINE static size_t add_hash(size_t start, const PN_float64 *floats, size_t num_floats); }; diff --git a/dtool/src/dtoolbase/atomicAdjustI386Impl.h b/dtool/src/dtoolbase/atomicAdjustI386Impl.h index c9db9a806d..3084a7172b 100644 --- a/dtool/src/dtoolbase/atomicAdjustI386Impl.h +++ b/dtool/src/dtoolbase/atomicAdjustI386Impl.h @@ -28,7 +28,7 @@ */ class EXPCL_DTOOL AtomicAdjustI386Impl { public: - typedef ALIGN_4BYTE PN_int32 Integer; + typedef ALIGN_4BYTE int32_t Integer; typedef void *UnalignedPointer; typedef ALIGN_4BYTE UnalignedPointer Pointer; diff --git a/dtool/src/dtoolbase/dlmalloc.h b/dtool/src/dtoolbase/dlmalloc.h deleted file mode 100644 index c79fb95e76..0000000000 --- a/dtool/src/dtoolbase/dlmalloc.h +++ /dev/null @@ -1,534 +0,0 @@ -/* - Default header file for malloc-2.8.x, written by Doug Lea - and released to the public domain, as explained at - http://creativecommons.org/licenses/publicdomain. - - last update: Mon Aug 15 08:55:52 2005 Doug Lea (dl at gee) - - This header is for ANSI C/C++ only. You can set any of - the following #defines before including: - - * If USE_DL_PREFIX is defined, it is assumed that malloc.c - was also compiled with this option, so all routines - have names starting with "dl". - - * If HAVE_USR_INCLUDE_MALLOC_H is defined, it is assumed that this - file will be #included AFTER . This is needed only if - your system defines a struct mallinfo that is incompatible with the - standard one declared here. Otherwise, you can include this file - INSTEAD of your system system . At least on ANSI, all - declarations should be compatible with system versions - - * If MSPACES is defined, declarations for mspace versions are included. -*/ - -#ifndef MALLOC_280_H -#define MALLOC_280_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include /* for size_t */ - -#if !ONLY_MSPACES - -#ifndef USE_DL_PREFIX -#define dlcalloc calloc -#define dlfree free -#define dlmalloc malloc -#define dlmemalign memalign -#define dlrealloc realloc -#define dlvalloc valloc -#define dlpvalloc pvalloc -#define dlmallinfo mallinfo -#define dlmallopt mallopt -#define dlmalloc_trim malloc_trim -#define dlmalloc_stats malloc_stats -#define dlmalloc_usable_size malloc_usable_size -#define dlmalloc_footprint malloc_footprint -#define dlindependent_calloc independent_calloc -#define dlindependent_comalloc independent_comalloc -#endif /* USE_DL_PREFIX */ - - -/* - malloc(size_t n) - Returns a pointer to a newly allocated chunk of at least n bytes, or - null if no space is available, in which case errno is set to ENOMEM - on ANSI C systems. - - If n is zero, malloc returns a minimum-sized chunk. (The minimum - size is 16 bytes on most 32bit systems, and 32 bytes on 64bit - systems.) Note that size_t is an unsigned type, so calls with - arguments that would be negative if signed are interpreted as - requests for huge amounts of space, which will often fail. The - maximum supported value of n differs across systems, but is in all - cases less than the maximum representable value of a size_t. -*/ -void* dlmalloc(size_t); - -/* - free(void* p) - Releases the chunk of memory pointed to by p, that had been previously - allocated using malloc or a related routine such as realloc. - It has no effect if p is null. If p was not malloced or already - freed, free(p) will by default cuase the current program to abort. -*/ -void dlfree(void*); - -/* - calloc(size_t n_elements, size_t element_size); - Returns a pointer to n_elements * element_size bytes, with all locations - set to zero. -*/ -void* dlcalloc(size_t, size_t); - -/* - realloc(void* p, size_t n) - Returns a pointer to a chunk of size n that contains the same data - as does chunk p up to the minimum of (n, p's size) bytes, or null - if no space is available. - - The returned pointer may or may not be the same as p. The algorithm - prefers extending p in most cases when possible, otherwise it - employs the equivalent of a malloc-copy-free sequence. - - If p is null, realloc is equivalent to malloc. - - If space is not available, realloc returns null, errno is set (if on - ANSI) and p is NOT freed. - - if n is for fewer bytes than already held by p, the newly unused - space is lopped off and freed if possible. realloc with a size - argument of zero (re)allocates a minimum-sized chunk. - - The old unix realloc convention of allowing the last-free'd chunk - to be used as an argument to realloc is not supported. -*/ - -void* dlrealloc(void*, size_t); - -/* - memalign(size_t alignment, size_t n); - Returns a pointer to a newly allocated chunk of n bytes, aligned - in accord with the alignment argument. - - The alignment argument should be a power of two. If the argument is - not a power of two, the nearest greater power is used. - 8-byte alignment is guaranteed by normal malloc calls, so don't - bother calling memalign with an argument of 8 or less. - - Overreliance on memalign is a sure way to fragment space. -*/ -void* dlmemalign(size_t, size_t); - -/* - valloc(size_t n); - Equivalent to memalign(pagesize, n), where pagesize is the page - size of the system. If the pagesize is unknown, 4096 is used. -*/ -void* dlvalloc(size_t); - -/* - mallopt(int parameter_number, int parameter_value) - Sets tunable parameters The format is to provide a - (parameter-number, parameter-value) pair. mallopt then sets the - corresponding parameter to the argument value if it can (i.e., so - long as the value is meaningful), and returns 1 if successful else - 0. SVID/XPG/ANSI defines four standard param numbers for mallopt, - normally defined in malloc.h. None of these are use in this malloc, - so setting them has no effect. But this malloc also supports other - options in mallopt: - - Symbol param # default allowed param values - M_TRIM_THRESHOLD -1 2*1024*1024 any (-1U disables trimming) - M_GRANULARITY -2 page size any power of 2 >= page size - M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) -*/ -int dlmallopt(int, int); - -#ifndef M_TRIM_THRESHOLD -#define M_TRIM_THRESHOLD (-1) -#endif -#ifndef M_GRANULARITY -#define M_GRANULARITY (-2) -#endif -#ifndef M_MMAP_THRESHOLD -#define M_MMAP_THRESHOLD (-3) -#endif - -/* - malloc_footprint(); - Returns the number of bytes obtained from the system. The total - number of bytes allocated by malloc, realloc etc., is less than this - value. Unlike mallinfo, this function returns only a precomputed - result, so can be called frequently to monitor memory consumption. - Even if locks are otherwise defined, this function does not use them, - so results might not be up to date. -*/ -size_t dlmalloc_footprint(); - -#if !NO_MALLINFO -/* - mallinfo() - Returns (by copy) a struct containing various summary statistics: - - arena: current total non-mmapped bytes allocated from system - ordblks: the number of free chunks - smblks: always zero. - hblks: current number of mmapped regions - hblkhd: total bytes held in mmapped regions - usmblks: the maximum total allocated space. This will be greater - than current total if trimming has occurred. - fsmblks: always zero - uordblks: current total allocated space (normal or mmapped) - fordblks: total free space - keepcost: the maximum number of bytes that could ideally be released - back to system via malloc_trim. ("ideally" means that - it ignores page restrictions etc.) - - Because these fields are ints, but internal bookkeeping may - be kept as longs, the reported values may wrap around zero and - thus be inaccurate. -*/ -#ifndef HAVE_USR_INCLUDE_MALLOC_H -#ifndef _MALLOC_H -#ifndef MALLINFO_FIELD_TYPE -#define MALLINFO_FIELD_TYPE size_t -#endif /* MALLINFO_FIELD_TYPE */ -struct mallinfo { - MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ - MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ - MALLINFO_FIELD_TYPE smblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ - MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ - MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ - MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ - MALLINFO_FIELD_TYPE fordblks; /* total free space */ - MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ -}; -#endif /* _MALLOC_H */ -#endif /* HAVE_USR_INCLUDE_MALLOC_H */ - -struct mallinfo dlmallinfo(void); -#endif /* NO_MALLINFO */ - -/* - independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); - - independent_calloc is similar to calloc, but instead of returning a - single cleared space, it returns an array of pointers to n_elements - independent elements that can hold contents of size elem_size, each - of which starts out cleared, and can be independently freed, - realloc'ed etc. The elements are guaranteed to be adjacently - allocated (this is not guaranteed to occur with multiple callocs or - mallocs), which may also improve cache locality in some - applications. - - The "chunks" argument is optional (i.e., may be null, which is - probably the most typical usage). If it is null, the returned array - is itself dynamically allocated and should also be freed when it is - no longer needed. Otherwise, the chunks array must be of at least - n_elements in length. It is filled in with the pointers to the - chunks. - - In either case, independent_calloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and "chunks" - is null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use regular calloc and assign pointers into this - space to represent elements. (In this case though, you cannot - independently free elements.) - - independent_calloc simplifies and speeds up implementations of many - kinds of pools. It may also be useful when constructing large data - structures that initially have a fixed number of fixed-sized nodes, - but the number is not known at compile time, and some of the nodes - may later need to be freed. For example: - - struct Node { int item; struct Node* next; }; - - struct Node* build_list() { - struct Node** pool; - int n = read_number_of_nodes_needed(); - if (n <= 0) return 0; - pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); - if (pool == 0) die(); - // organize into a linked list... - struct Node* first = pool[0]; - for (i = 0; i < n-1; ++i) - pool[i]->next = pool[i+1]; - free(pool); // Can now free the array (or not, if it is needed later) - return first; - } -*/ -void** dlindependent_calloc(size_t, size_t, void**); - -/* - independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); - - independent_comalloc allocates, all at once, a set of n_elements - chunks with sizes indicated in the "sizes" array. It returns - an array of pointers to these elements, each of which can be - independently freed, realloc'ed etc. The elements are guaranteed to - be adjacently allocated (this is not guaranteed to occur with - multiple callocs or mallocs), which may also improve cache locality - in some applications. - - The "chunks" argument is optional (i.e., may be null). If it is null - the returned array is itself dynamically allocated and should also - be freed when it is no longer needed. Otherwise, the chunks array - must be of at least n_elements in length. It is filled in with the - pointers to the chunks. - - In either case, independent_comalloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and chunks is - null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use a single regular malloc, and assign pointers at - particular offsets in the aggregate space. (In this case though, you - cannot independently free elements.) - - independent_comallac differs from independent_calloc in that each - element may have a different size, and also that it does not - automatically clear elements. - - independent_comalloc can be used to speed up allocation in cases - where several structs or objects must always be allocated at the - same time. For example: - - struct Head { ... } - struct Foot { ... } - - void send_message(char* msg) { - int msglen = strlen(msg); - size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; - void* chunks[3]; - if (independent_comalloc(3, sizes, chunks) == 0) - die(); - struct Head* head = (struct Head*)(chunks[0]); - char* body = (char*)(chunks[1]); - struct Foot* foot = (struct Foot*)(chunks[2]); - // ... - } - - In general though, independent_comalloc is worth using only for - larger values of n_elements. For small values, you probably won't - detect enough difference from series of malloc calls to bother. - - Overuse of independent_comalloc can increase overall memory usage, - since it cannot reuse existing noncontiguous small chunks that - might be available for some of the elements. -*/ -void** dlindependent_comalloc(size_t, size_t*, void**); - - -/* - pvalloc(size_t n); - Equivalent to valloc(minimum-page-that-holds(n)), that is, - round up n to nearest pagesize. - */ -void* dlpvalloc(size_t); - -/* - malloc_trim(size_t pad); - - If possible, gives memory back to the system (via negative arguments - to sbrk) if there is unused memory at the `high' end of the malloc - pool or in unused MMAP segments. You can call this after freeing - large blocks of memory to potentially reduce the system-level memory - requirements of a program. However, it cannot guarantee to reduce - memory. Under some allocation patterns, some large free blocks of - memory will be locked between two used chunks, so they cannot be - given back to the system. - - The `pad' argument to malloc_trim represents the amount of free - trailing space to leave untrimmed. If this argument is zero, only - the minimum amount of memory to maintain internal data structures - will be left. Non-zero arguments can be supplied to maintain enough - trailing space to service future expected allocations without having - to re-obtain memory from the system. - - Malloc_trim returns 1 if it actually released any memory, else 0. -*/ -int dlmalloc_trim(size_t); - -/* - malloc_usable_size(void* p); - - Returns the number of bytes you can actually use in - an allocated chunk, which may be more than you requested (although - often not) due to alignment and minimum size constraints. - You can use this many bytes without worrying about - overwriting other allocated objects. This is not a particularly great - programming practice. malloc_usable_size can be more useful in - debugging and assertions, for example: - - p = malloc(n); - assert(malloc_usable_size(p) >= 256); -*/ -size_t dlmalloc_usable_size(void*); - -/* - malloc_stats(); - Prints on stderr the amount of space obtained from the system (both - via sbrk and mmap), the maximum amount (which may be more than - current if malloc_trim and/or munmap got called), and the current - number of bytes allocated via malloc (or realloc, etc) but not yet - freed. Note that this is the number of bytes allocated, not the - number requested. It will be larger than the number requested - because of alignment and bookkeeping overhead. Because it includes - alignment wastage as being in use, this figure may be greater than - zero even when no user-level chunks are allocated. - - The reported current and maximum system memory can be inaccurate if - a program makes other calls to system memory allocation functions - (normally sbrk) outside of malloc. - - malloc_stats prints only the most commonly interesting statistics. - More information can be obtained by calling mallinfo. -*/ -void dlmalloc_stats(); - -#endif /* !ONLY_MSPACES */ - -#if MSPACES - -/* - mspace is an opaque type representing an independent - region of space that supports mspace_malloc, etc. -*/ -typedef void* mspace; - -/* - create_mspace creates and returns a new independent space with the - given initial capacity, or, if 0, the default granularity size. It - returns null if there is no system memory available to create the - space. If argument locked is non-zero, the space uses a separate - lock to control access. The capacity of the space will grow - dynamically as needed to service mspace_malloc requests. You can - control the sizes of incremental increases of this space by - compiling with a different DEFAULT_GRANULARITY or dynamically - setting with mallopt(M_GRANULARITY, value). -*/ -mspace create_mspace(size_t capacity, int locked); - -/* - destroy_mspace destroys the given space, and attempts to return all - of its memory back to the system, returning the total number of - bytes freed. After destruction, the results of access to all memory - used by the space become undefined. -*/ -size_t destroy_mspace(mspace msp); - -/* - create_mspace_with_base uses the memory supplied as the initial base - of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this - space is used for bookkeeping, so the capacity must be at least this - large. (Otherwise 0 is returned.) When this initial space is - exhausted, additional memory will be obtained from the system. - Destroying this space will deallocate all additionally allocated - space (if possible) but not the initial base. -*/ -mspace create_mspace_with_base(void* base, size_t capacity, int locked); - -/* - mspace_malloc behaves as malloc, but operates within - the given space. -*/ -void* mspace_malloc(mspace msp, size_t bytes); - -/* - mspace_free behaves as free, but operates within - the given space. - - If compiled with FOOTERS==1, mspace_free is not actually needed. - free may be called instead of mspace_free because freed chunks from - any space are handled by their originating spaces. -*/ -void mspace_free(mspace msp, void* mem); - -/* - mspace_realloc behaves as realloc, but operates within - the given space. - - If compiled with FOOTERS==1, mspace_realloc is not actually - needed. realloc may be called instead of mspace_realloc because - realloced chunks from any space are handled by their originating - spaces. -*/ -void* mspace_realloc(mspace msp, void* mem, size_t newsize); - -/* - mspace_calloc behaves as calloc, but operates within - the given space. -*/ -void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); - -/* - mspace_memalign behaves as memalign, but operates within - the given space. -*/ -void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); - -/* - mspace_independent_calloc behaves as independent_calloc, but - operates within the given space. -*/ -void** mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, void* chunks[]); - -/* - mspace_independent_comalloc behaves as independent_comalloc, but - operates within the given space. -*/ -void** mspace_independent_comalloc(mspace msp, size_t n_elements, - size_t sizes[], void* chunks[]); - -/* - mspace_footprint() returns the number of bytes obtained from the - system for this space. -*/ -size_t mspace_footprint(mspace msp); - - -#if !NO_MALLINFO -/* - mspace_mallinfo behaves as mallinfo, but reports properties of - the given space. -*/ -struct mallinfo mspace_mallinfo(mspace msp); -#endif /* NO_MALLINFO */ - -/* - mspace_malloc_stats behaves as malloc_stats, but reports - properties of the given space. -*/ -void mspace_malloc_stats(mspace msp); - -/* - mspace_trim behaves as malloc_trim, but - operates within the given space. -*/ -int mspace_trim(mspace msp, size_t pad); - -/* - An alias for mallopt. -*/ -int mspace_mallopt(int, int); - -#endif /* MSPACES */ - -#ifdef __cplusplus -}; /* end of extern "C" */ -#endif - -#endif /* MALLOC_280_H */ diff --git a/dtool/src/dtoolbase/dlmalloc_src.cxx b/dtool/src/dtoolbase/dlmalloc_src.cxx index 4e21f4c914..008350de73 100644 --- a/dtool/src/dtoolbase/dlmalloc_src.cxx +++ b/dtool/src/dtoolbase/dlmalloc_src.cxx @@ -1,22 +1,10 @@ - -#include "dtoolbase.h" - -#ifdef USE_MEMORY_DLMALLOC -#define USE_DL_PREFIX 1 -#define NO_MALLINFO 1 - -/* Define this to enable spammy "memmatch" debug output, which can be - processed by direct/src/directscripts/memmatch.py. */ -/*#define MEMMATCH 1*/ - /* This is a version (aka dlmalloc) of malloc/free/realloc written by Doug Lea and released to the public domain, as explained at - http://creativecommons.org/licenses/publicdomain. Send questions, + http://creativecommons.org/publicdomain/zero/1.0/ Send questions, comments, complaints, performance data, etc to dl@cs.oswego.edu -* Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee) - +* Version 2.8.6 Wed Aug 29 06:57:58 2012 Doug Lea Note: There may be an updated version of this malloc obtainable at ftp://gee.cs.oswego.edu/pub/misc/malloc.c Check before installing! @@ -30,7 +18,7 @@ compile-time and dynamic tuning options. For convenience, an include file for code using this malloc is at: - ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h + ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.6.h You don't really need this .h file unless you call functions not defined in your system include files. The .h file contains only the excerpts from this file needed for using this malloc on ANSI C/C++ @@ -52,7 +40,7 @@ than pointers, you can use a previous release of this malloc (e.g. 2.7.2) supporting these.) - Alignment: 8 bytes (default) + Alignment: 8 bytes (minimum) This suffices for nearly all current machines and C compilers. However, you can define MALLOC_ALIGNMENT to be wider than this if necessary (up to 128bytes), at the expense of using more space. @@ -115,15 +103,28 @@ no errors or vulnerabilities, you can define INSECURE to 1, which might (or might not) provide a small performance improvement. - Thread-safety: NOT thread-safe unless USE_LOCKS defined + It is also possible to limit the maximum total allocatable + space, using malloc_set_footprint_limit. This is not + designed as a security feature in itself (calls to set limits + are not screened or privileged), but may be useful as one + aspect of a secure implementation. + + Thread-safety: NOT thread-safe unless USE_LOCKS defined non-zero When USE_LOCKS is defined, each public call to malloc, free, - etc is surrounded with either a pthread mutex or a win32 - spinlock (depending on WIN32). This is not especially fast, and - can be a major bottleneck. It is designed only to provide - minimal protection in concurrent environments, and to provide a - basis for extensions. If you are using malloc in a concurrent - program, consider instead using ptmalloc, which is derived from - a version of this malloc. (See http://www.malloc.de). + etc is surrounded with a lock. By default, this uses a plain + pthread mutex, win32 critical section, or a spin-lock if if + available for the platform and not disabled by setting + USE_SPIN_LOCKS=0. However, if USE_RECURSIVE_LOCKS is defined, + recursive versions are used instead (which are not required for + base functionality but may be needed in layered extensions). + Using a global lock is not especially fast, and can be a major + bottleneck. It is designed only to provide minimal protection + in concurrent environments, and to provide a basis for + extensions. If you are using malloc in a concurrent program, + consider instead using nedmalloc + (http://www.nedprod.com/programs/portable/nedmalloc/) or + ptmalloc (See http://www.malloc.de), which are derived from + versions of this malloc. System requirements: Any combination of MORECORE and/or MMAP/MUNMAP This malloc can use unix sbrk or any emulation (invoked using @@ -164,7 +165,11 @@ a size_t, not counting any clearing in calloc or copying in realloc, or actions surrounding MORECORE and MMAP that have times proportional to the number of non-contiguous regions returned by - system allocation routines, which is often just 1. + system allocation routines, which is often just 1. In real-time + applications, you can optionally suppress segment traversals using + NO_SEGMENT_TRAVERSAL, which assures bounded execution even when + system allocators return non-contiguous spaces, at the typical + expense of carrying around more memory and increased fragmentation. The implementation is not very modular and seriously overuses macros. Perhaps someday all C compilers will do as good a job @@ -208,19 +213,39 @@ conformance is only weakly checked, so usage errors are not always caught). If FOOTERS is defined, then each chunk carries around a tag indicating its originating mspace, and frees are directed to their - originating spaces. + originating spaces. Normally, this requires use of locks. ------------------------- Compile-time options --------------------------- Be careful in setting #define values for numerical constants of type size_t. On some systems, literal values are not automatically extended -to size_t precision unless they are explicitly casted. +to size_t precision unless they are explicitly casted. You can also +use the symbolic values MAX_SIZE_T, SIZE_T_ONE, etc below. WIN32 default: defined if _WIN32 defined Defining WIN32 sets up defaults for MS environment and compilers. - Otherwise defaults are for unix. + Otherwise defaults are for unix. Beware that there seem to be some + cases where this malloc might not be a pure drop-in replacement for + Win32 malloc: Random-looking failures from Win32 GDI API's (eg; + SetDIBits()) may be due to bugs in some video driver implementations + when pixel buffers are malloc()ed, and the region spans more than + one VirtualAlloc()ed region. Because dlmalloc uses a small (64Kb) + default granularity, pixel buffers may straddle virtual allocation + regions more often than when using the Microsoft allocator. You can + avoid this by using VirtualAlloc() and VirtualFree() for all pixel + buffers rather than using malloc(). If this is not possible, + recompile this malloc with a larger DEFAULT_GRANULARITY. Note: + in cases where MSC and gcc (cygwin) are known to differ on WIN32, + conditions use _MSC_VER to distinguish them. -MALLOC_ALIGNMENT default: (size_t)8 +DLMALLOC_EXPORT default: extern + Defines how public APIs are declared. If you want to export via a + Windows DLL, you might define this as + #define DLMALLOC_EXPORT extern __declspec(dllexport) + If you want a POSIX ELF shared object, you might use + #define DLMALLOC_EXPORT extern __attribute__((visibility("default"))) + +MALLOC_ALIGNMENT default: (size_t)(2 * sizeof(void *)) Controls the minimum alignment for malloc'ed chunks. It must be a power of two and at least 8, even on machines for which smaller alignments would suffice. It may be defined as larger than this @@ -237,7 +262,27 @@ ONLY_MSPACES default: 0 (false) USE_LOCKS default: 0 (false) Causes each call to each public routine to be surrounded with pthread or WIN32 mutex lock/unlock. (If set true, this can be - overridden on a per-mspace basis for mspace versions.) + overridden on a per-mspace basis for mspace versions.) If set to a + non-zero value other than 1, locks are used, but their + implementation is left out, so lock functions must be supplied manually, + as described below. + +USE_SPIN_LOCKS default: 1 iff USE_LOCKS and spin locks available + If true, uses custom spin locks for locking. This is currently + supported only gcc >= 4.1, older gccs on x86 platforms, and recent + MS compilers. Otherwise, posix locks or win32 critical sections are + used. + +USE_RECURSIVE_LOCKS default: not defined + If defined nonzero, uses recursive (aka reentrant) locks, otherwise + uses plain mutexes. This is not required for malloc proper, but may + be needed for layered allocators such as nedmalloc. + +LOCK_AT_FORK default: not defined + If defined nonzero, performs pthread_atfork upon initialization + to initialize child lock while holding parent lock. The implementation + assumes that pthread locks (not custom locks) are being used. In other + cases, you may need to customize the implementation. FOOTERS default: 0 If true, provide extra checking and dispatching by placing @@ -252,6 +297,12 @@ USE_DL_PREFIX default: NOT defined This can be useful when you only want to use this malloc in one part of a program, using your regular system malloc elsewhere. +MALLOC_INSPECT_ALL default: NOT defined + If defined, compiles malloc_inspect_all and mspace_inspect_all, that + perform traversal of all heap space. Unless access to these + functions is otherwise restricted, you probably do not want to + include them in secure implementations. + ABORT default: defined as abort() Defines how to abort on failed checks. On most systems, a failed check cannot die with an "assert" or even print an informative @@ -308,11 +359,9 @@ MORECORE default: sbrk size_t (sometimes declared as "intptr_t"). It doesn't much matter though. Internally, we only call it with arguments less than half the max value of a size_t, which should work across all reasonable - possibilities, although sometimes generating compiler warnings. See - near the end of this file for guidelines for creating a custom - version of MORECORE. + possibilities, although sometimes generating compiler warnings. -MORECORE_CONTIGUOUS default: 1 (true) +MORECORE_CONTIGUOUS default: 1 (true) if HAVE_MORECORE If true, take advantage of fact that consecutive calls to MORECORE with positive arguments always return contiguous increasing addresses. This is true of unix sbrk. It does not hurt too much to @@ -326,6 +375,12 @@ MORECORE_CANNOT_TRIM default: NOT defined using a hand-crafted MORECORE function that cannot handle negative arguments. +NO_SEGMENT_TRAVERSAL default: 0 + If non-zero, suppresses traversals of memory segments + returned by either MORECORE or CALL_MMAP. This disables + merging of segments that are contiguous, and selectively + releasing them to the OS if unused, but bounds execution times. + HAVE_MMAP default: 1 (true) True if this system supports mmap or an emulation of it. If so, and HAVE_MORECORE is not true, MMAP is used for all system @@ -340,17 +395,17 @@ HAVE_MREMAP default: 1 on linux, else 0 If true realloc() uses mremap() to re-allocate large blocks and extend or shrink allocation spaces. -MMAP_CLEARS default: 1 on unix +MMAP_CLEARS default: 1 except on WINCE. True if mmap clears memory so calloc doesn't need to. This is true - for standard unix mmap using /dev/zero. + for standard unix mmap using /dev/zero and on WIN32 except for WINCE. USE_BUILTIN_FFS default: 0 (i.e., not used) Causes malloc to use the builtin ffs() function to compute indices. Some compilers may recognize and intrinsify ffs to be faster than the supplied C version. Also, the case of x86 using gcc is special-cased to an asm instruction, so is already as fast as it can be, and so - this setting has no effect. (On most x86s, the asm version is only - slightly faster than the C version.) + this setting has no effect. Similarly for Win32 under recent MS compilers. + (On most x86s, the asm version is only slightly faster than the C version.) malloc_getpagesize default: derive from system includes, or 4096. The system page size. To the extent possible, this malloc manages @@ -373,15 +428,19 @@ MALLINFO_FIELD_TYPE default: size_t defined as "int" in SVID etc, but is more usefully defined as size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set +NO_MALLOC_STATS default: 0 + If defined, don't compile "malloc_stats". This avoids calls to + fprintf and bringing in stdio dependencies you might not want. + REALLOC_ZERO_BYTES_FREES default: not defined - This should be set if a call to realloc with zero bytes should - be the same as a call to free. Some people think it should. Otherwise, - since this malloc returns a unique pointer for malloc(0), so does + This should be set if a call to realloc with zero bytes should + be the same as a call to free. Some people think it should. Otherwise, + since this malloc returns a unique pointer for malloc(0), so does realloc(p, 0). LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H -LACKS_STDLIB_H default: NOT defined unless on WIN32 +LACKS_STDLIB_H LACKS_SCHED_H LACKS_TIME_H default: NOT defined unless on WIN32 Define these if your system does not have these header files. You might need to manually insert some of the declarations they provide. @@ -447,25 +506,45 @@ DEFAULT_MMAP_THRESHOLD default: 256K empirically derived value that works well in most systems. You can disable mmap by setting to MAX_SIZE_T. +MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP + The number of consolidated frees between checks to release + unused segments when freeing. When using non-contiguous segments, + especially with multiple mspaces, checking only for topmost space + doesn't always suffice to trigger trimming. To compensate for this, + free() will, with a period of MAX_RELEASE_CHECK_RATE (or the + current number of segments, if greater) try to release unused + segments to the OS when freeing chunks that result in + consolidation. The best value for this parameter is a compromise + between slowing down frees with relatively costly checks that + rarely trigger versus holding on to unused memory. To effectively + disable, set to MAX_SIZE_T. This may lead to a very slight speed + improvement at the expense of carrying around more memory. */ -#ifdef LINMATH_ALIGN -// 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. -#define MALLOC_ALIGNMENT ((size_t)16U) +/* Version identifier to allow people to support multiple versions */ +#ifndef DLMALLOC_VERSION +#define DLMALLOC_VERSION 20806 +#endif /* DLMALLOC_VERSION */ + +#ifndef DLMALLOC_EXPORT +#define DLMALLOC_EXPORT extern #endif #ifndef WIN32 #ifdef _WIN32 #define WIN32 1 #endif /* _WIN32 */ +#ifdef _WIN32_WCE +#define LACKS_FCNTL_H +#define WIN32 1 +#endif /* _WIN32_WCE */ #endif /* WIN32 */ #ifdef WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif #include +#include #define HAVE_MMAP 1 #define HAVE_MORECORE 0 #define LACKS_UNISTD_H @@ -475,8 +554,17 @@ DEFAULT_MMAP_THRESHOLD default: 256K #define LACKS_STRINGS_H #define LACKS_SYS_TYPES_H #define LACKS_ERRNO_H +#define LACKS_SCHED_H +#ifndef MALLOC_FAILURE_ACTION #define MALLOC_FAILURE_ACTION -#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */ +#endif /* MALLOC_FAILURE_ACTION */ +#ifndef MMAP_CLEARS +#ifdef _WIN32_WCE /* WINCE reportedly does not clear */ +#define MMAP_CLEARS 0 +#else +#define MMAP_CLEARS 1 +#endif /* _WIN32_WCE */ +#endif /*MMAP_CLEARS */ #endif /* WIN32 */ #if defined(DARWIN) || defined(_DARWIN) @@ -484,6 +572,10 @@ DEFAULT_MMAP_THRESHOLD default: 256K #ifndef HAVE_MORECORE #define HAVE_MORECORE 0 #define HAVE_MMAP 1 +/* OSX allocators provide 16 byte alignment */ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT ((size_t)16U) +#endif #endif /* HAVE_MORECORE */ #endif /* DARWIN */ @@ -494,6 +586,26 @@ DEFAULT_MMAP_THRESHOLD default: 256K /* The maximum possible size_t value has all bits set */ #define MAX_SIZE_T (~(size_t)0) +#ifndef USE_LOCKS /* ensure true if spin or recursive locks set */ +#define USE_LOCKS ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \ + (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0)) +#endif /* USE_LOCKS */ + +#if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */ +#if ((defined(__GNUC__) && \ + ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \ + defined(__i386__) || defined(__x86_64__))) || \ + (defined(_MSC_VER) && _MSC_VER>=1310)) +#ifndef USE_SPIN_LOCKS +#define USE_SPIN_LOCKS 1 +#endif /* USE_SPIN_LOCKS */ +#elif USE_SPIN_LOCKS +#error "USE_SPIN_LOCKS defined without implementation" +#endif /* ... locks available... */ +#elif !defined(USE_SPIN_LOCKS) +#define USE_SPIN_LOCKS 0 +#endif /* USE_LOCKS */ + #ifndef ONLY_MSPACES #define ONLY_MSPACES 0 #endif /* ONLY_MSPACES */ @@ -505,7 +617,7 @@ DEFAULT_MMAP_THRESHOLD default: 256K #endif /* ONLY_MSPACES */ #endif /* MSPACES */ #ifndef MALLOC_ALIGNMENT -#define MALLOC_ALIGNMENT ((size_t)8U) +#define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *))) #endif /* MALLOC_ALIGNMENT */ #ifndef FOOTERS #define FOOTERS 0 @@ -519,12 +631,13 @@ DEFAULT_MMAP_THRESHOLD default: 256K #ifndef PROCEED_ON_ERROR #define PROCEED_ON_ERROR 0 #endif /* PROCEED_ON_ERROR */ -#ifndef USE_LOCKS -#define USE_LOCKS 0 -#endif /* USE_LOCKS */ + #ifndef INSECURE #define INSECURE 0 #endif /* INSECURE */ +#ifndef MALLOC_INSPECT_ALL +#define MALLOC_INSPECT_ALL 0 +#endif /* MALLOC_INSPECT_ALL */ #ifndef HAVE_MMAP #define HAVE_MMAP 1 #endif /* HAVE_MMAP */ @@ -534,6 +647,7 @@ DEFAULT_MMAP_THRESHOLD default: 256K #ifndef HAVE_MREMAP #ifdef linux #define HAVE_MREMAP 1 +#define _GNU_SOURCE /* Turns on mremap() definition */ #else /* linux */ #define HAVE_MREMAP 0 #endif /* linux */ @@ -551,15 +665,13 @@ DEFAULT_MMAP_THRESHOLD default: 256K #if !HAVE_MORECORE #define MORECORE_CONTIGUOUS 0 #else /* !HAVE_MORECORE */ -#ifndef MORECORE -#define MORECORE sbrk -#endif /* MORECORE */ +#define MORECORE_DEFAULT sbrk #ifndef MORECORE_CONTIGUOUS #define MORECORE_CONTIGUOUS 1 #endif /* MORECORE_CONTIGUOUS */ #endif /* HAVE_MORECORE */ #ifndef DEFAULT_GRANULARITY -#if MORECORE_CONTIGUOUS +#if (MORECORE_CONTIGUOUS || defined(WIN32)) #define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ #else /* MORECORE_CONTIGUOUS */ #define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) @@ -579,6 +691,13 @@ DEFAULT_MMAP_THRESHOLD default: 256K #define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T #endif /* HAVE_MMAP */ #endif /* DEFAULT_MMAP_THRESHOLD */ +#ifndef MAX_RELEASE_CHECK_RATE +#if HAVE_MMAP +#define MAX_RELEASE_CHECK_RATE 4095 +#else +#define MAX_RELEASE_CHECK_RATE MAX_SIZE_T +#endif /* HAVE_MMAP */ +#endif /* MAX_RELEASE_CHECK_RATE */ #ifndef USE_BUILTIN_FFS #define USE_BUILTIN_FFS 0 #endif /* USE_BUILTIN_FFS */ @@ -591,6 +710,12 @@ DEFAULT_MMAP_THRESHOLD default: 256K #ifndef MALLINFO_FIELD_TYPE #define MALLINFO_FIELD_TYPE size_t #endif /* MALLINFO_FIELD_TYPE */ +#ifndef NO_MALLOC_STATS +#define NO_MALLOC_STATS 0 +#endif /* NO_MALLOC_STATS */ +#ifndef NO_SEGMENT_TRAVERSAL +#define NO_SEGMENT_TRAVERSAL 0 +#endif /* NO_SEGMENT_TRAVERSAL */ /* mallopt tuning options. SVID/XPG defines four standard parameter @@ -639,7 +764,10 @@ DEFAULT_MMAP_THRESHOLD default: 256K #ifdef HAVE_USR_INCLUDE_MALLOC_H #include "/usr/include/malloc.h" #else /* HAVE_USR_INCLUDE_MALLOC_H */ - +#ifndef STRUCT_MALLINFO_DECLARED +/* HP-UX (and others?) redefines mallinfo unless _STRUCT_MALLINFO is defined */ +#define _STRUCT_MALLINFO +#define STRUCT_MALLINFO_DECLARED 1 struct mallinfo { MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ @@ -652,13 +780,41 @@ struct mallinfo { MALLINFO_FIELD_TYPE fordblks; /* total free space */ MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ }; - +#endif /* STRUCT_MALLINFO_DECLARED */ #endif /* HAVE_USR_INCLUDE_MALLOC_H */ #endif /* NO_MALLINFO */ +/* + Try to persuade compilers to inline. The most critical functions for + inlining are defined as macros, so these aren't used for them. +*/ + +#ifndef FORCEINLINE + #if defined(__GNUC__) +#define FORCEINLINE __inline __attribute__ ((always_inline)) + #elif defined(_MSC_VER) + #define FORCEINLINE __forceinline + #endif +#endif +#ifndef NOINLINE + #if defined(__GNUC__) + #define NOINLINE __attribute__ ((noinline)) + #elif defined(_MSC_VER) + #define NOINLINE __declspec(noinline) + #else + #define NOINLINE + #endif +#endif + #ifdef __cplusplus extern "C" { +#ifndef FORCEINLINE + #define FORCEINLINE inline +#endif #endif /* __cplusplus */ +#ifndef FORCEINLINE + #define FORCEINLINE +#endif #if !ONLY_MSPACES @@ -669,7 +825,9 @@ extern "C" { #define dlfree free #define dlmalloc malloc #define dlmemalign memalign +#define dlposix_memalign posix_memalign #define dlrealloc realloc +#define dlrealloc_in_place realloc_in_place #define dlvalloc valloc #define dlpvalloc pvalloc #define dlmallinfo mallinfo @@ -679,11 +837,14 @@ extern "C" { #define dlmalloc_usable_size malloc_usable_size #define dlmalloc_footprint malloc_footprint #define dlmalloc_max_footprint malloc_max_footprint +#define dlmalloc_footprint_limit malloc_footprint_limit +#define dlmalloc_set_footprint_limit malloc_set_footprint_limit +#define dlmalloc_inspect_all malloc_inspect_all #define dlindependent_calloc independent_calloc #define dlindependent_comalloc independent_comalloc +#define dlbulk_free bulk_free #endif /* USE_DL_PREFIX */ - /* malloc(size_t n) Returns a pointer to a newly allocated chunk of at least n bytes, or @@ -698,7 +859,7 @@ extern "C" { maximum supported value of n differs across systems, but is in all cases less than the maximum representable value of a size_t. */ -void* dlmalloc(size_t); +DLMALLOC_EXPORT void* dlmalloc(size_t); /* free(void* p) @@ -707,14 +868,14 @@ void* dlmalloc(size_t); It has no effect if p is null. If p was not malloced or already freed, free(p) will by default cause the current program to abort. */ -void dlfree(void*); +DLMALLOC_EXPORT void dlfree(void*); /* calloc(size_t n_elements, size_t element_size); Returns a pointer to n_elements * element_size bytes, with all locations set to zero. */ -void* dlcalloc(size_t, size_t); +DLMALLOC_EXPORT void* dlcalloc(size_t, size_t); /* realloc(void* p, size_t n) @@ -738,8 +899,22 @@ void* dlcalloc(size_t, size_t); The old unix realloc convention of allowing the last-free'd chunk to be used as an argument to realloc is not supported. */ +DLMALLOC_EXPORT void* dlrealloc(void*, size_t); -void* dlrealloc(void*, size_t); +/* + realloc_in_place(void* p, size_t n) + Resizes the space allocated for p to size n, only if this can be + done without moving p (i.e., only if there is adjacent space + available if n is greater than p's current allocated size, or n is + less than or equal to p's size). This may be used instead of plain + realloc if an alternative allocation strategy is needed upon failure + to expand space; for example, reallocation of a buffer that must be + memory-aligned or cleared. You can use realloc_in_place to trigger + these alternatives only when needed. + + Returns p if successful; otherwise null. +*/ +DLMALLOC_EXPORT void* dlrealloc_in_place(void*, size_t); /* memalign(size_t alignment, size_t n); @@ -753,14 +928,24 @@ void* dlrealloc(void*, size_t); Overreliance on memalign is a sure way to fragment space. */ -void* dlmemalign(size_t, size_t); +DLMALLOC_EXPORT void* dlmemalign(size_t, size_t); + +/* + int posix_memalign(void** pp, size_t alignment, size_t n); + Allocates a chunk of n bytes, aligned in accord with the alignment + argument. Differs from memalign only in that it (1) assigns the + allocated memory to *pp rather than returning it, (2) fails and + returns EINVAL if the alignment is not a power of two (3) fails and + returns ENOMEM if memory cannot be allocated. +*/ +DLMALLOC_EXPORT int dlposix_memalign(void**, size_t, size_t); /* valloc(size_t n); Equivalent to memalign(pagesize, n), where pagesize is the page size of the system. If the pagesize is unknown, 4096 is used. */ -void* dlvalloc(size_t); +DLMALLOC_EXPORT void* dlvalloc(size_t); /* mallopt(int parameter_number, int parameter_value) @@ -768,7 +953,11 @@ void* dlvalloc(size_t); (parameter-number, parameter-value) pair. mallopt then sets the corresponding parameter to the argument value if it can (i.e., so long as the value is meaningful), and returns 1 if successful else - 0. SVID/XPG/ANSI defines four standard param numbers for mallopt, + 0. To workaround the fact that mallopt is specified to use int, + not size_t parameters, the value -1 is specially treated as the + maximum unsigned size_t value. + + SVID/XPG/ANSI defines four standard param numbers for mallopt, normally defined in malloc.h. None of these are use in this malloc, so setting them has no effect. But this malloc also supports other options in mallopt. See below for details. Briefly, supported @@ -776,11 +965,11 @@ void* dlvalloc(size_t); configurations). Symbol param # default allowed param values - M_TRIM_THRESHOLD -1 2*1024*1024 any (MAX_SIZE_T disables) + M_TRIM_THRESHOLD -1 2*1024*1024 any (-1 disables) M_GRANULARITY -2 page size any power of 2 >= page size M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) */ -int dlmallopt(int, int); +DLMALLOC_EXPORT int dlmallopt(int, int); /* malloc_footprint(); @@ -791,7 +980,7 @@ int dlmallopt(int, int); Even if locks are otherwise defined, this function does not use them, so results might not be up to date. */ -size_t dlmalloc_footprint(void); +DLMALLOC_EXPORT size_t dlmalloc_footprint(void); /* malloc_max_footprint(); @@ -804,7 +993,66 @@ size_t dlmalloc_footprint(void); otherwise defined, this function does not use them, so results might not be up to date. */ -size_t dlmalloc_max_footprint(void); +DLMALLOC_EXPORT size_t dlmalloc_max_footprint(void); + +/* + malloc_footprint_limit(); + Returns the number of bytes that the heap is allowed to obtain from + the system, returning the last value returned by + malloc_set_footprint_limit, or the maximum size_t value if + never set. The returned value reflects a permission. There is no + guarantee that this number of bytes can actually be obtained from + the system. +*/ +DLMALLOC_EXPORT size_t dlmalloc_footprint_limit(); + +/* + malloc_set_footprint_limit(); + Sets the maximum number of bytes to obtain from the system, causing + failure returns from malloc and related functions upon attempts to + exceed this value. The argument value may be subject to page + rounding to an enforceable limit; this actual value is returned. + Using an argument of the maximum possible size_t effectively + disables checks. If the argument is less than or equal to the + current malloc_footprint, then all future allocations that require + additional system memory will fail. However, invocation cannot + retroactively deallocate existing used memory. +*/ +DLMALLOC_EXPORT size_t dlmalloc_set_footprint_limit(size_t bytes); + +#if MALLOC_INSPECT_ALL +/* + malloc_inspect_all(void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg); + Traverses the heap and calls the given handler for each managed + region, skipping all bytes that are (or may be) used for bookkeeping + purposes. Traversal does not include include chunks that have been + directly memory mapped. Each reported region begins at the start + address, and continues up to but not including the end address. The + first used_bytes of the region contain allocated data. If + used_bytes is zero, the region is unallocated. The handler is + invoked with the given callback argument. If locks are defined, they + are held during the entire traversal. It is a bad idea to invoke + other malloc functions from within the handler. + + For example, to count the number of in-use chunks with size greater + than 1000, you could write: + static int count = 0; + void count_chunks(void* start, void* end, size_t used, void* arg) { + if (used >= 1000) ++count; + } + then: + malloc_inspect_all(count_chunks, NULL); + + malloc_inspect_all is compiled only if MALLOC_INSPECT_ALL is defined. +*/ +DLMALLOC_EXPORT void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*), + void* arg); + +#endif /* MALLOC_INSPECT_ALL */ #if !NO_MALLINFO /* @@ -829,7 +1077,7 @@ size_t dlmalloc_max_footprint(void); be kept as longs, the reported values may wrap around zero and thus be inaccurate. */ -struct mallinfo dlmallinfo(void); +DLMALLOC_EXPORT struct mallinfo dlmallinfo(void); #endif /* NO_MALLINFO */ /* @@ -856,11 +1104,8 @@ struct mallinfo dlmallinfo(void); is null, it returns a chunk representing an array with zero elements (which should be freed if not wanted). - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use regular calloc and assign pointers into this - space to represent elements. (In this case though, you cannot - independently free elements.) + Each element must be freed when it is no longer needed. This can be + done all at once using bulk_free. independent_calloc simplifies and speeds up implementations of many kinds of pools. It may also be useful when constructing large data @@ -884,7 +1129,7 @@ struct mallinfo dlmallinfo(void); return first; } */ -void** dlindependent_calloc(size_t, size_t, void**); +DLMALLOC_EXPORT void** dlindependent_calloc(size_t, size_t, void**); /* independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); @@ -908,11 +1153,8 @@ void** dlindependent_calloc(size_t, size_t, void**); null, it returns a chunk representing an array with zero elements (which should be freed if not wanted). - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use a single regular malloc, and assign pointers at - particular offsets in the aggregate space. (In this case though, you - cannot independently free elements.) + Each element must be freed when it is no longer needed. This can be + done all at once using bulk_free. independent_comallac differs from independent_calloc in that each element may have a different size, and also that it does not @@ -945,15 +1187,25 @@ void** dlindependent_calloc(size_t, size_t, void**); since it cannot reuse existing noncontiguous small chunks that might be available for some of the elements. */ -void** dlindependent_comalloc(size_t, size_t*, void**); +DLMALLOC_EXPORT void** dlindependent_comalloc(size_t, size_t*, void**); +/* + bulk_free(void* array[], size_t n_elements) + Frees and clears (sets to null) each non-null pointer in the given + array. This is likely to be faster than freeing them one-by-one. + If footers are used, pointers that have been allocated in different + mspaces are not freed or cleared, and the count of all such pointers + is returned. For large arrays of pointers with poor locality, it + may be worthwhile to sort this array before calling bulk_free. +*/ +DLMALLOC_EXPORT size_t dlbulk_free(void**, size_t n_elements); /* pvalloc(size_t n); Equivalent to valloc(minimum-page-that-holds(n)), that is, round up n to nearest pagesize. */ -void* dlpvalloc(size_t); +DLMALLOC_EXPORT void* dlpvalloc(size_t); /* malloc_trim(size_t pad); @@ -976,23 +1228,7 @@ void* dlpvalloc(size_t); Malloc_trim returns 1 if it actually released any memory, else 0. */ -int dlmalloc_trim(size_t); - -/* - malloc_usable_size(void* p); - - Returns the number of bytes you can actually use in - an allocated chunk, which may be more than you requested (although - often not) due to alignment and minimum size constraints. - You can use this many bytes without worrying about - overwriting other allocated objects. This is not a particularly great - programming practice. malloc_usable_size can be more useful in - debugging and assertions, for example: - - p = malloc(n); - assert(malloc_usable_size(p) >= 256); -*/ -size_t dlmalloc_usable_size(void*); +DLMALLOC_EXPORT int dlmalloc_trim(size_t); /* malloc_stats(); @@ -1013,7 +1249,23 @@ size_t dlmalloc_usable_size(void*); malloc_stats prints only the most commonly interesting statistics. More information can be obtained by calling mallinfo. */ -void dlmalloc_stats(void); +DLMALLOC_EXPORT void dlmalloc_stats(void); + +/* + malloc_usable_size(void* p); + + Returns the number of bytes you can actually use in + an allocated chunk, which may be more than you requested (although + often not) due to alignment and minimum size constraints. + You can use this many bytes without worrying about + overwriting other allocated objects. This is not a particularly great + programming practice. malloc_usable_size can be more useful in + debugging and assertions, for example: + + p = malloc(n); + assert(malloc_usable_size(p) >= 256); +*/ +size_t dlmalloc_usable_size(void*); #endif /* ONLY_MSPACES */ @@ -1036,7 +1288,7 @@ typedef void* mspace; compiling with a different DEFAULT_GRANULARITY or dynamically setting with mallopt(M_GRANULARITY, value). */ -mspace create_mspace(size_t capacity, int locked); +DLMALLOC_EXPORT mspace create_mspace(size_t capacity, int locked); /* destroy_mspace destroys the given space, and attempts to return all @@ -1044,7 +1296,7 @@ mspace create_mspace(size_t capacity, int locked); bytes freed. After destruction, the results of access to all memory used by the space become undefined. */ -size_t destroy_mspace(mspace msp); +DLMALLOC_EXPORT size_t destroy_mspace(mspace msp); /* create_mspace_with_base uses the memory supplied as the initial base @@ -1055,13 +1307,27 @@ size_t destroy_mspace(mspace msp); Destroying this space will deallocate all additionally allocated space (if possible) but not the initial base. */ -mspace create_mspace_with_base(void* base, size_t capacity, int locked); +DLMALLOC_EXPORT mspace create_mspace_with_base(void* base, size_t capacity, int locked); + +/* + mspace_track_large_chunks controls whether requests for large chunks + are allocated in their own untracked mmapped regions, separate from + others in this mspace. By default large chunks are not tracked, + which reduces fragmentation. However, such chunks are not + necessarily released to the system upon destroy_mspace. Enabling + tracking by setting to true may increase fragmentation, but avoids + leakage when relying on destroy_mspace to release all memory + allocated using this space. The function returns the previous + setting. +*/ +DLMALLOC_EXPORT int mspace_track_large_chunks(mspace msp, int enable); + /* mspace_malloc behaves as malloc, but operates within the given space. */ -void* mspace_malloc(mspace msp, size_t bytes); +DLMALLOC_EXPORT void* mspace_malloc(mspace msp, size_t bytes); /* mspace_free behaves as free, but operates within @@ -1071,7 +1337,7 @@ void* mspace_malloc(mspace msp, size_t bytes); free may be called instead of mspace_free because freed chunks from any space are handled by their originating spaces. */ -void mspace_free(mspace msp, void* mem); +DLMALLOC_EXPORT void mspace_free(mspace msp, void* mem); /* mspace_realloc behaves as realloc, but operates within @@ -1082,45 +1348,45 @@ void mspace_free(mspace msp, void* mem); realloced chunks from any space are handled by their originating spaces. */ -void* mspace_realloc(mspace msp, void* mem, size_t newsize); +DLMALLOC_EXPORT void* mspace_realloc(mspace msp, void* mem, size_t newsize); /* mspace_calloc behaves as calloc, but operates within the given space. */ -void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); +DLMALLOC_EXPORT void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); /* mspace_memalign behaves as memalign, but operates within the given space. */ -void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); +DLMALLOC_EXPORT void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); /* mspace_independent_calloc behaves as independent_calloc, but operates within the given space. */ -void** mspace_independent_calloc(mspace msp, size_t n_elements, +DLMALLOC_EXPORT void** mspace_independent_calloc(mspace msp, size_t n_elements, size_t elem_size, void* chunks[]); /* mspace_independent_comalloc behaves as independent_comalloc, but operates within the given space. */ -void** mspace_independent_comalloc(mspace msp, size_t n_elements, +DLMALLOC_EXPORT void** mspace_independent_comalloc(mspace msp, size_t n_elements, size_t sizes[], void* chunks[]); /* mspace_footprint() returns the number of bytes obtained from the system for this space. */ -size_t mspace_footprint(mspace msp); +DLMALLOC_EXPORT size_t mspace_footprint(mspace msp); /* mspace_max_footprint() returns the peak number of bytes obtained from the system for this space. */ -size_t mspace_max_footprint(mspace msp); +DLMALLOC_EXPORT size_t mspace_max_footprint(mspace msp); #if !NO_MALLINFO @@ -1128,30 +1394,35 @@ size_t mspace_max_footprint(mspace msp); mspace_mallinfo behaves as mallinfo, but reports properties of the given space. */ -struct mallinfo mspace_mallinfo(mspace msp); +DLMALLOC_EXPORT struct mallinfo mspace_mallinfo(mspace msp); #endif /* NO_MALLINFO */ +/* + malloc_usable_size(void* p) behaves the same as malloc_usable_size; +*/ +DLMALLOC_EXPORT size_t mspace_usable_size(const void* mem); + /* mspace_malloc_stats behaves as malloc_stats, but reports properties of the given space. */ -void mspace_malloc_stats(mspace msp); +DLMALLOC_EXPORT void mspace_malloc_stats(mspace msp); /* mspace_trim behaves as malloc_trim, but operates within the given space. */ -int mspace_trim(mspace msp, size_t pad); +DLMALLOC_EXPORT int mspace_trim(mspace msp, size_t pad); /* An alias for mallopt. */ -int mspace_mallopt(int, int); +DLMALLOC_EXPORT int mspace_mallopt(int, int); #endif /* MSPACES */ #ifdef __cplusplus -}; /* end of extern "C" */ +} /* end of extern "C" */ #endif /* __cplusplus */ /* @@ -1166,30 +1437,34 @@ int mspace_mallopt(int, int); /*------------------------------ internal #includes ---------------------- */ -#ifdef WIN32 +#ifdef _MSC_VER #pragma warning( disable : 4146 ) /* no "unsigned" warnings */ -#endif /* WIN32 */ - +#endif /* _MSC_VER */ +#if !NO_MALLOC_STATS #include /* for printing in malloc_stats */ - +#endif /* NO_MALLOC_STATS */ #ifndef LACKS_ERRNO_H #include /* for MALLOC_FAILURE_ACTION */ #endif /* LACKS_ERRNO_H */ -#if FOOTERS -#include /* for magic initialization */ -#endif /* FOOTERS */ -#ifndef LACKS_STDLIB_H -#include /* for abort() */ -#endif /* LACKS_STDLIB_H */ #ifdef DEBUG #if ABORT_ON_ASSERT_FAILURE +#undef assert #define assert(x) if(!(x)) ABORT #else /* ABORT_ON_ASSERT_FAILURE */ #include #endif /* ABORT_ON_ASSERT_FAILURE */ #else /* DEBUG */ +#ifndef assert #define assert(x) +#endif +#define DEBUG 0 #endif /* DEBUG */ +#if !defined(WIN32) && !defined(LACKS_TIME_H) +#include /* for magic initialization */ +#endif /* WIN32 */ +#ifndef LACKS_STDLIB_H +#include /* for abort() */ +#endif /* LACKS_STDLIB_H */ #ifndef LACKS_STRING_H #include /* for memset etc */ #endif /* LACKS_STRING_H */ @@ -1200,21 +1475,83 @@ int mspace_mallopt(int, int); #endif /* USE_BUILTIN_FFS */ #if HAVE_MMAP #ifndef LACKS_SYS_MMAN_H +/* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */ +#if (defined(linux) && !defined(__USE_GNU)) +#define __USE_GNU 1 #include /* for mmap */ +#undef __USE_GNU +#else +#include /* for mmap */ +#endif /* linux */ #endif /* LACKS_SYS_MMAN_H */ #ifndef LACKS_FCNTL_H #include #endif /* LACKS_FCNTL_H */ #endif /* HAVE_MMAP */ -#if HAVE_MORECORE #ifndef LACKS_UNISTD_H -#include /* for sbrk */ +#include /* for sbrk, sysconf */ #else /* LACKS_UNISTD_H */ #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) extern void* sbrk(ptrdiff_t); #endif /* FreeBSD etc */ #endif /* LACKS_UNISTD_H */ -#endif /* HAVE_MMAP */ + +/* Declarations for locking */ +#if USE_LOCKS +#ifndef WIN32 +#if defined (__SVR4) && defined (__sun) /* solaris */ +#include +#elif !defined(LACKS_SCHED_H) +#include +#endif /* solaris or LACKS_SCHED_H */ +#if (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0) || !USE_SPIN_LOCKS +#include +#endif /* USE_RECURSIVE_LOCKS ... */ +#elif defined(_MSC_VER) +#ifndef _M_AMD64 +/* These are already defined on AMD64 builds */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp); +LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value); +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _M_AMD64 */ +#pragma intrinsic (_InterlockedCompareExchange) +#pragma intrinsic (_InterlockedExchange) +#define interlockedcompareexchange _InterlockedCompareExchange +#define interlockedexchange _InterlockedExchange +#elif defined(WIN32) && defined(__GNUC__) +#define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b) +#define interlockedexchange __sync_lock_test_and_set +#endif /* Win32 */ +#else /* USE_LOCKS */ +#endif /* USE_LOCKS */ + +#ifndef LOCK_AT_FORK +#define LOCK_AT_FORK 0 +#endif + +/* Declarations for bit scanning on win32 */ +#if defined(_MSC_VER) && _MSC_VER>=1300 +#ifndef BitScanForward /* Try to avoid pulling in WinNT.h */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +unsigned char _BitScanForward(unsigned long *index, unsigned long mask); +unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#define BitScanForward _BitScanForward +#define BitScanReverse _BitScanReverse +#pragma intrinsic(_BitScanForward) +#pragma intrinsic(_BitScanReverse) +#endif /* BitScanForward */ +#endif /* defined(_MSC_VER) && _MSC_VER>=1300 */ #ifndef WIN32 #ifndef malloc_getpagesize @@ -1270,10 +1607,11 @@ extern void* sbrk(ptrdiff_t); #define SIZE_T_BITSIZE (sizeof(size_t) << 3) /* Some constants coerced to size_t */ -/* Annoying but necessary to avoid errors on some plaftorms */ +/* Annoying but necessary to avoid errors on some platforms */ #define SIZE_T_ZERO ((size_t)0) #define SIZE_T_ONE ((size_t)1) #define SIZE_T_TWO ((size_t)2) +#define SIZE_T_FOUR ((size_t)4) #define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) #define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) #define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) @@ -1303,26 +1641,17 @@ extern void* sbrk(ptrdiff_t); #define MFAIL ((void*)(MAX_SIZE_T)) #define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ -#if !HAVE_MMAP -#define IS_MMAPPED_BIT (SIZE_T_ZERO) -#define USE_MMAP_BIT (SIZE_T_ZERO) -#define CALL_MMAP(s) MFAIL -#define CALL_MUNMAP(a, s) (-1) -#define DIRECT_MMAP(s) MFAIL - -#else /* HAVE_MMAP */ -#define IS_MMAPPED_BIT (SIZE_T_ONE) -#define USE_MMAP_BIT (SIZE_T_ONE) +#if HAVE_MMAP #ifndef WIN32 -#define CALL_MUNMAP(a, s) munmap((a), (s)) +#define MUNMAP_DEFAULT(a, s) munmap((a), (s)) #define MMAP_PROT (PROT_READ|PROT_WRITE) #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) #define MAP_ANONYMOUS MAP_ANON #endif /* MAP_ANON */ #ifdef MAP_ANONYMOUS #define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) -#define CALL_MMAP(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) +#define MMAP_DEFAULT(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) #else /* MAP_ANONYMOUS */ /* Nearly all versions of mmap support MAP_ANONYMOUS, so the following @@ -1330,38 +1659,31 @@ extern void* sbrk(ptrdiff_t); */ #define MMAP_FLAGS (MAP_PRIVATE) static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ -#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \ +#define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \ (dev_zero_fd = open("/dev/zero", O_RDWR), \ mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \ mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) #endif /* MAP_ANONYMOUS */ -#define DIRECT_MMAP(s) CALL_MMAP(s) +#define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s) + #else /* WIN32 */ -static size_t win32_total_mmap = 0; - /* Win32 MMAP via VirtualAlloc */ -static void* win32mmap(size_t size) { +static FORCEINLINE void* win32mmap(size_t size) { void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); - if (ptr != 0) { - win32_total_mmap += size; - } return (ptr != 0)? ptr: MFAIL; } /* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ -static void* win32direct_mmap(size_t size) { +static FORCEINLINE void* win32direct_mmap(size_t size) { void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, PAGE_READWRITE); - if (ptr != 0) { - win32_total_mmap += size; - } return (ptr != 0)? ptr: MFAIL; } /* This function supports releasing coalesed segments */ -static int win32munmap(void* ptr, size_t size) { +static FORCEINLINE int win32munmap(void* ptr, size_t size) { MEMORY_BASIC_INFORMATION minfo; char* cptr = (char*)ptr; while (size) { @@ -1374,29 +1696,80 @@ static int win32munmap(void* ptr, size_t size) { return -1; cptr += minfo.RegionSize; size -= minfo.RegionSize; - win32_total_mmap -= minfo.RegionSize; } return 0; } -#define CALL_MMAP(s) win32mmap(s) -#define CALL_MUNMAP(a, s) win32munmap((a), (s)) -#define DIRECT_MMAP(s) win32direct_mmap(s) +#define MMAP_DEFAULT(s) win32mmap(s) +#define MUNMAP_DEFAULT(a, s) win32munmap((a), (s)) +#define DIRECT_MMAP_DEFAULT(s) win32direct_mmap(s) #endif /* WIN32 */ #endif /* HAVE_MMAP */ -#if HAVE_MMAP && HAVE_MREMAP -#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) -#else /* HAVE_MMAP && HAVE_MREMAP */ -#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL -#endif /* HAVE_MMAP && HAVE_MREMAP */ +#if HAVE_MREMAP +#ifndef WIN32 +#define MREMAP_DEFAULT(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) +#endif /* WIN32 */ +#endif /* HAVE_MREMAP */ +/** + * Define CALL_MORECORE + */ #if HAVE_MORECORE -#define CALL_MORECORE(S) MORECORE(S) + #ifdef MORECORE + #define CALL_MORECORE(S) MORECORE(S) + #else /* MORECORE */ + #define CALL_MORECORE(S) MORECORE_DEFAULT(S) + #endif /* MORECORE */ #else /* HAVE_MORECORE */ -#define CALL_MORECORE(S) MFAIL + #define CALL_MORECORE(S) MFAIL #endif /* HAVE_MORECORE */ +/** + * Define CALL_MMAP/CALL_MUNMAP/CALL_DIRECT_MMAP + */ +#if HAVE_MMAP + #define USE_MMAP_BIT (SIZE_T_ONE) + + #ifdef MMAP + #define CALL_MMAP(s) MMAP(s) + #else /* MMAP */ + #define CALL_MMAP(s) MMAP_DEFAULT(s) + #endif /* MMAP */ + #ifdef MUNMAP + #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) + #else /* MUNMAP */ + #define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s)) + #endif /* MUNMAP */ + #ifdef DIRECT_MMAP + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) + #else /* DIRECT_MMAP */ + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s) + #endif /* DIRECT_MMAP */ +#else /* HAVE_MMAP */ + #define USE_MMAP_BIT (SIZE_T_ZERO) + + #define MMAP(s) MFAIL + #define MUNMAP(a, s) (-1) + #define DIRECT_MMAP(s) MFAIL + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) + #define CALL_MMAP(s) MMAP(s) + #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) +#endif /* HAVE_MMAP */ + +/** + * Define CALL_MREMAP + */ +#if HAVE_MMAP && HAVE_MREMAP + #ifdef MREMAP + #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv)) + #else /* MREMAP */ + #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv)) + #endif /* MREMAP */ +#else /* HAVE_MMAP && HAVE_MREMAP */ + #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL +#endif /* HAVE_MMAP && HAVE_MREMAP */ + /* mstate bit set if continguous morecore disabled or failed */ #define USE_NONCONTIGUOUS_BIT (4U) @@ -1406,92 +1779,277 @@ static int win32munmap(void* ptr, size_t size) { /* --------------------------- Lock preliminaries ------------------------ */ -#if USE_LOCKS - /* - When locks are defined, there are up to two global locks: + When locks are defined, there is one global lock, plus + one per-mspace lock. - * If HAVE_MORECORE, morecore_mutex protects sequences of calls to - MORECORE. In many cases sys_alloc requires two calls, that should - not be interleaved with calls by other threads. This does not - protect against direct calls to MORECORE by other threads not - using this lock, so there is still code to cope the best we can on - interference. + The global lock_ensures that mparams.magic and other unique + mparams values are initialized only once. It also protects + sequences of calls to MORECORE. In many cases sys_alloc requires + two calls, that should not be interleaved with calls by other + threads. This does not protect against direct calls to MORECORE + by other threads not using this lock, so there is still code to + cope the best we can on interference. + + Per-mspace locks surround calls to malloc, free, etc. + By default, locks are simple non-reentrant mutexes. + + Because lock-protected regions generally have bounded times, it is + OK to use the supplied simple spinlocks. Spinlocks are likely to + improve performance for lightly contended applications, but worsen + performance under heavy contention. + + If USE_LOCKS is > 1, the definitions of lock routines here are + bypassed, in which case you will need to define the type MLOCK_T, + and at least INITIAL_LOCK, DESTROY_LOCK, ACQUIRE_LOCK, RELEASE_LOCK + and TRY_LOCK. You must also declare a + static MLOCK_T malloc_global_mutex = { initialization values };. - * magic_init_mutex ensures that mparams.magic and other - unique mparams values are initialized only once. */ -#ifndef WIN32 -/* By default use posix locks */ -#include -#define MLOCK_T pthread_mutex_t -#define INITIAL_LOCK(l) pthread_mutex_init(l, NULL) -#define ACQUIRE_LOCK(l) pthread_mutex_lock(l) -#define RELEASE_LOCK(l) pthread_mutex_unlock(l) +#if !USE_LOCKS +#define USE_LOCK_BIT (0U) +#define INITIAL_LOCK(l) (0) +#define DESTROY_LOCK(l) (0) +#define ACQUIRE_MALLOC_GLOBAL_LOCK() +#define RELEASE_MALLOC_GLOBAL_LOCK() -#if HAVE_MORECORE -static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER; -#endif /* HAVE_MORECORE */ +#else +#if USE_LOCKS > 1 +/* ----------------------- User-defined locks ------------------------ */ +/* Define your own lock implementation here */ +/* #define INITIAL_LOCK(lk) ... */ +/* #define DESTROY_LOCK(lk) ... */ +/* #define ACQUIRE_LOCK(lk) ... */ +/* #define RELEASE_LOCK(lk) ... */ +/* #define TRY_LOCK(lk) ... */ +/* static MLOCK_T malloc_global_mutex = ... */ -static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER; +#elif USE_SPIN_LOCKS -#else /* WIN32 */ +/* First, define CAS_LOCK and CLEAR_LOCK on ints */ +/* Note CAS_LOCK defined to return 0 on success */ + +#if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) +#define CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1) +#define CLEAR_LOCK(sl) __sync_lock_release(sl) + +#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) +/* Custom spin locks for older gcc on x86 */ +static FORCEINLINE int x86_cas_lock(int *sl) { + int ret; + int val = 1; + int cmp = 0; + __asm__ __volatile__ ("lock; cmpxchgl %1, %2" + : "=a" (ret) + : "r" (val), "m" (*(sl)), "0"(cmp) + : "memory", "cc"); + return ret; +} + +static FORCEINLINE void x86_clear_lock(int* sl) { + assert(*sl != 0); + int prev = 0; + int ret; + __asm__ __volatile__ ("lock; xchgl %0, %1" + : "=r" (ret) + : "m" (*(sl)), "0"(prev) + : "memory"); +} + +#define CAS_LOCK(sl) x86_cas_lock(sl) +#define CLEAR_LOCK(sl) x86_clear_lock(sl) + +#else /* Win32 MSC */ +#define CAS_LOCK(sl) interlockedexchange(sl, (LONG)1) +#define CLEAR_LOCK(sl) interlockedexchange (sl, (LONG)0) + +#endif /* ... gcc spins locks ... */ + +/* How to yield for a spin lock */ +#define SPINS_PER_YIELD 63 +#if defined(_MSC_VER) +#define SLEEP_EX_DURATION 50 /* delay for yield/sleep */ +#define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE) +#elif defined (__SVR4) && defined (__sun) /* solaris */ +#define SPIN_LOCK_YIELD thr_yield(); +#elif !defined(LACKS_SCHED_H) +#define SPIN_LOCK_YIELD sched_yield(); +#else +#define SPIN_LOCK_YIELD +#endif /* ... yield ... */ + +#if !defined(USE_RECURSIVE_LOCKS) || USE_RECURSIVE_LOCKS == 0 +/* Plain spin locks use single word (embedded in malloc_states) */ +static int spin_acquire_lock(int *sl) { + int spins = 0; + while (*(volatile int *)sl != 0 || CAS_LOCK(sl)) { + if ((++spins & SPINS_PER_YIELD) == 0) { + SPIN_LOCK_YIELD; + } + } + return 0; +} + +#define MLOCK_T int +#define TRY_LOCK(sl) !CAS_LOCK(sl) +#define RELEASE_LOCK(sl) CLEAR_LOCK(sl) +#define ACQUIRE_LOCK(sl) (CAS_LOCK(sl)? spin_acquire_lock(sl) : 0) +#define INITIAL_LOCK(sl) (*sl = 0) +#define DESTROY_LOCK(sl) (0) +static MLOCK_T malloc_global_mutex = 0; + +#else /* USE_RECURSIVE_LOCKS */ +/* types for lock owners */ +#ifdef WIN32 +#define THREAD_ID_T DWORD +#define CURRENT_THREAD GetCurrentThreadId() +#define EQ_OWNER(X,Y) ((X) == (Y)) +#else /* - Because lock-protected regions have bounded times, and there - are no recursive lock calls, we can use simple spinlocks. + Note: the following assume that pthread_t is a type that can be + initialized to (casted) zero. If this is not the case, you will need to + somehow redefine these or not use spin locks. */ +#define THREAD_ID_T pthread_t +#define CURRENT_THREAD pthread_self() +#define EQ_OWNER(X,Y) pthread_equal(X, Y) +#endif -#define MLOCK_T long -static int win32_acquire_lock (MLOCK_T *sl) { - for (;;) { -#ifdef InterlockedCompareExchangePointer - if (!InterlockedCompareExchange(sl, 1, 0)) - return 0; -#else /* Use older void* version */ - if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0)) - return 0; -#endif /* InterlockedCompareExchangePointer */ - Sleep (0); +struct malloc_recursive_lock { + int sl; + unsigned int c; + THREAD_ID_T threadid; +}; + +#define MLOCK_T struct malloc_recursive_lock +static MLOCK_T malloc_global_mutex = { 0, 0, (THREAD_ID_T)0}; + +static FORCEINLINE void recursive_release_lock(MLOCK_T *lk) { + assert(lk->sl != 0); + if (--lk->c == 0) { + CLEAR_LOCK(&lk->sl); } } -static void win32_release_lock (MLOCK_T *sl) { - InterlockedExchange (sl, 0); +static FORCEINLINE int recursive_acquire_lock(MLOCK_T *lk) { + THREAD_ID_T mythreadid = CURRENT_THREAD; + int spins = 0; + for (;;) { + if (*((volatile int *)(&lk->sl)) == 0) { + if (!CAS_LOCK(&lk->sl)) { + lk->threadid = mythreadid; + lk->c = 1; + return 0; + } + } + else if (EQ_OWNER(lk->threadid, mythreadid)) { + ++lk->c; + return 0; + } + if ((++spins & SPINS_PER_YIELD) == 0) { + SPIN_LOCK_YIELD; + } + } } -#define INITIAL_LOCK(l) *(l)=0 -#define ACQUIRE_LOCK(l) win32_acquire_lock(l) -#define RELEASE_LOCK(l) win32_release_lock(l) -#if HAVE_MORECORE -static MLOCK_T morecore_mutex; -#endif /* HAVE_MORECORE */ -static MLOCK_T magic_init_mutex; -#endif /* WIN32 */ +static FORCEINLINE int recursive_try_lock(MLOCK_T *lk) { + THREAD_ID_T mythreadid = CURRENT_THREAD; + if (*((volatile int *)(&lk->sl)) == 0) { + if (!CAS_LOCK(&lk->sl)) { + lk->threadid = mythreadid; + lk->c = 1; + return 1; + } + } + else if (EQ_OWNER(lk->threadid, mythreadid)) { + ++lk->c; + return 1; + } + return 0; +} +#define RELEASE_LOCK(lk) recursive_release_lock(lk) +#define TRY_LOCK(lk) recursive_try_lock(lk) +#define ACQUIRE_LOCK(lk) recursive_acquire_lock(lk) +#define INITIAL_LOCK(lk) ((lk)->threadid = (THREAD_ID_T)0, (lk)->sl = 0, (lk)->c = 0) +#define DESTROY_LOCK(lk) (0) +#endif /* USE_RECURSIVE_LOCKS */ + +#elif defined(WIN32) /* Win32 critical sections */ +#define MLOCK_T CRITICAL_SECTION +#define ACQUIRE_LOCK(lk) (EnterCriticalSection(lk), 0) +#define RELEASE_LOCK(lk) LeaveCriticalSection(lk) +#define TRY_LOCK(lk) TryEnterCriticalSection(lk) +#define INITIAL_LOCK(lk) (!InitializeCriticalSectionAndSpinCount((lk), 0x80000000|4000)) +#define DESTROY_LOCK(lk) (DeleteCriticalSection(lk), 0) +#define NEED_GLOBAL_LOCK_INIT + +static MLOCK_T malloc_global_mutex; +static volatile LONG malloc_global_mutex_status; + +/* Use spin loop to initialize global lock */ +static void init_malloc_global_mutex() { + for (;;) { + long stat = malloc_global_mutex_status; + if (stat > 0) + return; + /* transition to < 0 while initializing, then to > 0) */ + if (stat == 0 && + interlockedcompareexchange(&malloc_global_mutex_status, (LONG)-1, (LONG)0) == 0) { + InitializeCriticalSection(&malloc_global_mutex); + interlockedexchange(&malloc_global_mutex_status, (LONG)1); + return; + } + SleepEx(0, FALSE); + } +} + +#else /* pthreads-based locks */ +#define MLOCK_T pthread_mutex_t +#define ACQUIRE_LOCK(lk) pthread_mutex_lock(lk) +#define RELEASE_LOCK(lk) pthread_mutex_unlock(lk) +#define TRY_LOCK(lk) (!pthread_mutex_trylock(lk)) +#define INITIAL_LOCK(lk) pthread_init_lock(lk) +#define DESTROY_LOCK(lk) pthread_mutex_destroy(lk) + +#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 && defined(linux) && !defined(PTHREAD_MUTEX_RECURSIVE) +/* Cope with old-style linux recursive lock initialization by adding */ +/* skipped internal declaration from pthread.h */ +extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr, + int __kind)); +#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP +#define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y) +#endif /* USE_RECURSIVE_LOCKS ... */ + +static MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER; + +static int pthread_init_lock (MLOCK_T *lk) { + pthread_mutexattr_t attr; + if (pthread_mutexattr_init(&attr)) return 1; +#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1; +#endif + if (pthread_mutex_init(lk, &attr)) return 1; + if (pthread_mutexattr_destroy(&attr)) return 1; + return 0; +} + +#endif /* ... lock types ... */ + +/* Common code for all lock types */ #define USE_LOCK_BIT (2U) -#else /* USE_LOCKS */ -#define USE_LOCK_BIT (0U) -#define INITIAL_LOCK(l) + +#ifndef ACQUIRE_MALLOC_GLOBAL_LOCK +#define ACQUIRE_MALLOC_GLOBAL_LOCK() ACQUIRE_LOCK(&malloc_global_mutex); +#endif + +#ifndef RELEASE_MALLOC_GLOBAL_LOCK +#define RELEASE_MALLOC_GLOBAL_LOCK() RELEASE_LOCK(&malloc_global_mutex); +#endif + #endif /* USE_LOCKS */ -#if USE_LOCKS && HAVE_MORECORE -#define ACQUIRE_MORECORE_LOCK() ACQUIRE_LOCK(&morecore_mutex); -#define RELEASE_MORECORE_LOCK() RELEASE_LOCK(&morecore_mutex); -#else /* USE_LOCKS && HAVE_MORECORE */ -#define ACQUIRE_MORECORE_LOCK() -#define RELEASE_MORECORE_LOCK() -#endif /* USE_LOCKS && HAVE_MORECORE */ - -#if USE_LOCKS -#define ACQUIRE_MAGIC_INIT_LOCK() ACQUIRE_LOCK(&magic_init_mutex); -#define RELEASE_MAGIC_INIT_LOCK() RELEASE_LOCK(&magic_init_mutex); -#else /* USE_LOCKS */ -#define ACQUIRE_MAGIC_INIT_LOCK() -#define RELEASE_MAGIC_INIT_LOCK() -#endif /* USE_LOCKS */ - - /* ----------------------- Chunk representations ------------------------ */ /* @@ -1517,7 +2075,7 @@ static MLOCK_T magic_init_mutex; A chunk that's in use looks like: chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk (if P = 1) | + | Size of previous chunk (if P = 0) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| | Size of this chunk 1| +-+ @@ -1588,13 +2146,14 @@ static MLOCK_T magic_init_mutex; The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of the chunk size redundantly records whether the current chunk is - inuse. This redundancy enables usage checks within free and realloc, - and reduces indirection when freeing and consolidating chunks. + inuse (unless the chunk is mmapped). This redundancy enables usage + checks within free and realloc, and reduces indirection when freeing + and consolidating chunks. Each freshly allocated chunk must have both cinuse and pinuse set. That is, each allocated chunk borders either a previously allocated and still in-use chunk, or the base of its memory arena. This is - ensured by making all allocations from the the `lowest' part of any + ensured by making all allocations from the `lowest' part of any found chunk. Further, no free chunk physically borders another one, so each free chunk is known to be preceded and followed by either inuse chunks or the ends of memory. @@ -1618,9 +2177,8 @@ static MLOCK_T magic_init_mutex; space is still allocated for it (TOP_FOOT_SIZE) to enable separation or merging when space is extended. - 3. Chunks allocated via mmap, which have the lowest-order bit - (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set - PINUSE_BIT in their head fields. Because they are allocated + 3. Chunks allocated via mmap, have both cinuse and pinuse bits + cleared in their head fields. Because they are allocated one-by-one, each must carry its own prev_foot field, which is also used to hold the offset this chunk has within its mmapped region, which is needed to preserve alignment. Each mmapped @@ -1686,14 +2244,16 @@ typedef unsigned int flag_t; /* The type of various bit flag sets */ /* The head field of a chunk is or'ed with PINUSE_BIT when previous adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in - use. If the chunk was obtained with mmap, the prev_foot field has - IS_MMAPPED_BIT set, otherwise holding the offset of the base of the - mmapped region to the base of the chunk. + use, unless mmapped, in which case both bits are cleared. + + FLAG4_BIT is not used by this malloc, but might be useful in extensions. */ #define PINUSE_BIT (SIZE_T_ONE) #define CINUSE_BIT (SIZE_T_TWO) +#define FLAG4_BIT (SIZE_T_FOUR) #define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) +#define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT) /* Head value for fenceposts */ #define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) @@ -1701,17 +2261,22 @@ typedef unsigned int flag_t; /* The type of various bit flag sets */ /* extraction of fields from head words */ #define cinuse(p) ((p)->head & CINUSE_BIT) #define pinuse(p) ((p)->head & PINUSE_BIT) -#define chunksize(p) ((p)->head & ~(INUSE_BITS)) +#define flag4inuse(p) ((p)->head & FLAG4_BIT) +#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT) +#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0) + +#define chunksize(p) ((p)->head & ~(FLAG_BITS)) #define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) -#define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT) +#define set_flag4(p) ((p)->head |= FLAG4_BIT) +#define clear_flag4(p) ((p)->head &= ~FLAG4_BIT) /* Treat space at ptr +/- offset as a chunk */ #define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) #define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) /* Ptr to next or previous physical malloc_chunk. */ -#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS))) +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS))) #define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) /* extract next chunk's pinuse bit */ @@ -1729,9 +2294,6 @@ typedef unsigned int flag_t; /* The type of various bit flag sets */ #define set_free_with_pinuse(p, s, n)\ (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) -#define is_mmapped(p)\ - (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT)) - /* Get the internal overhead associated with chunk p */ #define overhead_for(p)\ (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) @@ -1902,7 +2464,7 @@ typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ and so should not try to deallocate or merge with others. (This currently holds only for the initial segment passed into create_mspace_with_base.) - * If IS_MMAPPED_BIT set, the segment may be merged with + * If USE_MMAP_BIT set, the segment may be merged with other surrounding mmapped segments and trimmed/de-allocated using munmap. * If neither bit is set, then the segment was obtained using @@ -1917,7 +2479,7 @@ struct malloc_segment { flag_t sflags; /* mmap and extern flag */ }; -#define is_mmapped_segment(S) ((S)->sflags & IS_MMAPPED_BIT) +#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT) #define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) typedef struct malloc_segment msegment; @@ -1986,6 +2548,9 @@ typedef struct malloc_segment* msegmentptr; Magic tag A cross-check field that should always hold same value as mparams.magic. + Max allowed footprint + The maximum allowed bytes to allocate from system (zero means no limit) + Flags Bits recording whether to use MMAP, locks, or contiguous MORECORE @@ -1993,9 +2558,18 @@ typedef struct malloc_segment* msegmentptr; Each space keeps track of current and maximum system memory obtained via MORECORE or MMAP. + Trim support + Fields holding the amount of unused topmost memory that should trigger + trimming, and a counter to force periodic scanning to release unused + non-topmost segments. + Locking If USE_LOCKS is defined, the "mutex" lock is acquired and released around every public call using this mspace. + + Extension support + A void* pointer and a size_t field that can be used to help implement + extensions to this malloc. */ /* Bin types, widths and sizes */ @@ -2017,16 +2591,20 @@ struct malloc_state { mchunkptr dv; mchunkptr top; size_t trim_check; + size_t release_checks; size_t magic; mchunkptr smallbins[(NSMALLBINS+1)*2]; tbinptr treebins[NTREEBINS]; size_t footprint; size_t max_footprint; + size_t footprint_limit; /* zero means no limit */ flag_t mflags; #if USE_LOCKS MLOCK_T mutex; /* locate lock among fields that rarely change */ #endif /* USE_LOCKS */ msegment seg; + void* extp; /* Unused but available for extensions */ + size_t exts; }; typedef struct malloc_state* mstate; @@ -2036,7 +2614,8 @@ typedef struct malloc_state* mstate; /* malloc_params holds global properties, including those that can be dynamically set using mallopt. There is a single instance, mparams, - initialized in init_mparams. + initialized in init_mparams. Note that the non-zeroness of "magic" + also serves as an initialization flag. */ struct malloc_params { @@ -2050,15 +2629,19 @@ struct malloc_params { static struct malloc_params mparams; +/* Ensure mparams initialized */ +#define ensure_initialization() (void)(mparams.magic != 0 || init_mparams()) + +#if !ONLY_MSPACES + /* The global malloc_state used for all non-"mspace" calls */ static struct malloc_state _gm_; #define gm (&_gm_) #define is_global(M) ((M) == &_gm_) -#define is_initialized(M) ((M)->top != 0) -#ifdef MEMMATCH -static int output_counter = 0; -#endif +#endif /* !ONLY_MSPACES */ + +#define is_initialized(M) ((M)->top != 0) /* -------------------------- system alloc setup ------------------------- */ @@ -2066,11 +2649,19 @@ static int output_counter = 0; #define use_lock(M) ((M)->mflags & USE_LOCK_BIT) #define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) +#if USE_LOCKS #define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) +#else +#define disable_lock(M) +#endif #define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) #define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) +#if HAVE_MMAP #define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) +#else +#define disable_mmap(M) +#endif #define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) #define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) @@ -2082,11 +2673,23 @@ static int output_counter = 0; /* page-align a size */ #define page_align(S)\ - (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE)) + (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE)) /* granularity-align a size */ #define granularity_align(S)\ - (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE)) + (((S) + (mparams.granularity - SIZE_T_ONE))\ + & ~(mparams.granularity - SIZE_T_ONE)) + + +/* For mmap, use granularity alignment on windows, else page-align */ +#ifdef WIN32 +#define mmap_align(S) granularity_align(S) +#else +#define mmap_align(S) page_align(S) +#endif + +/* For sys_alloc, enough padding to ensure can malloc request on success */ +#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT) #define is_page_aligned(S)\ (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) @@ -2143,11 +2746,7 @@ static int has_segment_link(mstate m, msegmentptr ss) { */ #if USE_LOCKS - -/* Ensure locks are initialized */ -#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams()) - -#define PREACTION(M) ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) +#define PREACTION(M) ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) #define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } #else /* USE_LOCKS */ @@ -2192,6 +2791,7 @@ static void reset_on_error(mstate m); #endif /* PROCEED_ON_ERROR */ + /* -------------------------- Debugging setup ---------------------------- */ #if ! DEBUG @@ -2228,7 +2828,7 @@ static size_t traverse_and_check(mstate m); /* ---------------------------- Indexing Bins ---------------------------- */ #define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) -#define small_index(s) ((s) >> SMALLBIN_SHIFT) +#define small_index(s) (bindex_t)((s) >> SMALLBIN_SHIFT) #define small_index2size(i) ((i) << SMALLBIN_SHIFT) #define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) @@ -2236,8 +2836,36 @@ static size_t traverse_and_check(mstate m); #define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) #define treebin_at(M,i) (&((M)->treebins[i])) -/* assign tree index for size S to variable I */ -#if defined(__GNUC__) && defined(i386) +/* assign tree index for size S to variable I. Use x86 asm if possible */ +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +#define compute_tree_index(S, I)\ +{\ + unsigned int X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K = (unsigned) sizeof(X)*__CHAR_BIT__ - 1 - (unsigned) __builtin_clz(X); \ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} + +#elif defined (__INTEL_COMPILER) +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K = _bit_scan_reverse (X); \ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} + +#elif defined(_MSC_VER) && _MSC_VER>=1300 #define compute_tree_index(S, I)\ {\ size_t X = S >> TREEBIN_SHIFT;\ @@ -2247,10 +2875,11 @@ static size_t traverse_and_check(mstate m); I = NTREEBINS-1;\ else {\ unsigned int K;\ - __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm" (X));\ + _BitScanReverse((DWORD *) &K, (DWORD) X);\ I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ }\ } + #else /* GNUC */ #define compute_tree_index(S, I)\ {\ @@ -2300,21 +2929,45 @@ static size_t traverse_and_check(mstate m); #define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) #define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) -/* index corresponding to given bit */ +/* isolate the least set bit of a bitmap */ +#define least_bit(x) ((x) & -(x)) -#if defined(__GNUC__) && defined(i386) +/* mask with all bits to left of least bit of x on */ +#define left_bits(x) ((x<<1) | -(x<<1)) + +/* mask with all bits to left of or equal to least bit of x on */ +#define same_or_left_bits(x) ((x) | -(x)) + +/* index corresponding to given bit. Use x86 asm if possible */ + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) #define compute_bit2idx(X, I)\ {\ unsigned int J;\ - __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\ + J = __builtin_ctz(X); \ I = (bindex_t)J;\ } -#else /* GNUC */ -#if USE_BUILTIN_FFS +#elif defined (__INTEL_COMPILER) +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + J = _bit_scan_forward (X); \ + I = (bindex_t)J;\ +} + +#elif defined(_MSC_VER) && _MSC_VER>=1300 +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + _BitScanForward((DWORD *) &J, X);\ + I = (bindex_t)J;\ +} + +#elif USE_BUILTIN_FFS #define compute_bit2idx(X, I) I = ffs(X)-1 -#else /* USE_BUILTIN_FFS */ +#else #define compute_bit2idx(X, I)\ {\ unsigned int Y = X - 1;\ @@ -2326,18 +2979,8 @@ static size_t traverse_and_check(mstate m); N += K = Y >> (1-0) & 1; Y >>= K;\ I = (bindex_t)(N + Y);\ } -#endif /* USE_BUILTIN_FFS */ #endif /* GNUC */ -/* isolate the least set bit of a bitmap */ -#define least_bit(x) ((x) & -(x)) - -/* mask with all bits to left of least bit of x on */ -#define left_bits(x) ((x<<1) | -(x<<1)) - -/* mask with all bits to left of or equal to least bit of x on */ -#define same_or_left_bits(x) ((x) | -(x)) - /* ----------------------- Runtime Check Support ------------------------- */ @@ -2359,7 +3002,7 @@ static size_t traverse_and_check(mstate m); http://www.usenix.org/events/lisa03/tech/robertson.html The footer of an inuse chunk holds the xor of its mstate and a random seed, that is checked upon calls to free() and realloc(). This is - (probablistically) unguessable from outside the program, but can be + (probabalistically) unguessable from outside the program, but can be computed by any code successfully malloc'ing any chunk, so does not itself provide protection against code that has already broken security through some other means. Unlike Robertson et al, we @@ -2372,15 +3015,15 @@ static size_t traverse_and_check(mstate m); #define ok_address(M, a) ((char*)(a) >= (M)->least_addr) /* Check if address of next chunk n is higher than base chunk p */ #define ok_next(p, n) ((char*)(p) < (char*)(n)) -/* Check if p has its cinuse bit on */ -#define ok_cinuse(p) cinuse(p) +/* Check if p has inuse status */ +#define ok_inuse(p) is_inuse(p) /* Check if p has its pinuse bit on */ #define ok_pinuse(p) pinuse(p) #else /* !INSECURE */ #define ok_address(M, a) (1) #define ok_next(b, n) (1) -#define ok_cinuse(p) (1) +#define ok_inuse(p) (1) #define ok_pinuse(p) (1) #endif /* !INSECURE */ @@ -2391,7 +3034,6 @@ static size_t traverse_and_check(mstate m); #define ok_magic(M) (1) #endif /* (FOOTERS && !INSECURE) */ - /* In gcc, use __builtin_expect to minimize impact of checks */ #if !INSECURE #if defined(__GNUC__) && __GNUC__ >= 3 @@ -2409,6 +3051,8 @@ static size_t traverse_and_check(mstate m); #define mark_inuse_foot(M,p,s) +/* Macros for setting head/foot of non-mmapped chunks */ + /* Set cinuse bit and pinuse bit of next chunk */ #define set_inuse(M,p,s)\ ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ @@ -2451,60 +3095,35 @@ static size_t traverse_and_check(mstate m); /* ---------------------------- setting mparams -------------------------- */ +#if LOCK_AT_FORK +static void pre_fork(void) { ACQUIRE_LOCK(&(gm)->mutex); } +static void post_fork_parent(void) { RELEASE_LOCK(&(gm)->mutex); } +static void post_fork_child(void) { INITIAL_LOCK(&(gm)->mutex); } +#endif /* LOCK_AT_FORK */ + /* Initialize mparams */ static int init_mparams(void) { - if (mparams.page_size == 0) { - size_t s; +#ifdef NEED_GLOBAL_LOCK_INIT + if (malloc_global_mutex_status <= 0) + init_malloc_global_mutex(); +#endif - mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; - mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; -#if MORECORE_CONTIGUOUS - mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; -#else /* MORECORE_CONTIGUOUS */ - mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; -#endif /* MORECORE_CONTIGUOUS */ - -#if (FOOTERS && !INSECURE) - { -#if USE_DEV_RANDOM - int fd; - unsigned char buf[sizeof(size_t)]; - /* Try to use /dev/urandom, else fall back on using time */ - if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && - read(fd, buf, sizeof(buf)) == sizeof(buf)) { - s = *((size_t *) buf); - close(fd); - } - else -#endif /* USE_DEV_RANDOM */ - s = (size_t)(time(0) ^ (size_t)0x55555555U); - - s |= (size_t)8U; /* ensure nonzero */ - s &= ~(size_t)7U; /* improve chances of fault for bad values */ - - } -#else /* (FOOTERS && !INSECURE) */ - s = (size_t)0x58585858U; -#endif /* (FOOTERS && !INSECURE) */ - ACQUIRE_MAGIC_INIT_LOCK(); - if (mparams.magic == 0) { - mparams.magic = s; - /* Set up lock for main malloc area */ - INITIAL_LOCK(&gm->mutex); - gm->mflags = mparams.default_mflags; - } - RELEASE_MAGIC_INIT_LOCK(); + ACQUIRE_MALLOC_GLOBAL_LOCK(); + if (mparams.magic == 0) { + size_t magic; + size_t psize; + size_t gsize; #ifndef WIN32 - mparams.page_size = malloc_getpagesize; - mparams.granularity = ((DEFAULT_GRANULARITY != 0)? - DEFAULT_GRANULARITY : mparams.page_size); + psize = malloc_getpagesize; + gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize); #else /* WIN32 */ { SYSTEM_INFO system_info; GetSystemInfo(&system_info); - mparams.page_size = system_info.dwPageSize; - mparams.granularity = system_info.dwAllocationGranularity; + psize = system_info.dwPageSize; + gsize = ((DEFAULT_GRANULARITY != 0)? + DEFAULT_GRANULARITY : system_info.dwAllocationGranularity); } #endif /* WIN32 */ @@ -2518,19 +3137,65 @@ static int init_mparams(void) { (MAX_SIZE_T < MIN_CHUNK_SIZE) || (sizeof(int) < 4) || (MALLOC_ALIGNMENT < (size_t)8U) || - ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || - ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || - ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) || - ((mparams.page_size & (mparams.page_size-SIZE_T_ONE)) != 0)) + ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || + ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || + ((gsize & (gsize-SIZE_T_ONE)) != 0) || + ((psize & (psize-SIZE_T_ONE)) != 0)) ABORT; + mparams.granularity = gsize; + mparams.page_size = psize; + mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; + mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; +#if MORECORE_CONTIGUOUS + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; +#else /* MORECORE_CONTIGUOUS */ + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; +#endif /* MORECORE_CONTIGUOUS */ + +#if !ONLY_MSPACES + /* Set up lock for main malloc area */ + gm->mflags = mparams.default_mflags; + (void)INITIAL_LOCK(&gm->mutex); +#endif +#if LOCK_AT_FORK + pthread_atfork(&pre_fork, &post_fork_parent, &post_fork_child); +#endif + + { +#if USE_DEV_RANDOM + int fd; + unsigned char buf[sizeof(size_t)]; + /* Try to use /dev/urandom, else fall back on using time */ + if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && + read(fd, buf, sizeof(buf)) == sizeof(buf)) { + magic = *((size_t *) buf); + close(fd); + } + else +#endif /* USE_DEV_RANDOM */ +#ifdef WIN32 + magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U); +#elif defined(LACKS_TIME_H) + magic = (size_t)&magic ^ (size_t)0x55555555U; +#else + magic = (size_t)(time(0) ^ (size_t)0x55555555U); +#endif + magic |= (size_t)8U; /* ensure nonzero */ + magic &= ~(size_t)7U; /* improve chances of fault for bad values */ + /* Until memory modes commonly available, use volatile-write */ + (*(volatile size_t *)(&(mparams.magic))) = magic; + } } - return 0; + + RELEASE_MALLOC_GLOBAL_LOCK(); + return 1; } /* support for mallopt */ static int change_mparam(int param_number, int value) { - size_t val = (size_t)value; - init_mparams(); + size_t val; + ensure_initialization(); + val = (value == -1)? MAX_SIZE_T : (size_t)value; switch(param_number) { case M_TRIM_THRESHOLD: mparams.trim_threshold = val; @@ -2562,7 +3227,7 @@ static void do_check_any_chunk(mstate m, mchunkptr p) { /* Check properties of top chunk */ static void do_check_top_chunk(mstate m, mchunkptr p) { msegmentptr sp = segment_holding(m, (char*)p); - size_t sz = chunksize(p); + size_t sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */ assert(sp != 0); assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); assert(ok_address(m, p)); @@ -2570,13 +3235,13 @@ static void do_check_top_chunk(mstate m, mchunkptr p) { assert(sz > 0); assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE); assert(pinuse(p)); - assert(!next_pinuse(p)); + assert(!pinuse(chunk_plus_offset(p, sz))); } /* Check properties of (inuse) mmapped chunks */ static void do_check_mmapped_chunk(mstate m, mchunkptr p) { size_t sz = chunksize(p); - size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD); + size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD); assert(is_mmapped(p)); assert(use_mmap(m)); assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); @@ -2590,7 +3255,7 @@ static void do_check_mmapped_chunk(mstate m, mchunkptr p) { /* Check properties of inuse chunks */ static void do_check_inuse_chunk(mstate m, mchunkptr p) { do_check_any_chunk(m, p); - assert(cinuse(p)); + assert(is_inuse(p)); assert(next_pinuse(p)); /* If not pinuse and not mmapped, previous chunk has OK offset */ assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p); @@ -2600,10 +3265,10 @@ static void do_check_inuse_chunk(mstate m, mchunkptr p) { /* Check properties of free chunks */ static void do_check_free_chunk(mstate m, mchunkptr p) { - size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT); + size_t sz = chunksize(p); mchunkptr next = chunk_plus_offset(p, sz); do_check_any_chunk(m, p); - assert(!cinuse(p)); + assert(!is_inuse(p)); assert(!next_pinuse(p)); assert (!is_mmapped(p)); if (p != m->dv && p != m->top) { @@ -2612,7 +3277,7 @@ static void do_check_free_chunk(mstate m, mchunkptr p) { assert(is_aligned(chunk2mem(p))); assert(next->prev_foot == sz); assert(pinuse(p)); - assert (next == m->top || cinuse(next)); + assert (next == m->top || is_inuse(next)); assert(p->fd->bk == p); assert(p->bk->fd == p); } @@ -2625,7 +3290,7 @@ static void do_check_free_chunk(mstate m, mchunkptr p) { static void do_check_malloced_chunk(mstate m, void* mem, size_t s) { if (mem != 0) { mchunkptr p = mem2chunk(mem); - size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT); + size_t sz = p->head & ~INUSE_BITS; do_check_inuse_chunk(m, p); assert((sz & CHUNK_ALIGN_MASK) == 0); assert(sz >= MIN_CHUNK_SIZE); @@ -2652,7 +3317,7 @@ static void do_check_tree(mstate m, tchunkptr t) { do_check_any_chunk(m, ((mchunkptr)u)); assert(u->index == tindex); assert(chunksize(u) == tsize); - assert(!cinuse(u)); + assert(!is_inuse(u)); assert(!next_pinuse(u)); assert(u->fd->bk == u); assert(u->bk->fd == u); @@ -2770,13 +3435,13 @@ static size_t traverse_and_check(mstate m) { while (segment_holds(s, q) && q != m->top && q->head != FENCEPOST_HEAD) { sum += chunksize(q); - if (cinuse(q)) { + if (is_inuse(q)) { assert(!bin_find(m, q)); do_check_inuse_chunk(m, q); } else { assert(q == m->dv || bin_find(m, q)); - assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */ + assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */ do_check_free_chunk(m, q); } lastq = q; @@ -2788,6 +3453,7 @@ static size_t traverse_and_check(mstate m) { return sum; } + /* Check all properties of malloc_state. */ static void do_check_malloc_state(mstate m) { bindex_t i; @@ -2807,7 +3473,7 @@ static void do_check_malloc_state(mstate m) { if (m->top != 0) { /* check top chunk */ do_check_top_chunk(m, m->top); - assert(m->topsize == chunksize(m->top)); + /*assert(m->topsize == chunksize(m->top)); redundant */ assert(m->topsize > 0); assert(bin_find(m, m->top) == 0); } @@ -2823,6 +3489,7 @@ static void do_check_malloc_state(mstate m) { #if !NO_MALLINFO static struct mallinfo internal_mallinfo(mstate m) { struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + ensure_initialization(); if (!PREACTION(m)) { check_malloc_state(m); if (is_initialized(m)) { @@ -2836,7 +3503,7 @@ static struct mallinfo internal_mallinfo(mstate m) { q != m->top && q->head != FENCEPOST_HEAD) { size_t sz = chunksize(q); sum += sz; - if (!cinuse(q)) { + if (!is_inuse(q)) { mfree += sz; ++nfree; } @@ -2860,7 +3527,9 @@ static struct mallinfo internal_mallinfo(mstate m) { } #endif /* !NO_MALLINFO */ +#if !NO_MALLOC_STATS static void internal_malloc_stats(mstate m) { + ensure_initialization(); if (!PREACTION(m)) { size_t maxfp = 0; size_t fp = 0; @@ -2876,21 +3545,20 @@ static void internal_malloc_stats(mstate m) { mchunkptr q = align_as_chunk(s->base); while (segment_holds(s, q) && q != m->top && q->head != FENCEPOST_HEAD) { - if (!cinuse(q)) + if (!is_inuse(q)) used -= chunksize(q); q = next_chunk(q); } s = s->next; } } - + POSTACTION(m); /* drop lock */ fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp)); fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp)); fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used)); - - POSTACTION(m); } } +#endif /* NO_MALLOC_STATS */ /* ----------------------- Operations on smallbins ----------------------- */ @@ -2928,12 +3596,18 @@ static void internal_malloc_stats(mstate m) { assert(P != B);\ assert(P != F);\ assert(chunksize(P) == small_index2size(I));\ - if (F == B)\ - clear_smallmap(M, I);\ - else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\ - (B == smallbin_at(M,I) || ok_address(M, B)))) {\ - F->bk = B;\ - B->fd = F;\ + if (RTCHECK(F == smallbin_at(M,I) || (ok_address(M, F) && F->bk == P))) { \ + if (B == F) {\ + clear_smallmap(M, I);\ + }\ + else if (RTCHECK(B == smallbin_at(M,I) ||\ + (ok_address(M, B) && B->fd == P))) {\ + F->bk = B;\ + B->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ }\ else {\ CORRUPTION_ERROR_ACTION(M);\ @@ -2946,11 +3620,12 @@ static void internal_malloc_stats(mstate m) { assert(P != B);\ assert(P != F);\ assert(chunksize(P) == small_index2size(I));\ - if (B == F)\ + if (B == F) {\ clear_smallmap(M, I);\ - else if (RTCHECK(ok_address(M, F))) {\ - B->fd = F;\ + }\ + else if (RTCHECK(ok_address(M, F) && F->bk == P)) {\ F->bk = B;\ + B->fd = F;\ }\ else {\ CORRUPTION_ERROR_ACTION(M);\ @@ -2961,9 +3636,9 @@ static void internal_malloc_stats(mstate m) { /* Used only when dvsize known to be small */ #define replace_dv(M, P, S) {\ size_t DVS = M->dvsize;\ + assert(is_small(DVS));\ if (DVS != 0) {\ mchunkptr DV = M->dv;\ - assert(is_small(DVS));\ insert_small_chunk(M, DV, DVS);\ }\ M->dvsize = S;\ @@ -3047,7 +3722,7 @@ static void internal_malloc_stats(mstate m) { if (X->bk != X) {\ tchunkptr F = X->fd;\ R = X->bk;\ - if (RTCHECK(ok_address(M, F))) {\ + if (RTCHECK(ok_address(M, F) && F->bk == X && R->fd == X)) {\ F->bk = R;\ R->fd = F;\ }\ @@ -3131,7 +3806,7 @@ static void internal_malloc_stats(mstate m) { #else /* ONLY_MSPACES */ #if MSPACES #define internal_malloc(m, b)\ - (m == gm)? dlmalloc(b) : mspace_malloc(m, b) + ((m == gm)? dlmalloc(b) : mspace_malloc(m, b)) #define internal_free(m, mem)\ if (m == gm) dlfree(mem); else mspace_free(m,mem); #else /* MSPACES */ @@ -3147,28 +3822,31 @@ static void internal_malloc_stats(mstate m) { the mmapped region stored in the prev_foot field of the chunk. This allows reconstruction of the required argument to MUNMAP when freed, and also allows adjustment of the returned chunk to meet alignment - requirements (especially in memalign). There is also enough space - allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain - the PINUSE bit so frees can be checked. + requirements (especially in memalign). */ /* Malloc using mmap */ static void* mmap_alloc(mstate m, size_t nb) { - size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + if (m->footprint_limit != 0) { + size_t fp = m->footprint + mmsize; + if (fp <= m->footprint || fp > m->footprint_limit) + return 0; + } if (mmsize > nb) { /* Check for wrap around 0 */ - char* mm = (char*)(DIRECT_MMAP(mmsize)); + char* mm = (char*)(CALL_DIRECT_MMAP(mmsize)); if (mm != CMFAIL) { memory_hook->inc_heap(mmsize); size_t offset = align_offset(chunk2mem(mm)); size_t psize = mmsize - offset - MMAP_FOOT_PAD; mchunkptr p = (mchunkptr)(mm + offset); - p->prev_foot = offset | IS_MMAPPED_BIT; - (p)->head = (psize|CINUSE_BIT); + p->prev_foot = offset; + p->head = psize; mark_inuse_foot(m, p, psize); chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; - if (mm < m->least_addr) + if (m->least_addr == 0 || mm < m->least_addr) m->least_addr = mm; if ((m->footprint += mmsize) > m->max_footprint) m->max_footprint = m->footprint; @@ -3181,8 +3859,9 @@ static void* mmap_alloc(mstate m, size_t nb) { } /* Realloc using mmap */ -static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) { +static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) { size_t oldsize = chunksize(oldp); + (void)flags; /* placate people compiling -Wunused */ if (is_small(nb)) /* Can't shrink mmap regions below small size */ return 0; /* Keep old chunk if big enough but not too big */ @@ -3190,18 +3869,17 @@ static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) { (oldsize - nb) <= (mparams.granularity << 1)) return oldp; else { - size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT; + size_t offset = oldp->prev_foot; size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; - size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES + - CHUNK_ALIGN_MASK); + size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); char* cp = (char*)CALL_MREMAP((char*)oldp - offset, - oldmmsize, newmmsize, 1); + oldmmsize, newmmsize, flags); if (cp != CMFAIL) { memory_hook->dec_heap(oldsize); memory_hook->inc_heap(nb); mchunkptr newp = (mchunkptr)(cp + offset); size_t psize = newmmsize - offset - MMAP_FOOT_PAD; - newp->head = (psize|CINUSE_BIT); + newp->head = psize; mark_inuse_foot(m, newp, psize); chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; @@ -3217,6 +3895,7 @@ static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) { return 0; } + /* -------------------------- mspace management -------------------------- */ /* Initialize top chunk and its size */ @@ -3251,7 +3930,7 @@ static void reset_on_error(mstate m) { int i; ++malloc_corruption_error_count; /* Reinitialize fields to forget about all memory */ - m->smallbins = m->treebins = 0; + m->smallmap = m->treemap = 0; m->dvsize = m->topsize = 0; m->seg.base = 0; m->seg.size = 0; @@ -3290,7 +3969,7 @@ static void* prepend_alloc(mstate m, char* newbase, char* oldbase, set_size_and_pinuse_of_free_chunk(q, dsize); } else { - if (!cinuse(oldfirst)) { + if (!is_inuse(oldfirst)) { size_t nsize = chunksize(oldfirst); unlink_chunk(m, oldfirst, nsize); oldfirst = chunk_plus_offset(oldfirst, nsize); @@ -3305,7 +3984,6 @@ static void* prepend_alloc(mstate m, char* newbase, char* oldbase, return chunk2mem(p); } - /* Add a segment to hold a new noncontiguous region */ static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { /* Determine locations and sizes of segment, fenceposts, old top */ @@ -3366,16 +4044,26 @@ static void* sys_alloc(mstate m, size_t nb) { char* tbase = CMFAIL; size_t tsize = 0; flag_t mmap_flag = 0; + size_t asize; /* allocation size */ - init_mparams(); + ensure_initialization(); - /* Directly map large chunks */ - if (use_mmap(m) && nb >= mparams.mmap_threshold) { + /* Directly map large chunks, but only if already initialized */ + if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) { void* mem = mmap_alloc(m, nb); if (mem != 0) return mem; } + asize = granularity_align(nb + SYS_ALLOC_PADDING); + if (asize <= nb) + return 0; /* wraparound */ + if (m->footprint_limit != 0) { + size_t fp = m->footprint + asize; + if (fp <= m->footprint || fp > m->footprint_limit) + return 0; + } + /* Try getting memory in any of three ways (in most-preferred to least-preferred order): @@ -3391,51 +4079,58 @@ static void* sys_alloc(mstate m, size_t nb) { find space. 3. A call to MORECORE that cannot usually contiguously extend memory. (disabled if not HAVE_MORECORE) + + In all cases, we need to request enough bytes from system to ensure + we can malloc nb bytes upon success, so pad with enough space for + top_foot, plus alignment-pad to make sure we don't lose bytes if + not on boundary, and round this up to a granularity unit. */ if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) { char* br = CMFAIL; + size_t ssize = asize; /* sbrk call size */ msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top); - size_t asize = 0; - ACQUIRE_MORECORE_LOCK(); + ACQUIRE_MALLOC_GLOBAL_LOCK(); if (ss == 0) { /* First time through or recovery */ char* base = (char*)CALL_MORECORE(0); if (base != CMFAIL) { - asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE); + size_t fp; /* Adjust to end on a page boundary */ if (!is_page_aligned(base)) - asize += (page_align((size_t)base) - (size_t)base); - /* Can't call MORECORE if size is negative when treated as signed */ - if (asize < HALF_MAX_SIZE_T && - (br = (char*)(CALL_MORECORE(asize))) == base) { + ssize += (page_align((size_t)base) - (size_t)base); + fp = m->footprint + ssize; /* recheck limits */ + if (ssize > nb && ssize < HALF_MAX_SIZE_T && + (m->footprint_limit == 0 || + (fp > m->footprint && fp <= m->footprint_limit)) && + (br = (char*)(CALL_MORECORE(ssize))) == base) { tbase = base; - tsize = asize; + tsize = ssize; } } } else { /* Subtract out existing available top space from MORECORE request. */ - asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE); + ssize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING); /* Use mem here only if it did continuously extend old space */ - if (asize < HALF_MAX_SIZE_T && - (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) { + if (ssize < HALF_MAX_SIZE_T && + (br = (char*)(CALL_MORECORE(ssize))) == ss->base+ss->size) { tbase = br; - tsize = asize; + tsize = ssize; } } if (tbase == CMFAIL) { /* Cope with partial failure */ if (br != CMFAIL) { /* Try to use/extend the space we did get */ - if (asize < HALF_MAX_SIZE_T && - asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) { - size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize); + if (ssize < HALF_MAX_SIZE_T && + ssize < nb + SYS_ALLOC_PADDING) { + size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - ssize); if (esize < HALF_MAX_SIZE_T) { char* end = (char*)CALL_MORECORE(esize); if (end != CMFAIL) - asize += esize; + ssize += esize; else { /* Can't use; try to release */ - CALL_MORECORE(-asize); + (void) CALL_MORECORE(-ssize); br = CMFAIL; } } @@ -3443,37 +4138,32 @@ static void* sys_alloc(mstate m, size_t nb) { } if (br != CMFAIL) { /* Use the space we did get */ tbase = br; - tsize = asize; + tsize = ssize; } else disable_contiguous(m); /* Don't try contiguous path in the future */ } - RELEASE_MORECORE_LOCK(); + RELEASE_MALLOC_GLOBAL_LOCK(); } if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ - size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE; - size_t rsize = granularity_align(req); - if (rsize > nb) { /* Fail if wraps around zero */ - char* mp = (char*)(CALL_MMAP(rsize)); - if (mp != CMFAIL) { - tbase = mp; - tsize = rsize; - mmap_flag = IS_MMAPPED_BIT; - } + char* mp = (char*)(CALL_MMAP(asize)); + if (mp != CMFAIL) { + tbase = mp; + tsize = asize; + mmap_flag = USE_MMAP_BIT; } } if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ - size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE); if (asize < HALF_MAX_SIZE_T) { char* br = CMFAIL; char* end = CMFAIL; - ACQUIRE_MORECORE_LOCK(); + ACQUIRE_MALLOC_GLOBAL_LOCK(); br = (char*)(CALL_MORECORE(asize)); end = (char*)(CALL_MORECORE(0)); - RELEASE_MORECORE_LOCK(); + RELEASE_MALLOC_GLOBAL_LOCK(); if (br != CMFAIL && end != CMFAIL && br < end) { size_t ssize = end - br; if (ssize > nb + TOP_FOOT_SIZE) { @@ -3491,14 +4181,20 @@ static void* sys_alloc(mstate m, size_t nb) { m->max_footprint = m->footprint; if (!is_initialized(m)) { /* first-time initialization */ - m->seg.base = m->least_addr = tbase; + if (m->least_addr == 0 || tbase < m->least_addr) + m->least_addr = tbase; + m->seg.base = tbase; m->seg.size = tsize; m->seg.sflags = mmap_flag; m->magic = mparams.magic; + m->release_checks = MAX_RELEASE_CHECK_RATE; init_bins(m); - if (is_global(m)) +#if !ONLY_MSPACES + if (is_global(m)) init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); - else { + else +#endif + { /* Offset top by embedded malloc_state */ mchunkptr mn = next_chunk(mem2chunk(m)); init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); @@ -3508,11 +4204,12 @@ static void* sys_alloc(mstate m, size_t nb) { else { /* Try to merge with an existing segment */ msegmentptr sp = &m->seg; + /* Only consider most recent segment if traversal suppressed */ while (sp != 0 && tbase != sp->base + sp->size) - sp = sp->next; + sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; if (sp != 0 && !is_extern_segment(sp) && - (sp->sflags & IS_MMAPPED_BIT) == mmap_flag && + (sp->sflags & USE_MMAP_BIT) == mmap_flag && segment_holds(sp, m->top)) { /* append */ sp->size += tsize; init_top(m, m->top, m->topsize + tsize); @@ -3522,10 +4219,10 @@ static void* sys_alloc(mstate m, size_t nb) { m->least_addr = tbase; sp = &m->seg; while (sp != 0 && sp->base != tbase + tsize) - sp = sp->next; + sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; if (sp != 0 && !is_extern_segment(sp) && - (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) { + (sp->sflags & USE_MMAP_BIT) == mmap_flag) { char* oldbase = sp->base; sp->base = tbase; sp->size += tsize; @@ -3557,17 +4254,19 @@ static void* sys_alloc(mstate m, size_t nb) { /* Unmap and unlink any mmapped segments that don't contain used chunks */ static size_t release_unused_segments(mstate m) { size_t released = 0; + int nsegs = 0; msegmentptr pred = &m->seg; msegmentptr sp = pred->next; while (sp != 0) { char* base = sp->base; size_t size = sp->size; msegmentptr next = sp->next; + ++nsegs; if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { mchunkptr p = align_as_chunk(base); size_t psize = chunksize(p); /* Can unmap if first chunk holds entire segment and not pinned */ - if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { + if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { tchunkptr tp = (tchunkptr)p; assert(segment_holds(sp, (char*)sp)); if (p == m->dv) { @@ -3589,15 +4288,21 @@ static size_t release_unused_segments(mstate m) { } } } + if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */ + break; pred = sp; sp = next; } + /* Reset check counter */ + m->release_checks = (((size_t) nsegs > (size_t) MAX_RELEASE_CHECK_RATE)? + (size_t) nsegs : (size_t) MAX_RELEASE_CHECK_RATE); memory_hook->dec_heap(released); return released; } static int sys_trim(mstate m, size_t pad) { size_t released = 0; + ensure_initialization(); if (pad < MAX_REQUEST && is_initialized(m)) { pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ @@ -3614,6 +4319,7 @@ static int sys_trim(mstate m, size_t pad) { sp->size >= extra && !has_segment_link(m, sp)) { /* can't shrink if pinned */ size_t newsize = sp->size - extra; + (void)newsize; /* placate people compiling -Wunused-variable */ /* Prefer mremap, fall back to munmap */ if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || (CALL_MUNMAP(sp->base + newsize, extra) == 0)) { @@ -3624,7 +4330,7 @@ static int sys_trim(mstate m, size_t pad) { else if (HAVE_MORECORE) { if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit; - ACQUIRE_MORECORE_LOCK(); + ACQUIRE_MALLOC_GLOBAL_LOCK(); { /* Make sure end of memory is where we last set it. */ char* old_br = (char*)(CALL_MORECORE(0)); @@ -3635,7 +4341,7 @@ static int sys_trim(mstate m, size_t pad) { released = old_br - new_br; } } - RELEASE_MORECORE_LOCK(); + RELEASE_MALLOC_GLOBAL_LOCK(); } } @@ -3648,11 +4354,11 @@ static int sys_trim(mstate m, size_t pad) { } /* Unmap any unused mmapped segments */ - if (HAVE_MMAP) + if (HAVE_MMAP) released += release_unused_segments(m); /* On failure, disable autotrim to avoid repeated failed future calls */ - if (released == 0) + if (released == 0 && m->topsize > m->trim_check) m->trim_check = MAX_SIZE_T; } @@ -3661,7 +4367,78 @@ static int sys_trim(mstate m, size_t pad) { return (released != 0)? 1 : 0; } -/* ---------------------------- malloc support --------------------------- */ +/* Consolidate and bin a chunk. Differs from exported versions + of free mainly in that the chunk need not be marked as inuse. +*/ +static void dispose_chunk(mstate m, mchunkptr p, size_t psize) { + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + mchunkptr prev; + size_t prevsize = p->prev_foot; + if (is_mmapped(p)) { + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + m->footprint -= psize; + return; + } + prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(m, prev))) { /* consolidate backward */ + if (p != m->dv) { + unlink_chunk(m, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + m->dvsize = psize; + set_free_with_pinuse(p, psize, next); + return; + } + } + else { + CORRUPTION_ERROR_ACTION(m); + return; + } + } + if (RTCHECK(ok_address(m, next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == m->top) { + size_t tsize = m->topsize += psize; + m->top = p; + p->head = tsize | PINUSE_BIT; + if (p == m->dv) { + m->dv = 0; + m->dvsize = 0; + } + return; + } + else if (next == m->dv) { + size_t dsize = m->dvsize += psize; + m->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + return; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(m, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == m->dv) { + m->dvsize = psize; + return; + } + } + } + else { + set_free_with_pinuse(p, psize, next); + } + insert_chunk(m, p, psize); + } + else { + CORRUPTION_ERROR_ACTION(m); + } +} + +/* ---------------------------- malloc --------------------------- */ /* allocate a large request from the best fitting chunk in a treebin */ static void* tmalloc_large(mstate m, size_t nb) { @@ -3670,7 +4447,6 @@ static void* tmalloc_large(mstate m, size_t nb) { tchunkptr t; bindex_t idx; compute_tree_index(nb, idx); - if ((t = *treebin_at(m, idx)) != 0) { /* Traverse tree for this bin looking for node with size == nb */ size_t sizebits = nb << leftshift_for_tree_index(idx); @@ -3694,7 +4470,6 @@ static void* tmalloc_large(mstate m, size_t nb) { sizebits <<= 1; } } - if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; if (leftbits != 0) { @@ -3743,7 +4518,6 @@ static void* tmalloc_small(mstate m, size_t nb) { bindex_t i; binmap_t leastbit = least_bit(m->treemap); compute_bit2idx(leastbit, i); - v = t = *treebin_at(m, i); rsize = chunksize(t) - nb; @@ -3775,295 +4549,6 @@ static void* tmalloc_small(mstate m, size_t nb) { return 0; } -/* --------------------------- realloc support --------------------------- */ - -static void* internal_realloc(mstate m, void* oldmem, size_t bytes) { - if (bytes >= MAX_REQUEST) { - MALLOC_FAILURE_ACTION; - return 0; - } - if (!PREACTION(m)) { - mchunkptr oldp = mem2chunk(oldmem); - size_t oldsize = chunksize(oldp); - mchunkptr next = chunk_plus_offset(oldp, oldsize); - mchunkptr newp = 0; - void* extra = 0; - - /* Try to either shrink or extend into top. Else malloc-copy-free */ - - if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) && - ok_next(oldp, next) && ok_pinuse(next))) { - size_t nb = request2size(bytes); - if (is_mmapped(oldp)) - newp = mmap_resize(m, oldp, nb); - else if (oldsize >= nb) { /* already big enough */ - size_t rsize = oldsize - nb; - newp = oldp; - if (rsize >= MIN_CHUNK_SIZE) { - mchunkptr remainder = chunk_plus_offset(newp, nb); - set_inuse(m, newp, nb); - set_inuse(m, remainder, rsize); - extra = chunk2mem(remainder); - } - } - else if (next == m->top && oldsize + m->topsize > nb) { - /* Expand into top */ - size_t newsize = oldsize + m->topsize; - size_t newtopsize = newsize - nb; - mchunkptr newtop = chunk_plus_offset(oldp, nb); - set_inuse(m, oldp, nb); - newtop->head = newtopsize |PINUSE_BIT; - m->top = newtop; - m->topsize = newtopsize; - newp = oldp; - } - } - else { - USAGE_ERROR_ACTION(m, oldmem); - POSTACTION(m); - return 0; - } - - POSTACTION(m); - - if (newp != 0) { - if (extra != 0) { - internal_free(m, extra); - } - check_inuse_chunk(m, newp); - return chunk2mem(newp); - } - else { - void* newmem = internal_malloc(m, bytes); - if (newmem != 0) { - size_t oc = oldsize - overhead_for(oldp); - memcpy(newmem, oldmem, (oc < bytes)? oc : bytes); - internal_free(m, oldmem); - } - return newmem; - } - } - return 0; -} - -/* --------------------------- memalign support -------------------------- */ - -static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { - if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */ - return internal_malloc(m, bytes); - if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ - alignment = MIN_CHUNK_SIZE; - if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ - size_t a = MALLOC_ALIGNMENT << 1; - while (a < alignment) a <<= 1; - alignment = a; - } - - if (bytes >= MAX_REQUEST - alignment) { - if (m != 0) { /* Test isn't needed but avoids compiler warning */ - MALLOC_FAILURE_ACTION; - } - } - else { - size_t nb = request2size(bytes); - size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; - char* mem = (char*)internal_malloc(m, req); - if (mem != 0) { - void* leader = 0; - void* trailer = 0; - mchunkptr p = mem2chunk(mem); - - if (PREACTION(m)) return 0; - if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */ - /* - Find an aligned spot inside chunk. Since we need to give - back leading space in a chunk of at least MIN_CHUNK_SIZE, if - the first calculation places us at a spot with less than - MIN_CHUNK_SIZE leader, we can move to the next aligned spot. - We've allocated enough total room so that this is always - possible. - */ - char* br = (char*)mem2chunk((size_t)(((size_t)(mem + - alignment - - SIZE_T_ONE)) & - -alignment)); - char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? - br : br+alignment; - mchunkptr newp = (mchunkptr)pos; - size_t leadsize = pos - (char*)(p); - size_t newsize = chunksize(p) - leadsize; - - if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ - newp->prev_foot = p->prev_foot + leadsize; - newp->head = (newsize|CINUSE_BIT); - } - else { /* Otherwise, give back leader, use the rest */ - set_inuse(m, newp, newsize); - set_inuse(m, p, leadsize); - leader = chunk2mem(p); - } - p = newp; - } - - /* Give back spare room at the end */ - if (!is_mmapped(p)) { - size_t size = chunksize(p); - if (size > nb + MIN_CHUNK_SIZE) { - size_t remainder_size = size - nb; - mchunkptr remainder = chunk_plus_offset(p, nb); - set_inuse(m, p, nb); - set_inuse(m, remainder, remainder_size); - trailer = chunk2mem(remainder); - } - } - - assert (chunksize(p) >= nb); - assert((((size_t)(chunk2mem(p))) % alignment) == 0); - check_inuse_chunk(m, p); - POSTACTION(m); - if (leader != 0) { - internal_free(m, leader); - } - if (trailer != 0) { - internal_free(m, trailer); - } - return chunk2mem(p); - } - } - return 0; -} - -/* ------------------------ comalloc/coalloc support --------------------- */ - -static void** ialloc(mstate m, - size_t n_elements, - size_t* sizes, - int opts, - void* chunks[]) { - /* - This provides common support for independent_X routines, handling - all of the combinations that can result. - - The opts arg has: - bit 0 set if all elements are same size (using sizes[0]) - bit 1 set if elements should be zeroed - */ - - size_t element_size; /* chunksize of each element, if all same */ - size_t contents_size; /* total size of elements */ - size_t array_size; /* request size of pointer array */ - void* mem; /* malloced aggregate space */ - mchunkptr p; /* corresponding chunk */ - size_t remainder_size; /* remaining bytes while splitting */ - void** marray; /* either "chunks" or malloced ptr array */ - mchunkptr array_chunk; /* chunk for malloced ptr array */ - flag_t was_enabled; /* to disable mmap */ - size_t size; - size_t i; - - /* compute array length, if needed */ - if (chunks != 0) { - if (n_elements == 0) - return chunks; /* nothing to do */ - marray = chunks; - array_size = 0; - } - else { - /* if empty req, must still return chunk representing empty array */ - if (n_elements == 0) - return (void**)internal_malloc(m, 0); - marray = 0; - array_size = request2size(n_elements * (sizeof(void*))); - } - - /* compute total element size */ - if (opts & 0x1) { /* all-same-size */ - element_size = request2size(*sizes); - contents_size = n_elements * element_size; - } - else { /* add up all the sizes */ - element_size = 0; - contents_size = 0; - for (i = 0; i != n_elements; ++i) - contents_size += request2size(sizes[i]); - } - - size = contents_size + array_size; - - /* - Allocate the aggregate chunk. First disable direct-mmapping so - malloc won't use it, since we would not be able to later - free/realloc space internal to a segregated mmap region. - */ - was_enabled = use_mmap(m); - disable_mmap(m); - mem = internal_malloc(m, size - CHUNK_OVERHEAD); - if (was_enabled) - enable_mmap(m); - if (mem == 0) - return 0; - - if (PREACTION(m)) return 0; - p = mem2chunk(mem); - remainder_size = chunksize(p); - - assert(!is_mmapped(p)); - - if (opts & 0x2) { /* optionally clear the elements */ - memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); - } - - /* If not provided, allocate the pointer array as final part of chunk */ - if (marray == 0) { - size_t array_chunk_size; - array_chunk = chunk_plus_offset(p, contents_size); - array_chunk_size = remainder_size - contents_size; - marray = (void**) (chunk2mem(array_chunk)); - set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); - remainder_size = contents_size; - } - - /* split out elements */ - for (i = 0; ; ++i) { - marray[i] = chunk2mem(p); - if (i != n_elements-1) { - if (element_size != 0) - size = element_size; - else - size = request2size(sizes[i]); - remainder_size -= size; - set_size_and_pinuse_of_inuse_chunk(m, p, size); - p = chunk_plus_offset(p, size); - } - else { /* the final element absorbs any overallocation slop */ - set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); - break; - } - } - -#if DEBUG - if (marray != chunks) { - /* final element must have exactly exhausted chunk */ - if (element_size != 0) { - assert(remainder_size == element_size); - } - else { - assert(remainder_size == request2size(sizes[i])); - } - check_inuse_chunk(m, mem2chunk(marray)); - } - for (i = 0; i != n_elements; ++i) - check_inuse_chunk(m, mem2chunk(marray[i])); - -#endif /* DEBUG */ - - POSTACTION(m); - return marray; -} - - -/* -------------------------- public routines ---------------------------- */ - #if !ONLY_MSPACES void* dlmalloc(size_t bytes) { @@ -4090,6 +4575,10 @@ void* dlmalloc(size_t bytes) { The ugly goto's here ensure that postaction occurs along all paths. */ +#if USE_LOCKS + ensure_initialization(); /* initialize in sys_alloc if not using locks */ +#endif + if (!PREACTION(gm)) { void* mem; size_t nb; @@ -4192,20 +4681,14 @@ void* dlmalloc(size_t bytes) { postaction: POSTACTION(gm); -#ifdef MEMMATCH - fprintf(stderr, "memmatch %p %08d malloc(%d)\n", - mem, ++output_counter, bytes); -#endif return mem; } -#ifdef MEMMATCH - fprintf(stderr, "memmatch %p %08d malloc(%d)\n", - 0, ++output_counter, bytes); -#endif return 0; } +/* ---------------------------- free --------------------------- */ + void dlfree(void* mem) { /* Consolidate freed chunks with preceeding or succeeding bordering @@ -4213,11 +4696,6 @@ void dlfree(void* mem) { with special cases for top, dv, mmapped chunks, and usage errors. */ -#ifdef MEMMATCH - fprintf(stderr, "memmatch %p %08d free\n", - mem, ++output_counter); -#endif - if (mem != 0) { mchunkptr p = mem2chunk(mem); #if FOOTERS @@ -4231,13 +4709,12 @@ void dlfree(void* mem) { #endif /* FOOTERS */ if (!PREACTION(fm)) { check_inuse_chunk(fm, p); - if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) { + if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { size_t psize = chunksize(p); mchunkptr next = chunk_plus_offset(p, psize); if (!pinuse(p)) { size_t prevsize = p->prev_foot; - if ((prevsize & IS_MMAPPED_BIT) != 0) { - prevsize &= ~IS_MMAPPED_BIT; + if (is_mmapped(p)) { psize += prevsize + MMAP_FOOT_PAD; if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) { fm->footprint -= psize; @@ -4297,8 +4774,18 @@ void dlfree(void* mem) { } else set_free_with_pinuse(p, psize, next); - insert_chunk(fm, p, psize); - check_free_chunk(fm, p); + + if (is_small(psize)) { + insert_small_chunk(fm, p, psize); + check_free_chunk(fm, p); + } + else { + tchunkptr tp = (tchunkptr)p; + insert_large_chunk(fm, tp, psize); + check_free_chunk(fm, p); + if (--fm->release_checks == 0) + release_unused_segments(fm); + } goto postaction; } } @@ -4328,60 +4815,537 @@ void* dlcalloc(size_t n_elements, size_t elem_size) { return mem; } -void* dlrealloc(void* oldmem, size_t bytes) { - if (oldmem == 0) - return dlmalloc(bytes); -#ifdef REALLOC_ZERO_BYTES_FREES - if (bytes == 0) { - dlfree(oldmem); +#endif /* !ONLY_MSPACES */ + +/* ------------ Internal support for realloc, memalign, etc -------------- */ + +/* Try to realloc; only in-place unless can_move true */ +static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb, + int can_move) { + mchunkptr newp = 0; + size_t oldsize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, oldsize); + if (RTCHECK(ok_address(m, p) && ok_inuse(p) && + ok_next(p, next) && ok_pinuse(next))) { + if (is_mmapped(p)) { + newp = mmap_resize(m, p, nb, can_move); + } + else if (oldsize >= nb) { /* already big enough */ + size_t rsize = oldsize - nb; + if (rsize >= MIN_CHUNK_SIZE) { /* split off remainder */ + mchunkptr r = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, r, rsize); + dispose_chunk(m, r, rsize); + } + newp = p; + } + else if (next == m->top) { /* extend into top */ + if (oldsize + m->topsize > nb) { + size_t newsize = oldsize + m->topsize; + size_t newtopsize = newsize - nb; + mchunkptr newtop = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + newtop->head = newtopsize |PINUSE_BIT; + m->top = newtop; + m->topsize = newtopsize; + newp = p; + } + } + else if (next == m->dv) { /* extend into dv */ + size_t dvs = m->dvsize; + if (oldsize + dvs >= nb) { + size_t dsize = oldsize + dvs - nb; + if (dsize >= MIN_CHUNK_SIZE) { + mchunkptr r = chunk_plus_offset(p, nb); + mchunkptr n = chunk_plus_offset(r, dsize); + set_inuse(m, p, nb); + set_size_and_pinuse_of_free_chunk(r, dsize); + clear_pinuse(n); + m->dvsize = dsize; + m->dv = r; + } + else { /* exhaust dv */ + size_t newsize = oldsize + dvs; + set_inuse(m, p, newsize); + m->dvsize = 0; + m->dv = 0; + } + newp = p; + } + } + else if (!cinuse(next)) { /* extend into next free chunk */ + size_t nextsize = chunksize(next); + if (oldsize + nextsize >= nb) { + size_t rsize = oldsize + nextsize - nb; + unlink_chunk(m, next, nextsize); + if (rsize < MIN_CHUNK_SIZE) { + size_t newsize = oldsize + nextsize; + set_inuse(m, p, newsize); + } + else { + mchunkptr r = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, r, rsize); + dispose_chunk(m, r, rsize); + } + newp = p; + } + } + } + else { + USAGE_ERROR_ACTION(m, chunk2mem(p)); + } + return newp; +} + +static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { + void* mem = 0; + if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ + alignment = MIN_CHUNK_SIZE; + if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ + size_t a = MALLOC_ALIGNMENT << 1; + while (a < alignment) a <<= 1; + alignment = a; + } + if (bytes >= MAX_REQUEST - alignment) { + if (m != 0) { /* Test isn't needed but avoids compiler warning */ + MALLOC_FAILURE_ACTION; + } + } + else { + size_t nb = request2size(bytes); + size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; + mem = internal_malloc(m, req); + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (PREACTION(m)) + return 0; + if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */ + /* + Find an aligned spot inside chunk. Since we need to give + back leading space in a chunk of at least MIN_CHUNK_SIZE, if + the first calculation places us at a spot with less than + MIN_CHUNK_SIZE leader, we can move to the next aligned spot. + We've allocated enough total room so that this is always + possible. + */ + char* br = (char*)mem2chunk((size_t)(((size_t)((char*)mem + alignment - + SIZE_T_ONE)) & + -alignment)); + char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? + br : br+alignment; + mchunkptr newp = (mchunkptr)pos; + size_t leadsize = pos - (char*)(p); + size_t newsize = chunksize(p) - leadsize; + + if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ + newp->prev_foot = p->prev_foot + leadsize; + newp->head = newsize; + } + else { /* Otherwise, give back leader, use the rest */ + set_inuse(m, newp, newsize); + set_inuse(m, p, leadsize); + dispose_chunk(m, p, leadsize); + } + p = newp; + } + + /* Give back spare room at the end */ + if (!is_mmapped(p)) { + size_t size = chunksize(p); + if (size > nb + MIN_CHUNK_SIZE) { + size_t remainder_size = size - nb; + mchunkptr remainder = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, remainder, remainder_size); + dispose_chunk(m, remainder, remainder_size); + } + } + + mem = chunk2mem(p); + assert (chunksize(p) >= nb); + assert(((size_t)mem & (alignment - 1)) == 0); + check_inuse_chunk(m, p); + POSTACTION(m); + } + } + return mem; +} + +/* + Common support for independent_X routines, handling + all of the combinations that can result. + The opts arg has: + bit 0 set if all elements are same size (using sizes[0]) + bit 1 set if elements should be zeroed +*/ +static void** ialloc(mstate m, + size_t n_elements, + size_t* sizes, + int opts, + void* chunks[]) { + + size_t element_size; /* chunksize of each element, if all same */ + size_t contents_size; /* total size of elements */ + size_t array_size; /* request size of pointer array */ + void* mem; /* malloced aggregate space */ + mchunkptr p; /* corresponding chunk */ + size_t remainder_size; /* remaining bytes while splitting */ + void** marray; /* either "chunks" or malloced ptr array */ + mchunkptr array_chunk; /* chunk for malloced ptr array */ + flag_t was_enabled; /* to disable mmap */ + size_t size; + size_t i; + + ensure_initialization(); + /* compute array length, if needed */ + if (chunks != 0) { + if (n_elements == 0) + return chunks; /* nothing to do */ + marray = chunks; + array_size = 0; + } + else { + /* if empty req, must still return chunk representing empty array */ + if (n_elements == 0) + return (void**)internal_malloc(m, 0); + marray = 0; + array_size = request2size(n_elements * (sizeof(void*))); + } + + /* compute total element size */ + if (opts & 0x1) { /* all-same-size */ + element_size = request2size(*sizes); + contents_size = n_elements * element_size; + } + else { /* add up all the sizes */ + element_size = 0; + contents_size = 0; + for (i = 0; i != n_elements; ++i) + contents_size += request2size(sizes[i]); + } + + size = contents_size + array_size; + + /* + Allocate the aggregate chunk. First disable direct-mmapping so + malloc won't use it, since we would not be able to later + free/realloc space internal to a segregated mmap region. + */ + was_enabled = use_mmap(m); + disable_mmap(m); + mem = internal_malloc(m, size - CHUNK_OVERHEAD); + if (was_enabled) + enable_mmap(m); + if (mem == 0) return 0; + + if (PREACTION(m)) return 0; + p = mem2chunk(mem); + remainder_size = chunksize(p); + + assert(!is_mmapped(p)); + + if (opts & 0x2) { /* optionally clear the elements */ + memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); + } + + /* If not provided, allocate the pointer array as final part of chunk */ + if (marray == 0) { + size_t array_chunk_size; + array_chunk = chunk_plus_offset(p, contents_size); + array_chunk_size = remainder_size - contents_size; + marray = (void**) (chunk2mem(array_chunk)); + set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); + remainder_size = contents_size; + } + + /* split out elements */ + for (i = 0; ; ++i) { + marray[i] = chunk2mem(p); + if (i != n_elements-1) { + if (element_size != 0) + size = element_size; + else + size = request2size(sizes[i]); + remainder_size -= size; + set_size_and_pinuse_of_inuse_chunk(m, p, size); + p = chunk_plus_offset(p, size); + } + else { /* the final element absorbs any overallocation slop */ + set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); + break; + } + } + +#if DEBUG + if (marray != chunks) { + /* final element must have exactly exhausted chunk */ + if (element_size != 0) { + assert(remainder_size == element_size); + } + else { + assert(remainder_size == request2size(sizes[i])); + } + check_inuse_chunk(m, mem2chunk(marray)); + } + for (i = 0; i != n_elements; ++i) + check_inuse_chunk(m, mem2chunk(marray[i])); + +#endif /* DEBUG */ + + POSTACTION(m); + return marray; +} + +/* Try to free all pointers in the given array. + Note: this could be made faster, by delaying consolidation, + at the price of disabling some user integrity checks, We + still optimize some consolidations by combining adjacent + chunks before freeing, which will occur often if allocated + with ialloc or the array is sorted. +*/ +static size_t internal_bulk_free(mstate m, void* array[], size_t nelem) { + size_t unfreed = 0; + if (!PREACTION(m)) { + void** a; + void** fence = &(array[nelem]); + for (a = array; a != fence; ++a) { + void* mem = *a; + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + size_t psize = chunksize(p); +#if FOOTERS + if (get_mstate_for(p) != m) { + ++unfreed; + continue; + } +#endif + check_inuse_chunk(m, p); + *a = 0; + if (RTCHECK(ok_address(m, p) && ok_inuse(p))) { + void ** b = a + 1; /* try to merge with next chunk */ + mchunkptr next = next_chunk(p); + if (b != fence && *b == chunk2mem(next)) { + size_t newsize = chunksize(next) + psize; + set_inuse(m, p, newsize); + *b = chunk2mem(p); + } + else + dispose_chunk(m, p, psize); + } + else { + CORRUPTION_ERROR_ACTION(m); + break; + } + } + } + if (should_trim(m, m->topsize)) + sys_trim(m, 0); + POSTACTION(m); + } + return unfreed; +} + +/* Traversal */ +#if MALLOC_INSPECT_ALL +static void internal_inspect_all(mstate m, + void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + if (is_initialized(m)) { + mchunkptr top = m->top; + msegmentptr s; + for (s = &m->seg; s != 0; s = s->next) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && q->head != FENCEPOST_HEAD) { + mchunkptr next = next_chunk(q); + size_t sz = chunksize(q); + size_t used; + void* start; + if (is_inuse(q)) { + used = sz - CHUNK_OVERHEAD; /* must not be mmapped */ + start = chunk2mem(q); + } + else { + used = 0; + if (is_small(sz)) { /* offset by possible bookkeeping */ + start = (void*)((char*)q + sizeof(struct malloc_chunk)); + } + else { + start = (void*)((char*)q + sizeof(struct malloc_tree_chunk)); + } + } + if (start < (void*)next) /* skip if all space is bookkeeping */ + handler(start, next, used, arg); + if (q == top) + break; + q = next; + } + } + } +} +#endif /* MALLOC_INSPECT_ALL */ + +/* ------------------ Exported realloc, memalign, etc -------------------- */ + +#if !ONLY_MSPACES + +void* dlrealloc(void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem == 0) { + mem = dlmalloc(bytes); + } + else if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } +#ifdef REALLOC_ZERO_BYTES_FREES + else if (bytes == 0) { + dlfree(oldmem); } #endif /* REALLOC_ZERO_BYTES_FREES */ else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); #if ! FOOTERS mstate m = gm; #else /* FOOTERS */ - mstate m = get_mstate_for(mem2chunk(oldmem)); + mstate m = get_mstate_for(oldp); if (!ok_magic(m)) { USAGE_ERROR_ACTION(m, oldmem); return 0; } #endif /* FOOTERS */ - return internal_realloc(m, oldmem, bytes); + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); + POSTACTION(m); + if (newp != 0) { + check_inuse_chunk(m, newp); + mem = chunk2mem(newp); + } + else { + mem = internal_malloc(m, bytes); + if (mem != 0) { + size_t oc = chunksize(oldp) - overhead_for(oldp); + memcpy(mem, oldmem, (oc < bytes)? oc : bytes); + internal_free(m, oldmem); + } + } + } } + return mem; +} + +void* dlrealloc_in_place(void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem != 0) { + if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = gm; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); + POSTACTION(m); + if (newp == oldp) { + check_inuse_chunk(m, newp); + mem = oldmem; + } + } + } + } + return mem; } void* dlmemalign(size_t alignment, size_t bytes) { + if (alignment <= MALLOC_ALIGNMENT) { + return dlmalloc(bytes); + } return internal_memalign(gm, alignment, bytes); } -void** dlindependent_calloc(size_t n_elements, size_t elem_size, - void* chunks[]) { - size_t sz = elem_size; /* serves as 1-element array */ - return ialloc(gm, n_elements, &sz, 3, chunks); -} - -void** dlindependent_comalloc(size_t n_elements, size_t sizes[], - void* chunks[]) { - return ialloc(gm, n_elements, sizes, 0, chunks); +int dlposix_memalign(void** pp, size_t alignment, size_t bytes) { + void* mem = 0; + if (alignment == MALLOC_ALIGNMENT) + mem = dlmalloc(bytes); + else { + size_t d = alignment / sizeof(void*); + size_t r = alignment % sizeof(void*); + if (r != 0 || d == 0 || (d & (d-SIZE_T_ONE)) != 0) + return EINVAL; + else if (bytes <= MAX_REQUEST - alignment) { + if (alignment < MIN_CHUNK_SIZE) + alignment = MIN_CHUNK_SIZE; + mem = internal_memalign(gm, alignment, bytes); + } + } + if (mem == 0) + return ENOMEM; + else { + *pp = mem; + return 0; + } } void* dlvalloc(size_t bytes) { size_t pagesz; - init_mparams(); + ensure_initialization(); pagesz = mparams.page_size; return dlmemalign(pagesz, bytes); } void* dlpvalloc(size_t bytes) { size_t pagesz; - init_mparams(); + ensure_initialization(); pagesz = mparams.page_size; return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); } +void** dlindependent_calloc(size_t n_elements, size_t elem_size, + void* chunks[]) { + size_t sz = elem_size; /* serves as 1-element array */ + return ialloc(gm, n_elements, &sz, 3, chunks); +} + +void** dlindependent_comalloc(size_t n_elements, size_t sizes[], + void* chunks[]) { + return ialloc(gm, n_elements, sizes, 0, chunks); +} + +size_t dlbulk_free(void* array[], size_t nelem) { + return internal_bulk_free(gm, array, nelem); +} + +#if MALLOC_INSPECT_ALL +void dlmalloc_inspect_all(void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + ensure_initialization(); + if (!PREACTION(gm)) { + internal_inspect_all(gm, handler, arg); + POSTACTION(gm); + } +} +#endif /* MALLOC_INSPECT_ALL */ + int dlmalloc_trim(size_t pad) { int result = 0; + ensure_initialization(); if (!PREACTION(gm)) { result = sys_trim(gm, pad); POSTACTION(gm); @@ -4397,29 +5361,47 @@ size_t dlmalloc_max_footprint(void) { return gm->max_footprint; } +size_t dlmalloc_footprint_limit(void) { + size_t maf = gm->footprint_limit; + return maf == 0 ? MAX_SIZE_T : maf; +} + +size_t dlmalloc_set_footprint_limit(size_t bytes) { + size_t result; /* invert sense of 0 */ + if (bytes == 0) + result = granularity_align(1); /* Use minimal size */ + if (bytes == MAX_SIZE_T) + result = 0; /* disable */ + else + result = granularity_align(bytes); + return gm->footprint_limit = result; +} + #if !NO_MALLINFO struct mallinfo dlmallinfo(void) { return internal_mallinfo(gm); } #endif /* NO_MALLINFO */ +#if !NO_MALLOC_STATS void dlmalloc_stats() { internal_malloc_stats(gm); } +#endif /* NO_MALLOC_STATS */ + +int dlmallopt(int param_number, int value) { + return change_mparam(param_number, value); +} size_t dlmalloc_usable_size(void* mem) { if (mem != 0) { mchunkptr p = mem2chunk(mem); - if (cinuse(p)) + if (is_inuse(p)) return chunksize(p) - overhead_for(p); } return 0; } -int dlmallopt(int param_number, int value) { - return change_mparam(param_number, value); -} - #endif /* !ONLY_MSPACES */ /* ----------------------------- user mspaces ---------------------------- */ @@ -4432,12 +5414,15 @@ static mstate init_user_mstate(char* tbase, size_t tsize) { mchunkptr msp = align_as_chunk(tbase); mstate m = (mstate)(chunk2mem(msp)); memset(m, 0, msize); - INITIAL_LOCK(&m->mutex); - msp->head = (msize|PINUSE_BIT|CINUSE_BIT); + (void)INITIAL_LOCK(&m->mutex); + msp->head = (msize|INUSE_BITS); m->seg.base = m->least_addr = tbase; m->seg.size = m->footprint = m->max_footprint = tsize; m->magic = mparams.magic; + m->release_checks = MAX_RELEASE_CHECK_RATE; m->mflags = mparams.default_mflags; + m->extp = 0; + m->exts = 0; disable_contiguous(m); init_bins(m); mn = next_chunk(mem2chunk(m)); @@ -4448,9 +5433,9 @@ static mstate init_user_mstate(char* tbase, size_t tsize) { mspace create_mspace(size_t capacity, int locked) { mstate m = 0; - size_t msize = pad_request(sizeof(struct malloc_state)); - init_mparams(); /* Ensure pagesize etc initialized */ - + size_t msize; + ensure_initialization(); + msize = pad_request(sizeof(struct malloc_state)); if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { size_t rs = ((capacity == 0)? mparams.granularity : (capacity + TOP_FOOT_SIZE + msize)); @@ -4458,7 +5443,7 @@ mspace create_mspace(size_t capacity, int locked) { char* tbase = (char*)(CALL_MMAP(tsize)); if (tbase != CMFAIL) { m = init_user_mstate(tbase, tsize); - m->seg.sflags = IS_MMAPPED_BIT; + m->seg.sflags = USE_MMAP_BIT; set_lock(m, locked); } } @@ -4467,9 +5452,9 @@ mspace create_mspace(size_t capacity, int locked) { mspace create_mspace_with_base(void* base, size_t capacity, int locked) { mstate m = 0; - size_t msize = pad_request(sizeof(struct malloc_state)); - init_mparams(); /* Ensure pagesize etc initialized */ - + size_t msize; + ensure_initialization(); + msize = pad_request(sizeof(struct malloc_state)); if (capacity > msize + TOP_FOOT_SIZE && capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { m = init_user_mstate((char*)base, capacity); @@ -4479,17 +5464,36 @@ mspace create_mspace_with_base(void* base, size_t capacity, int locked) { return (mspace)m; } +int mspace_track_large_chunks(mspace msp, int enable) { + int ret = 0; + mstate ms = (mstate)msp; + if (!PREACTION(ms)) { + if (!use_mmap(ms)) { + ret = 1; + } + if (!enable) { + enable_mmap(ms); + } else { + disable_mmap(ms); + } + POSTACTION(ms); + } + return ret; +} + size_t destroy_mspace(mspace msp) { size_t freed = 0; mstate ms = (mstate)msp; if (ok_magic(ms)) { msegmentptr sp = &ms->seg; + (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */ while (sp != 0) { char* base = sp->base; size_t size = sp->size; flag_t flag = sp->sflags; + (void)base; /* placate people compiling -Wunused-variable */ sp = sp->next; - if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) && + if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) && CALL_MUNMAP(base, size) == 0) freed += size; } @@ -4505,7 +5509,6 @@ size_t destroy_mspace(mspace msp) { versions. This is not so nice but better than the alternatives. */ - void* mspace_malloc(mspace msp, size_t bytes) { mstate ms = (mstate)msp; if (!ok_magic(ms)) { @@ -4625,6 +5628,7 @@ void mspace_free(mspace msp, void* mem) { mchunkptr p = mem2chunk(mem); #if FOOTERS mstate fm = get_mstate_for(p); + (void)msp; /* placate people compiling -Wunused */ #else /* FOOTERS */ mstate fm = (mstate)msp; #endif /* FOOTERS */ @@ -4634,13 +5638,12 @@ void mspace_free(mspace msp, void* mem) { } if (!PREACTION(fm)) { check_inuse_chunk(fm, p); - if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) { + if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { size_t psize = chunksize(p); mchunkptr next = chunk_plus_offset(p, psize); if (!pinuse(p)) { size_t prevsize = p->prev_foot; - if ((prevsize & IS_MMAPPED_BIT) != 0) { - prevsize &= ~IS_MMAPPED_BIT; + if (is_mmapped(p)) { psize += prevsize + MMAP_FOOT_PAD; if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) fm->footprint -= psize; @@ -4698,8 +5701,18 @@ void mspace_free(mspace msp, void* mem) { } else set_free_with_pinuse(p, psize, next); - insert_chunk(fm, p, psize); - check_free_chunk(fm, p); + + if (is_small(psize)) { + insert_small_chunk(fm, p, psize); + check_free_chunk(fm, p); + } + else { + tchunkptr tp = (tchunkptr)p; + insert_large_chunk(fm, tp, psize); + check_free_chunk(fm, p); + if (--fm->release_checks == 0) + release_unused_segments(fm); + } goto postaction; } } @@ -4732,27 +5745,80 @@ void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { } void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) { - if (oldmem == 0) - return mspace_malloc(msp, bytes); + void* mem = 0; + if (oldmem == 0) { + mem = mspace_malloc(msp, bytes); + } + else if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } #ifdef REALLOC_ZERO_BYTES_FREES - if (bytes == 0) { + else if (bytes == 0) { mspace_free(msp, oldmem); - return 0; } #endif /* REALLOC_ZERO_BYTES_FREES */ else { -#if FOOTERS - mchunkptr p = mem2chunk(oldmem); - mstate ms = get_mstate_for(p); + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = (mstate)msp; #else /* FOOTERS */ - mstate ms = (mstate)msp; -#endif /* FOOTERS */ - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); + mstate m = get_mstate_for(oldp); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); return 0; } - return internal_realloc(ms, oldmem, bytes); +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); + POSTACTION(m); + if (newp != 0) { + check_inuse_chunk(m, newp); + mem = chunk2mem(newp); + } + else { + mem = mspace_malloc(m, bytes); + if (mem != 0) { + size_t oc = chunksize(oldp) - overhead_for(oldp); + memcpy(mem, oldmem, (oc < bytes)? oc : bytes); + mspace_free(m, oldmem); + } + } + } } + return mem; +} + +void* mspace_realloc_in_place(mspace msp, void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem != 0) { + if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = (mstate)msp; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + (void)msp; /* placate people compiling -Wunused */ + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); + POSTACTION(m); + if (newp == oldp) { + check_inuse_chunk(m, newp); + mem = oldmem; + } + } + } + } + return mem; } void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { @@ -4761,6 +5827,8 @@ void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { USAGE_ERROR_ACTION(ms,ms); return 0; } + if (alignment <= MALLOC_ALIGNMENT) + return mspace_malloc(msp, bytes); return internal_memalign(ms, alignment, bytes); } @@ -4785,6 +5853,30 @@ void** mspace_independent_comalloc(mspace msp, size_t n_elements, return ialloc(ms, n_elements, sizes, 0, chunks); } +size_t mspace_bulk_free(mspace msp, void* array[], size_t nelem) { + return internal_bulk_free((mstate)msp, array, nelem); +} + +#if MALLOC_INSPECT_ALL +void mspace_inspect_all(mspace msp, + void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (!PREACTION(ms)) { + internal_inspect_all(ms, handler, arg); + POSTACTION(ms); + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } +} +#endif /* MALLOC_INSPECT_ALL */ + int mspace_trim(mspace msp, size_t pad) { int result = 0; mstate ms = (mstate)msp; @@ -4800,6 +5892,7 @@ int mspace_trim(mspace msp, size_t pad) { return result; } +#if !NO_MALLOC_STATS void mspace_malloc_stats(mspace msp) { mstate ms = (mstate)msp; if (ok_magic(ms)) { @@ -4809,28 +5902,62 @@ void mspace_malloc_stats(mspace msp) { USAGE_ERROR_ACTION(ms,ms); } } +#endif /* NO_MALLOC_STATS */ size_t mspace_footprint(mspace msp) { - size_t result; + size_t result = 0; mstate ms = (mstate)msp; if (ok_magic(ms)) { result = ms->footprint; } - USAGE_ERROR_ACTION(ms,ms); + else { + USAGE_ERROR_ACTION(ms,ms); + } return result; } - size_t mspace_max_footprint(mspace msp) { - size_t result; + size_t result = 0; mstate ms = (mstate)msp; if (ok_magic(ms)) { result = ms->max_footprint; } - USAGE_ERROR_ACTION(ms,ms); + else { + USAGE_ERROR_ACTION(ms,ms); + } return result; } +size_t mspace_footprint_limit(mspace msp) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + size_t maf = ms->footprint_limit; + result = (maf == 0) ? MAX_SIZE_T : maf; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +size_t mspace_set_footprint_limit(mspace msp, size_t bytes) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (bytes == 0) + result = granularity_align(1); /* Use minimal size */ + if (bytes == MAX_SIZE_T) + result = 0; /* disable */ + else + result = granularity_align(bytes); + ms->footprint_limit = result; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} #if !NO_MALLINFO struct mallinfo mspace_mallinfo(mspace msp) { @@ -4842,12 +5969,22 @@ struct mallinfo mspace_mallinfo(mspace msp) { } #endif /* NO_MALLINFO */ +size_t mspace_usable_size(const void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (is_inuse(p)) + return chunksize(p) - overhead_for(p); + } + return 0; +} + int mspace_mallopt(int param_number, int value) { return change_mparam(param_number, value); } #endif /* MSPACES */ + /* -------------------- Alternative MORECORE functions ------------------- */ /* @@ -4942,6 +6079,44 @@ int mspace_mallopt(int param_number, int value) { /* ----------------------------------------------------------------------- History: + v2.8.6 Wed Aug 29 06:57:58 2012 Doug Lea + * fix bad comparison in dlposix_memalign + * don't reuse adjusted asize in sys_alloc + * add LOCK_AT_FORK -- thanks to Kirill Artamonov for the suggestion + * reduce compiler warnings -- thanks to all who reported/suggested these + + v2.8.5 Sun May 22 10:26:02 2011 Doug Lea (dl at gee) + * Always perform unlink checks unless INSECURE + * Add posix_memalign. + * Improve realloc to expand in more cases; expose realloc_in_place. + Thanks to Peter Buhr for the suggestion. + * Add footprint_limit, inspect_all, bulk_free. Thanks + to Barry Hayes and others for the suggestions. + * Internal refactorings to avoid calls while holding locks + * Use non-reentrant locks by default. Thanks to Roland McGrath + for the suggestion. + * Small fixes to mspace_destroy, reset_on_error. + * Various configuration extensions/changes. Thanks + to all who contributed these. + + V2.8.4a Thu Apr 28 14:39:43 2011 (dl at gee.cs.oswego.edu) + * Update Creative Commons URL + + V2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee) + * Use zeros instead of prev foot for is_mmapped + * Add mspace_track_large_chunks; thanks to Jean Brouwers + * Fix set_inuse in internal_realloc; thanks to Jean Brouwers + * Fix insufficient sys_alloc padding when using 16byte alignment + * Fix bad error check in mspace_footprint + * Adaptations for ptmalloc; thanks to Wolfram Gloger. + * Reentrant spin locks; thanks to Earl Chew and others + * Win32 improvements; thanks to Niall Douglas and Earl Chew + * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options + * Extension hook in malloc_state + * Various small adjustments to reduce warnings on some compilers + * Various configuration extensions/changes for more platforms. Thanks + to all who contributed these. + V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee) * Add max_footprint functions * Ensure all appropriate literals are size_t @@ -5118,7 +6293,5 @@ History: Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) * Based loosely on libg++-1.2X malloc. (It retains some of the overall structure of old version, but most details differ.) - -*/ -#endif // USE_MEMORY_DLMALLOC +*/ diff --git a/dtool/src/dtoolbase/dtoolbase.h b/dtool/src/dtoolbase/dtoolbase.h index cfa1d9b0e3..7ec1cb6f04 100644 --- a/dtool/src/dtoolbase/dtoolbase.h +++ b/dtool/src/dtoolbase/dtoolbase.h @@ -415,7 +415,7 @@ typedef struct _object PyObject; #define MAKE_PROPERTY(property_name, ...) __make_property(property_name, __VA_ARGS__) #define MAKE_PROPERTY2(property_name, ...) __make_property2(property_name, __VA_ARGS__) #define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name) -#undef USE_STL_ALLOCATOR /* Don't try to parse these template classes in interrogate. */ +#define MAKE_SEQ_PROPERTY(property_name, ...) __make_seq_property(property_name, __VA_ARGS__) #define EXTENSION(x) __extension x #define EXTEND __extension #else @@ -425,6 +425,7 @@ typedef struct _object PyObject; #define MAKE_PROPERTY(property_name, ...) #define MAKE_PROPERTY2(property_name, ...) #define MAKE_SEQ(seq_name, num_name, element_name) +#define MAKE_SEQ_PROPERTY(property_name, ...) #define EXTENSION(x) #define EXTEND #endif diff --git a/dtool/src/dtoolbase/lookup3.c b/dtool/src/dtoolbase/lookup3.c index 1cd36c58d0..34c8eaa94a 100644 --- a/dtool/src/dtoolbase/lookup3.c +++ b/dtool/src/dtoolbase/lookup3.c @@ -149,25 +149,25 @@ and these came close: /* -------------------------------------------------------------------- This works on all machines. To be useful, it requires - -- that the key be an array of PN_uint32's, and - -- that the length be the number of PN_uint32's in the key + -- that the key be an array of uint32_t's, and + -- that the length be the number of uint32_t's in the key The function hashword() is identical to hashlittle() on little-endian machines, and identical to hashbig() on big-endian machines, - except that the length has to be measured in PN_uint32s rather than in + except that the length has to be measured in uint32_ts rather than in bytes. hashlittle() is more complicated than hashword() only because hashlittle() has to dance around fitting the key bytes into registers. -------------------------------------------------------------------- */ -PN_uint32 hashword( -const PN_uint32 *k, /* the key, an array of PN_uint32 values */ -size_t length, /* the length of the key, in PN_uint32s */ -PN_uint32 initval) /* the previous hash, or an arbitrary value */ +uint32_t hashword( +const uint32_t *k, /* the key, an array of uint32_t values */ +size_t length, /* the length of the key, in uint32_ts */ +uint32_t initval) /* the previous hash, or an arbitrary value */ { - PN_uint32 a,b,c; + uint32_t a,b,c; /* Set up the internal state */ - a = b = c = 0xdeadbeef + (((PN_uint32)length)<<2) + initval; + a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval; /*------------------------------------------------- handle most of the key */ while (length > 3) @@ -180,7 +180,7 @@ PN_uint32 initval) /* the previous hash, or an arbitrary value */ k += 3; } - /*------------------------------------------- handle the last 3 PN_uint32's */ + /*------------------------------------------- handle the last 3 uint32_t's */ switch(length) /* all the case statements fall through */ { case 3 : c+=k[2]; @@ -211,7 +211,7 @@ use a bitmask. For example, if you need only 10 bits, do h = (h & hashmask(10)); In which case, the hash table should have hashsize(10) elements. -If you are hashing n strings (PN_uint8 **)k, do it like this: +If you are hashing n strings (uint8_t **)k, do it like this: for (i=0, h=0; i 12) { - a += k[0] + (((PN_uint32)k[1])<<16); - b += k[2] + (((PN_uint32)k[3])<<16); - c += k[4] + (((PN_uint32)k[5])<<16); + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); mix(a,b,c); length -= 12; k += 6; } /*----------------------------- handle the last (probably partial) block */ - k8 = (const PN_uint8 *)k; + k8 = (const uint8_t *)k; switch(length) { - case 12: c+=k[4]+(((PN_uint32)k[5])<<16); - b+=k[2]+(((PN_uint32)k[3])<<16); - a+=k[0]+(((PN_uint32)k[1])<<16); + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); break; - case 11: c+=((PN_uint32)k8[10])<<16; /* fall through */ + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ case 10: c+=k[4]; - b+=k[2]+(((PN_uint32)k[3])<<16); - a+=k[0]+(((PN_uint32)k[1])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); break; case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[2]+(((PN_uint32)k[3])<<16); - a+=k[0]+(((PN_uint32)k[1])<<16); + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); break; - case 7 : b+=((PN_uint32)k8[6])<<16; /* fall through */ + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ case 6 : b+=k[2]; - a+=k[0]+(((PN_uint32)k[1])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); break; case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]+(((PN_uint32)k[1])<<16); + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); break; - case 3 : a+=((PN_uint32)k8[2])<<16; /* fall through */ + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ case 2 : a+=k[0]; break; case 1 : a+=k8[0]; @@ -347,23 +347,23 @@ PN_uint32 hashlittle( const void *key, size_t length, PN_uint32 initval) } } else { /* need to read the key one byte at a time */ - const PN_uint8 *k =(PN_uint8*) key; + const uint8_t *k =(uint8_t*) key; /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ while (length > 12) { a += k[0]; - a += ((PN_uint32)k[1])<<8; - a += ((PN_uint32)k[2])<<16; - a += ((PN_uint32)k[3])<<24; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; b += k[4]; - b += ((PN_uint32)k[5])<<8; - b += ((PN_uint32)k[6])<<16; - b += ((PN_uint32)k[7])<<24; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; c += k[8]; - c += ((PN_uint32)k[9])<<8; - c += ((PN_uint32)k[10])<<16; - c += ((PN_uint32)k[11])<<24; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; mix(a,b,c); length -= 12; k += 12; @@ -372,17 +372,17 @@ PN_uint32 hashlittle( const void *key, size_t length, PN_uint32 initval) /*-------------------------------- last block: affect all 32 bits of (c) */ switch(length) /* all the case statements fall through */ { - case 12: c+=((PN_uint32)k[11])<<24; - case 11: c+=((PN_uint32)k[10])<<16; - case 10: c+=((PN_uint32)k[9])<<8; + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; case 9 : c+=k[8]; - case 8 : b+=((PN_uint32)k[7])<<24; - case 7 : b+=((PN_uint32)k[6])<<16; - case 6 : b+=((PN_uint32)k[5])<<8; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; case 5 : b+=k[4]; - case 4 : a+=((PN_uint32)k[3])<<24; - case 3 : a+=((PN_uint32)k[2])<<16; - case 2 : a+=((PN_uint32)k[1])<<8; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; case 1 : a+=k[0]; break; case 0 : return c; @@ -407,21 +407,21 @@ PN_uint32 hashlittle( const void *key, size_t length, PN_uint32 initval) void hashlittle2( const void *key, /* the key to hash */ size_t length, /* length of the key */ - PN_uint32 *pc, /* IN: primary initval, OUT: primary hash */ - PN_uint32 *pb) /* IN: secondary initval, OUT: secondary hash */ + uint32_t *pc, /* IN: primary initval, OUT: primary hash */ + uint32_t *pb) /* IN: secondary initval, OUT: secondary hash */ { - PN_uint32 a,b,c; /* internal state */ + uint32_t a,b,c; /* internal state */ union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ /* Set up the internal state */ - a = b = c = 0xdeadbeef + ((PN_uint32)length) + *pc; + a = b = c = 0xdeadbeef + ((uint32_t)length) + *pc; c += *pb; u.ptr = key; if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { - const PN_uint32 *k = (PN_uint32*)key; /* read 32-bit chunks */ + const uint32_t *k = (uint32_t*)key; /* read 32-bit chunks */ #ifdef VALGRIND - const PN_uint8 *k8; + const uint8_t *k8; #endif /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ @@ -466,20 +466,20 @@ void hashlittle2( #else /* make valgrind happy */ - k8 = (const PN_uint8 *)k; + k8 = (const uint8_t *)k; switch(length) { case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=((PN_uint32)k8[10])<<16; /* fall through */ - case 10: c+=((PN_uint32)k8[9])<<8; /* fall through */ + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ case 9 : c+=k8[8]; /* fall through */ case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=((PN_uint32)k8[6])<<16; /* fall through */ - case 6 : b+=((PN_uint32)k8[5])<<8; /* fall through */ + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ case 5 : b+=k8[4]; /* fall through */ case 4 : a+=k[0]; break; - case 3 : a+=((PN_uint32)k8[2])<<16; /* fall through */ - case 2 : a+=((PN_uint32)k8[1])<<8; /* fall through */ + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ case 1 : a+=k8[0]; break; case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ } @@ -487,45 +487,45 @@ void hashlittle2( #endif /* !valgrind */ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { - const PN_uint16 *k = (PN_uint16*)key; /* read 16-bit chunks */ - const PN_uint8 *k8; + const uint16_t *k = (uint16_t*)key; /* read 16-bit chunks */ + const uint8_t *k8; /*--------------- all but last block: aligned reads and different mixing */ while (length > 12) { - a += k[0] + (((PN_uint32)k[1])<<16); - b += k[2] + (((PN_uint32)k[3])<<16); - c += k[4] + (((PN_uint32)k[5])<<16); + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); mix(a,b,c); length -= 12; k += 6; } /*----------------------------- handle the last (probably partial) block */ - k8 = (const PN_uint8 *)k; + k8 = (const uint8_t *)k; switch(length) { - case 12: c+=k[4]+(((PN_uint32)k[5])<<16); - b+=k[2]+(((PN_uint32)k[3])<<16); - a+=k[0]+(((PN_uint32)k[1])<<16); + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); break; - case 11: c+=((PN_uint32)k8[10])<<16; /* fall through */ + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ case 10: c+=k[4]; - b+=k[2]+(((PN_uint32)k[3])<<16); - a+=k[0]+(((PN_uint32)k[1])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); break; case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[2]+(((PN_uint32)k[3])<<16); - a+=k[0]+(((PN_uint32)k[1])<<16); + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); break; - case 7 : b+=((PN_uint32)k8[6])<<16; /* fall through */ + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ case 6 : b+=k[2]; - a+=k[0]+(((PN_uint32)k[1])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); break; case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]+(((PN_uint32)k[1])<<16); + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); break; - case 3 : a+=((PN_uint32)k8[2])<<16; /* fall through */ + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ case 2 : a+=k[0]; break; case 1 : a+=k8[0]; @@ -534,23 +534,23 @@ void hashlittle2( } } else { /* need to read the key one byte at a time */ - const PN_uint8 *k = (PN_uint8*)key; + const uint8_t *k = (uint8_t*)key; /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ while (length > 12) { a += k[0]; - a += ((PN_uint32)k[1])<<8; - a += ((PN_uint32)k[2])<<16; - a += ((PN_uint32)k[3])<<24; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; b += k[4]; - b += ((PN_uint32)k[5])<<8; - b += ((PN_uint32)k[6])<<16; - b += ((PN_uint32)k[7])<<24; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; c += k[8]; - c += ((PN_uint32)k[9])<<8; - c += ((PN_uint32)k[10])<<16; - c += ((PN_uint32)k[11])<<24; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; mix(a,b,c); length -= 12; k += 12; @@ -559,17 +559,17 @@ void hashlittle2( /*-------------------------------- last block: affect all 32 bits of (c) */ switch(length) /* all the case statements fall through */ { - case 12: c+=((PN_uint32)k[11])<<24; - case 11: c+=((PN_uint32)k[10])<<16; - case 10: c+=((PN_uint32)k[9])<<8; + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; case 9 : c+=k[8]; - case 8 : b+=((PN_uint32)k[7])<<24; - case 7 : b+=((PN_uint32)k[6])<<16; - case 6 : b+=((PN_uint32)k[5])<<8; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; case 5 : b+=k[4]; - case 4 : a+=((PN_uint32)k[3])<<24; - case 3 : a+=((PN_uint32)k[2])<<16; - case 2 : a+=((PN_uint32)k[1])<<8; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; case 1 : a+=k[0]; break; case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ @@ -588,19 +588,19 @@ void hashlittle2( * from hashlittle() on all machines. hashbig() takes advantage of * big-endian byte ordering. */ -PN_uint32 hashbig( const void *key, size_t length, PN_uint32 initval) +uint32_t hashbig( const void *key, size_t length, uint32_t initval) { - PN_uint32 a,b,c; + uint32_t a,b,c; union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */ /* Set up the internal state */ - a = b = c = 0xdeadbeef + ((PN_uint32)length) + initval; + a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; u.ptr = key; if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { - const PN_uint32 *k = (PN_uint32*)key; /* read 32-bit chunks */ + const uint32_t *k = (uint32_t*)key; /* read 32-bit chunks */ #ifdef VALGRIND - const PN_uint8 *k8; + const uint8_t *k8; #endif /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ @@ -645,44 +645,44 @@ PN_uint32 hashbig( const void *key, size_t length, PN_uint32 initval) #else /* make valgrind happy */ - k8 = (const PN_uint8 *)k; + k8 = (const uint8_t *)k; switch(length) /* all the case statements fall through */ { case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=((PN_uint32)k8[10])<<8; /* fall through */ - case 10: c+=((PN_uint32)k8[9])<<16; /* fall through */ - case 9 : c+=((PN_uint32)k8[8])<<24; /* fall through */ + case 11: c+=((uint32_t)k8[10])<<8; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<16; /* fall through */ + case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */ case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=((PN_uint32)k8[6])<<8; /* fall through */ - case 6 : b+=((PN_uint32)k8[5])<<16; /* fall through */ - case 5 : b+=((PN_uint32)k8[4])<<24; /* fall through */ + case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */ + case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */ case 4 : a+=k[0]; break; - case 3 : a+=((PN_uint32)k8[2])<<8; /* fall through */ - case 2 : a+=((PN_uint32)k8[1])<<16; /* fall through */ - case 1 : a+=((PN_uint32)k8[0])<<24; break; + case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */ + case 1 : a+=((uint32_t)k8[0])<<24; break; case 0 : return c; } #endif /* !VALGRIND */ } else { /* need to read the key one byte at a time */ - const PN_uint8 *k = (PN_uint8*)key; + const uint8_t *k = (uint8_t*)key; /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ while (length > 12) { - a += ((PN_uint32)k[0])<<24; - a += ((PN_uint32)k[1])<<16; - a += ((PN_uint32)k[2])<<8; - a += ((PN_uint32)k[3]); - b += ((PN_uint32)k[4])<<24; - b += ((PN_uint32)k[5])<<16; - b += ((PN_uint32)k[6])<<8; - b += ((PN_uint32)k[7]); - c += ((PN_uint32)k[8])<<24; - c += ((PN_uint32)k[9])<<16; - c += ((PN_uint32)k[10])<<8; - c += ((PN_uint32)k[11]); + a += ((uint32_t)k[0])<<24; + a += ((uint32_t)k[1])<<16; + a += ((uint32_t)k[2])<<8; + a += ((uint32_t)k[3]); + b += ((uint32_t)k[4])<<24; + b += ((uint32_t)k[5])<<16; + b += ((uint32_t)k[6])<<8; + b += ((uint32_t)k[7]); + c += ((uint32_t)k[8])<<24; + c += ((uint32_t)k[9])<<16; + c += ((uint32_t)k[10])<<8; + c += ((uint32_t)k[11]); mix(a,b,c); length -= 12; k += 12; @@ -692,17 +692,17 @@ PN_uint32 hashbig( const void *key, size_t length, PN_uint32 initval) switch(length) /* all the case statements fall through */ { case 12: c+=k[11]; - case 11: c+=((PN_uint32)k[10])<<8; - case 10: c+=((PN_uint32)k[9])<<16; - case 9 : c+=((PN_uint32)k[8])<<24; + case 11: c+=((uint32_t)k[10])<<8; + case 10: c+=((uint32_t)k[9])<<16; + case 9 : c+=((uint32_t)k[8])<<24; case 8 : b+=k[7]; - case 7 : b+=((PN_uint32)k[6])<<8; - case 6 : b+=((PN_uint32)k[5])<<16; - case 5 : b+=((PN_uint32)k[4])<<24; + case 7 : b+=((uint32_t)k[6])<<8; + case 6 : b+=((uint32_t)k[5])<<16; + case 5 : b+=((uint32_t)k[4])<<24; case 4 : a+=k[3]; - case 3 : a+=((PN_uint32)k[2])<<8; - case 2 : a+=((PN_uint32)k[1])<<16; - case 1 : a+=((PN_uint32)k[0])<<24; + case 3 : a+=((uint32_t)k[2])<<8; + case 2 : a+=((uint32_t)k[1])<<16; + case 1 : a+=((uint32_t)k[0])<<24; break; case 0 : return c; } @@ -718,9 +718,9 @@ PN_uint32 hashbig( const void *key, size_t length, PN_uint32 initval) /* used for timings */ void driver1() { - PN_uint8 buf[256]; - PN_uint32 i; - PN_uint32 h=0; + uint8_t buf[256]; + uint32_t i; + uint32_t h=0; time_t a,z; time(&a); @@ -740,11 +740,11 @@ void driver1() #define MAXLEN 70 void driver2() { - PN_uint8 qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1]; - PN_uint32 c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z; - PN_uint32 e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE]; - PN_uint32 x[HASHSTATE],y[HASHSTATE]; - PN_uint32 hlen; + uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1]; + uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z; + uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE]; + uint32_t x[HASHSTATE],y[HASHSTATE]; + uint32_t hlen; printf("No more than %d trials should ever be needed \n",MAXPAIR/2); for (hlen=0; hlen < MAXLEN; ++hlen) @@ -757,14 +757,14 @@ void driver2() for (m=1; m<8; ++m) /*------------ for serveral possible initvals, */ { for (l=0; l>(8-j)); @@ -810,23 +810,23 @@ void driver2() /* Check for reading beyond the end of the buffer and alignment problems */ void driver3() { - PN_uint8 buf[MAXLEN+20], *b; - PN_uint32 len; - PN_uint8 q[] = "This is the time for all good men to come to the aid of their country..."; - PN_uint32 h; - PN_uint8 qq[] = "xThis is the time for all good men to come to the aid of their country..."; - PN_uint32 i; - PN_uint8 qqq[] = "xxThis is the time for all good men to come to the aid of their country..."; - PN_uint32 j; - PN_uint8 qqqq[] = "xxxThis is the time for all good men to come to the aid of their country..."; - PN_uint32 ref,x,y; - PN_uint8 *p; + uint8_t buf[MAXLEN+20], *b; + uint32_t len; + uint8_t q[] = "This is the time for all good men to come to the aid of their country..."; + uint32_t h; + uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country..."; + uint32_t i; + uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country..."; + uint32_t j; + uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country..."; + uint32_t ref,x,y; + uint8_t *p; printf("Endianness. These lines should all be the same (for values filled in):\n"); printf("%.8x %.8x %.8x\n", - hashword((const PN_uint32 *)q, (sizeof(q)-1)/4, 13), - hashword((const PN_uint32 *)q, (sizeof(q)-5)/4, 13), - hashword((const PN_uint32 *)q, (sizeof(q)-9)/4, 13)); + hashword((const uint32_t *)q, (sizeof(q)-1)/4, 13), + hashword((const uint32_t *)q, (sizeof(q)-5)/4, 13), + hashword((const uint32_t *)q, (sizeof(q)-9)/4, 13)); p = q; printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), @@ -868,11 +868,11 @@ void driver3() for (j=0; j typedef double PN_float64; typedef float PN_float32; diff --git a/dtool/src/dtoolbase/pallocator.h b/dtool/src/dtoolbase/pallocator.h index 5c1c8d4d5d..deddc2abfc 100644 --- a/dtool/src/dtoolbase/pallocator.h +++ b/dtool/src/dtoolbase/pallocator.h @@ -32,7 +32,7 @@ * can allocate arrays of objects. */ -#ifndef USE_STL_ALLOCATOR +#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER) // If we're not trying to make custom allocators (either we don't know what // kind of syntax this STL library wants, or we're compiling with OPTIMIZE 4), // then simply use the standard allocator. diff --git a/dtool/src/dtoolbase/pdeque.h b/dtool/src/dtoolbase/pdeque.h index eca91125cf..245f7e299a 100644 --- a/dtool/src/dtoolbase/pdeque.h +++ b/dtool/src/dtoolbase/pdeque.h @@ -19,7 +19,7 @@ #include "register_type.h" #include -#ifndef USE_STL_ALLOCATOR +#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER) // If we're not using custom allocators, just use the standard class // definition. #define pdeque deque diff --git a/dtool/src/dtoolbase/pdtoa.cxx b/dtool/src/dtoolbase/pdtoa.cxx index a2778dc962..47aa2db50a 100644 --- a/dtool/src/dtoolbase/pdtoa.cxx +++ b/dtool/src/dtoolbase/pdtoa.cxx @@ -250,7 +250,7 @@ inline static unsigned CountDecimalDigit32(uint32_t n) { } inline static void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { - static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0, 0, 0, 0, 0 }; const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); const DiyFp wp_w = Mp - W; uint32_t p1 = static_cast(Mp.f >> -one.e); diff --git a/dtool/src/dtoolbase/plist.h b/dtool/src/dtoolbase/plist.h index c0ce518720..9effd8db6a 100644 --- a/dtool/src/dtoolbase/plist.h +++ b/dtool/src/dtoolbase/plist.h @@ -19,7 +19,7 @@ #include "register_type.h" #include -#ifndef USE_STL_ALLOCATOR +#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER) // If we're not using custom allocators, just use the standard class // definition. #define plist list diff --git a/dtool/src/dtoolbase/pmap.h b/dtool/src/dtoolbase/pmap.h index 08a9b1ec22..e9b318c36b 100644 --- a/dtool/src/dtoolbase/pmap.h +++ b/dtool/src/dtoolbase/pmap.h @@ -24,7 +24,7 @@ #include #endif -#ifndef USE_STL_ALLOCATOR +#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER) // If we're not using custom allocators, just use the standard class // definition. #define pmap map diff --git a/dtool/src/dtoolbase/pset.h b/dtool/src/dtoolbase/pset.h index 77bcfa2b67..4b1ca1617c 100644 --- a/dtool/src/dtoolbase/pset.h +++ b/dtool/src/dtoolbase/pset.h @@ -24,7 +24,7 @@ #include #endif -#ifndef USE_STL_ALLOCATOR +#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER) // If we're not using custom allocators, just use the standard class // definition. #define pset set diff --git a/dtool/src/dtoolbase/pvector.h b/dtool/src/dtoolbase/pvector.h index c9d89fe942..14bd542f37 100644 --- a/dtool/src/dtoolbase/pvector.h +++ b/dtool/src/dtoolbase/pvector.h @@ -25,6 +25,12 @@ // definition. #define pvector vector +#elif defined(CPPPARSER) +// Simplified definition to speed up Interrogate parsing. +template +class pvector : public vector { +}; + #else /** @@ -39,11 +45,25 @@ public: typedef vector base_class; typedef TYPENAME base_class::size_type size_type; - pvector(TypeHandle type_handle = pvector_type_handle) : base_class(allocator(type_handle)) { } + explicit pvector(TypeHandle type_handle = pvector_type_handle) : base_class(allocator(type_handle)) { } pvector(const pvector ©) : base_class(copy) { } - pvector(size_type n, TypeHandle type_handle = pvector_type_handle) : base_class(n, Type(), allocator(type_handle)) { } - pvector(size_type n, const Type &value, TypeHandle type_handle = pvector_type_handle) : base_class(n, value, allocator(type_handle)) { } + explicit pvector(size_type n, TypeHandle type_handle = pvector_type_handle) : base_class(n, Type(), allocator(type_handle)) { } + explicit pvector(size_type n, const Type &value, TypeHandle type_handle = pvector_type_handle) : base_class(n, value, allocator(type_handle)) { } pvector(const Type *begin, const Type *end, TypeHandle type_handle = pvector_type_handle) : base_class(begin, end, allocator(type_handle)) { } + +#ifdef USE_MOVE_SEMANTICS + pvector(pvector &&from) NOEXCEPT : base_class(move(from)) {}; + + pvector &operator =(pvector &&from) NOEXCEPT { + base_class::operator =(move(from)); + return *this; + } +#endif + + pvector &operator =(const pvector ©) { + base_class::operator =(copy); + return *this; + } }; #endif // USE_STL_ALLOCATOR diff --git a/dtool/src/dtoolbase/stl_compares.I b/dtool/src/dtoolbase/stl_compares.I index 5e087faa3e..501435f547 100644 --- a/dtool/src/dtoolbase/stl_compares.I +++ b/dtool/src/dtoolbase/stl_compares.I @@ -99,7 +99,7 @@ is_equal(const Key &a, const Key &b) const { template INLINE size_t integer_hash:: add_hash(size_t hash, const Key &key) { - PN_uint32 key32 = (PN_uint32)(key); + uint32_t key32 = (uint32_t)(key); return AddHash::add_hash(hash, &key32, 1); } @@ -109,7 +109,7 @@ add_hash(size_t hash, const Key &key) { INLINE size_t pointer_hash:: add_hash(size_t hash, const void *key) { // We don't mind if this loses precision. - PN_uint32 key32 = (PN_uint32)reinterpret_cast(key); + uint32_t key32 = (uint32_t)reinterpret_cast(key); return AddHash::add_hash(hash, &key32, 1); } @@ -147,7 +147,7 @@ operator () (const Key &a, const Key &b) const { template INLINE size_t floating_point_hash:: add_hash(size_t hash, const Key &key) const { - PN_uint32 key32 = (PN_uint32)(key / _threshold + 0.5f); + uint32_t key32 = (uint32_t)(key / _threshold + 0.5f); return AddHash::add_hash(hash, &key32, 1); } @@ -173,7 +173,7 @@ add_hash(size_t hash, const Key &key) { } #endif size_t num_bytes = (key.size() * sizeof(key[0])); - return AddHash::add_hash(hash, (const PN_uint8 *)&key[0], num_bytes); + return AddHash::add_hash(hash, (const uint8_t *)&key[0], num_bytes); } /** diff --git a/dtool/src/dtoolbase/typeHandle.h b/dtool/src/dtoolbase/typeHandle.h index ca0d1874f6..fe611c2fd1 100644 --- a/dtool/src/dtoolbase/typeHandle.h +++ b/dtool/src/dtoolbase/typeHandle.h @@ -114,6 +114,8 @@ PUBLISHED: MAKE_PROPERTY(index, get_index); MAKE_PROPERTY(name, get_name); + MAKE_SEQ_PROPERTY(parent_classes, get_num_parent_classes, get_parent_class); + MAKE_SEQ_PROPERTY(child_classes, get_num_child_classes, get_child_class); public: INLINE static TypeHandle from_index(int index); diff --git a/dtool/src/dtoolbase/typeRegistry.cxx b/dtool/src/dtoolbase/typeRegistry.cxx index a0393cb81c..99ac09be10 100644 --- a/dtool/src/dtoolbase/typeRegistry.cxx +++ b/dtool/src/dtoolbase/typeRegistry.cxx @@ -511,10 +511,10 @@ TypeRegistry() { // Here's a few sanity checks on the sizes of our words. We have to put it // here, at runtime, since there doesn't appear to be a cross-platform // compile-time way to verify that we've chosen the right word sizes. - assert(sizeof(PN_uint8) == 1 && sizeof(PN_int8) == 1); - assert(sizeof(PN_uint16) == 2 && sizeof(PN_int16) == 2); - assert(sizeof(PN_uint32) == 4 && sizeof(PN_int32) == 4); - assert(sizeof(PN_uint64) == 8 && sizeof(PN_int64) == 8); + assert(sizeof(uint8_t) == 1 && sizeof(int8_t) == 1); + assert(sizeof(uint16_t) == 2 && sizeof(int16_t) == 2); + assert(sizeof(uint32_t) == 4 && sizeof(int32_t) == 4); + assert(sizeof(uint64_t) == 8 && sizeof(int64_t) == 8); assert(sizeof(PN_float32) == 4); assert(sizeof(PN_float64) == 8); diff --git a/dtool/src/dtoolbase/typeRegistry.h b/dtool/src/dtoolbase/typeRegistry.h index 1526b6bc2f..828cee6c8c 100644 --- a/dtool/src/dtoolbase/typeRegistry.h +++ b/dtool/src/dtoolbase/typeRegistry.h @@ -37,14 +37,15 @@ class EXPCL_DTOOL TypeRegistry : public MemoryBase { public: // User code shouldn't generally need to call TypeRegistry::register_type() // or record_derivation() directly; instead, use the register_type - // convenience function, defined below. + // convenience function, defined in register_type.h. bool register_type(TypeHandle &type_handle, const string &name); + +PUBLISHED: TypeHandle register_dynamic_type(const string &name); void record_derivation(TypeHandle child, TypeHandle parent); void record_alternate_name(TypeHandle type, const string &name); -PUBLISHED: TypeHandle find_type(const string &name) const; TypeHandle find_type_by_id(int id) const; @@ -78,6 +79,9 @@ PUBLISHED: // ptr() returns the pointer to the global TypeRegistry object. static TypeRegistry *ptr(); + MAKE_SEQ_PROPERTY(typehandles, get_num_typehandles, get_typehandle); + MAKE_SEQ_PROPERTY(root_classes, get_num_root_classes, get_root_class); + private: // The TypeRegistry class should never be constructed by user code. There // is only one in the universe, and it constructs itself! diff --git a/dtool/src/dtoolutil/dSearchPath.h b/dtool/src/dtoolutil/dSearchPath.h index 712e77be4c..67cbd61135 100644 --- a/dtool/src/dtoolutil/dSearchPath.h +++ b/dtool/src/dtoolutil/dSearchPath.h @@ -71,6 +71,7 @@ PUBLISHED: size_t get_num_directories() const; const Filename &get_directory(size_t n) const; MAKE_SEQ(get_directories, get_num_directories, get_directory); + MAKE_SEQ_PROPERTY(directories, get_num_directories, get_directory); Filename find_file(const Filename &filename) const; size_t find_all_files(const Filename &filename, Results &results) const; diff --git a/dtool/src/dtoolutil/filename.cxx b/dtool/src/dtoolutil/filename.cxx index 8d6fa1e415..169f4bee05 100644 --- a/dtool/src/dtoolutil/filename.cxx +++ b/dtool/src/dtoolutil/filename.cxx @@ -443,7 +443,11 @@ temporary(const string &dirname, const string &prefix, const string &suffix, // generate a 6-character hex code. int hash = (clock() * time(NULL)) & 0xffffff; char hex_code[10]; - sprintf(hex_code, "%06x", hash); +#ifdef _WIN32 + sprintf_s(hex_code, 10, "%06x", hash); +#else + snprintf(hex_code, 10, "%06x", hash); +#endif result = Filename(fdirname, Filename(prefix + hex_code + suffix)); result.set_type(type); } while (result.exists()); diff --git a/dtool/src/dtoolutil/pandaSystem.h b/dtool/src/dtoolutil/pandaSystem.h index a401440b6b..d88e3b92a3 100644 --- a/dtool/src/dtoolutil/pandaSystem.h +++ b/dtool/src/dtoolutil/pandaSystem.h @@ -50,6 +50,7 @@ PUBLISHED: size_t get_num_systems() const; string get_system(size_t n) const; MAKE_SEQ(get_systems, get_num_systems, get_system); + MAKE_SEQ_PROPERTY(systems, get_num_systems, get_system); string get_system_tag(const string &system, const string &tag) const; diff --git a/dtool/src/dtoolutil/string_utils.I b/dtool/src/dtoolutil/string_utils.I index 597a7f603b..e4e71766f8 100644 --- a/dtool/src/dtoolutil/string_utils.I +++ b/dtool/src/dtoolutil/string_utils.I @@ -80,13 +80,13 @@ format_string(int value) { } INLINE string -format_string(PN_int64 value) { +format_string(int64_t value) { char buffer[21]; char *p = buffer + 20; *p = 0; if (value < 0) { - PN_uint64 posv = (PN_uint64)-value; + uint64_t posv = (uint64_t)-value; do { *--p = '0' + (posv % 10); posv /= 10; diff --git a/dtool/src/dtoolutil/string_utils.h b/dtool/src/dtoolutil/string_utils.h index 2737566cdf..a3d931af6e 100644 --- a/dtool/src/dtoolutil/string_utils.h +++ b/dtool/src/dtoolutil/string_utils.h @@ -73,7 +73,7 @@ INLINE string format_string(float value); INLINE string format_string(double value); INLINE string format_string(unsigned int value); INLINE string format_string(int value); -INLINE string format_string(PN_int64 value); +INLINE string format_string(int64_t value); #include "string_utils.I" diff --git a/dtool/src/interrogate/interfaceMaker.cxx b/dtool/src/interrogate/interfaceMaker.cxx index 6a7c63e40f..c84456983d 100644 --- a/dtool/src/interrogate/interfaceMaker.cxx +++ b/dtool/src/interrogate/interfaceMaker.cxx @@ -86,10 +86,12 @@ MakeSeq(const string &name, const InterrogateMakeSeq &imake_seq) : InterfaceMaker::Property:: Property(const InterrogateElement &ielement) : _ielement(ielement), + _length_function(NULL), _getter(NULL), _setter(NULL), _has_function(NULL), - _clear_function(NULL) + _clear_function(NULL), + _deleter(NULL) { } @@ -131,7 +133,8 @@ check_protocols() { if (func->_ifunc.get_name() == "__traverse__") { // If we have a method named __traverse__, we implement Python's cyclic // garbage collection protocol. - _protocol_types |= PT_python_gc; + //XXX disabled for now because it's too unstable. + //_protocol_types |= PT_python_gc; } } @@ -359,6 +362,18 @@ remap_parameter(CPPType *struct_type, CPPType *param_type) { } } } + if (struct_type == (CPPType *)NULL || + !TypeManager::is_vector_unsigned_char(struct_type)) { + if (TypeManager::is_vector_unsigned_char(param_type)) { + if (TypeManager::is_reference(param_type)) { + return new ParameterRemapReferenceToConcrete(param_type); + } else if (TypeManager::is_const(param_type)) { + return new ParameterRemapConstToNonConst(param_type); + } else { + return new ParameterRemapUnchanged(param_type); + } + } + } } if (manage_reference_counts) { diff --git a/dtool/src/interrogate/interfaceMaker.h b/dtool/src/interrogate/interfaceMaker.h index f76975d592..c84714eb51 100644 --- a/dtool/src/interrogate/interfaceMaker.h +++ b/dtool/src/interrogate/interfaceMaker.h @@ -126,10 +126,12 @@ public: Property(const InterrogateElement &ielement); const InterrogateElement &_ielement; + Function *_length_function; Function *_getter; Function *_setter; Function *_has_function; Function *_clear_function; + Function *_deleter; }; typedef vector Properties; diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 5ab6f54768..5d18fca7be 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -764,10 +764,6 @@ write_prototypes(ostream &out_code, ostream *out_h) { *out_h << "#include \"py_panda.h\"\n\n"; } - out_code << "//********************************************************************\n"; - out_code << "//*** prototypes for .. Global\n"; - out_code << "//********************************************************************\n"; - /* for (fi = _functions.begin(); fi != _functions.end(); ++fi) { @@ -792,9 +788,9 @@ write_prototypes(ostream &out_code, ostream *out_h) { } } - out_code << "//********************************************************************\n"; - out_code << "//*** prototypes for .. External Objects\n"; - out_code << "//********************************************************************\n"; + out_code << "/**\n"; + out_code << " * Extern declarations for imported classes\n"; + out_code << " */\n"; for (std::set::iterator ii = _external_imports.begin(); ii != _external_imports.end(); ii++) { CPPType *type = (*ii); @@ -897,9 +893,9 @@ write_prototypes_class_external(ostream &out, Object *obj) { std::string preferred_name = obj->_itype.get_name(); - out << "//********************************************************************\n"; - out << "//*** prototypes for external.. " << class_name << "\n"; - out << "//********************************************************************\n"; + out << "/**\n"; + out << " * Forward declaration of class " << class_name << "\n"; + out << " */\n"; // This typedef is necessary for class templates since we can't pass a comma // to a macro function. @@ -915,9 +911,9 @@ write_prototypes_class(ostream &out_code, ostream *out_h, Object *obj) { std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); Functions::iterator fi; - out_code << "//********************************************************************\n"; - out_code << "//*** prototypes for .. " << ClassName << "\n"; - out_code << "//********************************************************************\n"; + out_code << "/**\n"; + out_code << " * Forward declarations for top-level class " << ClassName << "\n"; + out_code << " */\n"; /* for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) { @@ -943,9 +939,9 @@ write_prototypes_class(ostream &out_code, ostream *out_h, Object *obj) { */ void InterfaceMakerPythonNative:: write_functions(ostream &out) { - out << "//********************************************************************\n"; - out << "//*** Functions for .. Global\n" ; - out << "//********************************************************************\n"; + out << "/**\n"; + out << " * Python wrappers for global functions\n" ; + out << " */\n"; FunctionsByIndex::iterator fi; for (fi = _functions.begin(); fi != _functions.end(); ++fi) { Function *func = (*fi).second; @@ -994,9 +990,9 @@ write_class_details(ostream &out, Object *obj) { std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); std::string cClassName = obj->_itype.get_true_name(); - out << "//********************************************************************\n"; - out << "//*** Functions for .. " << cClassName << "\n" ; - out << "//********************************************************************\n"; + out << "/**\n"; + out << " * Python wrappers for functions of class " << cClassName << "\n" ; + out << " */\n"; // First write out all the wrapper functions for the methods. for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) { @@ -1017,13 +1013,21 @@ write_class_details(ostream &out, Object *obj) { } // Write the constructors. + std::string fname = "static int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)"; for (fi = obj->_constructors.begin(); fi != obj->_constructors.end(); ++fi) { Function *func = (*fi); - std::string fname = "static int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)"; string expected_params; write_function_for_name(out, obj, func->_remaps, fname, expected_params, true, AT_keyword_args, RF_int); } + if (obj->_constructors.size() == 0) { + // We still need to write a dummy constructor to prevent inheriting the + // constructor from a base class. + out << fname << " {\n" + " Dtool_Raise_TypeError(\"cannot init abstract class\");\n" + " return -1;\n" + "}\n\n"; + } CPPType *cpptype = TypeManager::resolve_type(obj->_itype._cpptype); @@ -1183,7 +1187,6 @@ write_sub_module(ostream &out, Object *obj) { // Object * obj = _objects[_embeded_index] ; string class_name = make_safe_name(obj->_itype.get_scoped_name()); string class_ptr; - out << " // Module init upcall for " << obj->_itype.get_scoped_name() << "\n"; if (!obj->_itype.is_typedef()) { out << " // " << *(obj->_itype._cpptype) << "\n"; @@ -1212,6 +1215,10 @@ write_sub_module(ostream &out, Object *obj) { out << " assert(" << class_ptr << " != NULL);\n"; } else { class_ptr = "&Dtool_" + class_name; + + // If this is a typedef to a class defined in the same module, make sure + // that the class is initialized before we try to define the typedef. + out << " Dtool_PyModuleClassInit_" << class_name << "(module);\n"; } } @@ -1238,9 +1245,9 @@ write_sub_module(ostream &out, Object *obj) { */ void InterfaceMakerPythonNative:: write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { - out << "//********************************************************************\n"; - out << "//*** Module Object Linker ..\n"; - out << "//********************************************************************\n"; + out << "/**\n"; + out << " * Module Object Linker ..\n"; + out << " */\n"; Objects::iterator oi; @@ -1301,14 +1308,41 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { if (object->_itype.is_enum() && !object->_itype.is_nested() && isExportThisRun(object->_itype._cpptype)) { int enum_count = object->_itype.number_of_enum_values(); - for (int xx = 0; xx < enum_count; xx++) { - string name1 = classNameFromCppName(object->_itype.get_enum_value_name(xx), false); - string name2 = classNameFromCppName(object->_itype.get_enum_value_name(xx), true); - string enum_value = "::" + object->_itype.get_enum_value_name(xx); - out << " PyModule_AddIntConstant(module, \"" << name1 << "\", " << enum_value << ");\n"; - if (name1 != name2) { - // Also write the mangled name, for historical purposes. - out << " PyModule_AddIntConstant(module, \"" << name2 << "\", " << enum_value << ");\n"; + + if (object->_itype.is_scoped_enum()) { + // Convert as Python 3.4 enum. + CPPType *underlying_type = TypeManager::unwrap_const(object->_itype._cpptype->as_enum_type()->get_underlying_type()); + string cast_to = underlying_type->get_local_name(&parser); + out << "#if PY_VERSION_HEX >= 0x03040000\n\n"; + out << " // enum class " << object->_itype.get_scoped_name() << "\n"; + out << " {\n"; + out << " PyObject *members = PyTuple_New(" << enum_count << ");\n"; + out << " PyObject *member;\n"; + for (int xx = 0; xx < enum_count; xx++) { + out << " member = PyTuple_New(2);\n" + " PyTuple_SET_ITEM(member, 0, PyUnicode_FromString(\"" + << object->_itype.get_enum_value_name(xx) << "\"));\n" + " PyTuple_SET_ITEM(member, 1, Dtool_WrapValue((" + << cast_to << ")" << object->_itype.get_scoped_name() << "::" + << object->_itype.get_enum_value_name(xx) << "));\n" + " PyTuple_SET_ITEM(members, " << xx << ", member);\n"; + } + out << " PyModule_AddObject(module, \"" << object->_itype.get_name() + << "\", Dtool_EnumType_Create(\"" << object->_itype.get_name() + << "\", members, \"" << _def->module_name << "\"));\n"; + out << " }\n"; + out << "#endif\n"; + } else { + out << " // enum " << object->_itype.get_scoped_name() << "\n"; + for (int xx = 0; xx < enum_count; xx++) { + string name1 = classNameFromCppName(object->_itype.get_enum_value_name(xx), false); + string name2 = classNameFromCppName(object->_itype.get_enum_value_name(xx), true); + string enum_value = "::" + object->_itype.get_enum_value_name(xx); + out << " PyModule_AddObject(module, \"" << name1 << "\", Dtool_WrapValue(" << enum_value << "));\n"; + if (name1 != name2) { + // Also write the mangled name, for historical purposes. + out << " PyModule_AddObject(module, \"" << name2 << "\", Dtool_WrapValue(" << enum_value << "));\n"; + } } } } @@ -1356,13 +1390,6 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { } } } - out << "//********************************************************************\n"; - out << "//*** Module Init Upcall .. Externally Defined Class\n"; - out << "//********************************************************************\n"; - -// for (std::set< std::string >::iterator ii = _external_imports.begin(); ii -// != _external_imports.end(); ii++) out << "Dtool_" <<*ii << -// "._Dtool_ClassInit(NULL);\n"; out << "}\n\n"; @@ -1431,9 +1458,9 @@ write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) { InterfaceMakerPython::write_module(out, out_h, def); Objects::iterator oi; - out << "//********************************************************************\n"; - out << "//*** Py Init Code For .. GlobalScope\n" ; - out << "//********************************************************************\n"; + out << "/**\n"; + out << " * Module initialization functions for Python module \"" << def->module_name << "\"\n"; + out << " */\n"; out << "#if PY_MAJOR_VERSION >= 3\n" << "static struct PyModuleDef python_native_module = {\n" @@ -1448,14 +1475,16 @@ write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) { << "#ifdef _WIN32\n" << "extern \"C\" __declspec(dllexport) PyObject *PyInit_" << def->module_name << "();\n" << "#elif __GNUC__ >= 4\n" - << "extern \"C\" __attribute__((visibility(\"default\"))) PyInit_" << def->module_name << "();\n" + << "extern \"C\" __attribute__((visibility(\"default\"))) PyObject *PyInit_" << def->module_name << "();\n" << "#else\n" << "extern \"C\" PyObject *PyInit_" << def->module_name << "();\n" << "#endif\n" << "\n" << "PyObject *PyInit_" << def->module_name << "() {\n" << " LibraryDef *refs[] = {&" << def->library_name << "_moddef, NULL};\n" - << " return Dtool_PyModuleInitHelper(refs, &python_native_module);\n" + << " PyObject *module = Dtool_PyModuleInitHelper(refs, &python_native_module);\n" + << " Dtool_" << def->library_name << "_BuildInstants(module);\n" + << " return module;\n" << "}\n" << "\n" << "#else // Python 2 case\n" @@ -1463,14 +1492,15 @@ write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) { << "#ifdef _WIN32\n" << "extern \"C\" __declspec(dllexport) void init" << def->module_name << "();\n" << "#elif __GNUC__ >= 4\n" - << "extern \"C\" __attribute__((visibility(\"default\"))) init" << def->module_name << "();\n" + << "extern \"C\" __attribute__((visibility(\"default\"))) void init" << def->module_name << "();\n" << "#else\n" << "extern \"C\" void init" << def->module_name << "();\n" << "#endif\n" << "\n" << "void init" << def->module_name << "() {\n" << " LibraryDef *refs[] = {&" << def->library_name << "_moddef, NULL};\n" - << " Dtool_PyModuleInitHelper(refs, \"" << def->module_name << "\");\n" + << " PyObject *module = Dtool_PyModuleInitHelper(refs, \"" << def->module_name << "\");\n" + << " Dtool_" << def->library_name << "_BuildInstants(module);\n" << "}\n" << "\n" << "#endif\n" @@ -1516,9 +1546,9 @@ write_module_class(ostream &out, Object *obj) { } Functions::iterator fi; - out << "//********************************************************************\n"; - out << "//*** Py Init Code For .. " << ClassName << " | " << export_class_name << "\n" ; - out << "//********************************************************************\n"; + out << "/**\n"; + out << " * Python method tables for " << ClassName << " (" << export_class_name << ")\n" ; + out << " */\n"; out << "static PyMethodDef Dtool_Methods_" << ClassName << "[] = {\n"; SlottedFunctions slots; @@ -1734,7 +1764,7 @@ write_module_class(ostream &out, Object *obj) { switch (rfi->second._wrapper_type) { case WT_no_params: - case WT_iter_next: // TODO: fix iter_next to return NULL instead of None + case WT_iter_next: // PyObject *func(PyObject *self) { out << "//////////////////\n"; @@ -1747,9 +1777,15 @@ write_module_class(ostream &out, Object *obj) { out << " return NULL;\n"; out << " }\n\n"; + int return_flags = RF_pyobject | RF_err_null; + if (rfi->second._wrapper_type == WT_iter_next) { + // If the function returns NULL, we should return NULL to indicate + // a StopIteration, rather than returning None. + return_flags |= RF_preserve_null; + } string expected_params; write_function_forset(out, def._remaps, 0, 0, expected_params, 2, true, true, - AT_no_args, RF_pyobject | RF_err_null, false); + AT_no_args, return_flags, false); out << " if (!_PyErr_OCCURRED()) {\n"; out << " return Dtool_Raise_BadArgumentsError(\n"; @@ -2439,11 +2475,7 @@ write_module_class(ostream &out, Object *obj) { << classNameFromCppName(ClassName, false) << "\");\n"; } out << " std::string ss = os.str();\n"; - out << "#if PY_MAJOR_VERSION >= 3\n"; - out << " return PyUnicode_FromStringAndSize(ss.data(), ss.length());\n"; - out << "#else\n"; - out << " return PyString_FromStringAndSize(ss.data(), ss.length());\n"; - out << "#endif\n"; + out << " return Dtool_WrapValue(ss);\n"; out << "}\n\n"; has_local_repr = true; } @@ -2469,11 +2501,7 @@ write_module_class(ostream &out, Object *obj) { out << " local_this->write(os);\n"; } out << " std::string ss = os.str();\n"; - out << "#if PY_MAJOR_VERSION >= 3\n"; - out << " return PyUnicode_FromStringAndSize(ss.data(), ss.length());\n"; - out << "#else\n"; - out << " return PyString_FromStringAndSize(ss.data(), ss.length());\n"; - out << "#endif\n"; + out << " return Dtool_WrapValue(ss);\n"; out << "}\n\n"; has_local_str = true; } @@ -2598,7 +2626,8 @@ write_module_class(ostream &out, Object *obj) { string getter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter"; string setter = "NULL"; - if (property->_setter != NULL && is_function_legal(property->_setter)) { + if (property->_length_function == NULL && + property->_setter != NULL && is_function_legal(property->_setter)) { setter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter"; } @@ -2692,6 +2721,12 @@ write_module_class(ostream &out, Object *obj) { out << "#if PY_VERSION_HEX >= 0x02050000\n"; write_function_slot(out, 2, slots, "nb_index"); out << "#endif\n"; + + out << "#if PY_VERSION_HEX >= 0x03050000\n"; + write_function_slot(out, 2, slots, "nb_matrix_multiply"); + write_function_slot(out, 2, slots, "nb_inplace_matrix_multiply"); + out << "#endif\n"; + out << "};\n\n"; // NB: it's tempting not to write this table when a class doesn't have them. @@ -2855,10 +2890,12 @@ write_module_class(ostream &out, Object *obj) { } // traverseproc tp_traverse; - write_function_slot(out, 4, slots, "tp_traverse"); + out << " 0, // tp_traverse\n"; + //write_function_slot(out, 4, slots, "tp_traverse"); // inquiry tp_clear; - write_function_slot(out, 4, slots, "tp_clear"); + out << " 0, // tp_clear\n"; + //write_function_slot(out, 4, slots, "tp_clear"); // richcmpfunc tp_richcompare; if (has_local_richcompare) { @@ -2905,11 +2942,7 @@ write_module_class(ostream &out, Object *obj) { // Py_ssize_t tp_dictoffset; out << " 0, // tp_dictoffset\n"; // initproc tp_init; - if (obj->_constructors.size() > 0) { - out << " Dtool_Init_" << ClassName << ",\n"; - } else { - out << " 0,\n"; - } + out << " Dtool_Init_" << ClassName << ",\n"; // allocfunc tp_alloc; out << " PyType_GenericAlloc,\n"; // newfunc tp_new; @@ -2938,6 +2971,10 @@ write_module_class(ostream &out, Object *obj) { out << "#if PY_VERSION_HEX >= 0x02060000\n"; out << " 0, // tp_version_tag\n"; out << "#endif\n"; + // destructor tp_finalize + out << "#if PY_VERSION_HEX >= 0x03040000\n"; + out << " 0, // tp_finalize\n"; + out << "#endif\n"; out << " },\n"; // It's tempting to initialize the type handle here, but this causes static @@ -3017,7 +3054,7 @@ write_module_class(ostream &out, Object *obj) { } else if (nested_obj->_itype.is_typedef()) { ++num_dict_items; - } else if (nested_obj->_itype.is_enum()) { + } else if (nested_obj->_itype.is_enum() && !nested_obj->_itype.is_scoped_enum()) { CPPEnumType *enum_type = nested_obj->_itype._cpptype->as_enum_type(); num_dict_items += 2 * enum_type->_elements.size(); } @@ -3075,8 +3112,33 @@ write_module_class(ostream &out, Object *obj) { // No need to support mangled names for nested typedefs; we only added // support recently. + } else if (nested_obj->_itype.is_scoped_enum()) { + // Convert enum class as Python 3.4 enum. + int enum_count = nested_obj->_itype.number_of_enum_values(); + CPPType *underlying_type = TypeManager::unwrap_const(nested_obj->_itype._cpptype->as_enum_type()->get_underlying_type()); + string cast_to = underlying_type->get_local_name(&parser); + out << "#if PY_VERSION_HEX >= 0x03040000\n\n"; + out << " // enum class " << nested_obj->_itype.get_scoped_name() << ";\n"; + out << " {\n"; + out << " PyObject *members = PyTuple_New(" << enum_count << ");\n"; + out << " PyObject *member;\n"; + for (int xx = 0; xx < enum_count; xx++) { + out << " member = PyTuple_New(2);\n" + " PyTuple_SET_ITEM(member, 0, PyUnicode_FromString(\"" + << nested_obj->_itype.get_enum_value_name(xx) << "\"));\n" + " PyTuple_SET_ITEM(member, 1, Dtool_WrapValue((" + << cast_to << ")" << nested_obj->_itype.get_scoped_name() << "::" + << nested_obj->_itype.get_enum_value_name(xx) << "));\n" + " PyTuple_SET_ITEM(members, " << xx << ", member);\n"; + } + out << " PyDict_SetItemString(dict, \"" << nested_obj->_itype.get_name() + << "\", Dtool_EnumType_Create(\"" << nested_obj->_itype.get_name() + << "\", members, \"" << _def->module_name << "\"));\n"; + out << " }\n"; + out << "#endif\n"; + } else if (nested_obj->_itype.is_enum()) { - out << " // Enum " << nested_obj->_itype.get_scoped_name() << ";\n"; + out << " // enum " << nested_obj->_itype.get_scoped_name() << ";\n"; CPPEnumType *enum_type = nested_obj->_itype._cpptype->as_enum_type(); CPPEnumType::Elements::const_iterator ei; for (ei = enum_type->_elements.begin(); ei != enum_type->_elements.end(); ++ei) { @@ -3091,9 +3153,9 @@ write_module_class(ostream &out, Object *obj) { name2 = name1; } string enum_value = obj->_itype.get_scoped_name() + "::" + (*ei)->get_simple_name(); - out << " PyDict_SetItemString(dict, \"" << name1 << "\", PyLongOrInt_FromLong(" << enum_value << "));\n"; + out << " PyDict_SetItemString(dict, \"" << name1 << "\", Dtool_WrapValue(" << enum_value << "));\n"; if (name1 != name2) { - out << " PyDict_SetItemString(dict, \"" << name2 << "\", PyLongOrInt_FromLong(" << enum_value << "));\n"; + out << " PyDict_SetItemString(dict, \"" << name2 << "\", Dtool_WrapValue(" << enum_value << "));\n"; } } } @@ -3320,7 +3382,7 @@ write_function_for_name(ostream &out, Object *obj, int max_required_args = 0; bool all_nonconst = true; - out << "/******************************************************************\n" << " * Python type method wrapper for\n"; + out << "/**\n * Python function wrapper for:\n"; for (ri = remaps.begin(); ri != remaps.end(); ++ri) { remap = (*ri); if (is_remap_legal(remap)) { @@ -3349,7 +3411,7 @@ write_function_for_name(ostream &out, Object *obj, } } - out << " *******************************************************************/\n"; + out << " */\n"; out << function_name << " {\n"; @@ -3915,13 +3977,7 @@ collapse_default_remaps(std::map > &map_sets, goto abort_iteration; } } - } else if (TypeManager::is_bool(type)) { - } else if (TypeManager::is_char(type)) { - } else if (TypeManager::is_wchar(type)) { - goto abort_iteration; - } else if (TypeManager::is_longlong(type)) { } else if (TypeManager::is_integer(type)) { - } else if (TypeManager::is_double(type)) { } else if (TypeManager::is_float(type)) { } else if (TypeManager::is_const_char_pointer(type)) { } else if (TypeManager::is_pointer_to_PyTypeObject(type)) { @@ -4703,9 +4759,18 @@ write_function_instance(ostream &out, FunctionRemap *remap, if (args_type == AT_single_arg) { out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << param_name << "_str = PyUnicode_AsUTF8AndSize(arg, &" - << param_name << "_len);\n"; + // As a special hack to fix pickling in Python 3, if the method name + // starts with py_decode_, we take a bytes object instead of a str. + if (remap->_cppfunc->get_local_name().substr(0, 10) == "py_decode_") { + indent(out, indent_level) << "if (PyBytes_AsStringAndSize(arg, &" + << param_name << "_str, &" << param_name << "_len) == -1) {\n"; + indent(out, indent_level + 2) << param_name << "_str = NULL;\n"; + indent(out, indent_level) << "}\n"; + } else { + indent(out, indent_level) + << param_name << "_str = PyUnicode_AsUTF8AndSize(arg, &" + << param_name << "_len);\n"; + } out << "#else\n"; // NB. PyString_AsStringAndSize also accepts a PyUnicode. indent(out, indent_level) << "if (PyString_AsStringAndSize(arg, &" << param_name << "_str, &" << param_name << "_len) == -1) {\n"; @@ -4720,17 +4785,37 @@ write_function_instance(ostream &out, FunctionRemap *remap, + "_str, &" + param_name + "_len"; } -// if (TypeManager::is_const_ptr_to_basic_string_char(orig_type)) { -// pexpr_string = "&std::string(" + param_name + "_str, " + param_name + -// "_len)"; } else { - pexpr_string = param_name + "_str, " + param_name + "_len"; -// } + //if (TypeManager::is_const_ptr_to_basic_string_char(orig_type)) { + // pexpr_string = "&std::string(" + param_name + "_str, " + param_name + "_len)"; + //} else { + pexpr_string = param_name + "_str, " + param_name + "_len"; + //} expected_params += "str"; } // Remember to clear the TypeError that any of the above methods raise. clear_error = true; only_pyobjects = false; + } else if (TypeManager::is_vector_unsigned_char(type)) { + indent(out, indent_level) << "unsigned char *" << param_name << "_str = NULL;\n"; + indent(out, indent_level) << "Py_ssize_t " << param_name << "_len;\n"; + + if (args_type == AT_single_arg) { + extra_param_check << " && PyBytes_AsStringAndSize(arg, (char **)&" + << param_name << "_str, &" << param_name << "_len) >= 0"; + } else { + format_specifiers += "\" FMTCHAR_BYTES \"#"; + parameter_list += ", &" + param_name + "_str, &" + param_name + "_len"; + } + + pexpr_string = type->get_local_name(&parser); + pexpr_string += "(" + param_name + "_str, " + param_name + "_str + " + param_name + "_len" + ")"; + expected_params += "bytes"; + + // Remember to clear the TypeError that any of the above methods raise. + clear_error = true; + only_pyobjects = false; + } else if (TypeManager::is_bool(type)) { if (args_type == AT_single_arg) { param_name = "arg"; @@ -5833,8 +5918,15 @@ write_function_instance(ostream &out, FunctionRemap *remap, indent(out, indent_level) << "Py_INCREF(Py_None);\n"; indent(out, indent_level) << "return Py_None;\n"; + } else if (return_flags & RF_preserve_null) { + indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; + indent(out, indent_level) << " return NULL;\n"; + indent(out, indent_level) << "} else {\n"; + pack_return_value(out, indent_level + 2, remap, return_expr, return_flags); + indent(out, indent_level) << "}\n"; + } else { - pack_return_value(out, indent_level, remap, return_expr); + pack_return_value(out, indent_level, remap, return_expr, return_flags); } } else if (return_flags & RF_coerced) { @@ -5991,170 +6083,23 @@ error_raise_return(ostream &out, int indent_level, int return_flags, */ void InterfaceMakerPythonNative:: pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, - string return_expr) { + string return_expr, int return_flags) { ParameterRemap *return_type = remap->_return_type; CPPType *orig_type = return_type->get_orig_type(); CPPType *type = return_type->get_new_type(); - if (return_type->new_type_is_atomic_string()) { - if (TypeManager::is_char_pointer(orig_type)) { - indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; - indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "} else {\n"; - - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) << " return " - << "PyUnicode_FromString(" << return_expr << ");\n"; - out << "#else\n"; - indent(out, indent_level) << " return " - << "PyString_FromString(" << return_expr << ");\n"; - out << "#endif\n"; - - indent(out, indent_level) << "}\n"; - - } else if (TypeManager::is_wchar_pointer(orig_type)) { - indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; - indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "} else {\n"; - indent(out, indent_level+2) - << "return PyUnicode_FromWideChar(" - << return_expr << ", wcslen(" << return_expr << "));\n"; - indent(out, indent_level) << "}\n"; - - } else if (TypeManager::is_wstring(orig_type)) { - indent(out, indent_level) - << "return PyUnicode_FromWideChar(" - << return_expr << ".data(), (int) " << return_expr << ".length());\n"; - - } else if (TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) { - indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; - indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "} else {\n"; - - indent(out, indent_level) << " return " - << "PyUnicode_FromWideChar(" - << return_expr << "->data(), (int) " << return_expr << "->length());\n"; - - indent(out, indent_level) << "}\n"; - - } else if (TypeManager::is_const_ptr_to_basic_string_char(orig_type)) { - indent(out, indent_level) << "if (" << return_expr<< " == NULL) {\n"; - indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "} else {\n"; - - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) << " return " - << "PyUnicode_FromStringAndSize(" - << return_expr << "->data(), (Py_ssize_t)" << return_expr << "->length());\n"; - out << "#else\n"; - indent(out, indent_level) << " return " - << "PyString_FromStringAndSize(" - << return_expr << "->data(), (Py_ssize_t)" << return_expr << "->length());\n"; - out << "#endif\n"; - - indent(out, indent_level) << "}\n"; - - } else { - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromStringAndSize(" - << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromStringAndSize(" - << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n"; - out << "#endif\n"; - } - - } else if (TypeManager::is_bool(type)) { + if (return_type->new_type_is_atomic_string() || + TypeManager::is_simple(type) || + TypeManager::is_char_pointer(type) || + TypeManager::is_wchar_pointer(type) || + TypeManager::is_pointer_to_PyObject(type) || + TypeManager::is_pointer_to_Py_buffer(type) || + TypeManager::is_vector_unsigned_char(type)) { + // Most types are now handled by the many overloads of Dtool_WrapValue, + // defined in py_panda.h. indent(out, indent_level) - << "return PyBool_FromLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_ssize(type)) { - indent(out, indent_level) - << "return PyLongOrInt_FromSsize_t(" << return_expr << ");\n"; - - } else if (TypeManager::is_size(type)) { - indent(out, indent_level) - << "return PyLongOrInt_FromSize_t(" << return_expr << ");\n"; - - } else if (TypeManager::is_char(type)) { - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromStringAndSize(&" << return_expr << ", 1);\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromStringAndSize(&" << return_expr << ", 1);\n"; - out << "#endif\n"; - - } else if (TypeManager::is_wchar(type)) { - indent(out, indent_level) - << "return PyUnicode_FromWideChar(&" << return_expr << ", 1);\n"; - - } else if (TypeManager::is_unsigned_longlong(type)) { - indent(out, indent_level) - << "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_longlong(type)) { - indent(out, indent_level) - << "return PyLong_FromLongLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_unsigned_integer(type)){ - indent(out, indent_level) - << "return PyLongOrInt_FromUnsignedLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_integer(type)) { - indent(out, indent_level) - << "return PyLongOrInt_FromLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_float(type)) { - indent(out, indent_level) - << "return PyFloat_FromDouble(" << return_expr << ");\n"; - - } else if (TypeManager::is_char_pointer(type)) { - indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; - indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "} else {\n"; - - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) << " return " - << "PyUnicode_FromString(" << return_expr << ");\n"; - out << "#else\n"; - indent(out, indent_level) << " return " - << "PyString_FromString(" << return_expr << ");\n"; - out << "#endif\n"; - - indent(out, indent_level) << "}\n"; - - } else if (TypeManager::is_wchar_pointer(type)) { - indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; - indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "} else {\n"; - indent(out, indent_level) << " return " - << "PyUnicode_FromWideChar(" - << return_expr << ", wcslen(" << return_expr << "));\n"; - - indent(out, indent_level) << "}\n"; - - } else if (TypeManager::is_pointer_to_PyObject(type)) { - indent(out, indent_level) - << "return " << return_expr << ";\n"; - - } else if (TypeManager::is_pointer_to_Py_buffer(type)) { - indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n"; - indent(out, indent_level) << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) << " return Py_None;\n"; - indent(out, indent_level) << "} else {\n"; - indent(out, indent_level) << " return " - << "PyMemoryView_FromBuffer(" << return_expr << ");\n"; - indent(out, indent_level) << "}\n"; + << "return Dtool_WrapValue(" << return_expr << ");\n"; } else if (TypeManager::is_pointer(type)) { bool is_const = TypeManager::is_const_pointer_to_anything(type); @@ -6198,13 +6143,13 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, } else { indent(out, indent_level) << "Should Never Reach This InterfaceMakerPythonNative::pack_python_value"; - // << "return PyLongOrInt_FromLong((int) " << return_expr << ");\n"; + // << "return Dtool_Integer((int) " << return_expr << ");\n"; } } else { // Return None. indent(out, indent_level) - << "return Py_BuildValue(\"\");\n"; + << "return Py_BuildValue(\"\"); // Don't know how to wrap type.\n"; } } @@ -6215,8 +6160,9 @@ void InterfaceMakerPythonNative:: write_make_seq(ostream &out, Object *obj, const std::string &ClassName, const std::string &cClassName, MakeSeq *make_seq) { - out << "/******************************************************************\n" << " * Python make_seq wrapper\n"; - out << " *******************************************************************/\n"; + out << "/*\n" + " * Python make_seq wrapper\n" + " */\n"; out << "static PyObject *" << make_seq->_name + "(PyObject *self, PyObject *) {\n"; @@ -6252,11 +6198,7 @@ write_make_seq(ostream &out, Object *obj, const std::string &ClassName, " PyObject *tuple = PyTuple_New(count);\n" "\n" " for (Py_ssize_t i = 0; i < count; ++i) {\n" - "#if PY_MAJOR_VERSION >= 3\n" - " PyObject *index = PyLong_FromSsize_t(i);\n" - "#else\n" - " PyObject *index = PyInt_FromSsize_t(i);\n" - "#endif\n"; + " PyObject *index = Dtool_WrapValue(i);\n"; switch (elem_getter->_args_type) { case AT_keyword_args: @@ -6309,10 +6251,156 @@ write_getset(ostream &out, Object *obj, Property *property) { const InterrogateElement &ielem = property->_ielement; - if (property->_getter != NULL) { + if (property->_length_function != NULL) { + // This is actually a sequence. Wrap this with a special class. + FunctionRemap *len_remap = property->_length_function->_remaps.front(); + vector_string pexprs; + + out << "/**\n" + " * sequence length function for property " << cClassName << "::" << ielem.get_name() << "\n" + " */\n" + "static Py_ssize_t Dtool_" + ClassName + "_" + ielem.get_name() + "_Len(PyObject *self) {\n"; + if (property->_length_function->_has_this) { + out << + " " << cClassName << " *local_this = NULL;\n" + " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n" + " return -1;\n" + " }\n" + " return (Py_ssize_t)" << len_remap->get_call_str("local_this", pexprs) << ";\n"; + } else { + out << " return (Py_ssize_t)" << len_remap->get_call_str("", pexprs) << ";\n"; + } + out << "}\n\n"; + + // Now write out the getitem helper function. + if (property->_getter != NULL) { + out << + "/**\n" + " * sequence getter for property " << cClassName << "::" << ielem.get_name() << "\n" + " */\n" + "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getitem(PyObject *self, Py_ssize_t index) {\n" + " " << cClassName << " *local_this = NULL;\n" + " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n" + " return NULL;\n" + " }\n"; + + // This is a getitem of a sequence type. This means we *need* to raise + // IndexError if we're out of bounds. + out << " if (index < 0 || index >= (Py_ssize_t)" + << len_remap->get_call_str("local_this", pexprs) << ") {\n"; + out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << "." << ielem.get_name() << "[] index out of range\");\n"; + out << " return NULL;\n"; + out << " }\n"; + + if (property->_has_function != NULL) { + out << " if (!local_this->" << property->_has_function->_ifunc.get_name() << "(index)) {\n" + << " Py_INCREF(Py_None);\n" + << " return Py_None;\n" + << " }\n"; + } + + std::set remaps; + + // Extract only the getters that take one argument. + Function::Remaps::iterator it; + for (it = property->_getter->_remaps.begin(); + it != property->_getter->_remaps.end(); + ++it) { + FunctionRemap *remap = *it; + int min_num_args = remap->get_min_num_args(); + int max_num_args = remap->get_max_num_args(); + if (min_num_args <= 1 && max_num_args >= 1) { + remaps.insert(remap); + } + } + + string expected_params; + write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, + AT_no_args, RF_pyobject | RF_err_null, false, true, "index"); + + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " return Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n" + " }\n" + "}\n\n"; + } + + // Write out a setitem if this is not a read-only property. + if (property->_setter != NULL) { + out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setitem(PyObject *self, Py_ssize_t index, PyObject *arg) {\n"; + out << " " << cClassName << " *local_this = NULL;\n"; + out << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \"" + << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n"; + out << " return -1;\n"; + out << " }\n\n"; + + out << " if (arg == (PyObject *)NULL) {\n"; + if (property->_deleter != NULL) { + out << " local_this->" << property->_deleter->_ifunc.get_name() << "(index);\n" + << " return 0;\n"; + } else { + out << " Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << "[] attribute\");\n" + " return -1;\n"; + } + out << " }\n"; + + if (property->_clear_function != NULL) { + out << " if (arg == Py_None) {\n" + << " local_this->" << property->_clear_function->_ifunc.get_name() << "(index);\n" + << " return 0;\n" + << " }\n"; + } + + std::set remaps; + + // Extract only the setters that take two arguments. + Function::Remaps::iterator it; + for (it = property->_setter->_remaps.begin(); + it != property->_setter->_remaps.end(); + ++it) { + FunctionRemap *remap = *it; + int min_num_args = remap->get_min_num_args(); + int max_num_args = remap->get_max_num_args(); + if (min_num_args <= 2 && max_num_args >= 2) { + remaps.insert(remap); + } + } + + string expected_params; + write_function_forset(out, remaps, 2, 2, + expected_params, 2, true, true, AT_single_arg, + RF_int, false, false, "index"); + + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return -1;\n"; + out << "}\n\n"; + } + + // Now write the getter, which returns a special wrapper object. + out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n" + " Py_INCREF(self);\n" + " Dtool_SequenceWrapper *wrap = PyObject_New(Dtool_SequenceWrapper, &Dtool_SequenceWrapper_Type);\n" + " wrap->_base = self;\n" + " wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n" + " wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Getitem;\n"; + if (property->_setter != NULL) { + out << " wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Setitem;\n"; + } else { + out << " wrap->_setitem_func = NULL;\n"; + } + out << " return (PyObject *)wrap;\n" + "}\n\n"; + + } else if (property->_getter != NULL) { + // Write out a regular, unwrapped getter. + out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n"; FunctionRemap *remap = property->_getter->_remaps.front(); - out << "PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n"; if (remap->_const_method) { out << " const " << cClassName << " *local_this = NULL;\n"; out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; @@ -6339,50 +6427,61 @@ write_getset(ostream &out, Object *obj, Property *property) { expected_params, 2, false, true, AT_no_args, RF_pyobject | RF_err_null, false, false); out << "}\n\n"; - } - if (property->_setter != NULL) { - out << "int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter(PyObject *self, PyObject *arg, void *) {\n"; - out << " " << cClassName << " *local_this = NULL;\n"; - out << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \"" - << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n"; - out << " return -1;\n"; - out << " }\n\n"; + // Write out a setter if this is not a read-only property. + if (property->_setter != NULL) { + out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter(PyObject *self, PyObject *arg, void *) {\n"; + out << " " << cClassName << " *local_this = NULL;\n"; + out << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \"" + << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n"; + out << " return -1;\n"; + out << " }\n\n"; - if (property->_clear_function != NULL) { - out << " if (arg == Py_None) {\n" - << " local_this->" << property->_clear_function->_ifunc.get_name() << "();\n" - << " return 0;\n" - << " }\n"; - } - - std::set remaps; - - // Extract only the setters that take one argument. - Function::Remaps::iterator it; - for (it = property->_setter->_remaps.begin(); - it != property->_setter->_remaps.end(); - ++it) { - FunctionRemap *remap = *it; - int min_num_args = remap->get_min_num_args(); - int max_num_args = remap->get_max_num_args(); - if (min_num_args <= 1 && max_num_args >= 1) { - remaps.insert(remap); + out << " if (arg == (PyObject *)NULL) {\n"; + if (property->_deleter != NULL) { + out << " local_this->" << property->_deleter->_ifunc.get_name() << "();\n" + << " return 0;\n"; + } else { + out << " Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << " attribute\");\n" + " return -1;\n"; } + out << " }\n"; + + if (property->_clear_function != NULL) { + out << " if (arg == Py_None) {\n" + << " local_this->" << property->_clear_function->_ifunc.get_name() << "();\n" + << " return 0;\n" + << " }\n"; + } + + std::set remaps; + + // Extract only the setters that take one argument. + Function::Remaps::iterator it; + for (it = property->_setter->_remaps.begin(); + it != property->_setter->_remaps.end(); + ++it) { + FunctionRemap *remap = *it; + int min_num_args = remap->get_min_num_args(); + int max_num_args = remap->get_max_num_args(); + if (min_num_args <= 1 && max_num_args >= 1) { + remaps.insert(remap); + } + } + + string expected_params; + write_function_forset(out, remaps, 1, 1, + expected_params, 2, true, true, AT_single_arg, + RF_int, false, false); + + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return -1;\n"; + out << "}\n\n"; } - - string expected_params; - write_function_forset(out, remaps, 1, 1, - expected_params, 2, true, true, AT_single_arg, - RF_int, false, false); - - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return -1;\n"; - out << "}\n\n"; } } @@ -6507,6 +6606,19 @@ record_object(TypeIndex type_index) { } } + if (ielement.has_del_function()) { + FunctionIndex func_index = ielement.get_del_function(); + Function *del_function = record_function(itype, func_index); + if (is_function_legal(del_function)) { + property->_deleter = del_function; + } + } + + if (ielement.is_sequence()) { + FunctionIndex func_index = ielement.get_length_function(); + property->_length_function = record_function(itype, func_index); + } + if (property->_getter != NULL) { object->_properties.push_back(property); } else { @@ -6624,6 +6736,8 @@ is_cpp_type_legal(CPPType *in_ctype) { return true; } else if (TypeManager::is_basic_string_wchar(type)) { return true; + } else if (TypeManager::is_vector_unsigned_char(type)) { + return true; } else if (TypeManager::is_simple(type)) { return true; } else if (TypeManager::is_pointer_to_simple(type)) { diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h index 1c7b7d98de..a571e3323f 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -101,6 +101,9 @@ private: // Assign to the coerced argument, in the case of a coercion constructor. RF_coerced = 0x040, + // Don't automatically map NULL to None + RF_preserve_null = 0x080, + // These indicate what should be returned on error. RF_err_notimplemented = 0x002, RF_err_null = 0x004, @@ -164,7 +167,7 @@ private: const string &exc_type, const string &message, const string &format_args = ""); void pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, - std::string return_expr); + std::string return_expr, int return_flags); void write_make_seq(ostream &out, Object *obj, const std::string &ClassName, const std::string &cClassName, MakeSeq *make_seq); diff --git a/dtool/src/interrogate/interrogateBuilder.cxx b/dtool/src/interrogate/interrogateBuilder.cxx index b11b2a4d3e..342ffdd4b9 100644 --- a/dtool/src/interrogate/interrogateBuilder.cxx +++ b/dtool/src/interrogate/interrogateBuilder.cxx @@ -1167,8 +1167,10 @@ scan_typedef_type(CPPTypedefType *type) { return; } - // A typedef cannot be a template declaration. - assert(!type->is_template()); + if (type->is_template()) { + // The type is a template declaration, not a true type. + return; + } if (type->_file.is_c_file()) { // This type declaration appears in a .C file. We can only export types @@ -1782,9 +1784,9 @@ get_function(CPPInstance *function, string description, } /** - * Adds the indicated make_property to the database, if it is not already - * present. In either case, returns the MakeSeqIndex of the make_seq within - * the database. + * Adds the indicated make_property or make_seq_property to the database, if + * it is not already present. In either case, returns the ElementIndex + * of the created property within the database. */ ElementIndex InterrogateBuilder:: get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CPPScope *scope) { @@ -1805,20 +1807,58 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP return index; } + // If we have a length function (ie. this is a sequence property), we should + // find the function that will give us the length. + FunctionIndex length_function = 0; + bool is_seq = false; + + CPPFunctionGroup::Instances::const_iterator fi; + CPPFunctionGroup *fgroup = make_property->_length_function; + if (fgroup != NULL) { + is_seq = true; + + for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { + CPPInstance *function = (*fi); + CPPFunctionType *ftype = + function->_type->as_function_type(); + if (ftype != NULL) { + length_function = get_function(function, "", struct_type, + struct_type->get_scope(), 0); + if (length_function != 0) { + break; + } + } + } + if (length_function == 0) { + cerr << "No instance of length method '" + << fgroup->_name << "' is suitable!\n"; + return 0; + } + } + // Find the getter so we can get its return type. CPPInstance *getter = NULL; CPPType *return_type = NULL; - CPPFunctionGroup *fgroup = make_property->_get_function; + fgroup = make_property->_get_function; if (fgroup != NULL) { CPPFunctionGroup::Instances::const_iterator fi; for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { CPPInstance *function = (*fi); CPPFunctionType *ftype = function->_type->as_function_type(); + if (ftype == NULL) { + continue; + } // The getter must either take no arguments, or all defaults. - if (ftype != NULL && (ftype->_parameters->_parameters.size() == 0 || - ftype->_parameters->_parameters[0]->_initializer != NULL)) { + if (ftype->_parameters->_parameters.size() == (int)is_seq || + (ftype->_parameters->_parameters.size() > (int)is_seq && + ftype->_parameters->_parameters[(int)is_seq]->_initializer != NULL)) { + // If this is a sequence getter, it must take an index argument. + if (is_seq && !TypeManager::is_integer(ftype->_parameters->_parameters[0]->_type)) { + continue; + } + getter = function; return_type = ftype->_return_type; @@ -1860,6 +1900,28 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP } } + // And the "deleter". + CPPInstance *deleter = NULL; + + fgroup = make_property->_del_function; + if (fgroup != NULL) { + CPPFunctionGroup::Instances::const_iterator fi; + for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { + CPPInstance *function = (*fi); + CPPFunctionType *ftype = function->_type->as_function_type(); + if (ftype != NULL && ftype->_parameters->_parameters.size() == (int)is_seq) { + deleter = function; + break; + } + } + + if (deleter == NULL || return_type == NULL) { + cerr << "No instance of delete-function '" + << fgroup->_name << "' is suitable!\n"; + return 0; + } + } + InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); // It isn't here, so we'll have to define it. ElementIndex index = idb->get_next_index(); @@ -1875,22 +1937,30 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP iproperty._type = 0; } + if (length_function != 0) { + iproperty._flags |= InterrogateElement::F_sequence; + iproperty._length_function = length_function; + } + if (getter != NULL) { iproperty._flags |= InterrogateElement::F_has_getter; iproperty._getter = get_function(getter, "", struct_type, struct_type->get_scope(), 0); - if (iproperty._getter == 0) { - cerr << "failed " << *getter << "\n"; - } + nassertr(iproperty._getter, 0); } if (hasser != NULL) { iproperty._flags |= InterrogateElement::F_has_has_function; iproperty._has_function = get_function(hasser, "", struct_type, struct_type->get_scope(), 0); - if (iproperty._has_function == 0) { - cerr << "failed " << *hasser << "\n"; - } + nassertr(iproperty._has_function, 0); + } + + if (deleter != NULL) { + iproperty._flags |= InterrogateElement::F_has_del_function; + iproperty._del_function = get_function(deleter, "", struct_type, + struct_type->get_scope(), 0); + nassertr(iproperty._del_function, 0); } // See if there happens to be a comment before the MAKE_PROPERTY macro. @@ -1907,9 +1977,7 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP iproperty._flags |= InterrogateElement::F_has_setter; iproperty._setter = get_function(function, "", struct_type, struct_type->get_scope(), 0); - if (iproperty._setter == 0) { - cerr << "failed " << *function << "\n"; - } + nassertr(iproperty._setter, 0); break; } } @@ -1922,15 +1990,12 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP iproperty._flags |= InterrogateElement::F_has_clear_function; iproperty._clear_function = get_function(function, "", struct_type, struct_type->get_scope(), 0); - if (iproperty._clear_function == 0) { - cerr << "failed " << *function << "\n"; - } + nassertr(iproperty._clear_function, 0); break; } } idb->add_element(index, iproperty); - return index; } @@ -2838,6 +2903,10 @@ define_enum_type(InterrogateType &itype, CPPEnumType *cpptype) { return; } + if (cpptype->is_scoped()) { + itype._flags |= InterrogateType::F_scoped_enum; + } + int next_value = 0; CPPEnumType::Elements::const_iterator ei; @@ -2919,6 +2988,8 @@ define_extension_type(InterrogateType &itype, CPPExtensionType *cpptype) { // But we can at least indicate which of the various extension types it is. switch (cpptype->_type) { case CPPExtensionType::T_enum: + case CPPExtensionType::T_enum_class: + case CPPExtensionType::T_enum_struct: itype._flags |= InterrogateType::F_enum; break; diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx index 1fe51f8111..7c9b6582a3 100644 --- a/dtool/src/interrogate/typeManager.cxx +++ b/dtool/src/interrogate/typeManager.cxx @@ -937,6 +937,66 @@ is_wstring(CPPType *type) { return is_basic_string_wchar(type); } +/** + * Returns true if the type is vector, or a const reference to + * it. + */ +bool TypeManager:: +is_vector_unsigned_char(CPPType *type) { + if (type->get_local_name(&parser) == "vector< unsigned char >" || + type->get_local_name(&parser) == "pvector< unsigned char >") { + return true; + } + + switch (type->get_subtype()) { + case CPPDeclaration::ST_const: + return is_vector_unsigned_char(type->as_const_type()->_wrapped_around); + + case CPPDeclaration::ST_reference: + return is_const_vector_unsigned_char(type->as_reference_type()->_pointing_at); + + case CPPDeclaration::ST_struct: + { + CPPStructType *stype = type->as_struct_type(); + CPPStructType::Derivation::const_iterator di; + for (di = stype->_derivation.begin(); + di != stype->_derivation.end(); + ++di) { + if (is_vector_unsigned_char((*di)._base)) { + return true; + } + } + } + break; + + case CPPDeclaration::ST_typedef: + return is_vector_unsigned_char(type->as_typedef_type()->_type); + + default: + break; + } + + return false; +} + +/** + * Returns true if the indicated type is a const wrapper around + * vector. + */ +bool TypeManager:: +is_const_vector_unsigned_char(CPPType *type) { + switch (type->get_subtype()) { + case CPPDeclaration::ST_const: + return is_vector_unsigned_char(type->as_const_type()->_wrapped_around); + + case CPPDeclaration::ST_typedef: + return is_const_vector_unsigned_char(type->as_typedef_type()->_type); + + default: + return false; + } +} + /** * Returns true if the indicated type is bool, or some trivial variant. */ diff --git a/dtool/src/interrogate/typeManager.h b/dtool/src/interrogate/typeManager.h index 5c5ed18190..4e5356a24e 100644 --- a/dtool/src/interrogate/typeManager.h +++ b/dtool/src/interrogate/typeManager.h @@ -81,6 +81,8 @@ public: static bool is_const_ref_to_basic_string_wchar(CPPType *type); static bool is_const_ptr_to_basic_string_wchar(CPPType *type); static bool is_wstring(CPPType *type); + static bool is_vector_unsigned_char(CPPType *type); + static bool is_const_vector_unsigned_char(CPPType *type); static bool is_pair(CPPType *type); static bool is_bool(CPPType *type); static bool is_integer(CPPType *type); diff --git a/dtool/src/interrogatedb/interrogateDatabase.cxx b/dtool/src/interrogatedb/interrogateDatabase.cxx index 22d424b6e9..559f707ca5 100644 --- a/dtool/src/interrogatedb/interrogateDatabase.cxx +++ b/dtool/src/interrogatedb/interrogateDatabase.cxx @@ -20,7 +20,7 @@ InterrogateDatabase *InterrogateDatabase::_global_ptr = NULL; int InterrogateDatabase::_file_major_version = 0; int InterrogateDatabase::_file_minor_version = 0; int InterrogateDatabase::_current_major_version = 3; -int InterrogateDatabase::_current_minor_version = 1; +int InterrogateDatabase::_current_minor_version = 2; /** * diff --git a/dtool/src/interrogatedb/interrogateElement.I b/dtool/src/interrogatedb/interrogateElement.I index 4fea0bf105..7e3ba61f77 100644 --- a/dtool/src/interrogatedb/interrogateElement.I +++ b/dtool/src/interrogatedb/interrogateElement.I @@ -24,6 +24,8 @@ InterrogateElement(InterrogateModuleDef *def) : _setter = 0; _has_function = 0; _clear_function = 0; + _del_function = 0; + _length_function = 0; } /** @@ -48,6 +50,8 @@ operator = (const InterrogateElement ©) { _setter = copy._setter; _has_function = copy._has_function; _clear_function = copy._clear_function; + _del_function = copy._del_function; + _length_function = copy._length_function; } /** @@ -163,6 +167,38 @@ get_clear_function() const { return _clear_function; } +/** + * + */ +INLINE bool InterrogateElement:: +has_del_function() const { + return (_flags & F_has_del_function) != 0; +} + +/** + * + */ +INLINE FunctionIndex InterrogateElement:: +get_del_function() const { + return _del_function; +} + +/** + * + */ +INLINE bool InterrogateElement:: +is_sequence() const { + return (_flags & F_sequence) != 0; +} + +/** + * + */ +INLINE FunctionIndex InterrogateElement:: +get_length_function() const { + return _length_function; +} + INLINE ostream & operator << (ostream &out, const InterrogateElement &element) { diff --git a/dtool/src/interrogatedb/interrogateElement.cxx b/dtool/src/interrogatedb/interrogateElement.cxx index 754f88ba33..a7469b9941 100644 --- a/dtool/src/interrogatedb/interrogateElement.cxx +++ b/dtool/src/interrogatedb/interrogateElement.cxx @@ -27,7 +27,9 @@ output(ostream &out) const { << _getter << " " << _setter << " " << _has_function << " " - << _clear_function << " "; + << _clear_function << " " + << _del_function << " " + << _length_function << " "; idf_output_string(out, _scoped_name); idf_output_string(out, _comment, '\n'); } @@ -41,6 +43,9 @@ input(istream &in) { in >> _flags >> _type >> _getter >> _setter; if (InterrogateDatabase::get_file_minor_version() >= 1) { in >> _has_function >> _clear_function; + if (InterrogateDatabase::get_file_minor_version() >= 2) { + in >> _del_function >> _length_function; + } } idf_input_string(in, _scoped_name); idf_input_string(in, _comment); @@ -55,4 +60,8 @@ remap_indices(const IndexRemapper &remap) { _type = remap.map_from(_type); _getter = remap.map_from(_getter); _setter = remap.map_from(_setter); + _has_function = remap.map_from(_has_function); + _clear_function = remap.map_from(_clear_function); + _del_function = remap.map_from(_del_function); + _length_function = remap.map_from(_length_function); } diff --git a/dtool/src/interrogatedb/interrogateElement.h b/dtool/src/interrogatedb/interrogateElement.h index a69be7f5d1..3506d7b9a8 100644 --- a/dtool/src/interrogatedb/interrogateElement.h +++ b/dtool/src/interrogatedb/interrogateElement.h @@ -47,6 +47,10 @@ public: INLINE FunctionIndex get_has_function() const; INLINE bool has_clear_function() const; INLINE FunctionIndex get_clear_function() const; + INLINE bool has_del_function() const; + INLINE FunctionIndex get_del_function() const; + INLINE bool is_sequence() const; + INLINE FunctionIndex get_length_function() const; void output(ostream &out) const; void input(istream &in); @@ -60,16 +64,21 @@ private: F_has_setter = 0x0004, F_has_has_function= 0x0008, F_has_clear_function= 0x0010, + F_has_del_function= 0x0020, + F_sequence = 0x0040, + F_mapping = 0x0080, }; int _flags; string _scoped_name; string _comment; TypeIndex _type; + FunctionIndex _length_function; FunctionIndex _getter; FunctionIndex _setter; FunctionIndex _has_function; FunctionIndex _clear_function; + FunctionIndex _del_function; friend class InterrogateBuilder; }; diff --git a/dtool/src/interrogatedb/interrogateType.I b/dtool/src/interrogatedb/interrogateType.I index be8e40960f..f6037fc571 100644 --- a/dtool/src/interrogatedb/interrogateType.I +++ b/dtool/src/interrogatedb/interrogateType.I @@ -205,6 +205,14 @@ is_enum() const { return (_flags & F_enum) != 0; } +/** + * Returns true if enum values are only available under a scope. + */ +INLINE bool InterrogateType:: +is_scoped_enum() const { + return (_flags & F_scoped_enum) != 0; +} + /** * */ diff --git a/dtool/src/interrogatedb/interrogateType.h b/dtool/src/interrogatedb/interrogateType.h index 3887569694..a1cedd1d82 100644 --- a/dtool/src/interrogatedb/interrogateType.h +++ b/dtool/src/interrogatedb/interrogateType.h @@ -65,6 +65,7 @@ public: INLINE int get_array_size() const; INLINE bool is_enum() const; + INLINE bool is_scoped_enum() const; INLINE int number_of_enum_values() const; INLINE const string &get_enum_value_name(int n) const; INLINE const string &get_enum_value_scoped_name(int n) const; @@ -136,6 +137,7 @@ private: F_unpublished = 0x100000, F_typedef = 0x200000, F_array = 0x400000, + F_scoped_enum = 0x800000, }; public: diff --git a/dtool/src/interrogatedb/interrogate_request.cxx b/dtool/src/interrogatedb/interrogate_request.cxx index 49ccff4333..3e02a9eecb 100644 --- a/dtool/src/interrogatedb/interrogate_request.cxx +++ b/dtool/src/interrogatedb/interrogate_request.cxx @@ -20,7 +20,11 @@ void interrogate_request_database(const char *database_filename) { InterrogateModuleDef *def = new InterrogateModuleDef; memset(def, 0, sizeof(InterrogateModuleDef)); +#ifdef _WIN32 + def->database_filename = _strdup(database_filename); +#else def->database_filename = strdup(database_filename); +#endif // Don't think of this as a leak; think of it as a one-time database // allocation. diff --git a/dtool/src/interrogatedb/py_panda.I b/dtool/src/interrogatedb/py_panda.I new file mode 100644 index 0000000000..3b171f14c7 --- /dev/null +++ b/dtool/src/interrogatedb/py_panda.I @@ -0,0 +1,219 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file py_panda.I + * @author rdb + * @date 2016-06-06 + */ + +/** + * Template function that can be used to extract any TypedObject pointer from + * a wrapped Python object. + */ +template INLINE bool +DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into) { + if (DtoolCanThisBeAPandaInstance(self)) { + Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index()); + if (target_class != NULL) { + into = (T*) ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, target_class); + return (into != NULL); + } + } + into = NULL; + return false; +} + +/** + * These functions wrap a pointer for a class that defines get_type_handle(). + */ +template INLINE PyObject * +DTool_CreatePyInstance(const T *obj, bool memory_rules) { + Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index()); + nassertr(known_class != NULL, NULL); + return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, true); +} + +template INLINE PyObject * +DTool_CreatePyInstance(T *obj, bool memory_rules) { + Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index()); + nassertr(known_class != NULL, NULL); + return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, false); +} + +template INLINE PyObject * +DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules) { + Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index()); + nassertr(known_class != NULL, NULL); + return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, true, obj->get_type().get_index()); +} + +template INLINE PyObject * +DTool_CreatePyInstanceTyped(T *obj, bool memory_rules) { + Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index()); + nassertr(known_class != NULL, NULL); + return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, false, obj->get_type().get_index()); +} + +/** + * The following functions wrap an arbitrary C++ value into a PyObject. + */ +ALWAYS_INLINE PyObject *Dtool_WrapValue(int value) { +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromLong((long)value); +#else + return PyInt_FromLong((long)value); +#endif +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned int value) { +#if PY_MAJOR_VERSION >= 3 && SIZEOF_INT < SIZEOF_LONG + return PyLong_FromLong((long)value); +#elif PY_MAJOR_VERSION >= 3 + return PyLong_FromUnsignedLong((unsigned long)value); +#elif SIZEOF_INT < SIZEOF_LONG + return PyInt_FromLong((long)value); +#else + return (value > LONG_MAX) + ? PyLong_FromUnsignedLong((unsigned long)value) + : PyInt_FromLong((long)value); +#endif +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(long value) { +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromLong(value); +#else + return PyInt_FromLong(value); +#endif +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long value) { +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromUnsignedLong(value); +#else + return (value > LONG_MAX) + ? PyLong_FromUnsignedLong(value) + : PyInt_FromLong((long)value); +#endif +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(long long value) { + return PyLong_FromLongLong(value); +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long long value) { + return PyLong_FromUnsignedLongLong(value); +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(bool value) { + PyObject *result = (value ? Py_True : Py_False); + Py_INCREF(result); + return result; +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(double value) { + return PyFloat_FromDouble(value); +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(const char *value) { + if (value == (const char *)NULL) { + Py_INCREF(Py_None); + return Py_None; + } else { +#if PY_MAJOR_VERSION >= 3 + return PyUnicode_FromString(value); +#else + return PyString_FromString(value); +#endif + } +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(const wchar_t *value) { + if (value == (const wchar_t *)NULL) { + Py_INCREF(Py_None); + return Py_None; + } else { + return PyUnicode_FromWideChar(value, (Py_ssize_t)wcslen(value)); + } +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string &value) { +#if PY_MAJOR_VERSION >= 3 + return PyUnicode_FromStringAndSize(value.data(), (Py_ssize_t)value.length()); +#else + return PyString_FromStringAndSize(value.data(), (Py_ssize_t)value.length()); +#endif +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring &value) { + return PyUnicode_FromWideChar(value.data(), (Py_ssize_t)value.length()); +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string *value) { + if (value == (const std::string *)NULL) { + Py_INCREF(Py_None); + return Py_None; + } else { +#if PY_MAJOR_VERSION >= 3 + return PyUnicode_FromStringAndSize(value->data(), (Py_ssize_t)value->length()); +#else + return PyString_FromStringAndSize(value->data(), (Py_ssize_t)value->length()); +#endif + } +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring *value) { + if (value == (const std::wstring *)NULL) { + Py_INCREF(Py_None); + return Py_None; + } else { + return PyUnicode_FromWideChar(value->data(), (Py_ssize_t)value->length()); + } +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(char value) { +#if PY_MAJOR_VERSION >= 3 + return PyUnicode_FromStringAndSize(&value, 1); +#else + return PyString_FromStringAndSize(&value, 1); +#endif +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(wchar_t value) { + return PyUnicode_FromWideChar(&value, 1); +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(PyObject *value) { + return value; +} + +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::vector &value) { +#if PY_MAJOR_VERSION >= 3 + return PyBytes_FromStringAndSize((char *)value.data(), (Py_ssize_t)value.size()); +#else + return PyString_FromStringAndSize((char *)value.data(), (Py_ssize_t)value.size()); +#endif +} + +#if PY_MAJOR_VERSION >= 0x02060000 +ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value) { + if (value == (Py_buffer *)NULL) { + return value; + } else { + return PyMemoryView_FromBuffer(value); + } +} +#endif + +template +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::pair &value) { + PyObject *tuple = PyTuple_New(2); + PyTuple_SET_ITEM(tuple, 0, Dtool_WrapValue(value.first)); + PyTuple_SET_ITEM(tuple, 1, Dtool_WrapValue(value.second)); + return tuple; +} diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index fc6338170e..a25a5c614b 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -172,7 +172,6 @@ void *DTOOL_Call_GetPointerThis(PyObject *self) { return NULL; } -#ifndef NDEBUG /** * This is similar to a PyErr_Occurred() check, except that it also checks * Notify to see if an assertion has occurred. If that is the case, then it @@ -193,7 +192,6 @@ bool _Dtool_CheckErrorOccurred() { } return false; } -#endif // NDEBUG /** * Raises an AssertionError containing the last thrown assert message, and @@ -335,6 +333,33 @@ PyObject *_Dtool_Return(PyObject *value) { return value; } +/** + * Creates a Python 3.4-style enum type. Steals reference to 'names'. + */ +PyObject *Dtool_EnumType_Create(const char *name, PyObject *names, const char *module) { + static PyObject *enum_class = NULL; + static PyObject *enum_meta = NULL; + static PyObject *enum_create = NULL; + if (enum_meta == NULL) { + PyObject *enum_module = PyImport_ImportModule("enum"); + nassertr_always(enum_module != NULL, NULL); + + enum_class = PyObject_GetAttrString(enum_module, "Enum"); + enum_meta = PyObject_GetAttrString(enum_module, "EnumMeta"); + enum_create = PyObject_GetAttrString(enum_meta, "_create_"); + nassertr(enum_meta != NULL, NULL); + } + + PyObject *result = PyObject_CallFunction(enum_create, (char *)"OsN", enum_class, name, names); + nassertr(result != NULL, NULL); + if (module != NULL) { + PyObject *modstr = PyUnicode_FromString(module); + PyObject_SetAttrString(result, "__module__", modstr); + Py_DECREF(modstr); + } + return result; +} + /** */ @@ -544,8 +569,19 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) { return (PyObject *)NULL; } - // Initialize the base class of everything. - Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(NULL); + // Initialize the types we define in py_panda. + static bool dtool_inited = false; + if (!dtool_inited) { + dtool_inited = true; + + if (PyType_Ready(&Dtool_SequenceWrapper_Type) < 0) { + PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_SequenceWrapper)"); + return NULL; + } + + // Initialize the base class of everything. + Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(NULL); + } // the module level function inits.... MethodDefmap functions; @@ -834,18 +870,106 @@ PyObject *map_deepcopy_to_copy(PyObject *self, PyObject *args) { } /** - * Similar to PyLong_FromUnsignedLong(), but returns either a regular integer - * or a long integer, according to whether the indicated value will fit. + * This class is returned from properties that require a settable interface, + * ie. something.children[i] = 3. */ -#if PY_MAJOR_VERSION < 3 -EXPCL_INTERROGATEDB PyObject * -PyLongOrInt_FromUnsignedLong(unsigned long value) { - if ((long)value < 0) { - return PyLong_FromUnsignedLong(value); - } else { - return PyInt_FromLong((long)value); - } +static void Dtool_SequenceWrapper_dealloc(PyObject *self) { + Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self; + nassertv(wrap); + Py_DECREF(wrap->_base); } + +static Py_ssize_t Dtool_SequenceWrapper_length(PyObject *self) { + Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self; + nassertr(wrap, -1); + nassertr(wrap->_len_func, -1); + return wrap->_len_func(wrap->_base); +} + +static PyObject *Dtool_SequenceWrapper_getitem(PyObject *self, Py_ssize_t index) { + Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self; + nassertr(wrap, NULL); + nassertr(wrap->_getitem_func, NULL); + return wrap->_getitem_func(wrap->_base, index); +} + +static int Dtool_SequenceWrapper_setitem(PyObject *self, Py_ssize_t index, PyObject *value) { + Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self; + nassertr(wrap, -1); + nassertr(wrap->_setitem_func, -1); + return wrap->_setitem_func(wrap->_base, index, value); +} + +static PySequenceMethods Dtool_SequenceWrapper_SequenceMethods = { + Dtool_SequenceWrapper_length, + 0, // sq_concat + 0, // sq_repeat + Dtool_SequenceWrapper_getitem, + 0, // sq_slice + Dtool_SequenceWrapper_setitem, + 0, // sq_ass_slice + 0, // sq_contains + 0, // sq_inplace_concat + 0, // sq_inplace_repeat +}; + +PyTypeObject Dtool_SequenceWrapper_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "sequence wrapper", + sizeof(Dtool_SequenceWrapper), + 0, // tp_itemsize + Dtool_SequenceWrapper_dealloc, + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr +#if PY_MAJOR_VERSION >= 3 + 0, // tp_reserved +#else + 0, // tp_compare #endif + 0, // tp_repr + 0, // tp_as_number + &Dtool_SequenceWrapper_SequenceMethods, + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + PyObject_GenericGetAttr, + PyObject_GenericSetAttr, + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, + 0, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + PyType_GenericAlloc, + 0, // tp_new + PyObject_Del, + 0, // tp_is_gc + 0, // tp_bases + 0, // tp_mro + 0, // tp_cache + 0, // tp_subclasses + 0, // tp_weaklist + 0, // tp_del +#if PY_VERSION_HEX >= 0x02060000 + 0, // tp_version_tag +#endif +#if PY_VERSION_HEX >= 0x03040000 + 0, // tp_finalize +#endif +}; #endif // HAVE_PYTHON diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index 422fb5ffe1..8491c7529f 100644 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -103,10 +103,6 @@ inline PyObject* doPy_RETURN_FALSE() #define nb_inplace_divide nb_inplace_true_divide #define PyLongOrInt_Check(x) PyLong_Check(x) -#define PyLongOrInt_FromSize_t PyLong_FromSize_t -#define PyLongOrInt_FromSsize_t PyLong_FromSsize_t -#define PyLongOrInt_FromLong PyLong_FromLong -#define PyLongOrInt_FromUnsignedLong PyLong_FromUnsignedLong #define PyLongOrInt_AS_LONG PyLong_AS_LONG #define PyInt_Check PyLong_Check #define PyInt_AsLong PyLong_AsLong @@ -114,9 +110,6 @@ inline PyObject* doPy_RETURN_FALSE() #else #define PyLongOrInt_Check(x) (PyInt_Check(x) || PyLong_Check(x)) // PyInt_FromSize_t automatically picks the right type. -#define PyLongOrInt_FromSize_t PyInt_FromSize_t -#define PyLongOrInt_FromSsize_t PyInt_FromSsize_t -#define PyLongOrInt_FromLong PyInt_FromLong #define PyLongOrInt_AS_LONG PyInt_AsLong // For more portably defining hash functions. @@ -135,6 +128,13 @@ typedef long Py_hash_t; #endif #endif +// Which character to use in PyArg_ParseTuple et al for a byte string. +#if PY_MAJOR_VERSION >= 3 +#define FMTCHAR_BYTES "y" +#else +#define FMTCHAR_BYTES "s" +#endif + using namespace std; // this is tempory .. untill this is glued better into the panda build system @@ -159,9 +159,6 @@ typedef void *(*DowncastFunction)(void *, Dtool_PyTypedObject *); typedef void *(*CoerceFunction)(PyObject *, void *); typedef void (*ModuleClassInitFunction)(PyObject *module); -// inline Dtool_PyTypedObject * Dtool_RuntimeTypeDtoolType(int -// type); inline void Dtool_Deallocate_General(PyObject * self); inline -// int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2); THIS IS THE // INSTANCE CONTAINER FOR ALL panda py objects.... struct Dtool_PyInstDef { PyObject_HEAD @@ -300,17 +297,7 @@ EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyT EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef, void **answer, const char *method_name); -template INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into) { - if (DtoolCanThisBeAPandaInstance(self)) { - Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index()); - if (target_class != NULL) { - into = (T*) ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, target_class); - return (into != NULL); - } - } - into = NULL; - return false; -} +template INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into); // Functions related to error reporting. EXPCL_INTERROGATEDB bool _Dtool_CheckErrorOccurred(); @@ -348,6 +335,12 @@ EXPCL_INTERROGATEDB PyObject *_Dtool_Return(PyObject *value); #define Dtool_Return(value) _Dtool_Return(value) #endif +/** + * Wrapper around Python 3.4's enum library, which does not have a C API. + */ +EXPCL_INTERROGATEDB PyObject *Dtool_EnumType_Create(const char *name, PyObject *names, + const char *module = NULL); + /** */ @@ -359,29 +352,10 @@ EXPCL_INTERROGATEDB PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyT // These template methods allow use when the Dtool_PyTypedObject is not known. // They require a get_class_type() to be defined for the class. -template INLINE PyObject *DTool_CreatePyInstance(const T *obj, bool memory_rules) { - Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index()); - nassertr(known_class != NULL, NULL); - return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, true); -} - -template INLINE PyObject *DTool_CreatePyInstance(T *obj, bool memory_rules) { - Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index()); - nassertr(known_class != NULL, NULL); - return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, false); -} - -template INLINE PyObject *DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules) { - Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index()); - nassertr(known_class != NULL, NULL); - return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, true, obj->get_type().get_index()); -} - -template INLINE PyObject *DTool_CreatePyInstanceTyped(T *obj, bool memory_rules) { - Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index()); - nassertr(known_class != NULL, NULL); - return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, false, obj->get_type().get_index()); -} +template INLINE PyObject *DTool_CreatePyInstance(const T *obj, bool memory_rules); +template INLINE PyObject *DTool_CreatePyInstance(T *obj, bool memory_rules); +template INLINE PyObject *DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules); +template INLINE PyObject *DTool_CreatePyInstanceTyped(T *obj, bool memory_rules); // Macro(s) class definition .. Used to allocate storage and init some values // for a Dtool Py Type object. @@ -474,18 +448,59 @@ copy_from_copy_constructor(PyObject *self, PyObject *noargs); EXPCL_INTERROGATEDB PyObject * map_deepcopy_to_copy(PyObject *self, PyObject *args); -#if PY_MAJOR_VERSION < 3 -// In the Python 3 case, it is defined as a macro, at the beginning of this -// file. -EXPCL_INTERROGATEDB PyObject * -PyLongOrInt_FromUnsignedLong(unsigned long value); +/** + * This class is returned from properties that require a settable interface, + * ie. something.children[i] = 3. + */ +struct Dtool_SequenceWrapper { + PyObject_HEAD + PyObject *_base; + lenfunc _len_func; + ssizeargfunc _getitem_func; + ssizeobjargproc _setitem_func; +}; + +EXPCL_INTERROGATEDB extern PyTypeObject Dtool_SequenceWrapper_Type; + +/** + * These functions convert a C++ value into the corresponding Python object. + * This used to be generated by the code generator, but it seems more reliable + * and maintainable to define these as overloads and have the compiler sort + * it out. + */ +ALWAYS_INLINE PyObject *Dtool_WrapValue(int value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned int value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(long value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(long long value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long long value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(bool value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(double value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(const char *value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(const wchar_t *value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string &value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring &value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string *value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring *value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(char value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(wchar_t value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(PyObject *value); +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::vector &value); + +#if PY_MAJOR_VERSION >= 0x02060000 +ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value); #endif +template +ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::pair &value); + EXPCL_INTERROGATEDB extern struct Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE; EXPCL_INTERROGATEDB extern void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module); #define Dtool_Ptr_DTOOL_SUPER_BASE (&Dtool_DTOOL_SUPER_BASE) +#include "py_panda.I" + #endif // HAVE_PYTHON && !CPPPARSER #endif // PY_PANDA_H_ diff --git a/dtool/src/parser-inc/netinet/in.h b/dtool/src/parser-inc/netinet/in.h new file mode 100644 index 0000000000..b0b3bc605e --- /dev/null +++ b/dtool/src/parser-inc/netinet/in.h @@ -0,0 +1,17 @@ +#include +#include + +typedef uint32_t in_addr_t; +struct in_addr; +typedef uint16_t in_port_t; +struct in6_addr; +struct sockaddr_in; +struct sockaddr_in6; +struct ip_mreq; +struct ip_mreq_source; +struct ipv6_mreq; +struct group_req; +struct group_source_req; +struct ip_msfilter; +struct group_filter; + diff --git a/dtool/src/parser-inc/socket.h b/dtool/src/parser-inc/socket.h deleted file mode 100644 index 2881dc3780..0000000000 --- a/dtool/src/parser-inc/socket.h +++ /dev/null @@ -1,10 +0,0 @@ -typedef int SOCKET ; - -struct sockaddr_in -{ -}; - -typedef struct fd_set { - unsigned int fd_count; /* how many are SET? */ - SOCKET fd_array[10]; /* an array of SOCKETs */ -} fd_set; diff --git a/dtool/src/parser-inc/sys/socket.h b/dtool/src/parser-inc/sys/socket.h new file mode 100644 index 0000000000..6fefc30af9 --- /dev/null +++ b/dtool/src/parser-inc/sys/socket.h @@ -0,0 +1,18 @@ +#pragma once + +typedef int socklen_t; +typedef unsigned short int sa_family_t; + +struct sockaddr { + sa_family_t sa_family; + char sa_data[]; +}; + +struct sockaddr_storage { + sa_family_t ss_family; +}; + +typedef struct fd_set { + unsigned int fd_count; /* how many are SET? */ + int fd_array[10]; /* an array of SOCKETs */ +} fd_set; diff --git a/dtool/src/parser-inc/sys/time.h b/dtool/src/parser-inc/sys/time.h index 98d3ef73ad..7da313e913 100644 --- a/dtool/src/parser-inc/sys/time.h +++ b/dtool/src/parser-inc/sys/time.h @@ -2,3 +2,4 @@ struct timeval; struct fd_set; +struct timezone; diff --git a/dtool/src/parser-inc/winsock2.h b/dtool/src/parser-inc/winsock2.h index c63bef39b2..492d85ec02 100644 --- a/dtool/src/parser-inc/winsock2.h +++ b/dtool/src/parser-inc/winsock2.h @@ -6,6 +6,9 @@ typedef unsigned long SOCKET; +struct sockaddr; struct sockaddr_in; +struct sockaddr_in6; +struct sockaddr_storage; #endif diff --git a/dtool/src/parser-inc/ws2tcpip.h b/dtool/src/parser-inc/ws2tcpip.h new file mode 100644 index 0000000000..49262434c5 --- /dev/null +++ b/dtool/src/parser-inc/ws2tcpip.h @@ -0,0 +1 @@ +typedef DWORD socklen_t; diff --git a/dtool/src/parser-inc/zlib.h b/dtool/src/parser-inc/zlib.h index 74b373394a..925d60eb1a 100644 --- a/dtool/src/parser-inc/zlib.h +++ b/dtool/src/parser-inc/zlib.h @@ -21,8 +21,8 @@ #include "zconf.h" -class z_stream { -}; +typedef struct z_stream_s z_stream; +typedef struct gz_header_s gz_header; #endif diff --git a/dtool/src/prc/configDeclaration.I b/dtool/src/prc/configDeclaration.I index 889a01a4c4..a93fbdab10 100644 --- a/dtool/src/prc/configDeclaration.I +++ b/dtool/src/prc/configDeclaration.I @@ -187,7 +187,7 @@ get_int_word(size_t n) const { * Returns the int64 value of the nth word of the declaration's value, or 0 if * there is no nth value. See also has_int64_word(). */ -INLINE PN_int64 ConfigDeclaration:: +INLINE int64_t ConfigDeclaration:: get_int64_word(size_t n) const { // We use has_string_word() instead of has_int64_word(), so we can return a // partial answer if there was one. diff --git a/dtool/src/prc/configDeclaration.cxx b/dtool/src/prc/configDeclaration.cxx index 2c7550e90d..d692bec013 100644 --- a/dtool/src/prc/configDeclaration.cxx +++ b/dtool/src/prc/configDeclaration.cxx @@ -108,7 +108,7 @@ set_int_word(size_t n, int value) { * words. */ void ConfigDeclaration:: -set_int64_word(size_t n, PN_int64 value) { +set_int64_word(size_t n, int64_t value) { set_string_word(n, format_string(value)); _words[n]._flags |= (F_checked_int64 | F_valid_int64); @@ -294,8 +294,8 @@ check_int64_word(size_t n) { ++pi; // Negative number. while (pi != word._str.end() && isdigit(*pi)) { - PN_int64 next = word._int_64 * 10 - (int)((*pi) - '0'); - if ((PN_int64)(next / 10) != word._int_64) { + int64_t next = word._int_64 * 10 - (int)((*pi) - '0'); + if ((int64_t)(next / 10) != word._int_64) { // Overflow. overflow = true; } @@ -306,8 +306,8 @@ check_int64_word(size_t n) { } else { // Positive number. while (pi != word._str.end() && isdigit(*pi)) { - PN_int64 next = word._int_64 * 10 + (int)((*pi) - '0'); - if ((PN_int64)(next / 10) != word._int_64) { + int64_t next = word._int_64 * 10 + (int)((*pi) - '0'); + if ((int64_t)(next / 10) != word._int_64) { // Overflow. overflow = true; } diff --git a/dtool/src/prc/configDeclaration.h b/dtool/src/prc/configDeclaration.h index 7e9c96b6a5..696f4771d4 100644 --- a/dtool/src/prc/configDeclaration.h +++ b/dtool/src/prc/configDeclaration.h @@ -59,13 +59,13 @@ PUBLISHED: INLINE string get_string_word(size_t n) const; INLINE bool get_bool_word(size_t n) const; INLINE int get_int_word(size_t n) const; - INLINE PN_int64 get_int64_word(size_t n) const; + INLINE int64_t get_int64_word(size_t n) const; INLINE double get_double_word(size_t n) const; void set_string_word(size_t n, const string &value); void set_bool_word(size_t n, bool value); void set_int_word(size_t n, int value); - void set_int64_word(size_t n, PN_int64 value); + void set_int64_word(size_t n, int64_t value); void set_double_word(size_t n, double value); INLINE int get_decl_seq() const; @@ -106,7 +106,7 @@ private: string _str; bool _bool; int _int; - PN_int64 _int_64; + int64_t _int_64; double _double; short _flags; }; diff --git a/dtool/src/prc/configPage.h b/dtool/src/prc/configPage.h index 63ec9106df..8c143de836 100644 --- a/dtool/src/prc/configPage.h +++ b/dtool/src/prc/configPage.h @@ -44,6 +44,8 @@ PUBLISHED: INLINE bool is_special() const; INLINE bool is_implicit() const; + MAKE_PROPERTY(special, is_special); + MAKE_PROPERTY(implicit, is_implicit); void set_sort(int sort); INLINE int get_sort() const; @@ -72,6 +74,8 @@ PUBLISHED: string get_string_value(size_t n) const; bool is_variable_used(size_t n) const; + MAKE_SEQ_PROPERTY(declarations, get_num_declarations, modify_declaration); + void output(ostream &out) const; void output_brief_signature(ostream &out) const; void write(ostream &out) const; diff --git a/dtool/src/prc/configVariable.I b/dtool/src/prc/configVariable.I index 65ef0380aa..b46bc63529 100644 --- a/dtool/src/prc/configVariable.I +++ b/dtool/src/prc/configVariable.I @@ -196,7 +196,7 @@ get_int_word(size_t n) const { * Returns the int64 value of the nth word of the variable's value, or 0 if * there is no nth value. See also has_int_word(). */ -INLINE PN_int64 ConfigVariable:: +INLINE int64_t ConfigVariable:: get_int64_word(size_t n) const { nassertr(is_constructed(), 0); const ConfigDeclaration *decl = _core->get_declaration(0); @@ -249,7 +249,7 @@ set_int_word(size_t n, int value) { * words. */ INLINE void ConfigVariable:: -set_int64_word(size_t n, PN_int64 value) { +set_int64_word(size_t n, int64_t value) { nassertv(is_constructed()); _core->make_local_value()->set_int64_word(n, value); } diff --git a/dtool/src/prc/configVariable.h b/dtool/src/prc/configVariable.h index a937b1cdea..c8adb39e65 100644 --- a/dtool/src/prc/configVariable.h +++ b/dtool/src/prc/configVariable.h @@ -56,13 +56,13 @@ protected: INLINE string get_string_word(size_t n) const; INLINE bool get_bool_word(size_t n) const; INLINE int get_int_word(size_t n) const; - INLINE PN_int64 get_int64_word(size_t n) const; + INLINE int64_t get_int64_word(size_t n) const; INLINE double get_double_word(size_t n) const; INLINE void set_string_word(size_t n, const string &value); INLINE void set_bool_word(size_t n, bool value); INLINE void set_int_word(size_t n, int value); - INLINE void set_int64_word(size_t n, PN_int64 value); + INLINE void set_int64_word(size_t n, int64_t value); INLINE void set_double_word(size_t n, double value); protected: diff --git a/dtool/src/prc/configVariableCore.h b/dtool/src/prc/configVariableCore.h index 11af6061ce..e857dd3cc2 100644 --- a/dtool/src/prc/configVariableCore.h +++ b/dtool/src/prc/configVariableCore.h @@ -75,10 +75,25 @@ PUBLISHED: INLINE size_t get_num_unique_references() const; INLINE const ConfigDeclaration *get_unique_reference(size_t n) const; MAKE_SEQ(get_unique_references, get_num_unique_references, get_unique_reference); + MAKE_SEQ_PROPERTY(declarations, get_num_declarations, get_declaration); void output(ostream &out) const; void write(ostream &out) const; + MAKE_PROPERTY(name, get_name); + MAKE_PROPERTY(used, is_used); + MAKE_PROPERTY(closed, is_closed); + MAKE_PROPERTY(trust_level, get_trust_level); + MAKE_PROPERTY(dynamic, is_dynamic); + + MAKE_PROPERTY(value_type, get_value_type, set_value_type); + MAKE_PROPERTY(description, get_description, set_description); + MAKE_PROPERTY(default_value, get_default_value, set_default_value); + + MAKE_SEQ_PROPERTY(references, get_num_references, get_reference); + MAKE_SEQ_PROPERTY(trusted_references, get_num_trusted_references, get_trusted_reference); + MAKE_SEQ_PROPERTY(unique_references, get_num_unique_references, get_unique_reference); + private: void add_declaration(ConfigDeclaration *decl); void remove_declaration(ConfigDeclaration *decl); diff --git a/dtool/src/prc/configVariableInt64.I b/dtool/src/prc/configVariableInt64.I index 94d405cd76..f7c1c5d66b 100644 --- a/dtool/src/prc/configVariableInt64.I +++ b/dtool/src/prc/configVariableInt64.I @@ -26,7 +26,7 @@ ConfigVariableInt64(const string &name) : * */ INLINE ConfigVariableInt64:: -ConfigVariableInt64(const string &name, PN_int64 default_value, +ConfigVariableInt64(const string &name, int64_t default_value, const string &description, int flags) : #ifdef PRC_SAVE_DESCRIPTIONS ConfigVariable(name, ConfigVariableCore::VT_int64, description, flags), @@ -60,7 +60,7 @@ ConfigVariableInt64(const string &name, const string &default_value, * Reassigns the variable's local value. */ INLINE void ConfigVariableInt64:: -operator = (PN_int64 value) { +operator = (int64_t value) { set_value(value); } @@ -68,7 +68,7 @@ operator = (PN_int64 value) { * Returns the variable's value. */ INLINE ConfigVariableInt64:: -operator PN_int64 () const { +operator int64_t () const { return get_value(); } @@ -83,7 +83,7 @@ size() const { /** * Returns the value of the variable's nth word. */ -INLINE PN_int64 ConfigVariableInt64:: +INLINE int64_t ConfigVariableInt64:: operator [] (size_t n) const { return get_word(n); } @@ -92,7 +92,7 @@ operator [] (size_t n) const { * Reassigns the variable's local value. */ INLINE void ConfigVariableInt64:: -set_value(PN_int64 value) { +set_value(int64_t value) { set_string_value(""); set_int64_word(0, value); } @@ -100,9 +100,9 @@ set_value(PN_int64 value) { /** * Returns the variable's value. */ -INLINE PN_int64 ConfigVariableInt64:: +INLINE int64_t ConfigVariableInt64:: get_value() const { - TAU_PROFILE("PN_int64 ConfigVariableInt64::get_value() const", " ", TAU_USER); + TAU_PROFILE("int64_t ConfigVariableInt64::get_value() const", " ", TAU_USER); if (!is_cache_valid(_local_modified)) { mark_cache_valid(((ConfigVariableInt64 *)this)->_local_modified); ((ConfigVariableInt64 *)this)->_cache = get_int64_word(0); @@ -113,7 +113,7 @@ get_value() const { /** * Returns the variable's default value. */ -INLINE PN_int64 ConfigVariableInt64:: +INLINE int64_t ConfigVariableInt64:: get_default_value() const { const ConfigDeclaration *decl = ConfigVariable::get_default_value(); if (decl != (ConfigDeclaration *)NULL) { @@ -125,7 +125,7 @@ get_default_value() const { /** * Returns the variable's nth value. */ -INLINE PN_int64 ConfigVariableInt64:: +INLINE int64_t ConfigVariableInt64:: get_word(size_t n) const { return get_int64_word(n); } @@ -135,6 +135,6 @@ get_word(size_t n) const { * variable's overall value. */ INLINE void ConfigVariableInt64:: -set_word(size_t n, PN_int64 value) { +set_word(size_t n, int64_t value) { set_int64_word(n, value); } diff --git a/dtool/src/prc/configVariableInt64.cxx b/dtool/src/prc/configVariableInt64.cxx index 5545678685..1b8166d496 100644 --- a/dtool/src/prc/configVariableInt64.cxx +++ b/dtool/src/prc/configVariableInt64.cxx @@ -18,6 +18,6 @@ * */ void ConfigVariableInt64:: -set_default_value(PN_int64 default_value) { +set_default_value(int64_t default_value) { _core->set_default_value(format_string(default_value)); } diff --git a/dtool/src/prc/configVariableInt64.h b/dtool/src/prc/configVariableInt64.h index 835c165f8a..40477f87cc 100644 --- a/dtool/src/prc/configVariableInt64.h +++ b/dtool/src/prc/configVariableInt64.h @@ -25,34 +25,34 @@ class EXPCL_DTOOLCONFIG ConfigVariableInt64 : public ConfigVariable { PUBLISHED: INLINE ConfigVariableInt64(const string &name); - INLINE ConfigVariableInt64(const string &name, PN_int64 default_value, + INLINE ConfigVariableInt64(const string &name, int64_t default_value, const string &description = string(), int flags = 0); INLINE ConfigVariableInt64(const string &name, const string &default_value, const string &description = string(), int flags = 0); - INLINE void operator = (PN_int64 value); - INLINE operator PN_int64 () const; + INLINE void operator = (int64_t value); + INLINE operator int64_t () const; INLINE size_t size() const; - INLINE PN_int64 operator [] (size_t n) const; + INLINE int64_t operator [] (size_t n) const; - INLINE void set_value(PN_int64 value); - INLINE PN_int64 get_value() const; - INLINE PN_int64 get_default_value() const; + INLINE void set_value(int64_t value); + INLINE int64_t get_value() const; + INLINE int64_t get_default_value() const; MAKE_PROPERTY(value, get_value, set_value); MAKE_PROPERTY(default_value, get_default_value); - INLINE PN_int64 get_word(size_t n) const; - INLINE void set_word(size_t n, PN_int64 value); + INLINE int64_t get_word(size_t n) const; + INLINE void set_word(size_t n, int64_t value); private: - void set_default_value(PN_int64 default_value); + void set_default_value(int64_t default_value); private: AtomicAdjust::Integer _local_modified; - PN_int64 _cache; + int64_t _cache; }; #include "configVariableInt64.I" diff --git a/dtool/src/prc/configVariableManager.h b/dtool/src/prc/configVariableManager.h index eccdf2945c..78b943fef7 100644 --- a/dtool/src/prc/configVariableManager.h +++ b/dtool/src/prc/configVariableManager.h @@ -48,6 +48,8 @@ PUBLISHED: string get_variable_name(size_t n) const; bool is_variable_used(size_t n) const; + MAKE_SEQ_PROPERTY(variables, get_num_variables, get_variable); + void output(ostream &out) const; void write(ostream &out) const; diff --git a/dtool/src/prc/configVariableSearchPath.h b/dtool/src/prc/configVariableSearchPath.h index 25524b86d4..6a6cfeb0ab 100644 --- a/dtool/src/prc/configVariableSearchPath.h +++ b/dtool/src/prc/configVariableSearchPath.h @@ -68,6 +68,7 @@ PUBLISHED: INLINE size_t get_num_directories() const; INLINE const Filename &get_directory(size_t n) const; MAKE_SEQ(get_directories, get_num_directories, get_directory); + MAKE_SEQ_PROPERTY(directories, get_num_directories, get_directory); INLINE Filename find_file(const Filename &filename) const; INLINE size_t find_all_files(const Filename &filename, diff --git a/dtool/src/prc/encryptStream.I b/dtool/src/prc/encryptStream.I index bdb911ebf8..bad15bd7e7 100644 --- a/dtool/src/prc/encryptStream.I +++ b/dtool/src/prc/encryptStream.I @@ -109,6 +109,29 @@ close() { return *this; } +/** + * Returns the encryption algorithm that was read from the stream. + */ +INLINE const string &OEncryptStream:: +get_algorithm() const { + return _buf.get_algorithm(); +} + +/** + * Returns the encryption key length, in bits, that was read from the stream. + */ +INLINE int OEncryptStream:: +get_key_length() const { + return _buf.get_key_length(); +} + +/** + * Returns the value that was was read from the stream. + */ +INLINE int OEncryptStream:: +get_iteration_count() const { + return _buf.get_iteration_count(); +} /** * Specifies the encryption algorithm that should be used for future calls to diff --git a/dtool/src/prc/encryptStream.h b/dtool/src/prc/encryptStream.h index e69ab0f9a9..3093e5d12f 100644 --- a/dtool/src/prc/encryptStream.h +++ b/dtool/src/prc/encryptStream.h @@ -49,6 +49,10 @@ PUBLISHED: INLINE int get_key_length() const; INLINE int get_iteration_count() const; + MAKE_PROPERTY(algorithm, get_algorithm); + MAKE_PROPERTY(key_length, get_key_length); + MAKE_PROPERTY(iteration_count, get_iteration_count); + private: EncryptStreamBuf _buf; }; @@ -76,10 +80,20 @@ PUBLISHED: const string &password); INLINE OEncryptStream &close(); +public: + INLINE const string &get_algorithm() const; + INLINE int get_key_length() const; + INLINE int get_iteration_count() const; + +PUBLISHED: INLINE void set_algorithm(const string &algorithm); INLINE void set_key_length(int key_length); INLINE void set_iteration_count(int iteration_count); + MAKE_PROPERTY(algorithm, get_algorithm, set_algorithm); + MAKE_PROPERTY(key_length, get_key_length, set_key_length); + MAKE_PROPERTY(iteration_count, get_iteration_count, set_iteration_count); + private: EncryptStreamBuf _buf; }; diff --git a/dtool/src/prc/encryptStreamBuf.cxx b/dtool/src/prc/encryptStreamBuf.cxx index a308412797..acf76f9c0a 100644 --- a/dtool/src/prc/encryptStreamBuf.cxx +++ b/dtool/src/prc/encryptStreamBuf.cxx @@ -276,12 +276,12 @@ open_write(ostream *dest, bool owns_dest, const string &password) { // Now write the header information to the stream. StreamWriter sw(_dest, false); - nassertv((PN_uint16)nid == nid); - sw.add_uint16((PN_uint16)nid); - nassertv((PN_uint16)key_length == key_length); - sw.add_uint16((PN_uint16)key_length); - nassertv((PN_uint16)count == count); - sw.add_uint16((PN_uint16)count); + nassertv((uint16_t)nid == nid); + sw.add_uint16((uint16_t)nid); + nassertv((uint16_t)key_length == key_length); + sw.add_uint16((uint16_t)key_length); + nassertv((uint16_t)count == count); + sw.add_uint16((uint16_t)count); sw.append_data(iv, iv_length); _write_valid = true; diff --git a/dtool/src/prc/nativeNumericData.I b/dtool/src/prc/nativeNumericData.I index 9a43707c9f..9f08e4cfe3 100644 --- a/dtool/src/prc/nativeNumericData.I +++ b/dtool/src/prc/nativeNumericData.I @@ -54,24 +54,24 @@ get_data() const { // this is for a intel compile .. it is native format and it is readable off // word boundries -inline void TS_SetVal1(const PN_int8 * src, PN_int8 *dst) +inline void TS_SetVal1(const int8_t * src, int8_t *dst) { *dst = *src; } inline void TS_SetVal2(const char * src, char *dst) { - *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); + *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); } inline void TS_SetVal4(const char * src, char *dst) { - *(reinterpret_cast (dst)) = *(reinterpret_cast (src)); + *(reinterpret_cast (dst)) = *(reinterpret_cast (src)); } inline void TS_SetVal8(const char * src, char *dst) { - *(reinterpret_cast(dst)) = *(reinterpret_cast(src)); + *(reinterpret_cast(dst)) = *(reinterpret_cast(src)); } template inline type TS_GetInteger(type &val,const char * _src) diff --git a/dtool/src/prc/notifyCategory.cxx b/dtool/src/prc/notifyCategory.cxx index e44b33dffa..a6e0a0181c 100644 --- a/dtool/src/prc/notifyCategory.cxx +++ b/dtool/src/prc/notifyCategory.cxx @@ -74,10 +74,15 @@ out(NotifySeverity severity, bool prefix) const { if (get_notify_timestamp()) { // Format a timestamp to include as a prefix as well. time_t now = time(NULL) + _server_delta; - struct tm *ptm = localtime(&now); + struct tm atm; +#ifdef _WIN32 + localtime_s(&atm, &now); +#else + localtime_r(&now, &atm); +#endif char buffer[128]; - strftime(buffer, 128, ":%m-%d-%Y %H:%M:%S ", ptm); + strftime(buffer, 128, ":%m-%d-%Y %H:%M:%S ", &atm); nout << buffer; } diff --git a/dtool/src/prc/notifyCategory.h b/dtool/src/prc/notifyCategory.h index fe9a7255e6..343591d122 100644 --- a/dtool/src/prc/notifyCategory.h +++ b/dtool/src/prc/notifyCategory.h @@ -74,6 +74,7 @@ PUBLISHED: size_t get_num_children() const; NotifyCategory *get_child(size_t i) const; MAKE_SEQ(get_children, get_num_children, get_child); + MAKE_SEQ_PROPERTY(children, get_num_children, get_child); static void set_server_delta(long delta); diff --git a/dtool/src/prc/streamReader.I b/dtool/src/prc/streamReader.I index e02e3e9aec..8f96aa85f4 100644 --- a/dtool/src/prc/streamReader.I +++ b/dtool/src/prc/streamReader.I @@ -83,25 +83,25 @@ get_bool() { /** * Extracts a signed 8-bit integer. */ -INLINE PN_int8 StreamReader:: +INLINE int8_t StreamReader:: get_int8() { - return (PN_int8)_in->get(); + return (int8_t)_in->get(); } /** * Extracts an unsigned 8-bit integer. */ -INLINE PN_uint8 StreamReader:: +INLINE uint8_t StreamReader:: get_uint8() { - return (PN_uint8)_in->get(); + return (uint8_t)_in->get(); } /** * Extracts a signed 16-bit integer. */ -INLINE PN_int16 StreamReader:: +INLINE int16_t StreamReader:: get_int16() { - PN_int16 readval, retval; + int16_t readval, retval; _in->read((char *)&readval, sizeof(readval)); LittleEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); @@ -111,9 +111,9 @@ get_int16() { /** * Extracts a signed 32-bit integer. */ -INLINE PN_int32 StreamReader:: +INLINE int32_t StreamReader:: get_int32() { - PN_int32 readval, retval; + int32_t readval, retval; _in->read((char *)&readval, sizeof(readval)); LittleEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); @@ -123,9 +123,9 @@ get_int32() { /** * Extracts a signed 64-bit integer. */ -INLINE PN_int64 StreamReader:: +INLINE int64_t StreamReader:: get_int64() { - PN_int64 readval, retval; + int64_t readval, retval; _in->read((char *)&readval, sizeof(readval)); LittleEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); @@ -135,9 +135,9 @@ get_int64() { /** * Extracts an unsigned 16-bit integer. */ -INLINE PN_uint16 StreamReader:: +INLINE uint16_t StreamReader:: get_uint16() { - PN_uint16 readval, retval; + uint16_t readval, retval; _in->read((char *)&readval, sizeof(readval)); LittleEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); @@ -147,9 +147,9 @@ get_uint16() { /** * Extracts an unsigned 32-bit integer. */ -INLINE PN_uint32 StreamReader:: +INLINE uint32_t StreamReader:: get_uint32() { - PN_uint32 readval, retval; + uint32_t readval, retval; _in->read((char *)&readval, sizeof(readval)); LittleEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); @@ -159,9 +159,9 @@ get_uint32() { /** * Extracts an unsigned 64-bit integer. */ -INLINE PN_uint64 StreamReader:: +INLINE uint64_t StreamReader:: get_uint64() { - PN_uint64 readval, retval; + uint64_t readval, retval; _in->read((char *)&readval, sizeof(readval)); LittleEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); @@ -202,9 +202,9 @@ get_float64() { /** * Extracts a signed big-endian 16-bit integer. */ -INLINE PN_int16 StreamReader:: +INLINE int16_t StreamReader:: get_be_int16() { - PN_int16 readval, retval; + int16_t readval, retval; _in->read((char *)&readval, sizeof(readval)); BigEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); @@ -214,9 +214,9 @@ get_be_int16() { /** * Extracts a signed big-endian 32-bit integer. */ -INLINE PN_int32 StreamReader:: +INLINE int32_t StreamReader:: get_be_int32() { - PN_int32 readval, retval; + int32_t readval, retval; _in->read((char *)&readval, sizeof(readval)); BigEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); @@ -226,9 +226,9 @@ get_be_int32() { /** * Extracts a signed big-endian 64-bit integer. */ -INLINE PN_int64 StreamReader:: +INLINE int64_t StreamReader:: get_be_int64() { - PN_int64 readval, retval; + int64_t readval, retval; _in->read((char *)&readval, sizeof(readval)); BigEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); @@ -238,9 +238,9 @@ get_be_int64() { /** * Extracts an unsigned big-endian 16-bit integer. */ -INLINE PN_uint16 StreamReader:: +INLINE uint16_t StreamReader:: get_be_uint16() { - PN_uint16 readval, retval; + uint16_t readval, retval; _in->read((char *)&readval, sizeof(readval)); BigEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); @@ -250,9 +250,9 @@ get_be_uint16() { /** * Extracts an unsigned big-endian 32-bit integer. */ -INLINE PN_uint32 StreamReader:: +INLINE uint32_t StreamReader:: get_be_uint32() { - PN_uint32 readval, retval; + uint32_t readval, retval; _in->read((char *)&readval, sizeof(readval)); BigEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); @@ -262,9 +262,9 @@ get_be_uint32() { /** * Extracts an unsigned big-endian 64-bit integer. */ -INLINE PN_uint64 StreamReader:: +INLINE uint64_t StreamReader:: get_be_uint64() { - PN_uint64 readval, retval; + uint64_t readval, retval; _in->read((char *)&readval, sizeof(readval)); BigEndian s(&readval, 0, sizeof(readval)); s.store_value(&retval, sizeof(retval)); diff --git a/dtool/src/prc/streamReader.h b/dtool/src/prc/streamReader.h index f8f4678537..1c820253c1 100644 --- a/dtool/src/prc/streamReader.h +++ b/dtool/src/prc/streamReader.h @@ -34,26 +34,27 @@ PUBLISHED: INLINE ~StreamReader(); INLINE istream *get_istream() const; + MAKE_PROPERTY(istream, get_istream); BLOCKING INLINE bool get_bool(); - BLOCKING INLINE PN_int8 get_int8(); - BLOCKING INLINE PN_uint8 get_uint8(); + BLOCKING INLINE int8_t get_int8(); + BLOCKING INLINE uint8_t get_uint8(); - BLOCKING INLINE PN_int16 get_int16(); - BLOCKING INLINE PN_int32 get_int32(); - BLOCKING INLINE PN_int64 get_int64(); - BLOCKING INLINE PN_uint16 get_uint16(); - BLOCKING INLINE PN_uint32 get_uint32(); - BLOCKING INLINE PN_uint64 get_uint64(); + BLOCKING INLINE int16_t get_int16(); + BLOCKING INLINE int32_t get_int32(); + BLOCKING INLINE int64_t get_int64(); + BLOCKING INLINE uint16_t get_uint16(); + BLOCKING INLINE uint32_t get_uint32(); + BLOCKING INLINE uint64_t get_uint64(); BLOCKING INLINE float get_float32(); BLOCKING INLINE PN_float64 get_float64(); - BLOCKING INLINE PN_int16 get_be_int16(); - BLOCKING INLINE PN_int32 get_be_int32(); - BLOCKING INLINE PN_int64 get_be_int64(); - BLOCKING INLINE PN_uint16 get_be_uint16(); - BLOCKING INLINE PN_uint32 get_be_uint32(); - BLOCKING INLINE PN_uint64 get_be_uint64(); + BLOCKING INLINE int16_t get_be_int16(); + BLOCKING INLINE int32_t get_be_int32(); + BLOCKING INLINE int64_t get_be_int64(); + BLOCKING INLINE uint16_t get_be_uint16(); + BLOCKING INLINE uint32_t get_be_uint32(); + BLOCKING INLINE uint64_t get_be_uint64(); BLOCKING INLINE float get_be_float32(); BLOCKING INLINE PN_float64 get_be_float64(); diff --git a/dtool/src/prc/streamWrapper.h b/dtool/src/prc/streamWrapper.h index de25a4267d..97d391a894 100644 --- a/dtool/src/prc/streamWrapper.h +++ b/dtool/src/prc/streamWrapper.h @@ -53,6 +53,7 @@ PUBLISHED: ~IStreamWrapper(); INLINE istream *get_istream() const; + MAKE_PROPERTY(istream, get_istream); public: void read(char *buffer, streamsize num_bytes); @@ -79,6 +80,7 @@ PUBLISHED: ~OStreamWrapper(); INLINE ostream *get_ostream() const; + MAKE_PROPERTY(ostream, get_ostream); public: void write(const char *buffer, streamsize num_bytes); @@ -114,6 +116,7 @@ PUBLISHED: ~StreamWrapper(); INLINE iostream *get_iostream() const; + MAKE_PROPERTY(iostream, get_iostream); private: iostream *_iostream; diff --git a/dtool/src/prc/streamWriter.I b/dtool/src/prc/streamWriter.I index 9db035094f..8bbe23af62 100644 --- a/dtool/src/prc/streamWriter.I +++ b/dtool/src/prc/streamWriter.I @@ -92,7 +92,7 @@ add_bool(bool b) { * Adds a signed 8-bit integer to the stream. */ INLINE void StreamWriter:: -add_int8(PN_int8 value) { +add_int8(int8_t value) { append_data(&value, 1); } @@ -100,7 +100,7 @@ add_int8(PN_int8 value) { * Adds an unsigned 8-bit integer to the stream. */ INLINE void StreamWriter:: -add_uint8(PN_uint8 value) { +add_uint8(uint8_t value) { append_data(&value, 1); } @@ -108,7 +108,7 @@ add_uint8(PN_uint8 value) { * Adds a signed 16-bit integer to the stream. */ INLINE void StreamWriter:: -add_int16(PN_int16 value) { +add_int16(int16_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -117,7 +117,7 @@ add_int16(PN_int16 value) { * Adds a signed 32-bit integer to the stream. */ INLINE void StreamWriter:: -add_int32(PN_int32 value) { +add_int32(int32_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -126,7 +126,7 @@ add_int32(PN_int32 value) { * Adds a signed 64-bit integer to the stream. */ INLINE void StreamWriter:: -add_int64(PN_int64 value) { +add_int64(int64_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -135,7 +135,7 @@ add_int64(PN_int64 value) { * Adds an unsigned 16-bit integer to the stream. */ INLINE void StreamWriter:: -add_uint16(PN_uint16 value) { +add_uint16(uint16_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -144,7 +144,7 @@ add_uint16(PN_uint16 value) { * Adds an unsigned 32-bit integer to the stream. */ INLINE void StreamWriter:: -add_uint32(PN_uint32 value) { +add_uint32(uint32_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -153,7 +153,7 @@ add_uint32(PN_uint32 value) { * Adds an unsigned 64-bit integer to the stream. */ INLINE void StreamWriter:: -add_uint64(PN_uint64 value) { +add_uint64(uint64_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -186,7 +186,7 @@ add_float64(PN_float64 value) { * Adds a signed 16-bit big-endian integer to the streamWriter. */ INLINE void StreamWriter:: -add_be_int16(PN_int16 value) { +add_be_int16(int16_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -195,7 +195,7 @@ add_be_int16(PN_int16 value) { * Adds a signed 32-bit big-endian integer to the streamWriter. */ INLINE void StreamWriter:: -add_be_int32(PN_int32 value) { +add_be_int32(int32_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -204,7 +204,7 @@ add_be_int32(PN_int32 value) { * Adds a signed 64-bit big-endian integer to the streamWriter. */ INLINE void StreamWriter:: -add_be_int64(PN_int64 value) { +add_be_int64(int64_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -213,7 +213,7 @@ add_be_int64(PN_int64 value) { * Adds an unsigned 16-bit big-endian integer to the streamWriter. */ INLINE void StreamWriter:: -add_be_uint16(PN_uint16 value) { +add_be_uint16(uint16_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -222,7 +222,7 @@ add_be_uint16(PN_uint16 value) { * Adds an unsigned 32-bit big-endian integer to the streamWriter. */ INLINE void StreamWriter:: -add_be_uint32(PN_uint32 value) { +add_be_uint32(uint32_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -231,7 +231,7 @@ add_be_uint32(PN_uint32 value) { * Adds an unsigned 64-bit big-endian integer to the streamWriter. */ INLINE void StreamWriter:: -add_be_uint64(PN_uint64 value) { +add_be_uint64(uint64_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -267,10 +267,10 @@ add_be_float64(PN_float64 value) { INLINE void StreamWriter:: add_string(const string &str) { // The max sendable length for a string is 2^16. - nassertv(str.length() <= (PN_uint16)0xffff); + nassertv(str.length() <= (uint16_t)0xffff); // Strings always are preceded by their length - add_uint16((PN_uint16)str.length()); + add_uint16((uint16_t)str.length()); // Add the string append_data(str); @@ -282,7 +282,7 @@ add_string(const string &str) { INLINE void StreamWriter:: add_string32(const string &str) { // Strings always are preceded by their length - add_uint32((PN_uint32)str.length()); + add_uint32((uint32_t)str.length()); // Add the string append_data(str); diff --git a/dtool/src/prc/streamWriter.h b/dtool/src/prc/streamWriter.h index e21dc3cbed..2f04a9ab8d 100644 --- a/dtool/src/prc/streamWriter.h +++ b/dtool/src/prc/streamWriter.h @@ -36,28 +36,29 @@ PUBLISHED: INLINE ~StreamWriter(); INLINE ostream *get_ostream() const; + MAKE_PROPERTY(ostream, get_ostream); BLOCKING INLINE void add_bool(bool value); - BLOCKING INLINE void add_int8(PN_int8 value); - BLOCKING INLINE void add_uint8(PN_uint8 value); + BLOCKING INLINE void add_int8(int8_t value); + BLOCKING INLINE void add_uint8(uint8_t value); // The default numeric packing is little-endian. - BLOCKING INLINE void add_int16(PN_int16 value); - BLOCKING INLINE void add_int32(PN_int32 value); - BLOCKING INLINE void add_int64(PN_int64 value); - BLOCKING INLINE void add_uint16(PN_uint16 value); - BLOCKING INLINE void add_uint32(PN_uint32 value); - BLOCKING INLINE void add_uint64(PN_uint64 value); + BLOCKING INLINE void add_int16(int16_t value); + BLOCKING INLINE void add_int32(int32_t value); + BLOCKING INLINE void add_int64(int64_t value); + BLOCKING INLINE void add_uint16(uint16_t value); + BLOCKING INLINE void add_uint32(uint32_t value); + BLOCKING INLINE void add_uint64(uint64_t value); BLOCKING INLINE void add_float32(float value); BLOCKING INLINE void add_float64(PN_float64 value); // These functions pack numbers big-endian, in case that's desired. - BLOCKING INLINE void add_be_int16(PN_int16 value); - BLOCKING INLINE void add_be_int32(PN_int32 value); - BLOCKING INLINE void add_be_int64(PN_int64 value); - BLOCKING INLINE void add_be_uint16(PN_uint16 value); - BLOCKING INLINE void add_be_uint32(PN_uint32 value); - BLOCKING INLINE void add_be_uint64(PN_uint64 value); + BLOCKING INLINE void add_be_int16(int16_t value); + BLOCKING INLINE void add_be_int32(int32_t value); + BLOCKING INLINE void add_be_int64(int64_t value); + BLOCKING INLINE void add_be_uint16(uint16_t value); + BLOCKING INLINE void add_be_uint32(uint32_t value); + BLOCKING INLINE void add_be_uint64(uint64_t value); BLOCKING INLINE void add_be_float32(float value); BLOCKING INLINE void add_be_float64(PN_float64 value); diff --git a/makepanda/installer.nsi b/makepanda/installer.nsi index c5e0df0e5f..e5fcf2164c 100755 --- a/makepanda/installer.nsi +++ b/makepanda/installer.nsi @@ -15,7 +15,6 @@ ; BUILT - location of panda install tree. ; SOURCE - location of the panda source-tree if available, OR location of panda install tree. ; PYVER - version of Python that Panda was built with (ie, "2.7") -; PYEXTRAS - directory containing python extras, if any. ; REGVIEW - either 32 or 64, depending on the build architecture. ; @@ -372,11 +371,6 @@ SectionGroup "Python support" SetOutPath "$INSTDIR\python" File /r "${BUILT}\python\*" - !ifdef PYEXTRAS - SetOutPath "$INSTDIR\python\lib" - File /nonfatal /r "${PYEXTRAS}\*" - !endif - SetDetailsPrint both DetailPrint "Adding registry keys for Python..." SetDetailsPrint listonly diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 9c5b247185..b3026f1167 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -46,7 +46,7 @@ CFLAGS="" CXXFLAGS="" LDFLAGS="" RTDIST=0 -RTDIST_VERSION="dev" +RTDIST_VERSION=None RUNTIME=0 DISTRIBUTOR="" VERSION=None @@ -78,7 +78,7 @@ PkgListSet(["PYTHON", "DIRECT", # Python support "VORBIS", "FFMPEG", "SWSCALE", "SWRESAMPLE", # Audio decoding "ODE", "PHYSX", "BULLET", "PANDAPHYSICS", # Physics "SPEEDTREE", # SpeedTree - "ZLIB", "PNG", "JPEG", "TIFF", "SQUISH", "FREETYPE", # 2D Formats support + "ZLIB", "PNG", "JPEG", "TIFF", "OPENEXR", "SQUISH", "FREETYPE", # 2D Formats support ] + MAYAVERSIONS + MAXVERSIONS + [ "FCOLLADA", "ASSIMP", # 3D Formats support "VRPN", "OPENSSL", # Transport "FFTW", # Algorithm helpers @@ -162,13 +162,13 @@ def usage(problem): def parseopts(args): global INSTALLER,RTDIST,RUNTIME,GENMAN,DISTRIBUTOR,VERSION global COMPRESSOR,THREADCOUNT,OSXTARGET,OSX_ARCHS,HOST_URL - global DEBVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX + global DEBVERSION,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", "version=","lzma","no-python","threads=","outputdir=","override=", - "static","host=","debversion=","rpmrelease=","p3dsuffix=", + "static","host=","debversion=","rpmrelease=","p3dsuffix=","rtdist-version=", "directx-sdk=", "windows-sdk=", "msvc-version=", "clean", "use-icl", "universal", "target=", "arch=", "git-commit="] anything = 0 @@ -213,6 +213,7 @@ def parseopts(args): elif (option=="--rpmrelease"): RPMRELEASE=value elif (option=="--git-commit"): GIT_COMMIT=value elif (option=="--p3dsuffix"): P3DSUFFIX=value + elif (option=="--rtdist-version"): RTDIST_VERSION=value # Backward compatibility, OPENGL was renamed to GL elif (option=="--use-opengl"): PkgEnable("GL") elif (option=="--no-opengl"): PkgDisable("GL") @@ -399,9 +400,12 @@ if (RUNTIME or RTDIST): if DISTRIBUTOR == "": DISTRIBUTOR = "makepanda" -else: +elif not RTDIST_VERSION: RTDIST_VERSION = DISTRIBUTOR.strip() + "_" + MAJOR_VERSION +if not RTDIST_VERSION: + RTDIST_VERSION = "dev" + if not IsCustomOutputDir(): if GetTarget() == "windows" and GetTargetArch() == 'x64': outputdir_suffix += '_x64' @@ -561,6 +565,10 @@ if (COMPILER == "MSVC"): LibName(pkg, 'dxerrVNUM.lib'.replace("VNUM", vnum)) #LibName(pkg, 'ddraw.lib') LibName(pkg, 'dxguid.lib') + + if not PkgSkip("FREETYPE") and os.path.isdir(GetThirdpartyDir() + "freetype/include/freetype2"): + IncDirectory("FREETYPE", GetThirdpartyDir() + "freetype/include/freetype2") + IncDirectory("ALWAYS", GetThirdpartyDir() + "extras/include") LibName("WINSOCK", "wsock32.lib") LibName("WINSOCK2", "wsock32.lib") @@ -588,22 +596,43 @@ if (COMPILER == "MSVC"): if (PkgSkip("DIRECTCAM")==0): LibName("DIRECTCAM", "quartz.lib") if (PkgSkip("DIRECTCAM")==0): LibName("DIRECTCAM", "odbc32.lib") if (PkgSkip("DIRECTCAM")==0): LibName("DIRECTCAM", "odbccp32.lib") - if (PkgSkip("PNG")==0): LibName("PNG", GetThirdpartyDir() + "png/lib/libpng_static.lib") + if (PkgSkip("OPENSSL")==0): + if os.path.isfile(GetThirdpartyDir() + "openssl/lib/libpandassl.lib"): + LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libpandassl.lib") + LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libpandaeay.lib") + else: + LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libeay32.lib") + LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/ssleay32.lib") + if (PkgSkip("PNG")==0): + if os.path.isfile(GetThirdpartyDir() + "png/lib/libpng16_static.lib"): + LibName("PNG", GetThirdpartyDir() + "png/lib/libpng16_static.lib") + else: + LibName("PNG", GetThirdpartyDir() + "png/lib/libpng_static.lib") + if (PkgSkip("TIFF")==0): + if os.path.isfile(GetThirdpartyDir() + "tiff/lib/libtiff.lib"): + LibName("TIFF", GetThirdpartyDir() + "tiff/lib/libtiff.lib") + else: + LibName("TIFF", GetThirdpartyDir() + "tiff/lib/tiff.lib") + if (PkgSkip("OPENEXR")==0): + suffix = "" + if os.path.isfile(GetThirdpartyDir() + "openexr/lib/IlmImf-2_2.lib"): + suffix = "-2_2" + LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/IlmImf" + suffix + ".lib") + LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/IlmThread" + suffix + ".lib") + LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Iex" + suffix + ".lib") + LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Half.lib") + IncDirectory("OPENEXR", GetThirdpartyDir() + "openexr/include/OpenEXR") if (PkgSkip("JPEG")==0): LibName("JPEG", GetThirdpartyDir() + "jpeg/lib/jpeg-static.lib") - if (PkgSkip("TIFF")==0): LibName("TIFF", GetThirdpartyDir() + "tiff/lib/libtiff.lib") if (PkgSkip("ZLIB")==0): LibName("ZLIB", GetThirdpartyDir() + "zlib/lib/zlibstatic.lib") if (PkgSkip("VRPN")==0): LibName("VRPN", GetThirdpartyDir() + "vrpn/lib/vrpn.lib") if (PkgSkip("VRPN")==0): LibName("VRPN", GetThirdpartyDir() + "vrpn/lib/quat.lib") if (PkgSkip("NVIDIACG")==0): LibName("CGGL", GetThirdpartyDir() + "nvidiacg/lib/cgGL.lib") if (PkgSkip("NVIDIACG")==0): LibName("CGDX9", GetThirdpartyDir() + "nvidiacg/lib/cgD3D9.lib") if (PkgSkip("NVIDIACG")==0): LibName("NVIDIACG", GetThirdpartyDir() + "nvidiacg/lib/cg.lib") - if (PkgSkip("OPENSSL")==0): LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libpandassl.lib") - if (PkgSkip("OPENSSL")==0): LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libpandaeay.lib") if (PkgSkip("FREETYPE")==0): LibName("FREETYPE", GetThirdpartyDir() + "freetype/lib/freetype.lib") if (PkgSkip("FFTW")==0): LibName("FFTW", GetThirdpartyDir() + "fftw/lib/rfftw.lib") if (PkgSkip("FFTW")==0): LibName("FFTW", GetThirdpartyDir() + "fftw/lib/fftw.lib") if (PkgSkip("ARTOOLKIT")==0):LibName("ARTOOLKIT",GetThirdpartyDir() + "artoolkit/lib/libAR.lib") - if (PkgSkip("FCOLLADA")==0): LibName("FCOLLADA", GetThirdpartyDir() + "fcollada/lib/FCollada.lib") if (PkgSkip("ASSIMP")==0): PkgDisable("ASSIMP") # Not yet supported if (PkgSkip("OPENCV")==0): LibName("OPENCV", GetThirdpartyDir() + "opencv/lib/cv.lib") if (PkgSkip("OPENCV")==0): LibName("OPENCV", GetThirdpartyDir() + "opencv/lib/highgui.lib") @@ -616,6 +645,9 @@ if (COMPILER == "MSVC"): if (PkgSkip("FFMPEG")==0): LibName("FFMPEG", GetThirdpartyDir() + "ffmpeg/lib/avutil.lib") if (PkgSkip("SWSCALE")==0): LibName("SWSCALE", GetThirdpartyDir() + "ffmpeg/lib/swscale.lib") if (PkgSkip("SWRESAMPLE")==0):LibName("SWRESAMPLE",GetThirdpartyDir() + "ffmpeg/lib/swresample.lib") + if (PkgSkip("FCOLLADA")==0): + LibName("FCOLLADA", GetThirdpartyDir() + "fcollada/lib/FCollada.lib") + IncDirectory("FCOLLADA", GetThirdpartyDir() + "fcollada/include/FCollada") if (PkgSkip("SQUISH")==0): if GetOptimize() <= 2: LibName("SQUISH", GetThirdpartyDir() + "squish/lib/squishd.lib") @@ -628,7 +660,11 @@ if (COMPILER == "MSVC"): LibName("ROCKET", GetThirdpartyDir() + "rocket/lib/" + SDK["PYTHONVERSION"] + "/boost_python-vc100-mt-1_54.lib") if (GetOptimize() <= 3): LibName("ROCKET", GetThirdpartyDir() + "rocket/lib/RocketDebugger.lib") - if (PkgSkip("OPENAL")==0): LibName("OPENAL", GetThirdpartyDir() + "openal/lib/OpenAL32.lib") + if (PkgSkip("OPENAL")==0): + LibName("OPENAL", GetThirdpartyDir() + "openal/lib/OpenAL32.lib") + if not os.path.isfile(GetThirdpartyDir() + "openal/bin/OpenAL32.dll"): + # Link OpenAL Soft statically. + DefSymbol("OPENAL", "AL_LIBTYPE_STATIC") if (PkgSkip("ODE")==0): LibName("ODE", GetThirdpartyDir() + "ode/lib/ode_single.lib") DefSymbol("ODE", "dSINGLE", "") @@ -704,7 +740,7 @@ if (COMPILER == "MSVC"): IncDirectory("SPEEDTREE", SDK["SPEEDTREE"] + "/Include") if (PkgSkip("BULLET")==0): suffix = '.lib' - if GetTargetArch() == 'x64': + if GetTargetArch() == 'x64' and os.path.isfile(GetThirdpartyDir() + "bullet/lib/BulletCollision_x64.lib"): suffix = '_x64.lib' LibName("BULLET", GetThirdpartyDir() + "bullet/lib/LinearMath" + suffix) LibName("BULLET", GetThirdpartyDir() + "bullet/lib/BulletCollision" + suffix) @@ -751,9 +787,9 @@ if (COMPILER=="GCC"): SmartPkgEnable("ARTOOLKIT", "", ("AR"), "AR/ar.h") SmartPkgEnable("FCOLLADA", "", ChooseLib(fcollada_libs, "FCOLLADA"), ("FCollada", "FCollada/FCollada.h")) SmartPkgEnable("ASSIMP", "assimp", ("assimp"), "assimp") - SmartPkgEnable("FFMPEG", ffmpeg_libs, ffmpeg_libs, ffmpeg_libs) - SmartPkgEnable("SWSCALE", "libswscale", "libswscale", ("libswscale", "libswscale/swscale.h"), target_pkg = "FFMPEG") - SmartPkgEnable("SWRESAMPLE","libswresample", "libswresample", ("libswresample", "libswresample/swresample.h"), target_pkg = "FFMPEG") + SmartPkgEnable("FFMPEG", ffmpeg_libs, ffmpeg_libs, ("libavformat/avformat.h", "libavcodec/avcodec.h", "libavutil/avutil.h")) + SmartPkgEnable("SWSCALE", "libswscale", "libswscale", ("libswscale/swscale.h"), target_pkg = "FFMPEG", thirdparty_dir = "ffmpeg") + SmartPkgEnable("SWRESAMPLE","libswresample", "libswresample", ("libswresample/swresample.h"), target_pkg = "FFMPEG", thirdparty_dir = "ffmpeg") SmartPkgEnable("FFTW", "", ("rfftw", "fftw"), ("fftw.h", "rfftw.h")) SmartPkgEnable("FMODEX", "", ("fmodex"), ("fmodex", "fmodex/fmod.h")) SmartPkgEnable("FREETYPE", "freetype2", ("freetype"), ("freetype2", "freetype2/freetype/freetype.h")) @@ -766,6 +802,7 @@ if (COMPILER=="GCC"): SmartPkgEnable("OPENAL", "openal", ("openal"), "AL/al.h", framework = "OpenAL") SmartPkgEnable("SQUISH", "", ("squish"), "squish.h") SmartPkgEnable("TIFF", "libtiff-4", ("tiff"), "tiff.h") + SmartPkgEnable("OPENEXR", "OpenEXR", ("IlmImf", "Imath", "Half", "Iex", "IexMath", "IlmThread"), ("OpenEXR", "OpenEXR/ImfOutputFile.h")) SmartPkgEnable("VRPN", "", ("vrpn", "quat"), ("vrpn", "quat.h", "vrpn/vrpn_Types.h")) SmartPkgEnable("BULLET", "bullet", ("BulletSoftBody", "BulletDynamics", "BulletCollision", "LinearMath"), ("bullet", "bullet/btBulletDynamicsCommon.h")) SmartPkgEnable("VORBIS", "vorbisfile",("vorbisfile", "vorbis", "ogg"), ("ogg/ogg.h", "vorbis/vorbisfile.h")) @@ -1020,7 +1057,7 @@ def CompileCxx(obj,src,opts): cmd = "cl " if GetTargetArch() == 'x64': cmd += "/favor:blend " - cmd += "/wd4996 /wd4275 /wd4267 /wd4101 /wd4273 " + cmd += "/wd4996 /wd4275 /wd4273 " # Enable Windows 7 interfaces if we need Touchinput. if PkgSkip("TOUCHINPUT") == 0: @@ -2171,7 +2208,7 @@ DTOOL_CONFIG=[ ("PHAVE_DIRENT_H", 'UNDEF', '1'), ("PHAVE_SYS_SOUNDCARD_H", 'UNDEF', '1'), ("PHAVE_UCONTEXT_H", 'UNDEF', '1'), - ("PHAVE_STDINT_H", 'UNDEF', '1'), + ("PHAVE_STDINT_H", '1', '1'), ("HAVE_RTTI", '1', '1'), ("HAVE_X11", 'UNDEF', '1'), ("HAVE_XRANDR", 'UNDEF', '1'), @@ -2189,12 +2226,14 @@ DTOOL_CONFIG=[ ("PHAVE_JPEGINT_H", '1', '1'), ("HAVE_VIDEO4LINUX", 'UNDEF', '1'), ("HAVE_TIFF", 'UNDEF', 'UNDEF'), + ("HAVE_OPENEXR", 'UNDEF', 'UNDEF'), ("HAVE_SGI_RGB", '1', '1'), ("HAVE_TGA", '1', '1'), ("HAVE_IMG", '1', '1'), ("HAVE_SOFTIMAGE_PIC", '1', '1'), ("HAVE_BMP", '1', '1'), ("HAVE_PNM", '1', '1'), + ("HAVE_STB_IMAGE", '1', '1'), ("HAVE_VORBIS", 'UNDEF', 'UNDEF'), ("HAVE_NVIDIACG", 'UNDEF', 'UNDEF'), ("HAVE_FREETYPE", 'UNDEF', 'UNDEF'), @@ -3408,8 +3447,7 @@ if (not RUNTIME): TargetAdd('libp3putil.in', opts=OPTS, input=IGATEFILES) TargetAdd('libp3putil.in', opts=['IMOD:panda3d.core', 'ILIB:libp3putil', 'SRCDIR:panda/src/putil']) TargetAdd('libp3putil_igate.obj', input='libp3putil.in', opts=["DEPENDENCYONLY"]) - TargetAdd('p3putil_typedWritable_ext.obj', opts=OPTS, input='typedWritable_ext.cxx') - TargetAdd('p3putil_pythonCallbackObject.obj', opts=OPTS, input='pythonCallbackObject.cxx') + TargetAdd('p3putil_ext_composite.obj', opts=OPTS, input='p3putil_ext_composite.cxx') # # DIRECTORY: panda/src/audio/ @@ -3812,7 +3850,7 @@ if (not RUNTIME): # if (not RUNTIME): - OPTS=['DIR:panda/src/pnmimagetypes', 'DIR:panda/src/pnmimage', 'BUILDING:PANDA', 'PNG', 'ZLIB', 'JPEG', 'TIFF'] + OPTS=['DIR:panda/src/pnmimagetypes', 'DIR:panda/src/pnmimage', 'BUILDING:PANDA', 'PNG', 'ZLIB', 'JPEG', 'TIFF', 'OPENEXR', 'EXCEPTIONS'] TargetAdd('p3pnmimagetypes_composite1.obj', opts=OPTS, input='p3pnmimagetypes_composite1.cxx') TargetAdd('p3pnmimagetypes_composite2.obj', opts=OPTS, input='p3pnmimagetypes_composite2.cxx') @@ -3856,9 +3894,9 @@ if (not RUNTIME): # if (not RUNTIME): - OPTS=['DIR:panda/metalibs/panda', 'BUILDING:PANDA', 'JPEG', 'PNG', 'TIFF', - 'ZLIB', 'OPENSSL', 'FREETYPE', 'FFTW', 'ADVAPI', 'WINSOCK2', 'SETUPAPI', - 'SQUISH', 'NVIDIACG', 'VORBIS', 'WINUSER', 'WINMM', 'WINGDI', 'IPHLPAPI'] + OPTS=['DIR:panda/metalibs/panda', 'BUILDING:PANDA', 'JPEG', 'PNG', + 'TIFF', 'OPENEXR', 'ZLIB', 'OPENSSL', 'FREETYPE', 'FFTW', 'ADVAPI', 'WINSOCK2', + 'SQUISH', 'NVIDIACG', 'VORBIS', 'WINUSER', 'WINMM', 'WINGDI', 'IPHLPAPI', 'SETUPAPI'] TargetAdd('panda_panda.obj', opts=OPTS, input='panda.cxx') @@ -4010,8 +4048,7 @@ if (not RUNTIME): if PkgSkip("FREETYPE")==0: TargetAdd('core.pyd', input="libp3pnmtext_igate.obj") - TargetAdd('core.pyd', input='p3putil_typedWritable_ext.obj') - TargetAdd('core.pyd', input='p3putil_pythonCallbackObject.obj') + TargetAdd('core.pyd', input='p3putil_ext_composite.obj') TargetAdd('core.pyd', input='p3pnmimage_pfmFile_ext.obj') TargetAdd('core.pyd', input='p3event_pythonTask.obj') TargetAdd('core.pyd', input='p3gobj_ext_composite.obj') @@ -4021,7 +4058,8 @@ if (not RUNTIME): TargetAdd('core.pyd', input='p3display_pythonGraphicsWindowProc.obj') TargetAdd('core.pyd', input='core_module.obj') - TargetAdd('core.pyd', input='libp3tinyxml.ilb') + if not GetLinkAllStatic() and GetTarget() != 'emscripten': + TargetAdd('core.pyd', input='libp3tinyxml.ilb') TargetAdd('core.pyd', input='libp3interrogatedb.dll') TargetAdd('core.pyd', input=COMMON_PANDA_LIBS) TargetAdd('core.pyd', opts=['PYTHON', 'WINSOCK2']) @@ -4241,7 +4279,7 @@ if PkgSkip("OPENAL") == 0 and not RUNTIME: TargetAdd('openal_audio_openal_audio_composite1.obj', opts=OPTS, input='openal_audio_composite1.cxx') TargetAdd('libp3openal_audio.dll', input='openal_audio_openal_audio_composite1.obj') TargetAdd('libp3openal_audio.dll', input=COMMON_PANDA_LIBS) - TargetAdd('libp3openal_audio.dll', opts=['MODULE', 'ADVAPI', 'WINUSER', 'WINMM', 'OPENAL']) + TargetAdd('libp3openal_audio.dll', opts=['MODULE', 'ADVAPI', 'WINUSER', 'WINMM', 'WINSHELL', 'WINOLE', 'OPENAL']) # # DIRECTORY: panda/src/downloadertools/ @@ -6511,7 +6549,6 @@ def MakeInstallerNSIS(file, title, installdir): 'BUILT' : panda, 'SOURCE' : psource, 'PYVER' : SDK["PYTHONVERSION"][6:9], - 'PYEXTRAS' : os.path.join(os.path.abspath(GetThirdpartyBase()), 'win-extras'), 'REGVIEW' : regview, } @@ -6888,8 +6925,8 @@ def MakeInstallerOSX(): oscmd("cp -R %s/pandac dstroot/pythoncode/Developer/Panda3D/pandac" % GetOutputDir()) oscmd("cp -R %s/direct dstroot/pythoncode/Developer/Panda3D/direct" % GetOutputDir()) oscmd("ln -s %s dstroot/pythoncode/usr/local/bin/ppython" % SDK["PYTHONEXEC"]) - oscmd("cp -R %s/*.so dstroot/pythoncode/Developer/Panda3D/" % GetOutputDir()) - oscmd("cp -R %s/*.py dstroot/pythoncode/Developer/Panda3D/" % GetOutputDir()) + oscmd("cp -R %s/*.so dstroot/pythoncode/Developer/Panda3D/" % GetOutputDir(), True) + oscmd("cp -R %s/*.py dstroot/pythoncode/Developer/Panda3D/" % GetOutputDir(), True) if os.path.isdir(GetOutputDir()+"/Pmw"): oscmd("cp -R %s/Pmw dstroot/pythoncode/Developer/Panda3D/Pmw" % GetOutputDir()) compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/Pmw") diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 05b6053053..9321a79060 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -16,10 +16,10 @@ else: import cPickle as pickle import thread -SUFFIX_INC = [".cxx",".c",".h",".I",".yxx",".lxx",".mm",".rc",".r"] +SUFFIX_INC = [".cxx",".cpp",".c",".h",".I",".yxx",".lxx",".mm",".rc",".r"] SUFFIX_DLL = [".dll",".dlo",".dle",".dli",".dlm",".mll",".exe",".pyd",".ocx"] SUFFIX_LIB = [".lib",".ilb"] -VCS_DIRS = set(["CVS", "CVSROOT", ".git", ".hg"]) +VCS_DIRS = set(["CVS", "CVSROOT", ".git", ".hg", "__pycache__"]) VCS_FILES = set([".cvsignore", ".gitignore", ".gitmodules", ".hgignore"]) STARTTIME = time.time() MAINTHREAD = threading.currentThread() @@ -76,6 +76,7 @@ MAYAVERSIONINFO = [("MAYA6", "6.0"), ("MAYA2014","2014"), ("MAYA2015","2015"), ("MAYA2016","2016"), + ("MAYA20165","2016.5") ] MAXVERSIONINFO = [("MAX6", "SOFTWARE\\Autodesk\\3DSMAX\\6.0", "installdir", "maxsdk\\cssdk\\include"), @@ -1122,12 +1123,12 @@ def GetThirdpartyDir(): target_arch = GetTargetArch() if (target == 'windows'): + vc = SDK["VISUALSTUDIO_VERSION"].split('.')[0] + if target_arch == 'x64': - THIRDPARTYDIR = base + "/win-libs-vc10-x64/" - if not os.path.isdir(THIRDPARTYDIR): - THIRDPARTYDIR = base + "/win-libs-vc10/" + THIRDPARTYDIR = base + "/win-libs-vc" + vc + "-x64/" else: - THIRDPARTYDIR = base + "/win-libs-vc10/" + THIRDPARTYDIR = base + "/win-libs-vc" + vc + "/" elif (target == 'darwin'): # OSX thirdparty binaries are universal, where possible. @@ -1392,7 +1393,12 @@ def PkgConfigGetDefSymbols(pkgname, tool = "pkg-config"): for l in result.split(" "): if (l.startswith("-D")): d = l.replace("-D", "").replace("\"", "").strip().split("=") - if (len(d) == 1): + + if d[0] in ('NDEBUG', '_DEBUG'): + # Setting one of these flags by accident could cause serious harm. + if GetVerbose(): + print("Ignoring %s flag provided by %s" % (l, tool)) + elif len(d) == 1: defs[d[0]] = "" else: defs[d[0]] = d[1] @@ -1409,10 +1415,16 @@ def PkgConfigEnable(opt, pkgname, tool = "pkg-config"): for i, j in PkgConfigGetDefSymbols(pkgname, tool).items(): DefSymbol(opt, i, j) -def LocateLibrary(lib, lpath=[]): - """ Returns True if this library was found in the given search path, False otherwise. """ +def LocateLibrary(lib, lpath=[], prefer_static=False): + """Searches for the library in the search path, returning its path if found, + or None if it was not found.""" target = GetTarget() + if prefer_static and target != 'windows': + for dir in lpath: + if os.path.isfile(os.path.join(dir, 'lib%s.a' % lib)): + return os.path.join(dir, 'lib%s.a' % lib) + for dir in lpath: if target == 'darwin' and os.path.isfile(os.path.join(dir, 'lib%s.dylib' % lib)): return os.path.join(dir, 'lib%s.dylib' % lib) @@ -1446,7 +1458,7 @@ def ChooseLib(libs, thirdparty=None): print(ColorText("cyan", "Couldn't find any of the libraries " + ", ".join(libs))) return libs[0] -def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, framework = None, target_pkg = None, tool = "pkg-config"): +def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, framework = None, target_pkg = None, tool = "pkg-config", thirdparty_dir = None): global PKG_LIST_ALL if (pkg in PkgListGet() and PkgSkip(pkg)): return @@ -1476,15 +1488,12 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, custom_loc = PkgHasCustomLocation(pkg) - if pkg.lower() == "swscale" and os.path.isfile(GetThirdpartyDir() + "ffmpeg/include/libswscale/swscale.h"): - # Let it be handled by the ffmpeg package - LibName(target_pkg, "-lswscale") - return - if pkg.lower() == "swresample" and os.path.isfile(GetThirdpartyDir() + "ffmpeg/include/libswresample/swresample.h"): - LibName(target_pkg, "-lswresample") - return + # Determine the location of the thirdparty directory. + if not thirdparty_dir: + thirdparty_dir = pkg.lower() + pkg_dir = os.path.join(GetThirdpartyDir(), thirdparty_dir) - pkg_dir = os.path.join(GetThirdpartyDir(), pkg.lower()) + # First check if the library can be found in the thirdparty directory. if not custom_loc and os.path.isdir(pkg_dir): if framework and os.path.isdir(os.path.join(pkg_dir, framework + ".framework")): FrameworkDirectory(target_pkg, pkg_dir) @@ -1494,32 +1503,60 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, if os.path.isdir(os.path.join(pkg_dir, "include")): IncDirectory(target_pkg, os.path.join(pkg_dir, "include")) - if os.path.isdir(os.path.join(pkg_dir, "lib")): - LibDirectory(target_pkg, os.path.join(pkg_dir, "lib")) + # Handle cases like freetype2 where the include dir is a subdir under "include" + for i in incs: + if os.path.isdir(os.path.join(pkg_dir, "include", i)): + IncDirectory(target_pkg, os.path.join(pkg_dir, "include", i)) - if (PkgSkip("PYTHON") == 0): + lpath = [os.path.join(pkg_dir, "lib")] + + if not PkgSkip("PYTHON"): py_lib_dir = os.path.join(pkg_dir, "lib", SDK["PYTHONVERSION"]) if os.path.isdir(py_lib_dir): - LibDirectory(target_pkg, py_lib_dir) + lpath.append(py_lib_dir) - # TODO: check for a .pc file in the lib/pkg-config/ dir + # TODO: check for a .pc file in the lib/pkgconfig/ dir if (tool != None and os.path.isfile(os.path.join(pkg_dir, "bin", tool))): tool = os.path.join(pkg_dir, "bin", tool) for i in PkgConfigGetLibs(None, tool): - LibName(target_pkg, i) + if i.startswith('-l'): + # To make sure we don't pick up the system copy, write out + # the full path instead. + libname = i[2:] + location = LocateLibrary(libname, lpath, prefer_static=True) + if location is not None: + LibName(target_pkg, location) + else: + print(GetColor("cyan") + "Couldn't find library lib" + libname + " in thirdparty directory " + pkg.lower() + GetColor()) + LibName(target_pkg, i) + else: + LibName(target_pkg, i) for i, j in PkgConfigGetDefSymbols(None, tool).items(): DefSymbol(target_pkg, i, j) return + # Now search for the libraries in the package's lib directories. for l in libs: libname = l if l.startswith("lib"): libname = l[3:] - # This is for backward compatibility - in the thirdparty dir, we kept some libs with "panda" prefix, like libpandatiff. - if len(glob.glob(os.path.join(pkg_dir, "lib", "libpanda%s.*" % (libname)))) > 0 \ - and len(glob.glob(os.path.join(pkg_dir, "lib", "lib%s.*" % (libname)))) == 0: - libname = "panda" + libname - LibName(target_pkg, "-l" + libname) + + location = LocateLibrary(libname, lpath, prefer_static=True) + if location is not None: + # If it's a .so or .dylib we may have changed it and copied it to the built/lib dir. + if location.endswith('.so') or location.endswith('.dylib'): + location = os.path.join(GetOutputDir(), "lib", os.path.basename(location)) + LibName(target_pkg, location) + else: + # This is for backward compatibility - in the thirdparty dir, + # we kept some libs with "panda" prefix, like libpandatiff. + location = LocateLibrary("panda" + libname, lpath, prefer_static=True) + if location is not None: + if location.endswith('.so') or location.endswith('.dylib'): + location = os.path.join(GetOutputDir(), "lib", os.path.basename(location)) + LibName(target_pkg, location) + else: + print(GetColor("cyan") + "Couldn't find library lib" + libname + " in thirdparty directory " + pkg.lower() + GetColor()) for d, v in defs.values(): DefSymbol(target_pkg, d, v) @@ -2274,7 +2311,7 @@ def SetupVisualStudioEnviron(): binpath = SDK["VISUALSTUDIO"] + "VC\\bin\\" + bindir if not os.path.isdir(binpath): - exit("Couldn't find compilers in %s. You may need to install the Windows SDK 7.1 and the Visual C++ 2010 SP1 Compiler Update for Windows SDK 7.1.") + exit("Couldn't find compilers in %s. You may need to install the Windows SDK 7.1 and the Visual C++ 2010 SP1 Compiler Update for Windows SDK 7.1." % binpath) AddToPathEnv("PATH", binpath) AddToPathEnv("PATH", SDK["VISUALSTUDIO"] + "Common7\\IDE") @@ -2287,8 +2324,8 @@ def SetupVisualStudioEnviron(): AddToPathEnv("PATH", SDK["MSPLATFORM"] + "bin\\" + arch) # Windows Kit 10 introduces the "universal CRT". - inc_dir = SDK["MSPLATFORM"] + "Include\\10.0.10240.0\\" - lib_dir = SDK["MSPLATFORM"] + "Lib\\10.0.10240.0\\" + inc_dir = SDK["MSPLATFORM"] + "Include\\10.0.10586.0\\" + lib_dir = SDK["MSPLATFORM"] + "Lib\\10.0.10586.0\\" AddToPathEnv("INCLUDE", inc_dir + "shared") AddToPathEnv("INCLUDE", inc_dir + "ucrt") AddToPathEnv("INCLUDE", inc_dir + "um") @@ -2821,6 +2858,17 @@ def GetOrigExt(x): def SetOrigExt(x, v): ORIG_EXT[x] = v +def GetExtensionSuffix(): + if sys.version_info >= (3, 0): + suffix = sysconfig.get_config_var('EXT_SUFFIX') + if suffix: + return suffix + target = GetTarget() + if target == 'windows': + return '.pyd' + else: + return '.so' + def CalcLocation(fn, ipath): if fn.startswith("panda3d/") and fn.endswith(".py"): return OUTPUTDIR + "/" + fn @@ -2842,6 +2890,7 @@ def CalcLocation(fn, ipath): if (fn.endswith(".xml")): return CxxFindSource(fn, ipath) if (fn.endswith(".egg")): return OUTPUTDIR+"/models/"+fn if (fn.endswith(".egg.pz")):return OUTPUTDIR+"/models/"+fn + if (fn.endswith(".pyd")): return OUTPUTDIR+"/panda3d/"+fn[:-4]+GetExtensionSuffix() if (target == 'windows'): if (fn.endswith(".def")): return CxxFindSource(fn, ipath) if (fn.endswith(".rc")): return CxxFindSource(fn, ipath) @@ -2850,7 +2899,6 @@ def CalcLocation(fn, ipath): if (fn.endswith(".res")): return OUTPUTDIR+"/tmp/"+fn if (fn.endswith(".tlb")): return OUTPUTDIR+"/tmp/"+fn if (fn.endswith(".dll")): return OUTPUTDIR+"/bin/"+fn[:-4]+dllext+".dll" - if (fn.endswith(".pyd")): return OUTPUTDIR+"/panda3d/"+fn[:-4]+".pyd" if (fn.endswith(".ocx")): return OUTPUTDIR+"/plugins/"+fn[:-4]+dllext+".ocx" if (fn.endswith(".mll")): return OUTPUTDIR+"/plugins/"+fn[:-4]+dllext+".mll" if (fn.endswith(".dlo")): return OUTPUTDIR+"/plugins/"+fn[:-4]+dllext+".dlo" @@ -2867,7 +2915,6 @@ def CalcLocation(fn, ipath): if (fn.endswith(".plist")): return CxxFindSource(fn, ipath) if (fn.endswith(".obj")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".o" if (fn.endswith(".dll")): return OUTPUTDIR+"/lib/"+fn[:-4]+".dylib" - if (fn.endswith(".pyd")): return OUTPUTDIR+"/panda3d/"+fn[:-4]+".so" if (fn.endswith(".mll")): return OUTPUTDIR+"/plugins/"+fn if (fn.endswith(".exe")): return OUTPUTDIR+"/bin/"+fn[:-4] if (fn.endswith(".p3d")): return OUTPUTDIR+"/bin/"+fn[:-4] @@ -2880,7 +2927,6 @@ def CalcLocation(fn, ipath): # On Android, we build the libraries into built/tmp, then copy them. if (fn.endswith(".obj")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".o" if (fn.endswith(".dll")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".so" - if (fn.endswith(".pyd")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".so" if (fn.endswith(".mll")): return OUTPUTDIR+"/plugins/"+fn if (fn.endswith(".plugin")):return OUTPUTDIR+"/plugins/"+fn[:-7]+dllext+".so" if (fn.endswith(".exe")): return OUTPUTDIR+"/tmp/lib"+fn[:-4]+".so" @@ -2889,7 +2935,6 @@ def CalcLocation(fn, ipath): else: if (fn.endswith(".obj")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".o" if (fn.endswith(".dll")): return OUTPUTDIR+"/lib/"+fn[:-4]+".so" - if (fn.endswith(".pyd")): return OUTPUTDIR+"/panda3d/"+fn[:-4]+".so" if (fn.endswith(".mll")): return OUTPUTDIR+"/plugins/"+fn if (fn.endswith(".plugin")):return OUTPUTDIR+"/plugins/"+fn[:-7]+dllext+".so" if (fn.endswith(".exe")): return OUTPUTDIR+"/bin/"+fn[:-4] diff --git a/panda/metalibs/pandaegg/pandaegg.h b/panda/metalibs/pandaegg/pandaegg.h index 0a11258a17..5b09de593f 100644 --- a/panda/metalibs/pandaegg/pandaegg.h +++ b/panda/metalibs/pandaegg/pandaegg.h @@ -9,6 +9,6 @@ #include "pandabase.h" -EXPCL_PANDAEGG void init_libpandaegg(); +extern "C" EXPCL_PANDAEGG void init_libpandaegg(); #endif diff --git a/panda/src/audio/audioManager.cxx b/panda/src/audio/audioManager.cxx index bbcf6167a3..d7eb0846fe 100644 --- a/panda/src/audio/audioManager.cxx +++ b/panda/src/audio/audioManager.cxx @@ -36,32 +36,42 @@ namespace { } } -Create_AudioManager_proc* AudioManager::_create_AudioManager - =create_NullAudioManager; +Create_AudioManager_proc *AudioManager::_create_AudioManager = NULL; -void AudioManager::register_AudioManager_creator(Create_AudioManager_proc* proc) { - nassertv(_create_AudioManager==create_NullAudioManager); - _create_AudioManager=proc; +void AudioManager:: +register_AudioManager_creator(Create_AudioManager_proc* proc) { + nassertv(_create_AudioManager == NULL); + _create_AudioManager = proc; } - - // Factory method for getting a platform specific AudioManager: PT(AudioManager) AudioManager::create_AudioManager() { audio_debug("create_AudioManager()\n audio_library_name=\""<is_exact_type(NullAudioManager::get_class_type()) && !am->is_valid()) { + audio_error(" " << am->get_type() << " is not valid, will use NullAudioManager"); + am = create_NullAudioManager(); + } + return am; + } + static bool lib_load = false; if (!lib_load) { lib_load = true; - if (!audio_library_name.empty() && !(audio_library_name == "null")) { + if (!audio_library_name.empty() && audio_library_name != "null") { Filename dl_name = Filename::dso_filename( - "lib"+string(audio_library_name)+".so"); + "lib" + string(audio_library_name) + ".so"); dl_name.to_os_specific(); audio_debug(" dl_name=\""<is_exact_type(NullAudioManager::get_class_type()) && !am->is_valid()) { audio_error(" " << am->get_type() << " is not valid, will use NullAudioManager"); diff --git a/panda/src/audiotraits/config_openalAudio.cxx b/panda/src/audiotraits/config_openalAudio.cxx index 43ba4d890c..4f9019c013 100644 --- a/panda/src/audiotraits/config_openalAudio.cxx +++ b/panda/src/audiotraits/config_openalAudio.cxx @@ -48,6 +48,8 @@ init_libOpenALAudio() { OpenALAudioManager::init_type(); OpenALAudioSound::init_type(); + AudioManager::register_AudioManager_creator(&Create_OpenALAudioManager); + PandaSystem *ps = PandaSystem::get_global_ptr(); ps->add_system("OpenAL"); ps->add_system("audio"); diff --git a/panda/src/audiotraits/config_openalAudio.h b/panda/src/audiotraits/config_openalAudio.h index dd24d208eb..bcd8481acf 100644 --- a/panda/src/audiotraits/config_openalAudio.h +++ b/panda/src/audiotraits/config_openalAudio.h @@ -22,7 +22,7 @@ ConfigureDecl(config_openalAudio, EXPCL_OPENAL_AUDIO, EXPTP_OPENAL_AUDIO); NotifyCategoryDecl(openalAudio, EXPCL_OPENAL_AUDIO, EXPTP_OPENAL_AUDIO); -extern EXPCL_OPENAL_AUDIO void init_libOpenALAudio(); +extern "C" EXPCL_OPENAL_AUDIO void init_libOpenALAudio(); extern "C" EXPCL_OPENAL_AUDIO Create_AudioManager_proc *get_audio_manager_func_openal_audio(); extern ConfigVariableString openal_device; diff --git a/panda/src/audiotraits/milesAudioManager.cxx b/panda/src/audiotraits/milesAudioManager.cxx index 5414d49574..750475dee1 100644 --- a/panda/src/audiotraits/milesAudioManager.cxx +++ b/panda/src/audiotraits/milesAudioManager.cxx @@ -893,7 +893,7 @@ load(const Filename &file_name) { sd->_basename = file_name.get_basename(); string extension = sd->_basename.get_extension(); - if (extension == "pz") { + if (extension == "pz" || extension == "gz") { extension = Filename(sd->_basename.get_basename_wo_extension()).get_extension(); } diff --git a/panda/src/audiotraits/openalAudioManager.cxx b/panda/src/audiotraits/openalAudioManager.cxx index c32407970c..ba1b4684a3 100644 --- a/panda/src/audiotraits/openalAudioManager.cxx +++ b/panda/src/audiotraits/openalAudioManager.cxx @@ -438,7 +438,7 @@ get_sound_data(MovieAudio *movie, int mode) { } int channels = stream->audio_channels(); int samples = (int)(stream->length() * stream->audio_rate()); - PN_int16 *data = new PN_int16[samples * channels]; + int16_t *data = new int16_t[samples * channels]; stream->read_samples(samples, data); alBufferData(sd->_sample, (channels>1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, diff --git a/panda/src/audiotraits/openalAudioSound.cxx b/panda/src/audiotraits/openalAudioSound.cxx index 7237b2fefe..43ebd149cb 100644 --- a/panda/src/audiotraits/openalAudioSound.cxx +++ b/panda/src/audiotraits/openalAudioSound.cxx @@ -383,8 +383,8 @@ read_stream_data(int bytelen, unsigned char *buffer) { if (samples > _sd->_stream->ready()) { samples = _sd->_stream->ready(); } - cursor->read_samples(samples, (PN_int16 *)buffer); - size_t hval = AddHash::add_hash(0, (PN_uint8*)buffer, samples*channels*2); + cursor->read_samples(samples, (int16_t *)buffer); + size_t hval = AddHash::add_hash(0, (uint8_t*)buffer, samples*channels*2); audio_debug("Streaming " << cursor->get_source()->get_name() << " at " << t << " hash " << hval); fill += samples; space -= samples; diff --git a/panda/src/bullet/bulletContactResult.I b/panda/src/bullet/bulletContactResult.I index 5509f35092..9299631374 100644 --- a/panda/src/bullet/bulletContactResult.I +++ b/panda/src/bullet/bulletContactResult.I @@ -86,7 +86,7 @@ get_num_contacts() const { /** * */ -INLINE BulletContact &BulletContactResult:: +INLINE BulletContact BulletContactResult:: get_contact(int idx) { nassertr(idx >= 0 && idx < (int)_contacts.size(), _empty); diff --git a/panda/src/bullet/bulletContactResult.h b/panda/src/bullet/bulletContactResult.h index 77ada41468..3e0e216135 100644 --- a/panda/src/bullet/bulletContactResult.h +++ b/panda/src/bullet/bulletContactResult.h @@ -62,7 +62,7 @@ struct EXPCL_PANDABULLET BulletContactResult : public btCollisionWorld::ContactR PUBLISHED: INLINE int get_num_contacts() const; - INLINE BulletContact &get_contact(int idx); + INLINE BulletContact get_contact(int idx); MAKE_SEQ(get_contacts, get_num_contacts, get_contact); public: diff --git a/panda/src/bullet/bulletHeightfieldShape.I b/panda/src/bullet/bulletHeightfieldShape.I index 4794eab227..6607443110 100644 --- a/panda/src/bullet/bulletHeightfieldShape.I +++ b/panda/src/bullet/bulletHeightfieldShape.I @@ -18,7 +18,7 @@ INLINE BulletHeightfieldShape:: ~BulletHeightfieldShape() { delete _shape; - delete _data; + delete [] _data; } /** diff --git a/panda/src/bullet/bulletSoftBodyMaterial.I b/panda/src/bullet/bulletSoftBodyMaterial.I index f0da7e10ce..ff8182f6ed 100644 --- a/panda/src/bullet/bulletSoftBodyMaterial.I +++ b/panda/src/bullet/bulletSoftBodyMaterial.I @@ -20,7 +20,7 @@ INLINE BulletSoftBodyMaterial:: } /** - * Named constructor intended to be used for asserts with have to return a + * Named constructor intended to be used for asserts which have to return a * concrete value. */ INLINE BulletSoftBodyMaterial BulletSoftBodyMaterial:: @@ -44,7 +44,7 @@ get_material() const { * Getter for the property m_kLST. */ INLINE PN_stdfloat BulletSoftBodyMaterial:: -getLinearStiffness() const { +get_linear_stiffness() const { return (PN_stdfloat)_material.m_kLST; } @@ -53,7 +53,7 @@ getLinearStiffness() const { * Setter for the property m_kLST. */ INLINE void BulletSoftBodyMaterial:: -setLinearStiffness(PN_stdfloat value) { +set_linear_stiffness(PN_stdfloat value) { _material.m_kLST = (btScalar)value; } @@ -62,7 +62,7 @@ setLinearStiffness(PN_stdfloat value) { * Getter for the property m_kAST. */ INLINE PN_stdfloat BulletSoftBodyMaterial:: -getAngularStiffness() const { +get_angular_stiffness() const { return (PN_stdfloat)_material.m_kAST; } @@ -71,7 +71,7 @@ getAngularStiffness() const { * Setter for the property m_kAST. */ INLINE void BulletSoftBodyMaterial:: -setAngularStiffness(PN_stdfloat value) { +set_angular_stiffness(PN_stdfloat value) { _material.m_kAST = (btScalar)value; } @@ -80,7 +80,7 @@ setAngularStiffness(PN_stdfloat value) { * Getter for the property m_kVST. */ INLINE PN_stdfloat BulletSoftBodyMaterial:: -getVolumePreservation() const { +get_volume_preservation() const { return (PN_stdfloat)_material.m_kVST; } @@ -89,7 +89,7 @@ getVolumePreservation() const { * Setter for the property m_kVST. */ INLINE void BulletSoftBodyMaterial:: -setVolumePreservation(PN_stdfloat value) { +set_volume_preservation(PN_stdfloat value) { _material.m_kVST = (btScalar)value; } diff --git a/panda/src/bullet/bulletSoftBodyMaterial.h b/panda/src/bullet/bulletSoftBodyMaterial.h index fdcd453f4d..b2a70c1d9d 100644 --- a/panda/src/bullet/bulletSoftBodyMaterial.h +++ b/panda/src/bullet/bulletSoftBodyMaterial.h @@ -27,13 +27,17 @@ PUBLISHED: INLINE ~BulletSoftBodyMaterial(); INLINE static BulletSoftBodyMaterial empty(); - INLINE void setLinearStiffness(PN_stdfloat value); - INLINE void setAngularStiffness(PN_stdfloat value); - INLINE void setVolumePreservation(PN_stdfloat value); - - INLINE PN_stdfloat getLinearStiffness() const; - INLINE PN_stdfloat getAngularStiffness() const; - INLINE PN_stdfloat getVolumePreservation() const; + INLINE void set_linear_stiffness(PN_stdfloat value); + INLINE PN_stdfloat get_linear_stiffness() const; + MAKE_PROPERTY(linear_stiffness, get_linear_stiffness, set_linear_stiffness); + + INLINE void set_angular_stiffness(PN_stdfloat value); + INLINE PN_stdfloat get_angular_stiffness() const; + MAKE_PROPERTY(angular_stiffness, get_angular_stiffness, set_angular_stiffness); + + INLINE void set_volume_preservation(PN_stdfloat value); + INLINE PN_stdfloat get_volume_preservation() const; + MAKE_PROPERTY(volume_preservation, get_volume_preservation, set_volume_preservation); public: BulletSoftBodyMaterial(btSoftBody::Material &material); diff --git a/panda/src/bullet/bulletTriangleMesh.cxx b/panda/src/bullet/bulletTriangleMesh.cxx index 651f7979bc..d776d572d7 100644 --- a/panda/src/bullet/bulletTriangleMesh.cxx +++ b/panda/src/bullet/bulletTriangleMesh.cxx @@ -134,6 +134,8 @@ add_geom(const Geom *geom, bool remove_duplicate_vertices, const TransformState _mesh->addTriangle(v0, v1, v2, remove_duplicate_vertices); } } + + delete [] vertices; } /** @@ -163,6 +165,8 @@ add_array(const PTA_LVecBase3 &points, const PTA_int &indices, bool remove_dupli _mesh->addTriangle(v0, v1, v2, remove_duplicate_vertices); } + + delete [] vertices; } /** diff --git a/panda/src/chan/animChannelMatrixXfmTable.cxx b/panda/src/chan/animChannelMatrixXfmTable.cxx index 0ae15b7ba1..6c404d06fe 100644 --- a/panda/src/chan/animChannelMatrixXfmTable.cxx +++ b/panda/src/chan/animChannelMatrixXfmTable.cxx @@ -327,10 +327,16 @@ void AnimChannelMatrixXfmTable:: write_datagram(BamWriter *manager, Datagram &me) { AnimChannelMatrix::write_datagram(manager, me); - if (compress_channels && !FFTCompressor::is_compression_available()) { - chan_cat.error() - << "Compression is not available; writing uncompressed channels.\n"; - compress_channels = false; + if (compress_channels) { + chan_cat.warning() + << "FFT compression of animations is deprecated. For compatibility " + "with future versions of Panda3D, set compress-channels to false.\n"; + + if (!FFTCompressor::is_compression_available()) { + chan_cat.error() + << "Compression is not available; writing uncompressed channels.\n"; + compress_channels = false; + } } me.add_bool(compress_channels); diff --git a/panda/src/chan/animChannelScalarTable.cxx b/panda/src/chan/animChannelScalarTable.cxx index 5bcbd0cb40..195258b9c7 100644 --- a/panda/src/chan/animChannelScalarTable.cxx +++ b/panda/src/chan/animChannelScalarTable.cxx @@ -146,10 +146,16 @@ void AnimChannelScalarTable:: write_datagram(BamWriter *manager, Datagram &me) { AnimChannelScalar::write_datagram(manager, me); - if (compress_channels && !FFTCompressor::is_compression_available()) { - chan_cat.error() - << "Compression is not available; writing uncompressed channels.\n"; - compress_channels = false; + if (compress_channels) { + chan_cat.warning() + << "FFT compression of animations is deprecated. For compatibility " + "with future versions of Panda3D, set compress-channels to false.\n"; + + if (!FFTCompressor::is_compression_available()) { + chan_cat.error() + << "Compression is not available; writing uncompressed channels.\n"; + compress_channels = false; + } } me.add_bool(compress_channels); diff --git a/panda/src/chan/animGroup.h b/panda/src/chan/animGroup.h index 8bcb9c41eb..af81aba3b1 100644 --- a/panda/src/chan/animGroup.h +++ b/panda/src/chan/animGroup.h @@ -44,6 +44,8 @@ PUBLISHED: AnimGroup *get_child(int n) const; MAKE_SEQ(get_children, get_num_children, get_child); + MAKE_SEQ_PROPERTY(children, get_num_children, get_child); + AnimGroup *get_child_named(const string &name) const; AnimGroup *find_child(const string &name) const; void sort_descendants(); diff --git a/panda/src/chan/config_chan.cxx b/panda/src/chan/config_chan.cxx index ab9b343d23..9772f2d661 100644 --- a/panda/src/chan/config_chan.cxx +++ b/panda/src/chan/config_chan.cxx @@ -138,4 +138,15 @@ ConfigureFn(config_chan) { AnimChannelScalarTable::register_with_read_factory(); AnimChannelScalarDynamic::register_with_read_factory(); AnimPreloadTable::register_with_read_factory(); + + // For compatibility with old .bam files. +#ifndef STDFLOAT_DOUBLE + TypeRegistry *reg = TypeRegistry::ptr(); + reg->record_alternate_name(AnimChannelFixed::get_class_type(), + "AnimChannelFixed"); + reg->record_alternate_name(MovingPart::get_class_type(), + "MovingPart"); + reg->record_alternate_name(MovingPart::get_class_type(), + "MovingPart"); +#endif } diff --git a/panda/src/chan/partBundle.h b/panda/src/chan/partBundle.h index 82272df52c..0d22fe5e73 100644 --- a/panda/src/chan/partBundle.h +++ b/panda/src/chan/partBundle.h @@ -113,6 +113,12 @@ PUBLISHED: INLINE PartBundleNode *get_node(int n) const; MAKE_SEQ(get_nodes, get_num_nodes, get_node); + MAKE_PROPERTY(blend_type, get_blend_type, set_blend_type); + MAKE_PROPERTY(anim_blend_flag, get_anim_blend_flag, set_anim_blend_flag); + MAKE_PROPERTY(frame_blend_flag, get_frame_blend_flag, set_frame_blend_flag); + MAKE_PROPERTY(root_xform, get_root_xform, set_root_xform); + MAKE_SEQ_PROPERTY(nodes, get_num_nodes, get_node); + void clear_control_effects(); INLINE void set_control_effect(AnimControl *control, PN_stdfloat effect); INLINE PN_stdfloat get_control_effect(AnimControl *control) const; diff --git a/panda/src/chan/partBundleHandle.h b/panda/src/chan/partBundleHandle.h index 7a5e26e8ce..f62b30c791 100644 --- a/panda/src/chan/partBundleHandle.h +++ b/panda/src/chan/partBundleHandle.h @@ -38,6 +38,8 @@ PUBLISHED: INLINE PartBundle *get_bundle(); INLINE void set_bundle(PartBundle *bundle); + MAKE_PROPERTY(bundle, get_bundle, set_bundle); + private: PT(PartBundle) _bundle; }; diff --git a/panda/src/chan/partBundleNode.h b/panda/src/chan/partBundleNode.h index 5a6de285e1..f4cafaf056 100644 --- a/panda/src/chan/partBundleNode.h +++ b/panda/src/chan/partBundleNode.h @@ -54,6 +54,9 @@ PUBLISHED: INLINE PartBundleHandle *get_bundle_handle(int n) const; MAKE_SEQ(get_bundle_handles, get_num_bundles, get_bundle_handle); + MAKE_SEQ_PROPERTY(bundles, get_num_bundles, get_bundle); + MAKE_SEQ_PROPERTY(bundle_handles, get_num_bundles, get_bundle_handle); + protected: void add_bundle(PartBundle *bundle); void add_bundle_handle(PartBundleHandle *handle); diff --git a/panda/src/chan/partGroup.h b/panda/src/chan/partGroup.h index 16b497f842..0d5967a39a 100644 --- a/panda/src/chan/partGroup.h +++ b/panda/src/chan/partGroup.h @@ -70,6 +70,7 @@ PUBLISHED: int get_num_children() const; PartGroup *get_child(int n) const; MAKE_SEQ(get_children, get_num_children, get_child); + MAKE_SEQ_PROPERTY(children, get_num_children, get_child); PartGroup *get_child_named(const string &name) const; PartGroup *find_child(const string &name) const; diff --git a/panda/src/cocoadisplay/cocoaPandaApp.mm b/panda/src/cocoadisplay/cocoaPandaApp.mm index 7c28adda40..e7226786da 100644 --- a/panda/src/cocoadisplay/cocoaPandaApp.mm +++ b/panda/src/cocoadisplay/cocoaPandaApp.mm @@ -25,4 +25,24 @@ [super sendEvent: event]; } } + +- (void) _setup: (void *) interp { + // This is called by Tk when it launches and naively assumes that it is + // the first to create an NSApplication. We can't do anything about it + // at this point except display an error message. + + cocoadisplay_cat.error() + << "Detected attempt to initialize Tk after creating a Panda window. " + "This will likely cause a crash.\n" + "To fix this, set 'want-tk true' in Config.prc to force " + "initialization of Tk before opening the Panda window.\n"; +} + +- (void) _setupEventLoop { + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + [self finishLaunching]; + [self setWindowsNeedUpdate:YES]; + [pool drain]; +} + @end diff --git a/panda/src/collada/loaderFileTypeDae.cxx b/panda/src/collada/loaderFileTypeDae.cxx index d6474fb3ed..9fc5785514 100644 --- a/panda/src/collada/loaderFileTypeDae.cxx +++ b/panda/src/collada/loaderFileTypeDae.cxx @@ -56,7 +56,7 @@ get_additional_extensions() const { /** * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. + * (with a .pz or .gz extension), false otherwise. */ bool LoaderFileTypeDae:: supports_compressed() const { diff --git a/panda/src/collide/collisionFloorMesh.h b/panda/src/collide/collisionFloorMesh.h index 02861262c7..44e9d18e32 100644 --- a/panda/src/collide/collisionFloorMesh.h +++ b/panda/src/collide/collisionFloorMesh.h @@ -40,7 +40,6 @@ public: } TriangleIndices; PUBLISHED: - INLINE CollisionFloorMesh(); INLINE void add_vertex(const LPoint3 &vert); @@ -55,6 +54,10 @@ PUBLISHED: virtual LPoint3 get_collision_origin() const; +PUBLISHED: + MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex); + MAKE_SEQ_PROPERTY(triangles, get_num_triangles, get_triangle); + public: CollisionFloorMesh(const CollisionFloorMesh ©); virtual CollisionSolid *make_copy(); diff --git a/panda/src/collide/collisionHandlerEvent.h b/panda/src/collide/collisionHandlerEvent.h index c5ebfe78c9..a1240882d6 100644 --- a/panda/src/collide/collisionHandlerEvent.h +++ b/panda/src/collide/collisionHandlerEvent.h @@ -60,6 +60,10 @@ PUBLISHED: INLINE string get_out_pattern(int n) const; MAKE_SEQ(get_out_patterns, get_num_out_patterns, get_out_pattern); + MAKE_SEQ_PROPERTY(in_patterns, get_num_in_patterns, get_in_pattern); + MAKE_SEQ_PROPERTY(again_patterns, get_num_again_patterns, get_out_pattern); + MAKE_SEQ_PROPERTY(out_patterns, get_num_out_patterns, get_out_pattern); + void clear(); void flush(); diff --git a/panda/src/collide/collisionHandlerQueue.h b/panda/src/collide/collisionHandlerQueue.h index 397aa11809..0651b545c7 100644 --- a/panda/src/collide/collisionHandlerQueue.h +++ b/panda/src/collide/collisionHandlerQueue.h @@ -40,6 +40,7 @@ PUBLISHED: int get_num_entries() const; CollisionEntry *get_entry(int n) const; MAKE_SEQ(get_entries, get_num_entries, get_entry); + MAKE_SEQ_PROPERTY(entries, get_num_entries, get_entry); void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; diff --git a/panda/src/collide/collisionNode.h b/panda/src/collide/collisionNode.h index 5a939a284d..6c95e6d435 100644 --- a/panda/src/collide/collisionNode.h +++ b/panda/src/collide/collisionNode.h @@ -68,6 +68,7 @@ PUBLISHED: INLINE void set_solid(int n, CollisionSolid *solid); INLINE void remove_solid(int n); INLINE int add_solid(const CollisionSolid *solid); + MAKE_SEQ_PROPERTY(solids, get_num_solids, get_solid, set_solid, remove_solid); INLINE int get_collider_sort() const; INLINE void set_collider_sort(int sort); diff --git a/panda/src/collide/collisionPolygon.h b/panda/src/collide/collisionPolygon.h index 147920f580..464c0e73b6 100644 --- a/panda/src/collide/collisionPolygon.h +++ b/panda/src/collide/collisionPolygon.h @@ -60,6 +60,7 @@ PUBLISHED: bool is_concave() const; PUBLISHED: + MAKE_SEQ_PROPERTY(points, get_num_points, get_point); MAKE_PROPERTY(valid, is_valid); MAKE_PROPERTY(concave, is_concave); diff --git a/panda/src/collide/collisionTraverser.h b/panda/src/collide/collisionTraverser.h index cd7916fc09..d4f2b2a24b 100644 --- a/panda/src/collide/collisionTraverser.h +++ b/panda/src/collide/collisionTraverser.h @@ -60,6 +60,7 @@ PUBLISHED: MAKE_SEQ(get_colliders, get_num_colliders, get_collider); CollisionHandler *get_handler(const NodePath &collider) const; void clear_colliders(); + MAKE_SEQ_PROPERTY(colliders, get_num_colliders, get_collider); void traverse(const NodePath &root); diff --git a/panda/src/device/linuxJoystickDevice.cxx b/panda/src/device/linuxJoystickDevice.cxx index 33c3362105..826b4ac442 100644 --- a/panda/src/device/linuxJoystickDevice.cxx +++ b/panda/src/device/linuxJoystickDevice.cxx @@ -104,7 +104,7 @@ open_device() { _name = name; // Get the number of axes. - PN_uint8 num_axes = 0, num_buttons = 0; + uint8_t num_axes = 0, num_buttons = 0; ioctl(_fd, JSIOCGAXES, &num_axes); ioctl(_fd, JSIOCGBUTTONS, &num_buttons); @@ -112,7 +112,7 @@ open_device() { _controls.resize(num_axes); if (num_buttons > 0) { - PN_uint16 btnmap[512]; + uint16_t btnmap[512]; ioctl(_fd, JSIOCGBTNMAP, btnmap); for (char i = 0; i < num_buttons; ++i) { @@ -204,7 +204,7 @@ open_device() { } if (num_axes > 0) { - PN_uint8 axmap[512]; + uint8_t axmap[512]; ioctl(_fd, JSIOCGAXMAP, axmap); for (char i = 0; i < num_axes; ++i) { diff --git a/panda/src/display/displayInformation.cxx b/panda/src/display/displayInformation.cxx index aa83cfdf97..60e3a69e8b 100644 --- a/panda/src/display/displayInformation.cxx +++ b/panda/src/display/displayInformation.cxx @@ -81,8 +81,8 @@ DisplayInformation() { DisplayMode *display_mode_array; int video_memory; int texture_memory; - PN_uint64 physical_memory; - PN_uint64 available_physical_memory; + uint64_t physical_memory; + uint64_t available_physical_memory; state = DisplayInformation::DS_unknown; get_adapter_display_mode_state = false; @@ -325,7 +325,7 @@ update_memory_information() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_physical_memory() { return _physical_memory; } @@ -333,7 +333,7 @@ get_physical_memory() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_available_physical_memory() { return _available_physical_memory; } @@ -341,7 +341,7 @@ get_available_physical_memory() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_page_file_size() { return _page_file_size; } @@ -349,7 +349,7 @@ get_page_file_size() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_available_page_file_size() { return _available_page_file_size; } @@ -357,7 +357,7 @@ get_available_page_file_size() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_process_virtual_memory() { return _process_virtual_memory; } @@ -365,7 +365,7 @@ get_process_virtual_memory() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_available_process_virtual_memory() { return _available_process_virtual_memory; } @@ -381,7 +381,7 @@ get_memory_load() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_page_fault_count() { return _page_fault_count; } @@ -389,7 +389,7 @@ get_page_fault_count() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_process_memory() { return _process_memory; } @@ -397,7 +397,7 @@ get_process_memory() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_peak_process_memory() { return _peak_process_memory; } @@ -405,7 +405,7 @@ get_peak_process_memory() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_page_file_usage() { return _page_file_usage; } @@ -413,7 +413,7 @@ get_page_file_usage() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_peak_page_file_usage() { return _peak_page_file_usage; } @@ -570,7 +570,7 @@ get_cpu_brand_index() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_cpu_frequency() { return _cpu_frequency; } @@ -578,9 +578,9 @@ get_cpu_frequency() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_cpu_time() { - PN_uint64 cpu_time; + uint64_t cpu_time; cpu_time = 0; if (_cpu_time_function) { @@ -593,7 +593,7 @@ get_cpu_time() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_maximum_cpu_frequency() { return _maximum_cpu_frequency; } @@ -601,7 +601,7 @@ get_maximum_cpu_frequency() { /** * */ -PN_uint64 DisplayInformation:: +uint64_t DisplayInformation:: get_current_cpu_frequency() { return _current_cpu_frequency; } diff --git a/panda/src/display/displayInformation.h b/panda/src/display/displayInformation.h index e8ddfd2a72..440e3e8ee8 100644 --- a/panda/src/display/displayInformation.h +++ b/panda/src/display/displayInformation.h @@ -69,18 +69,18 @@ PUBLISHED: int get_texture_memory(); void update_memory_information(); - PN_uint64 get_physical_memory(); - PN_uint64 get_available_physical_memory(); - PN_uint64 get_page_file_size(); - PN_uint64 get_available_page_file_size(); - PN_uint64 get_process_virtual_memory(); - PN_uint64 get_available_process_virtual_memory(); + uint64_t get_physical_memory(); + uint64_t get_available_physical_memory(); + uint64_t get_page_file_size(); + uint64_t get_available_page_file_size(); + uint64_t get_process_virtual_memory(); + uint64_t get_available_process_virtual_memory(); int get_memory_load(); - PN_uint64 get_page_fault_count(); - PN_uint64 get_process_memory(); - PN_uint64 get_peak_process_memory(); - PN_uint64 get_page_file_usage(); - PN_uint64 get_peak_page_file_usage(); + uint64_t get_page_fault_count(); + uint64_t get_process_memory(); + uint64_t get_peak_process_memory(); + uint64_t get_page_file_usage(); + uint64_t get_peak_page_file_usage(); int get_vendor_id(); int get_device_id(); @@ -103,11 +103,11 @@ PUBLISHED: unsigned int get_cpu_version_information(); unsigned int get_cpu_brand_index(); - PN_uint64 get_cpu_frequency(); - PN_uint64 get_cpu_time(); + uint64_t get_cpu_frequency(); + uint64_t get_cpu_time(); - PN_uint64 get_maximum_cpu_frequency(); - PN_uint64 get_current_cpu_frequency(); + uint64_t get_maximum_cpu_frequency(); + uint64_t get_current_cpu_frequency(); void update_cpu_frequency(int processor_number); int get_num_cpu_cores(); @@ -131,18 +131,18 @@ public: int _video_memory; int _texture_memory; - PN_uint64 _physical_memory; - PN_uint64 _available_physical_memory; - PN_uint64 _page_file_size; - PN_uint64 _available_page_file_size; - PN_uint64 _process_virtual_memory; - PN_uint64 _available_process_virtual_memory; + uint64_t _physical_memory; + uint64_t _available_physical_memory; + uint64_t _page_file_size; + uint64_t _available_page_file_size; + uint64_t _process_virtual_memory; + uint64_t _available_process_virtual_memory; - PN_uint64 _page_fault_count; - PN_uint64 _process_memory; - PN_uint64 _peak_process_memory; - PN_uint64 _page_file_usage; - PN_uint64 _peak_page_file_usage; + uint64_t _page_fault_count; + uint64_t _process_memory; + uint64_t _peak_process_memory; + uint64_t _page_file_usage; + uint64_t _peak_page_file_usage; int _memory_load; @@ -167,16 +167,16 @@ public: unsigned int _cpu_version_information; unsigned int _cpu_brand_index; - PN_uint64 _cpu_frequency; + uint64_t _cpu_frequency; - PN_uint64 _maximum_cpu_frequency; - PN_uint64 _current_cpu_frequency; + uint64_t _maximum_cpu_frequency; + uint64_t _current_cpu_frequency; int _num_cpu_cores; int _num_logical_cpus; void (*_get_memory_information_function) (DisplayInformation *display_information); - PN_uint64 (*_cpu_time_function) (void); + uint64_t (*_cpu_time_function) (void); int (*_update_cpu_frequency_function) (int processor_number, DisplayInformation *display_information); int _os_version_major; diff --git a/panda/src/display/drawableRegion.I b/panda/src/display/drawableRegion.I index b7bf511df6..677a345683 100644 --- a/panda/src/display/drawableRegion.I +++ b/panda/src/display/drawableRegion.I @@ -17,10 +17,10 @@ INLINE DrawableRegion:: DrawableRegion() : _screenshot_buffer_type(RenderBuffer::T_front), - _draw_buffer_type(RenderBuffer::T_back) + _draw_buffer_type(RenderBuffer::T_back), + _clear_mask(0) { - for (int i=0; i= 0)&&(n < RTP_COUNT)); - _clear_active[n] = clear_active; + nassertv(n >= 0 && n < RTP_COUNT); + if (clear_active) { + _clear_mask |= 1 << n; + } else { + _clear_mask &= ~(1 << n); + } update_pixel_factor(); } @@ -37,8 +41,8 @@ set_clear_active(int n, bool clear_active) { */ bool DrawableRegion:: get_clear_active(int n) const { - nassertr((n >= 0)&&(n < RTP_COUNT), false); - return _clear_active[n]; + nassertr(n >= 0 && n < RTP_COUNT, false); + return (_clear_mask & (1 << n)) != 0; } /** @@ -66,9 +70,7 @@ get_clear_value(int n) const { */ void DrawableRegion:: disable_clears() { - for (int i = 0; i < RTP_COUNT; ++i) { - _clear_active[i] = false; - } + _clear_mask = 0; update_pixel_factor(); } @@ -79,12 +81,7 @@ disable_clears() { */ bool DrawableRegion:: is_any_clear_active() const { - for (int i = 0; i < RTP_COUNT; ++i) { - if (get_clear_active(i)) { - return true; - } - } - return false; + return (_clear_mask != 0); } /** diff --git a/panda/src/display/drawableRegion.h b/panda/src/display/drawableRegion.h index 10fafcf687..b5bb9bfd14 100644 --- a/panda/src/display/drawableRegion.h +++ b/panda/src/display/drawableRegion.h @@ -109,9 +109,9 @@ protected: protected: int _screenshot_buffer_type; int _draw_buffer_type; + int _clear_mask; private: - bool _clear_active[RTP_COUNT]; LColor _clear_value[RTP_COUNT]; PN_stdfloat _pixel_zoom; diff --git a/panda/src/display/frameBufferProperties.cxx b/panda/src/display/frameBufferProperties.cxx index 4d0751a7d2..51120fbec1 100644 --- a/panda/src/display/frameBufferProperties.cxx +++ b/panda/src/display/frameBufferProperties.cxx @@ -480,6 +480,13 @@ get_quality(const FrameBufferProperties &reqs) const { quality -= 10000000; } + // Deduct for software-only renderers in absence of a special request. + // Cost: 2,000,000 + + if (get_force_software() && !reqs.get_force_software()) { + quality -= 2000000; + } + // Deduct for missing depth, color, alpha, stencil, or accum. Cost: // 1,000,000 diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 41f6df5f34..ac2c194195 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -415,6 +415,9 @@ make_output(GraphicsPipe *pipe, if (flags & GraphicsPipe::BF_fb_props_optional) { display_cat.warning() << "FrameBufferProperties available less than requested.\n"; + display_cat.warning(false) + << " requested: " << fb_prop << "\n" + << " got: " << window->get_fb_properties() << "\n"; return window; } display_cat.error() @@ -594,6 +597,9 @@ remove_all_windows() { // And, hey, let's stop the vertex paging threads, if any. VertexDataPage::stop_threads(); + // Stopping the tasks means we have to release the Python GIL while + // this method runs (hence it is marked BLOCKING), so that any + // Python tasks on other threads won't deadlock grabbing the GIL. AsyncTaskManager::get_global_ptr()->stop_threads(); #ifdef DO_PSTATS diff --git a/panda/src/display/graphicsEngine.h b/panda/src/display/graphicsEngine.h index 7945b6d039..89cfb7c616 100644 --- a/panda/src/display/graphicsEngine.h +++ b/panda/src/display/graphicsEngine.h @@ -53,7 +53,7 @@ class Texture; class EXPCL_PANDA_DISPLAY GraphicsEngine : public ReferenceCount { PUBLISHED: GraphicsEngine(Pipeline *pipeline = NULL); - ~GraphicsEngine(); + BLOCKING ~GraphicsEngine(); void set_threading_model(const GraphicsThreadingModel &threading_model); GraphicsThreadingModel get_threading_model() const; @@ -94,13 +94,14 @@ PUBLISHED: bool add_window(GraphicsOutput *window, int sort); bool remove_window(GraphicsOutput *window); - void remove_all_windows(); + BLOCKING void remove_all_windows(); void reset_all_windows(bool swapchain); bool is_empty() const; int get_num_windows() const; GraphicsOutput *get_window(int n) const; MAKE_SEQ(get_windows, get_num_windows, get_window); + MAKE_SEQ_PROPERTY(windows, get_num_windows, get_window); BLOCKING void render_frame(); BLOCKING void open_windows(); diff --git a/panda/src/display/graphicsOutput.h b/panda/src/display/graphicsOutput.h index 59d94489cf..295467f458 100644 --- a/panda/src/display/graphicsOutput.h +++ b/panda/src/display/graphicsOutput.h @@ -195,6 +195,7 @@ PUBLISHED: INLINE void set_child_sort(int child_sort); INLINE void clear_child_sort(); INLINE int get_child_sort() const; + MAKE_PROPERTY(child_sort, get_child_sort, set_child_sort); INLINE void trigger_copy(); @@ -216,10 +217,12 @@ PUBLISHED: int get_num_display_regions() const; PT(DisplayRegion) get_display_region(int n) const; MAKE_SEQ(get_display_regions, get_num_display_regions, get_display_region); + MAKE_SEQ_PROPERTY(display_regions, get_num_display_regions, get_display_region); int get_num_active_display_regions() const; PT(DisplayRegion) get_active_display_region(int n) const; MAKE_SEQ(get_active_display_regions, get_num_active_display_regions, get_active_display_region); + MAKE_SEQ_PROPERTY(active_display_regions, get_num_active_display_regions, get_active_display_region); GraphicsOutput *make_texture_buffer( const string &name, int x_size, int y_size, diff --git a/panda/src/display/graphicsPipeSelection.h b/panda/src/display/graphicsPipeSelection.h index 2f0955211c..d1dc5b641e 100644 --- a/panda/src/display/graphicsPipeSelection.h +++ b/panda/src/display/graphicsPipeSelection.h @@ -39,6 +39,7 @@ PUBLISHED: int get_num_pipe_types() const; TypeHandle get_pipe_type(int n) const; MAKE_SEQ(get_pipe_types, get_num_pipe_types, get_pipe_type); + MAKE_SEQ_PROPERTY(pipe_types, get_num_pipe_types, get_pipe_type); void print_pipe_types() const; PT(GraphicsPipe) make_pipe(const string &type_name, diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index db8e1f198f..ea3a9b61ac 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -684,6 +684,15 @@ get_max_color_targets() const { return _max_color_targets; } +/** + * Returns true if dual source (incoming1_color and incoming1_alpha) blend + * operands are supported by this GSG. + */ +INLINE bool GraphicsStateGuardian:: +get_supports_dual_source_blending() const { + return _supports_dual_source_blending; +} + /** * Deprecated. Use get_max_color_targets() instead, which returns the exact * same value. diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index d294dc47f3..18d35d7f78 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -246,6 +246,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, // Assume a maximum of 1 render target in absence of MRT. _max_color_targets = 1; + _supports_dual_source_blending = false; _supported_geom_rendering = 0; @@ -2195,7 +2196,10 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, bool force) { _munger = munger; _data_reader = data_reader; - return _data_reader->has_vertex(); + + // Always draw if we have a shader, since the shader might use a different + // mechanism for fetching vertex data. + return _data_reader->has_vertex() || (_target_shader && _target_shader->has_shader()); } /** diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 401c538b31..825b03286d 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -172,6 +172,7 @@ PUBLISHED: INLINE int get_max_color_targets() const; INLINE int get_maximum_simultaneous_render_targets() const; + INLINE bool get_supports_dual_source_blending() const; MAKE_PROPERTY(max_vertices_per_array, get_max_vertices_per_array); MAKE_PROPERTY(max_vertices_per_primitive, get_max_vertices_per_primitive); @@ -217,6 +218,7 @@ PUBLISHED: MAKE_PROPERTY(supports_timer_query, get_supports_timer_query); MAKE_PROPERTY(timer_queries_active, get_timer_queries_active); MAKE_PROPERTY(max_color_targets, get_max_color_targets); + MAKE_PROPERTY(supports_dual_source_blending, get_supports_dual_source_blending); INLINE ShaderModel get_shader_model() const; INLINE void set_shader_model(ShaderModel shader_model); @@ -609,6 +611,7 @@ protected: bool _supports_indirect_draw; int _max_color_targets; + bool _supports_dual_source_blending; int _supported_geom_rendering; bool _color_scale_via_lighting; diff --git a/panda/src/downloader/bioPtr.I b/panda/src/downloader/bioPtr.I index a1e1f13e1d..f09ee7bbc8 100644 --- a/panda/src/downloader/bioPtr.I +++ b/panda/src/downloader/bioPtr.I @@ -18,6 +18,14 @@ INLINE BioPtr:: BioPtr(BIO *bio) : _bio(bio) { } +/** + * + */ +INLINE bool BioPtr:: +should_retry() const { + return (_bio != NULL) && BIO_should_retry(_bio); +} + /** * */ diff --git a/panda/src/downloader/bioPtr.cxx b/panda/src/downloader/bioPtr.cxx index 1aee90d207..15fe997c02 100644 --- a/panda/src/downloader/bioPtr.cxx +++ b/panda/src/downloader/bioPtr.cxx @@ -18,13 +18,46 @@ #include "urlSpec.h" #include "config_downloader.h" +#ifdef _WIN32 +#include +#else +#include +#include +#include +#include +#include +#endif + +#ifdef _WIN32 +static string format_error() { + PVOID buffer; + DWORD len; + len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, WSAGetLastError(), 0, (LPTSTR)&buffer, 0, NULL); + if (len == 0) { + return string("Unknown error message"); + } + + const char *text = (const char *)buffer; + while (len > 0 && isspace(text[len - 1])) { + --len; + } + + string result(text, len); + LocalFree(buffer); + return result; +} +#else +#define format_error() strerror(errno) +#endif + /** * This flavor of the constructor automatically creates a socket BIO and feeds * it the server and port name from the indicated URL. It doesn't call * BIO_do_connect(), though. */ BioPtr:: -BioPtr(const URLSpec &url) { +BioPtr(const URLSpec &url) : _connecting(false) { if (url.get_scheme() == "file") { // We're just reading a disk file. string filename = URLSpec::unquote(url.get_path()); @@ -48,14 +81,143 @@ BioPtr(const URLSpec &url) { _bio = BIO_new_file(filename.c_str(), "rb"); } else { - // A normal network-based URL. + // A normal network-based URL. We don't use BIO_new_connect since it + // doesn't handle IPv6 properly. _server_name = url.get_server(); _port = url.get_port(); - _bio = BIO_new_connect((char *)_server_name.c_str()); - BIO_set_conn_int_port(_bio, &_port); + _bio = NULL; + + // These hints tell getaddrinfo what kind of address to return. + struct addrinfo hints, *res = NULL; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; + hints.ai_family = support_ipv6 ? AF_UNSPEC : AF_INET; + hints.ai_socktype = SOCK_STREAM; + + // Resolve the hostname or address string. + int result = getaddrinfo(_server_name.c_str(), NULL, &hints, &res); + if (result != 0) { + const char *errmsg; +#ifndef _WIN32 + if (result == EAI_SYSTEM && errno != 0) { + errmsg = strerror(errno); + } else +#endif + { + errmsg = gai_strerror(result); + } + downloader_cat.error() + << "Failed to resolve " << url.get_server() << ": " << errmsg << "\n"; + return; + } + nassertv(res != NULL && res->ai_addr != NULL); + + // Store the real resolved address. + char buf[48]; + buf[0] = 0; +#ifdef _WIN32 + DWORD bufsize = sizeof(buf); + WSAAddressToStringA(res->ai_addr, res->ai_addrlen, NULL, buf, &bufsize); +#else + if (res->ai_addr->sa_family == AF_INET) { + inet_ntop(AF_INET, (char *)&((sockaddr_in *)res->ai_addr)->sin_addr, buf, sizeof(buf)); + + } else if (res->ai_addr->sa_family == AF_INET6) { + inet_ntop(AF_INET6, (char *)&((sockaddr_in6 *)res->ai_addr)->sin6_addr, buf, sizeof(buf)); + } +#endif + + if (buf[0]) { + _server_name = buf; + } + if (downloader_cat.is_debug()) { + downloader_cat.debug() + << "Resolved " << url.get_server() << " to " << buf << "\n"; + } + + // Create the socket. + int fd = socket(res->ai_family, SOCK_STREAM, IPPROTO_TCP); + if (fd < 0) { + downloader_cat.error() + << "Failed to create socket: " << format_error() << "\n"; + _bio = NULL; + freeaddrinfo(res); + return; + } + + // Store the address and length for later use in connect(). + nassertv(res->ai_addrlen <= sizeof(_addr)); + memcpy(&_addr, res->ai_addr, res->ai_addrlen); + _addrlen = res->ai_addrlen; + freeaddrinfo(res); + + // Also set the port we'd like to connect to. + if (_addr.ss_family == AF_INET) { + ((sockaddr_in &)_addr).sin_port = htons(_port); + } else if (_addr.ss_family == AF_INET6) { + ((sockaddr_in6 &)_addr).sin6_port = htons(_port); + } + + _bio = BIO_new_socket(fd, 1); } } +/** + * Sets the non-blocking flag on the socket. + */ +void BioPtr:: +set_nbio(bool nbio) { + if (_bio == NULL) { + return; + } + + int fd = -1; + BIO_get_fd(_bio, &fd); + nassertv_always(fd >= 0); + + BIO_socket_nbio(fd, nbio); +} + +/** + * Connects to the socket. Returns true on success. + */ +bool BioPtr:: +connect() { + if (_bio == NULL) { + return false; + } + + int fd = -1; + BIO_get_fd(_bio, &fd); + nassertr(fd >= 0, false); + + int result; + if (_connecting) { + result = BIO_sock_error(fd); + } else { + result = ::connect(fd, (sockaddr *)&_addr, _addrlen); + + if (result != 0 && BIO_sock_should_retry(-1)) { + // It's still in progress; we should retry later. This causes + // should_reply() to return true. + BIO_set_flags(_bio, BIO_FLAGS_SHOULD_RETRY); + _connecting = true; + return false; + } + } + BIO_clear_retry_flags(_bio); + _connecting = false; + + if (result != 0) { + downloader_cat.warning() + << "Failed to connect to " << _server_name << " port " << _port + << ": " << format_error() << "\n"; + return false; + } + + return true; +} + /** * */ @@ -64,7 +226,7 @@ BioPtr:: if (_bio != (BIO *)NULL) { if (downloader_cat.is_debug() && !_server_name.empty()) { downloader_cat.debug() - << "Dropping connection to " << _server_name << ":" << _port << "\n"; + << "Dropping connection to " << _server_name << " port " << _port << "\n"; } BIO_free_all(_bio); diff --git a/panda/src/downloader/bioPtr.h b/panda/src/downloader/bioPtr.h index 077a37ea84..332a1fc715 100644 --- a/panda/src/downloader/bioPtr.h +++ b/panda/src/downloader/bioPtr.h @@ -27,6 +27,14 @@ #include "openSSLWrapper.h" // must be included before any other openssl. #include "openssl/ssl.h" +#ifdef _WIN32 +#include +#include +#else +#include +#include +#endif + class URLSpec; /** @@ -41,6 +49,11 @@ public: BioPtr(const URLSpec &url); virtual ~BioPtr(); + void set_nbio(bool nbio); + bool connect(); + + INLINE bool should_retry() const; + INLINE BIO &operator *() const; INLINE BIO *operator -> () const; INLINE operator BIO * () const; @@ -55,6 +68,9 @@ private: BIO *_bio; string _server_name; int _port; + struct sockaddr_storage _addr; + socklen_t _addrlen; + bool _connecting; }; #include "bioPtr.I" diff --git a/panda/src/downloader/config_downloader.cxx b/panda/src/downloader/config_downloader.cxx index e1ee26ace5..c1db208d01 100644 --- a/panda/src/downloader/config_downloader.cxx +++ b/panda/src/downloader/config_downloader.cxx @@ -111,6 +111,12 @@ ConfigVariableInt tcp_header_size "length when writing a datagram on a TCP stream. This may be " "0, 2, or 4. The server and client must agree on this value.")); +ConfigVariableBool support_ipv6 +("support-ipv6", true, + PRC_DESC("Specifies whether IPv6 support should be enabled. This should " + "be true unless you are experiencing issues with Panda's IPv6 " + "support or are using a misconfigured system.")); + ConfigureFn(config_downloader) { init_libdownloader(); } diff --git a/panda/src/downloader/config_downloader.h b/panda/src/downloader/config_downloader.h index b31a7d2bd8..2ffd9be37a 100644 --- a/panda/src/downloader/config_downloader.h +++ b/panda/src/downloader/config_downloader.h @@ -45,6 +45,7 @@ extern ConfigVariableDouble http_idle_timeout; extern ConfigVariableInt http_max_connect_count; extern EXPCL_PANDAEXPRESS ConfigVariableInt tcp_header_size; +extern EXPCL_PANDAEXPRESS ConfigVariableBool support_ipv6; extern EXPCL_PANDAEXPRESS void init_libdownloader(); diff --git a/panda/src/downloader/decompressor.cxx b/panda/src/downloader/decompressor.cxx index 61b564a9eb..da78e19fa3 100644 --- a/panda/src/downloader/decompressor.cxx +++ b/panda/src/downloader/decompressor.cxx @@ -55,7 +55,7 @@ Decompressor:: int Decompressor:: initiate(const Filename &source_file) { string extension = source_file.get_extension(); - if (extension == "pz") { + if (extension == "pz" || extension == "gz") { Filename dest_file = source_file; dest_file = source_file.get_fullpath_wo_extension(); return initiate(source_file, dest_file); diff --git a/panda/src/downloader/downloadDb.cxx b/panda/src/downloader/downloadDb.cxx index 7e56101ffa..f2a734af17 100644 --- a/panda/src/downloader/downloadDb.cxx +++ b/panda/src/downloader/downloadDb.cxx @@ -23,13 +23,13 @@ // Defines // Written at the top of the file so we know this is a downloadDb -PN_uint32 DownloadDb::_magic_number = 0xfeedfeed; +uint32_t DownloadDb::_magic_number = 0xfeedfeed; // Written at the top of the file to signify we are not done writing to the // file yet. If you load a db with this magic number that means the previous // time it got written out was probably interrupted in the middle of the // write. -PN_uint32 DownloadDb::_bogus_magic_number = 0x11111111; +uint32_t DownloadDb::_bogus_magic_number = 0x11111111; static string @@ -505,7 +505,7 @@ add_file_record(PT(FileRecord) fr) { DownloadDb::Db:: Db() { // The head is a magic number and the number of multifiles in the db - _header_length = sizeof(_magic_number) + sizeof(PN_int32); + _header_length = sizeof(_magic_number) + sizeof(int32_t); } @@ -588,7 +588,7 @@ parse_header(const string &data) { // Make sure we have a good header DatagramIterator di(dg); - PN_uint32 magic_number = di.get_uint32(); + uint32_t magic_number = di.get_uint32(); downloader_cat.debug() << "Parsed magic number: " << magic_number << endl; // If the magic number is equal to the bogus magic number it signifies that @@ -608,7 +608,7 @@ parse_header(const string &data) { return -1; } - PN_int32 num_multifiles = di.get_int32(); + int32_t num_multifiles = di.get_int32(); downloader_cat.debug() << "Parsed number of multifiles: " << num_multifiles << endl; @@ -626,7 +626,7 @@ int DownloadDb::Db:: parse_record_header(const string &data) { Datagram dg(data); DatagramIterator di(dg); - PN_int32 record_length = di.get_int32(); + int32_t record_length = di.get_int32(); downloader_cat.spam() << "Parsed record header length: " << record_length << endl; @@ -645,7 +645,7 @@ parse_mfr(const string &data) { Datagram dg(data); DatagramIterator di(dg); - PN_int32 mfr_name_length = di.get_int32(); + int32_t mfr_name_length = di.get_int32(); mfr->_name = di.extract_bytes(mfr_name_length); mfr->_phase = di.get_float64(); mfr->_size = di.get_int32(); @@ -682,7 +682,7 @@ parse_fr(const string &data) { Datagram dg(data); DatagramIterator di(dg); - PN_int32 fr_name_length = di.get_int32(); + int32_t fr_name_length = di.get_int32(); fr->_name = di.extract_bytes(fr_name_length); // At one time, we stored files in the database with a backslash separator. @@ -725,7 +725,7 @@ read(StreamReader &sr, bool want_server_info) { for (int i = 0; i < num_multifiles; i++) { // The multifile record header is just one int which represents the size // of the record - int mfr_header_length = sizeof(PN_int32); + int mfr_header_length = sizeof(int32_t); string mfr_header = sr.extract_bytes(mfr_header_length); if (mfr_header.size() != (size_t)mfr_header_length) { @@ -755,7 +755,7 @@ read(StreamReader &sr, bool want_server_info) { for (int j = 0; j < mfr->_num_files; j++) { // The file record header is just one int which represents the size of // the record - int fr_header_length = sizeof(PN_int32); + int fr_header_length = sizeof(int32_t); // Read the header string fr_header = sr.extract_bytes(fr_header_length); @@ -802,11 +802,11 @@ write(StreamWriter &sw, bool want_server_info) { // Declare these outside the loop so we do not keep creating and deleting // them PN_float64 phase; - PN_int32 size; - PN_int32 status; - PN_int32 num_files; - PN_int32 name_length; - PN_int32 header_length; + int32_t size; + int32_t status; + int32_t num_files; + int32_t name_length; + int32_t header_length; // Iterate over the multifiles writing them to the stream pvector< PT(MultifileRecord) >::const_iterator i = _mfile_records.begin(); @@ -825,7 +825,7 @@ write(StreamWriter &sw, bool want_server_info) { (*i)->_name.length() + // Size of the name string sizeof(phase) + sizeof(size) + sizeof(status) + sizeof(num_files) + - sizeof(PN_uint32)*4; // Size of hash value + sizeof(uint32_t)*4; // Size of hash value // Add the length of this entire datagram sw.add_int32(header_length); diff --git a/panda/src/downloader/downloadDb.h b/panda/src/downloader/downloadDb.h index d46f3a1890..e1605f6295 100644 --- a/panda/src/downloader/downloadDb.h +++ b/panda/src/downloader/downloadDb.h @@ -156,7 +156,7 @@ public: int _size; int _status; HashVal _hash; - PN_int32 _num_files; + int32_t _num_files; FileRecords _file_records; }; @@ -182,7 +182,7 @@ public: bool write_header(ostream &write_stream); bool write_bogus_header(StreamWriter &sw); private: - PN_int32 _header_length; + int32_t _header_length; }; PUBLISHED: @@ -197,8 +197,8 @@ public: Db _server_db; // Magic number for knowing this is a download Db - static PN_uint32 _magic_number; - static PN_uint32 _bogus_magic_number; + static uint32_t _magic_number; + static uint32_t _bogus_magic_number; typedef pvector VectorHash; typedef pmap VersionMap; diff --git a/panda/src/downloader/httpChannel.cxx b/panda/src/downloader/httpChannel.cxx index 7dbe4d1a32..96980fdfaa 100644 --- a/panda/src/downloader/httpChannel.cxx +++ b/panda/src/downloader/httpChannel.cxx @@ -375,26 +375,28 @@ run() { } // No connection. Attempt to establish one. + URLSpec url; if (_proxy.empty()) { - _bio = new BioPtr(_request.get_url()); + url = _request.get_url(); } else { - _bio = new BioPtr(_proxy); + url = _proxy; } + _bio = new BioPtr(url); _source = new BioStreamPtr(new BioStream(_bio)); if (_nonblocking) { - BIO_set_nbio(*_bio, 1); + _bio->set_nbio(true); } if (downloader_cat.is_debug()) { if (_connect_count > 0) { downloader_cat.debug() << _NOTIFY_HTTP_CHANNEL_ID - << "Reconnecting to " << _bio->get_server_name() << ":" + << "Reconnecting to " << _bio->get_server_name() << " port " << _bio->get_port() << "\n"; } else { downloader_cat.debug() << _NOTIFY_HTTP_CHANNEL_ID - << "Connecting to " << _bio->get_server_name() << ":" + << "Connecting to " << _bio->get_server_name() << " port " << _bio->get_port() << "\n"; } } @@ -941,14 +943,14 @@ bool HTTPChannel:: run_connecting() { _status_entry = StatusEntry(); - if (BIO_do_connect(*_bio) <= 0) { - if (BIO_should_retry(*_bio)) { + if (!_bio->connect()) { + if (_bio->should_retry()) { _state = S_connecting_wait; return false; } downloader_cat.info() << _NOTIFY_HTTP_CHANNEL_ID - << "Could not connect to " << _bio->get_server_name() << ":" + << "Could not connect to " << _bio->get_server_name() << " port " << _bio->get_port() << "\n"; OpenSSLWrapper::get_global_ptr()->notify_ssl_errors(); _status_entry._status_code = SC_no_connection; @@ -959,7 +961,7 @@ run_connecting() { if (downloader_cat.is_debug()) { downloader_cat.debug() << _NOTIFY_HTTP_CHANNEL_ID - << "Connected to " << _bio->get_server_name() << ":" + << "Connected to " << _bio->get_server_name() << " port " << _bio->get_port() << "\n"; } @@ -1362,6 +1364,10 @@ run_socks_proxy_connect_reply() { total_bytes += (unsigned int)reply[4]; break; + case 0x04: // IPv6 + total_bytes += 16; + break; + default: downloader_cat.info() << _NOTIFY_HTTP_CHANNEL_ID @@ -1396,6 +1402,18 @@ run_socks_proxy_connect_reply() { case 0x03: // DNS connect_host = string(&reply[5], (unsigned int)reply[4]); break; + + case 0x04: // IPv6 + { + char buf[48]; + sprintf(buf, "[%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx" + ":%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx]", + reply[4], reply[5], reply[6], reply[7], reply[8], reply[9], + reply[10], reply[11], reply[12], reply[13], reply[14], + reply[15], reply[16], reply[17], reply[18], reply[19]); + total_bytes += 16; + } + break; } int connect_port = @@ -2742,8 +2760,8 @@ server_getline(string &str) { } str = str.substr(0, p); } - if (downloader_cat.is_debug()) { - downloader_cat.debug() + if (downloader_cat.is_spam()) { + downloader_cat.spam() << _NOTIFY_HTTP_CHANNEL_ID << "recv: " << str << "\n"; } @@ -2915,7 +2933,7 @@ server_send(const string &str, bool secret) { } #ifndef NDEBUG - if (!secret && downloader_cat.is_debug()) { + if (!secret && downloader_cat.is_spam()) { show_send(str.substr(0, write_count)); } #endif @@ -3486,14 +3504,19 @@ make_header() { if (_client->get_http_version() >= HTTPEnum::HV_11) { - stream - << "Host: " << _request.get_url().get_server(); - if (!_request.get_url().is_default_port()) { + if (_request.get_url().has_port() && _request.get_url().is_default_port()) { // It appears that some servers (notably gstatic.com) might return a 404 // if you include an explicit port number in with the Host: header, even // if it is the default port. So, don't include the port number unless // we need to. - stream << ":" << _request.get_url().get_port(); + string server = _request.get_url().get_server(); + if (server.find(':') != string::npos) { + stream << "Host: [" << server << "]"; + } else { + stream << "Host: " << server; + } + } else { + stream << "Host: " << _request.get_url().get_server_and_port(); } stream << "\r\n"; if (!get_persistent_connection()) { @@ -3703,14 +3726,14 @@ show_send(const string &message) { size_t newline = message.find('\n', start); while (newline != string::npos) { // Assume every \n is preceded by a \r. - downloader_cat.debug() + downloader_cat.spam() << "send: " << message.substr(start, newline - start - 1) << "\n"; start = newline + 1; newline = message.find('\n', start); } if (start < message.length()) { - downloader_cat.debug() + downloader_cat.spam() << "send: " << message.substr(start) << " (no newline)\n"; } } diff --git a/panda/src/downloader/httpDate.cxx b/panda/src/downloader/httpDate.cxx index e2df9d1530..f3d156fc6a 100644 --- a/panda/src/downloader/httpDate.cxx +++ b/panda/src/downloader/httpDate.cxx @@ -223,8 +223,9 @@ HTTPDate(const string &format) { struct tm *tp = localtime(&now); _time -= tp->tm_gmtoff; #elif defined(_WIN32) - extern long int _timezone; - _time -= _timezone; + long int timezone; + _get_timezone(&timezone); + _time -= timezone; #else extern long int timezone; _time -= timezone; diff --git a/panda/src/downloader/multiplexStreamBuf.cxx b/panda/src/downloader/multiplexStreamBuf.cxx index e78eb1d838..daa2d78ed9 100644 --- a/panda/src/downloader/multiplexStreamBuf.cxx +++ b/panda/src/downloader/multiplexStreamBuf.cxx @@ -12,6 +12,7 @@ */ #include "multiplexStreamBuf.h" +#include "lightMutexHolder.h" #if defined(WIN32_VC) || defined(WIN64_VC) #define WINDOWS_LEAN_AND_MEAN @@ -113,10 +114,8 @@ void MultiplexStreamBuf:: add_output(MultiplexStreamBuf::BufferType buffer_type, MultiplexStreamBuf::OutputType output_type, ostream *out, FILE *fout, bool owns_obj) { -#ifdef OLD_HAVE_IPC // Ensure that we have the mutex while we fiddle with the list of outputs. - mutex_lock m(_lock); -#endif + LightMutexHolder holder(_lock); Output o; o._buffer_type = buffer_type; @@ -133,9 +132,7 @@ add_output(MultiplexStreamBuf::BufferType buffer_type, */ void MultiplexStreamBuf:: flush() { -#ifdef OLD_HAVE_IPC - mutex_lock m(_lock); -#endif + LightMutexHolder holder(_lock); write_chars("", 0, true); } @@ -146,9 +143,7 @@ flush() { */ int MultiplexStreamBuf:: overflow(int ch) { -#ifdef OLD_HAVE_IPC - mutex_lock m(_lock); -#endif + LightMutexHolder holder(_lock); streamsize n = pptr() - pbase(); @@ -172,9 +167,7 @@ overflow(int ch) { */ int MultiplexStreamBuf:: sync() { -#ifdef OLD_HAVE_IPC - mutex_lock m(_lock); -#endif + LightMutexHolder holder(_lock); streamsize n = pptr() - pbase(); @@ -242,5 +235,4 @@ write_chars(const char *start, int length, bool flush) { break; } } - } diff --git a/panda/src/downloader/multiplexStreamBuf.h b/panda/src/downloader/multiplexStreamBuf.h index e2d0f589b5..52a75c5ff9 100644 --- a/panda/src/downloader/multiplexStreamBuf.h +++ b/panda/src/downloader/multiplexStreamBuf.h @@ -17,6 +17,7 @@ #include "pandabase.h" #include "pvector.h" +#include "lightMutex.h" #include /** @@ -69,6 +70,7 @@ private: typedef pvector Outputs; Outputs _outputs; + LightMutex _lock; string _line_buffer; }; diff --git a/panda/src/downloader/socketStream.h b/panda/src/downloader/socketStream.h index 48c7524cbc..36065e42af 100644 --- a/panda/src/downloader/socketStream.h +++ b/panda/src/downloader/socketStream.h @@ -126,6 +126,10 @@ public: INLINE ISocketStream(streambuf *buf); virtual ~ISocketStream(); +#if _MSC_VER >= 1800 + INLINE ISocketStream(const ISocketStream ©) = delete; +#endif + PUBLISHED: enum ReadState { RS_initial, @@ -155,6 +159,10 @@ class EXPCL_PANDAEXPRESS OSocketStream : public ostream, public SSWriter { public: INLINE OSocketStream(streambuf *buf); +#if _MSC_VER >= 1800 + INLINE OSocketStream(const OSocketStream ©) = delete; +#endif + PUBLISHED: virtual bool is_closed() = 0; virtual void close() = 0; @@ -170,6 +178,10 @@ class EXPCL_PANDAEXPRESS SocketStream : public iostream, public SSReader, public public: INLINE SocketStream(streambuf *buf); +#if _MSC_VER >= 1800 + INLINE SocketStream(const SocketStream ©) = delete; +#endif + PUBLISHED: virtual bool is_closed() = 0; virtual void close() = 0; diff --git a/panda/src/downloader/urlSpec.I b/panda/src/downloader/urlSpec.I index 5d4654e1f7..7af6f4339b 100644 --- a/panda/src/downloader/urlSpec.I +++ b/panda/src/downloader/urlSpec.I @@ -19,14 +19,6 @@ URLSpec(const string &url, bool server_name_expected) { set_url(url, server_name_expected); } -/** - * - */ -INLINE URLSpec:: -URLSpec(const URLSpec ©) { - (*this) = copy; -} - /** * */ @@ -40,7 +32,7 @@ operator = (const string &url) { */ INLINE bool URLSpec:: operator == (const URLSpec &other) const { - return _url == other._url; + return compare_to(other) == 0; } /** @@ -48,7 +40,7 @@ operator == (const URLSpec &other) const { */ INLINE bool URLSpec:: operator != (const URLSpec &other) const { - return !operator == (other); + return compare_to(other) != 0; } /** @@ -56,16 +48,7 @@ operator != (const URLSpec &other) const { */ INLINE bool URLSpec:: operator < (const URLSpec &other) const { - return _url < other._url; -} - -/** - * Returns a number less than zero if this URLSpec sorts before the other one, - * greater than zero if it sorts after, or zero if they are equivalent. - */ -INLINE int URLSpec:: -compare_to(const URLSpec &other) const { - return strcmp(_url.c_str(), other._url.c_str()); + return compare_to(other) < 0; } /** @@ -148,7 +131,8 @@ get_username() const { } /** - * Returns the server name specified by the URL, if any. + * Returns the server name specified by the URL, if any. In case of an IPv6 + * address, does not include the enclosing brackets. */ INLINE string URLSpec:: get_server() const { @@ -218,13 +202,23 @@ c_str() const { } /** - * + * Returns false if the URLSpec is valid (not empty), or true if it is an + * empty string. */ INLINE bool URLSpec:: empty() const { return _url.empty(); } +/** + * Returns true if the URLSpec is valid (not empty), or false if it is an + * empty string. + */ +INLINE URLSpec:: +operator bool() const { + return !_url.empty(); +} + /** * */ @@ -233,12 +227,20 @@ length() const { return _url.length(); } +/** + * + */ +INLINE size_t URLSpec:: +size() const { + return _url.size(); +} + /** * */ INLINE char URLSpec:: -operator [] (int n) const { - nassertr(n >= 0 && n < (int)_url.length(), '\0'); +operator [] (size_t n) const { + nassertr(n < _url.length(), '\0'); return _url[n]; } diff --git a/panda/src/downloader/urlSpec.cxx b/panda/src/downloader/urlSpec.cxx index e724e9a044..09769f3693 100644 --- a/panda/src/downloader/urlSpec.cxx +++ b/panda/src/downloader/urlSpec.cxx @@ -12,10 +12,11 @@ */ #include "urlSpec.h" +#include "filename.h" +#include "string_utils.h" #include - /** * */ @@ -35,24 +36,88 @@ URLSpec() { _query_start = 0; } +/** + * Creates a URLSpec by appending a path to the end of the old URLSpec, + * inserting an intervening forward slash if necessary. + */ +URLSpec:: +URLSpec(const URLSpec &url, const Filename &path) { + (*this) = url; + if (!path.empty()) { + string dirname = get_path(); + + // Check if the path already ends in a slash. + if (!dirname.empty() && dirname[dirname.size() - 1] == '/') { + if (path[0] == '/') { + // And the filename begins with one. Remove the extra slash. + dirname.resize(dirname.size() - 1); + } + } else { + if (path[0] != '/') { + // Neither has a slash, so insert one. + dirname += '/'; + } + } + set_path(dirname + path.get_fullpath()); + } +} + +/** + * Returns a number less than zero if this URLSpec sorts before the other one, + * greater than zero if it sorts after, or zero if they are equivalent. + */ +int URLSpec:: +compare_to(const URLSpec &other) const { + int cmp; + if (has_scheme() != other.has_scheme()) { + return (has_scheme() < other.has_scheme()) ? -1 : 1; + } + if (has_scheme()) { + cmp = cmp_nocase(get_scheme(), other.get_scheme()); + if (cmp != 0) { + return cmp; + } + } + if (has_username() != other.has_username()) { + return (has_username() < other.has_username()) ? -1 : 1; + } + if (has_username()) { + cmp = get_username().compare(other.get_username()); + if (cmp != 0) { + return cmp; + } + } + if (has_server() != other.has_server()) { + return (has_server() < other.has_server()) ? -1 : 1; + } + if (has_server()) { + cmp = cmp_nocase(get_server(), other.get_server()); + if (cmp != 0) { + return cmp; + } + } + return get_path_and_query().compare(other.get_path_and_query()); +} + /** * */ -void URLSpec:: -operator = (const URLSpec ©) { - _url = copy._url; - _port = copy._port; - _flags = copy._flags; - _scheme_end = copy._scheme_end; - _username_start = copy._username_start; - _username_end = copy._username_end; - _server_start = copy._server_start; - _server_end = copy._server_end; - _port_start = copy._port_start; - _port_end = copy._port_end; - _path_start = copy._path_start; - _path_end = copy._path_end; - _query_start = copy._query_start; +size_t URLSpec:: +get_hash() const { + size_t hash = 0; + hash = int_hash::add_hash(hash, _flags & (F_has_scheme | F_has_username | F_has_server)); + if (has_scheme()) { + hash = string_hash::add_hash(hash, downcase(get_scheme())); + } + if (has_username()) { + hash = string_hash::add_hash(hash, get_username()); + } + if (has_server()) { + hash = string_hash::add_hash(hash, downcase(get_server())); + } + hash = int_hash::add_hash(hash, get_port()); + hash = string_hash::add_hash(hash, get_path_and_query()); + return hash; } /** @@ -71,7 +136,7 @@ get_scheme() const { * Returns the port number specified by the URL, or the default port if not * specified. */ -int URLSpec:: +uint16_t URLSpec:: get_port() const { if (has_port()) { return _port; @@ -115,14 +180,25 @@ get_default_port_for_scheme(const string &scheme) { * Returns a string consisting of the server name, followed by a colon, * followed by the port number. If the port number is not explicitly given in * the URL, this string will include the implicit port number. + * If the server is an IPv6 address, it will be enclosed in square brackets. */ string URLSpec:: get_server_and_port() const { - if (has_port()) { - return _url.substr(_server_start, _port_end - _server_start); - } ostringstream strm; - strm << get_server() << ":" << get_port(); + string server = get_server(); + if (server.find(':') != string::npos) { + // Protect an IPv6 address by enclosing it in square brackets. + strm << '[' << server << ']'; + + } else { + if (!has_port()) { + return server; + } + strm << server; + } + if (has_port()) { + strm << ":" << get_port(); + } return strm.str(); } @@ -285,7 +361,15 @@ set_username(const string &username) { if (!username.empty()) { authority = username + "@"; } - authority += get_server(); + + string server = get_server(); + if (server.find(':') != string::npos) { + // Protect an IPv6 address by enclosing it in square brackets. + authority += "[" + server + "]"; + } else { + authority += server; + } + if (has_port()) { authority += ":"; authority += get_port_str(); @@ -296,6 +380,8 @@ set_username(const string &username) { /** * Replaces the server part of the URL specification. + * Unlike set_server_and_port, this method does not require IPv6 addresses to + * be enclosed in square brackets. */ void URLSpec:: set_server(const string &server) { @@ -307,7 +393,14 @@ set_server(const string &server) { if (has_username()) { authority = get_username() + "@"; } - authority += server; + + if (server.find(':') != string::npos) { + // Protect an IPv6 address by enclosing it in square brackets. + authority += "[" + server + "]"; + } else { + authority += server; + } + if (has_port()) { authority += ":"; authority += get_port_str(); @@ -329,7 +422,14 @@ set_port(const string &port) { if (has_username()) { authority = get_username() + "@"; } - authority += get_server(); + + string server = get_server(); + if (server.find(':') != string::npos) { + // Protect an IPv6 address by enclosing it in square brackets. + authority += "[" + server + "]"; + } else { + authority += server; + } if (!port.empty()) { authority += ":"; @@ -344,16 +444,15 @@ set_port(const string &port) { * number. */ void URLSpec:: -set_port(int port) { - ostringstream str; - str << port; - set_port(str.str()); +set_port(uint16_t port) { + set_port(format_string(port)); } /** * Replaces the server and port parts of the URL specification simultaneously. * The input string should be of the form "server:port", or just "server" to * make the port number implicit. + * Any IPv6 address must be enclosed in square brackets. */ void URLSpec:: set_server_and_port(const string &server_and_port) { @@ -476,6 +575,18 @@ set_url(const string &url, bool server_name_expected) { } } + // Now normalize the percent-encoding sequences by making them uppercase. + for (p = 0; p + 2 < _url.length();) { + if (_url[p++] == '%') { + if (_url[p] != '%') { + _url[p] = toupper(_url[p]); + ++p; + _url[p] = toupper(_url[p]); + } + ++p; + } + } + // What have we got? _flags = 0; _port = 0; @@ -781,18 +892,39 @@ parse_authority() { _server_start = at_sign + 1; } - // Is there a port? - size_t colon = _url.find(':', _server_start); - if (colon < _port_end) { - // Yep. + // Is this an IPv6 address in square brackets? + size_t bracket = _url.find('[', _server_start); + if (bracket < _port_end) { + // We won't include the brackets in the server name. + ++_server_start; + + bracket = _url.find(']'); + if (bracket < _server_end) { + _server_end = bracket; + + // Is it followed directly by a port colon? + size_t colon = _url.find(':', _server_end); + if (colon < _port_end) { + _port_start = colon + 1; + } + } + } else { + // Is there a port? + size_t colon = _url.find(':', _server_start); + if (colon < _port_end) { + // Yep. + _server_end = colon; + _port_start = colon + 1; + } + } + + if (_port_start < _port_end) { _flags |= F_has_port; - _server_end = colon; - _port_start = colon + 1; // Decode the port into an integer. Don't bother to error check if it's // not really an integer. string port_str = _url.substr(_port_start, _port_end - _port_start); - _port = atoi(port_str.c_str()); + _port = (uint16_t)atoi(port_str.c_str()); } // Make sure the server name is lowercase only. diff --git a/panda/src/downloader/urlSpec.h b/panda/src/downloader/urlSpec.h index 7b7cc4e9b2..592fe22087 100644 --- a/panda/src/downloader/urlSpec.h +++ b/panda/src/downloader/urlSpec.h @@ -17,6 +17,8 @@ #include "pandabase.h" #include "pnotify.h" +class Filename; + /** * A container for a URL, e.g. "http://server:port/path". * @@ -27,14 +29,14 @@ class EXPCL_PANDAEXPRESS URLSpec { PUBLISHED: URLSpec(); INLINE URLSpec(const string &url, bool server_name_expected = false); - INLINE URLSpec(const URLSpec ©); + URLSpec(const URLSpec &url, const Filename &path); INLINE void operator = (const string &url); - void operator = (const URLSpec ©); INLINE bool operator == (const URLSpec &other) const; INLINE bool operator != (const URLSpec &other) const; INLINE bool operator < (const URLSpec &other) const; - INLINE int compare_to(const URLSpec &other) const; + int compare_to(const URLSpec &other) const; + size_t get_hash() const; INLINE bool has_scheme() const; INLINE bool has_authority() const; @@ -49,7 +51,7 @@ PUBLISHED: INLINE string get_username() const; INLINE string get_server() const; INLINE string get_port_str() const; - int get_port() const; + uint16_t get_port() const; string get_server_and_port() const; bool is_default_port() const; static int get_default_port_for_scheme(const string &scheme); @@ -65,7 +67,7 @@ PUBLISHED: void set_username(const string &username); void set_server(const string &server); void set_port(const string &port); - void set_port(int port); + void set_port(uint16_t port); void set_server_and_port(const string &server_and_port); void set_path(const string &path); void set_query(const string &query); @@ -75,8 +77,10 @@ PUBLISHED: INLINE operator const string & () const; INLINE const char *c_str() const; INLINE bool empty() const; + INLINE operator bool() const; INLINE size_t length() const; - INLINE char operator [] (int n) const; + INLINE size_t size() const; + INLINE char operator [] (size_t n) const; bool input(istream &in); void output(ostream &out) const; @@ -86,6 +90,16 @@ PUBLISHED: static string unquote(const string &source); static string unquote_plus(const string &source); + MAKE_PROPERTY(scheme, get_scheme, set_scheme); + MAKE_PROPERTY(authority, get_authority, set_authority); + MAKE_PROPERTY(username, get_username, set_username); + MAKE_PROPERTY(server, get_server, set_server); + MAKE_PROPERTY(port, get_port, set_port); + MAKE_PROPERTY(server_and_port, get_server_and_port, set_server_and_port); + MAKE_PROPERTY(path, get_path, set_path); + MAKE_PROPERTY(query, get_query, set_query); + MAKE_PROPERTY(ssl, is_ssl); + private: void parse_authority(); @@ -100,7 +114,7 @@ private: }; string _url; - int _port; + uint16_t _port; int _flags; size_t _scheme_end; diff --git a/panda/src/downloadertools/multify.cxx b/panda/src/downloadertools/multify.cxx index 8caaa80736..72506f4095 100644 --- a/panda/src/downloadertools/multify.cxx +++ b/panda/src/downloadertools/multify.cxx @@ -18,6 +18,7 @@ #include "filename.h" #include "pset.h" #include "vector_string.h" +#include "virtualFileSystem.h" #include #include @@ -631,8 +632,17 @@ list_files(const vector_string ¶ms) { cerr << multifile_name << " not found.\n"; return false; } + // We happen to know that we can read the index without doing a seek. + // So this is the only place where we accept a .pz/.gz compressed .mf. + VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); + istream *istr = vfs->open_read_file(multifile_name, true); + if (istr == NULL) { + cerr << "Unable to open " << multifile_name << " for reading.\n"; + return false; + } + PT(Multifile) multifile = new Multifile; - if (!multifile->open_read(multifile_name)) { + if (!multifile->open_read(new IStreamWrapper(istr, true), true)) { cerr << "Unable to open " << multifile_name << " for reading.\n"; return false; } diff --git a/panda/src/dxgsg9/config_dxgsg9.cxx b/panda/src/dxgsg9/config_dxgsg9.cxx index 64831d08c9..037d8dd919 100644 --- a/panda/src/dxgsg9/config_dxgsg9.cxx +++ b/panda/src/dxgsg9/config_dxgsg9.cxx @@ -265,3 +265,8 @@ init_libdxgsg9() { PandaSystem *ps = PandaSystem::get_global_ptr(); ps->add_system("DirectX9"); } + +// Necessary to allow use of dxerr from MSVC 2015 +#if _MSC_VER >= 1900 +int (WINAPIV * __vsnprintf)(char *, size_t, const char*, va_list) = _vsnprintf; +#endif diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index f71e01d298..43bf6d3311 100644 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -3766,43 +3766,24 @@ do_issue_blending() { } } - const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot())); - CPT(ColorBlendAttrib) color_blend = target_color_blend; - ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode(); + const ColorBlendAttrib *color_blend; + _target_rs->get_attrib_def(color_blend); + ColorBlendAttrib::Mode color_blend_mode = color_blend->get_mode(); - const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot())); + const TransparencyAttrib *target_transparency; + _target_rs->get_attrib_def(target_transparency); TransparencyAttrib::Mode transparency_mode = target_transparency->get_mode(); // Is there a color blend set? if (color_blend_mode != ColorBlendAttrib::M_none) { set_render_state(D3DRS_ALPHABLENDENABLE, TRUE); - - switch (color_blend_mode) { - case ColorBlendAttrib::M_add: - set_render_state(D3DRS_BLENDOP, D3DBLENDOP_ADD); - break; - - case ColorBlendAttrib::M_subtract: - set_render_state(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT); - break; - - case ColorBlendAttrib::M_inv_subtract: - set_render_state(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT); - break; - - case ColorBlendAttrib::M_min: - set_render_state(D3DRS_BLENDOP, D3DBLENDOP_MIN); - break; - - case ColorBlendAttrib::M_max: - set_render_state(D3DRS_BLENDOP, D3DBLENDOP_MAX); - break; - } - - set_render_state(D3DRS_SRCBLEND, - get_blend_func(color_blend->get_operand_a())); - set_render_state(D3DRS_DESTBLEND, - get_blend_func(color_blend->get_operand_b())); + set_render_state(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + set_render_state(D3DRS_BLENDOP, get_blend_mode(color_blend_mode)); + set_render_state(D3DRS_BLENDOPALPHA, get_blend_mode(color_blend->get_alpha_mode())); + set_render_state(D3DRS_SRCBLEND, get_blend_func(color_blend->get_operand_a())); + set_render_state(D3DRS_DESTBLEND, get_blend_func(color_blend->get_operand_b())); + set_render_state(D3DRS_SRCBLENDALPHA, get_blend_func(color_blend->get_alpha_operand_a())); + set_render_state(D3DRS_DESTBLENDALPHA, get_blend_func(color_blend->get_alpha_operand_b())); return; } @@ -3817,6 +3798,7 @@ do_issue_blending() { case TransparencyAttrib::M_multisample_mask: case TransparencyAttrib::M_dual: set_render_state(D3DRS_ALPHABLENDENABLE, TRUE); + set_render_state(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); set_render_state(D3DRS_BLENDOP, D3DBLENDOP_ADD); set_render_state(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); set_render_state(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); @@ -3824,6 +3806,7 @@ do_issue_blending() { case TransparencyAttrib::M_premultiplied_alpha: set_render_state(D3DRS_ALPHABLENDENABLE, TRUE); + set_render_state(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); set_render_state(D3DRS_BLENDOP, D3DBLENDOP_ADD); set_render_state(D3DRS_SRCBLEND, D3DBLEND_ONE); set_render_state(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); @@ -4052,6 +4035,33 @@ get_light_color(Light *light) const { return *(D3DCOLORVALUE *)cf.get_data(); } +/** + * Maps from ColorBlendAttrib::Mode to D3DBLENDOP vaule. + */ +D3DBLENDOP DXGraphicsStateGuardian9:: +get_blend_mode(ColorBlendAttrib::Mode mode) { + switch (mode) { + case ColorBlendAttrib::M_add: + return D3DBLENDOP_ADD; + + case ColorBlendAttrib::M_subtract: + return D3DBLENDOP_SUBTRACT; + + case ColorBlendAttrib::M_inv_subtract: + return D3DBLENDOP_REVSUBTRACT; + + case ColorBlendAttrib::M_min: + return D3DBLENDOP_MIN; + + case ColorBlendAttrib::M_max: + return D3DBLENDOP_MAX; + } + + dxgsg9_cat.error() + << "Unknown color blend mode " << (int)mode << endl; + return D3DBLENDOP_ADD; +} + /** * Maps from ColorBlendAttrib::Operand to D3DBLEND value. */ @@ -4106,6 +4116,20 @@ get_blend_func(ColorBlendAttrib::Operand operand) { case ColorBlendAttrib::O_incoming_color_saturate: return D3DBLEND_SRCALPHASAT; + + case ColorBlendAttrib::O_incoming1_color: + return (D3DBLEND)16; //D3DBLEND_SRCCOLOR2; + + case ColorBlendAttrib::O_one_minus_incoming1_color: + return (D3DBLEND)17; //D3DBLEND_INVSRCCOLOR2; + + case ColorBlendAttrib::O_incoming1_alpha: + // Not supported by DX9. + return (D3DBLEND)18; + + case ColorBlendAttrib::O_one_minus_incoming1_alpha: + // Not supported by DX9. + return (D3DBLEND)19; } dxgsg9_cat.error() diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h index 4a51d214cb..512cedbda2 100644 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h @@ -217,6 +217,7 @@ protected: const D3DCOLORVALUE &get_light_color(Light *light) const; INLINE static D3DTRANSFORMSTATETYPE get_tex_mat_sym(int stage_index); + static D3DBLENDOP get_blend_mode(ColorBlendAttrib::Mode mode); static D3DBLEND get_blend_func(ColorBlendAttrib::Operand operand); void report_texmgr_stats(); diff --git a/panda/src/dxml/config_dxml.cxx b/panda/src/dxml/config_dxml.cxx index 48c9161805..e6691bc676 100644 --- a/panda/src/dxml/config_dxml.cxx +++ b/panda/src/dxml/config_dxml.cxx @@ -94,7 +94,15 @@ BEGIN_PUBLISH void print_xml_to_file(const Filename &filename, TiXmlNode *xnode) { string os_name = filename.to_os_specific(); +#ifdef _WIN32 + FILE *file; + if (fopen_s(&file, os_name.c_str(), "w") != 0) { +#else FILE *file = fopen(os_name.c_str(), "w"); + if (file == NULL) { +#endif + dxml_cat.error() << "Failed to open " << filename << " for writing\n"; + } xnode->Print(file, 0); fclose(file); } diff --git a/panda/src/egg/eggCompositePrimitive.h b/panda/src/egg/eggCompositePrimitive.h index 7cbbcf0204..b816d816c7 100644 --- a/panda/src/egg/eggCompositePrimitive.h +++ b/panda/src/egg/eggCompositePrimitive.h @@ -38,6 +38,8 @@ PUBLISHED: MAKE_SEQ(get_components, get_num_components, get_component); INLINE void set_component(int i, const EggAttributes *attrib); + MAKE_SEQ_PROPERTY(components, get_num_components, get_component, set_component); + INLINE bool triangulate_into(EggGroupNode *container) const; PT(EggCompositePrimitive) triangulate_in_place(); diff --git a/panda/src/egg/eggGroup.h b/panda/src/egg/eggGroup.h index fc23e97554..69d72807a9 100644 --- a/panda/src/egg/eggGroup.h +++ b/panda/src/egg/eggGroup.h @@ -284,6 +284,45 @@ PUBLISHED: INLINE bool has_scrolling_uvs(); + MAKE_PROPERTY(group_type, get_group_type, set_group_type); + MAKE_PROPERTY(billboard_type, get_billboard_type, set_billboard_type); + MAKE_PROPERTY2(billboard_center, has_billboard_center, get_billboard_center, + set_billboard_center, clear_billboard_center); + MAKE_PROPERTY(cs_type, get_cs_type, set_cs_type); + MAKE_PROPERTY(collide_flags, get_collide_flags, set_collide_flags); + MAKE_PROPERTY(collision_name, get_collision_name, set_collision_name); + MAKE_PROPERTY(dcs_type, get_dcs_type, set_dcs_type); + MAKE_PROPERTY(dart_type, get_dart_type, set_dart_type); + MAKE_PROPERTY(switch_flag, get_switch_flag, set_switch_flag); + MAKE_PROPERTY(switch_fps, get_switch_fps, set_switch_fps); + MAKE_SEQ_PROPERTY(object_types, get_num_object_types, get_object_type); + MAKE_PROPERTY(model_flag, get_model_flag, set_model_flag); + MAKE_PROPERTY(texlist_flag, get_texlist_flag, set_texlist_flag); + MAKE_PROPERTY(nofog_flag, get_nofog_flag, set_nofog_flag); + MAKE_PROPERTY(decal_flag, get_decal_flag, set_decal_flag); + MAKE_PROPERTY(direct_flag, get_direct_flag, set_direct_flag); + MAKE_PROPERTY(portal_flag, get_portal_flag, set_portal_flag); + MAKE_PROPERTY(occluder_flag, get_occluder_flag, set_occluder_flag); + MAKE_PROPERTY2(indexed_flag, has_indexed_flag, get_indexed_flag, + set_indexed_flag, clear_indexed_flag); + MAKE_PROPERTY2(collide_mask, has_collide_mask, get_collide_mask, + set_collide_mask, clear_collide_mask); + MAKE_PROPERTY2(from_collide_mask, has_from_collide_mask, get_from_collide_mask, + set_from_collide_mask, clear_from_collide_mask); + MAKE_PROPERTY2(into_collide_mask, has_into_collide_mask, get_into_collide_mask, + set_into_collide_mask, clear_into_collide_mask); + MAKE_PROPERTY(blend_mode, get_blend_mode, set_blend_mode); + MAKE_PROPERTY(blend_operand_a, get_blend_operand_a, set_blend_operand_a); + MAKE_PROPERTY(blend_operand_b, get_blend_operand_b, set_blend_operand_b); + MAKE_PROPERTY2(blend_color, has_blend_color, get_blend_color, + set_blend_color, clear_blend_color); + MAKE_PROPERTY2(lod, has_lod, get_lod, set_lod, clear_lod); + MAKE_PROPERTY(default_pose, get_default_pose, set_default_pose); + MAKE_PROPERTY(scroll_u, get_scroll_u, set_scroll_u); + MAKE_PROPERTY(scroll_v, get_scroll_v, set_scroll_v); + MAKE_PROPERTY(scroll_w, get_scroll_w, set_scroll_w); + MAKE_PROPERTY(scroll_r, get_scroll_r, set_scroll_r); + public: INLINE TagData::const_iterator tag_begin() const; INLINE TagData::const_iterator tag_end() const; diff --git a/panda/src/egg/eggNurbsCurve.h b/panda/src/egg/eggNurbsCurve.h index 29f567573a..5eb8a054c8 100644 --- a/panda/src/egg/eggNurbsCurve.h +++ b/panda/src/egg/eggNurbsCurve.h @@ -50,6 +50,11 @@ PUBLISHED: virtual void write(ostream &out, int indent_level) const; + MAKE_PROPERTY(order, get_order, set_order); + MAKE_PROPERTY(degree, get_degree); + MAKE_PROPERTY(closed, is_closed); + MAKE_SEQ_PROPERTY(knots, get_num_knots, get_knot, set_knot); + private: typedef vector_double Knots; Knots _knots; diff --git a/panda/src/egg/eggPrimitive.I b/panda/src/egg/eggPrimitive.I index 56fa2f8792..68ba3de1e3 100644 --- a/panda/src/egg/eggPrimitive.I +++ b/panda/src/egg/eggPrimitive.I @@ -354,7 +354,7 @@ clear() { /** * */ -INLINE int EggPrimitive:: +INLINE size_t EggPrimitive:: get_num_vertices() const { return size(); } @@ -365,8 +365,8 @@ get_num_vertices() const { * mess with the iterators. */ INLINE void EggPrimitive:: -set_vertex(int index, EggVertex *vertex) { - nassertv(index >= 0 && index < (int)size()); +set_vertex(size_t index, EggVertex *vertex) { + nassertv(index < size()); replace(begin() + index, vertex); } @@ -374,8 +374,8 @@ set_vertex(int index, EggVertex *vertex) { * Returns a particular index based on its index number. */ INLINE EggVertex *EggPrimitive:: -get_vertex(int index) const { - nassertr(index >= 0 && index < (int)size(), NULL); +get_vertex(size_t index) const { + nassertr(index < size(), NULL); return *(begin() + index); } diff --git a/panda/src/egg/eggPrimitive.cxx b/panda/src/egg/eggPrimitive.cxx index 630c784ed3..e3eb0b16d7 100644 --- a/panda/src/egg/eggPrimitive.cxx +++ b/panda/src/egg/eggPrimitive.cxx @@ -684,6 +684,19 @@ remove_vertex(EggVertex *vertex) { } } +/** + * Removes the indicated vertex from the primitive. + */ +void EggPrimitive:: +remove_vertex(size_t index) { + nassertv(index < size()); + iterator i = begin() + index; + + // erase() calls prepare_remove_vertex(). + erase(i); + + test_vref_integrity(); +} /** * Replaces the current primitive's list of vertices with a copy of the list diff --git a/panda/src/egg/eggPrimitive.h b/panda/src/egg/eggPrimitive.h index f1e26c0478..4e8672249e 100644 --- a/panda/src/egg/eggPrimitive.h +++ b/panda/src/egg/eggPrimitive.h @@ -105,6 +105,14 @@ PUBLISHED: INLINE void set_bface_flag(bool flag); INLINE bool get_bface_flag() const; + MAKE_PROPERTY(sort_name, get_sort_name); + MAKE_PROPERTY(shading, get_shading); + MAKE_PROPERTY(connected_shading, get_connected_shading); + + MAKE_SEQ_PROPERTY(textures, get_num_textures, get_texture); + MAKE_PROPERTY2(material, has_material, get_material, set_material, clear_material); + MAKE_PROPERTY(bface_flag, get_bface_flag, set_bface_flag); + void copy_attributes(const EggAttributes &other); void copy_attributes(const EggPrimitive &other); @@ -166,16 +174,20 @@ PUBLISHED: EggVertex *add_vertex(EggVertex *vertex); EggVertex *remove_vertex(EggVertex *vertex); + void remove_vertex(size_t index); void copy_vertices(const EggPrimitive &other); // These are shorthands if you don't want to use the iterators. - INLINE int get_num_vertices() const; - INLINE void set_vertex(int index, EggVertex *vertex); - INLINE EggVertex *get_vertex(int index) const; + INLINE size_t get_num_vertices() const; + INLINE void set_vertex(size_t index, EggVertex *vertex); + INLINE EggVertex *get_vertex(size_t index) const; MAKE_SEQ(get_vertices, get_num_vertices, get_vertex); INLINE EggVertexPool *get_pool() const; + MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex, set_vertex, remove_vertex); + MAKE_PROPERTY(pool, get_pool); + virtual void write(ostream &out, int indent_level) const=0; #ifdef _DEBUG diff --git a/panda/src/egg2pg/eggBinner.cxx b/panda/src/egg2pg/eggBinner.cxx index 3f03a92515..66471661f8 100644 --- a/panda/src/egg2pg/eggBinner.cxx +++ b/panda/src/egg2pg/eggBinner.cxx @@ -50,16 +50,7 @@ prepare_node(EggNode *node) { */ int EggBinner:: get_bin_number(const EggNode *node) { - if (node->is_of_type(EggPrimitive::get_class_type())) { - return (int)BN_polyset; - - } else if (node->is_of_type(EggGroup::get_class_type())) { - const EggGroup *group = DCAST(EggGroup, node); - if (group->has_lod()) { - return (int)BN_lod; - } - - } else if (node->is_of_type(EggNurbsSurface::get_class_type())) { + if (node->is_of_type(EggNurbsSurface::get_class_type())) { return (int)BN_nurbs_surface; } else if (node->is_of_type(EggNurbsCurve::get_class_type())) { @@ -67,6 +58,15 @@ get_bin_number(const EggNode *node) { } else if (node->is_of_type(EggPatch::get_class_type())) { return (int)BN_patches; + + } else if (node->is_of_type(EggPrimitive::get_class_type())) { + return (int)BN_polyset; + + } else if (node->is_of_type(EggGroup::get_class_type())) { + const EggGroup *group = DCAST(EggGroup, node); + if (group->has_lod()) { + return (int)BN_lod; + } } return (int)BN_none; diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index feeab556c5..e093990ef9 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -2242,7 +2242,7 @@ make_vertex_data(const EggRenderState *render_state, PT(GeomVertexArrayFormat) anim_array_format = new GeomVertexArrayFormat; anim_array_format->add_column (InternalName::get_transform_blend(), 1, - Geom::NT_uint16, Geom::C_index); + Geom::NT_uint16, Geom::C_index, 0, 2); temp_format->add_array(anim_array_format); pmap slider_names; diff --git a/panda/src/egg2pg/eggSaver.cxx b/panda/src/egg2pg/eggSaver.cxx index 103ba24fe2..6767d5c287 100644 --- a/panda/src/egg2pg/eggSaver.cxx +++ b/panda/src/egg2pg/eggSaver.cxx @@ -578,8 +578,8 @@ convert_primitive(const GeomVertexData *vertex_data, // Check for a color scale. LVecBase4 color_scale(1.0f, 1.0f, 1.0f, 1.0f); - const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, net_state->get_attrib(ColorScaleAttrib::get_class_type())); - if (csa != (const ColorScaleAttrib *)NULL) { + const ColorScaleAttrib *csa; + if (net_state->get_attrib(csa)) { color_scale = csa->get_scale(); } @@ -587,8 +587,8 @@ convert_primitive(const GeomVertexData *vertex_data, bool has_color_override = false; bool has_color_off = false; LColor color_override; - const ColorAttrib *ca = DCAST(ColorAttrib, net_state->get_attrib(ColorAttrib::get_class_type())); - if (ca != (const ColorAttrib *)NULL) { + const ColorAttrib *ca; + if (net_state->get_attrib(ca)) { if (ca->get_color_type() == ColorAttrib::T_flat) { has_color_override = true; color_override = ca->get_color(); @@ -604,15 +604,15 @@ convert_primitive(const GeomVertexData *vertex_data, // Check for a material. EggMaterial *egg_mat = (EggMaterial *)NULL; - const MaterialAttrib *ma = DCAST(MaterialAttrib, net_state->get_attrib(MaterialAttrib::get_class_type())); - if (ma != (const MaterialAttrib *)NULL) { + const MaterialAttrib *ma; + if (net_state->get_attrib(ma)) { egg_mat = get_egg_material(ma->get_material()); } // Check for a texture. EggTexture *egg_tex = (EggTexture *)NULL; - const TextureAttrib *ta = DCAST(TextureAttrib, net_state->get_attrib(TextureAttrib::get_class_type())); - if (ta != (const TextureAttrib *)NULL) { + const TextureAttrib *ta; + if (net_state->get_attrib(ta)) { egg_tex = get_egg_texture(ta->get_texture()); } @@ -651,9 +651,8 @@ convert_primitive(const GeomVertexData *vertex_data, // Check the backface flag. bool bface = false; - const RenderAttrib *cf_attrib = net_state->get_attrib(CullFaceAttrib::get_class_type()); - if (cf_attrib != (const RenderAttrib *)NULL) { - const CullFaceAttrib *cfa = DCAST(CullFaceAttrib, cf_attrib); + const CullFaceAttrib *cfa; + if (net_state->get_attrib(cfa)) { if (cfa->get_effective_mode() == CullFaceAttrib::M_cull_none) { bface = true; } @@ -662,9 +661,8 @@ convert_primitive(const GeomVertexData *vertex_data, // Check the depth write flag - only needed for AM_blend_no_occlude bool has_depthwrite = false; DepthWriteAttrib::Mode depthwrite = DepthWriteAttrib::M_on; - const RenderAttrib *dw_attrib = net_state->get_attrib(DepthWriteAttrib::get_class_type()); - if (dw_attrib != (const RenderAttrib *)NULL) { - const DepthWriteAttrib *dwa = DCAST(DepthWriteAttrib, dw_attrib); + const DepthWriteAttrib *dwa; + if (net_state->get_attrib(dwa)) { depthwrite = dwa->get_mode(); has_depthwrite = true; } @@ -672,9 +670,8 @@ convert_primitive(const GeomVertexData *vertex_data, // Check the transparency flag. bool has_transparency = false; TransparencyAttrib::Mode transparency = TransparencyAttrib::M_none; - const RenderAttrib *tr_attrib = net_state->get_attrib(TransparencyAttrib::get_class_type()); - if (tr_attrib != (const RenderAttrib *)NULL) { - const TransparencyAttrib *tra = DCAST(TransparencyAttrib, tr_attrib); + const TransparencyAttrib *tra; + if (net_state->get_attrib(tra)) { transparency = tra->get_mode(); has_transparency = true; } @@ -715,6 +712,16 @@ convert_primitive(const GeomVertexData *vertex_data, } } + // Check for line thickness and such. + bool has_render_mode = false; + bool perspective = false; + PN_stdfloat thickness = 1; + const RenderModeAttrib *rma; + if (net_state->get_attrib(rma)) { + has_render_mode = true; + thickness = rma->get_thickness(); + perspective = rma->get_perspective(); + } LNormal normal; LColor color; @@ -754,6 +761,18 @@ convert_primitive(const GeomVertexData *vertex_data, egg_prim->set_bface_flag(true); } + if (has_render_mode) { + if (egg_prim->is_of_type(EggPoint::get_class_type())) { + EggPoint *egg_point = (EggPoint *)egg_prim.p(); + egg_point->set_thick(thickness); + egg_point->set_perspective(perspective); + + } else if (egg_prim->is_of_type(EggLine::get_class_type())) { + EggLine *egg_line = (EggLine *)egg_prim.p(); + egg_line->set_thick(thickness); + } + } + for (int j = 0; j < num_vertices; j++) { EggVertex egg_vert; diff --git a/panda/src/egg2pg/loaderFileTypeEgg.cxx b/panda/src/egg2pg/loaderFileTypeEgg.cxx index be2af1dfe1..a5bbd96210 100644 --- a/panda/src/egg2pg/loaderFileTypeEgg.cxx +++ b/panda/src/egg2pg/loaderFileTypeEgg.cxx @@ -44,7 +44,7 @@ get_extension() const { /** * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. + * (with a .pz or .gz extension), false otherwise. */ bool LoaderFileTypeEgg:: supports_compressed() const { diff --git a/panda/src/event/asyncTaskManager.h b/panda/src/event/asyncTaskManager.h index e8cdc220b7..967476c4af 100644 --- a/panda/src/event/asyncTaskManager.h +++ b/panda/src/event/asyncTaskManager.h @@ -82,9 +82,13 @@ PUBLISHED: AsyncTaskCollection get_tasks() const; AsyncTaskCollection get_active_tasks() const; AsyncTaskCollection get_sleeping_tasks() const; + MAKE_PROPERTY(tasks, get_tasks); + MAKE_PROPERTY(active_tasks, get_active_tasks); + MAKE_PROPERTY(sleeping_tasks, get_sleeping_tasks); void poll(); double get_next_wake_time() const; + MAKE_PROPERTY(next_wake_time, get_next_wake_time); virtual void output(ostream &out) const; virtual void write(ostream &out, int indent_level = 0) const; diff --git a/panda/src/event/event.h b/panda/src/event/event.h index 47075883b8..e09c4c2500 100644 --- a/panda/src/event/event.h +++ b/panda/src/event/event.h @@ -55,6 +55,10 @@ PUBLISHED: void output(ostream &out) const; + MAKE_PROPERTY(name, get_name, set_name); + MAKE_SEQ_PROPERTY(parameters, get_num_parameters, get_parameter); + MAKE_PROPERTY2(receiver, has_receiver, get_receiver, set_receiver, clear_receiver); + protected: typedef pvector ParameterList; ParameterList _parameters; diff --git a/panda/src/event/pythonTask.cxx b/panda/src/event/pythonTask.cxx index 7f288aba0a..61068759f1 100644 --- a/panda/src/event/pythonTask.cxx +++ b/panda/src/event/pythonTask.cxx @@ -319,12 +319,14 @@ __getattr__(PyObject *attr) const { */ int PythonTask:: __traverse__(visitproc visit, void *arg) { +/* Py_VISIT(_function); Py_VISIT(_args); Py_VISIT(_upon_death); Py_VISIT(_owner); Py_VISIT(__dict__); Py_VISIT(_generator); +*/ return 0; } @@ -333,12 +335,14 @@ __traverse__(visitproc visit, void *arg) { */ int PythonTask:: __clear__() { +/* Py_CLEAR(_function); Py_CLEAR(_args); Py_CLEAR(_upon_death); Py_CLEAR(_owner); Py_CLEAR(__dict__); Py_CLEAR(_generator); +*/ return 0; } diff --git a/panda/src/express/config_express.cxx b/panda/src/express/config_express.cxx index 8bf5dff316..dd590fcb38 100644 --- a/panda/src/express/config_express.cxx +++ b/panda/src/express/config_express.cxx @@ -127,15 +127,15 @@ init_libexpress() { // This is a fine place to ensure that the numeric types have been chosen // correctly. - nassertv(sizeof(PN_int8) == 1 && sizeof(PN_uint8) == 1); - nassertv(sizeof(PN_int16) == 2 && sizeof(PN_uint16) == 2); - nassertv(sizeof(PN_int32) == 4 && sizeof(PN_uint32) == 4); - nassertv(sizeof(PN_int64) == 8 && sizeof(PN_uint64) == 8); + nassertv(sizeof(int8_t) == 1 && sizeof(uint8_t) == 1); + nassertv(sizeof(int16_t) == 2 && sizeof(uint16_t) == 2); + nassertv(sizeof(int32_t) == 4 && sizeof(uint32_t) == 4); + nassertv(sizeof(int64_t) == 8 && sizeof(uint64_t) == 8); nassertv(sizeof(PN_float32) == 4); nassertv(sizeof(PN_float64) == 8); // Also, ensure that we have the right endianness. - PN_uint32 word; + uint32_t word; memcpy(&word, "\1\2\3\4", 4); #ifdef WORDS_BIGENDIAN nassertv(word == 0x01020304); diff --git a/panda/src/express/datagram.I b/panda/src/express/datagram.I index ded1a56d09..0ad4007b26 100644 --- a/panda/src/express/datagram.I +++ b/panda/src/express/datagram.I @@ -106,7 +106,7 @@ add_bool(bool b) { * Adds a signed 8-bit integer to the datagram. */ INLINE void Datagram:: -add_int8(PN_int8 value) { +add_int8(int8_t value) { append_data(&value, 1); } @@ -114,7 +114,7 @@ add_int8(PN_int8 value) { * Adds an unsigned 8-bit integer to the datagram. */ INLINE void Datagram:: -add_uint8(PN_uint8 value) { +add_uint8(uint8_t value) { append_data(&value, 1); } @@ -122,7 +122,7 @@ add_uint8(PN_uint8 value) { * Adds a signed 16-bit integer to the datagram. */ INLINE void Datagram:: -add_int16(PN_int16 value) { +add_int16(int16_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -131,7 +131,7 @@ add_int16(PN_int16 value) { * Adds a signed 32-bit integer to the datagram. */ INLINE void Datagram:: -add_int32(PN_int32 value) { +add_int32(int32_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -140,7 +140,7 @@ add_int32(PN_int32 value) { * Adds a signed 64-bit integer to the datagram. */ INLINE void Datagram:: -add_int64(PN_int64 value) { +add_int64(int64_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -149,7 +149,7 @@ add_int64(PN_int64 value) { * Adds an unsigned 16-bit integer to the datagram. */ INLINE void Datagram:: -add_uint16(PN_uint16 value) { +add_uint16(uint16_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -158,7 +158,7 @@ add_uint16(PN_uint16 value) { * Adds an unsigned 32-bit integer to the datagram. */ INLINE void Datagram:: -add_uint32(PN_uint32 value) { +add_uint32(uint32_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -167,7 +167,7 @@ add_uint32(PN_uint32 value) { * Adds an unsigned 64-bit integer to the datagram. */ INLINE void Datagram:: -add_uint64(PN_uint64 value) { +add_uint64(uint64_t value) { LittleEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -209,7 +209,7 @@ add_stdfloat(PN_stdfloat value) { * Adds a signed 16-bit big-endian integer to the datagram. */ INLINE void Datagram:: -add_be_int16(PN_int16 value) { +add_be_int16(int16_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -218,7 +218,7 @@ add_be_int16(PN_int16 value) { * Adds a signed 32-bit big-endian integer to the datagram. */ INLINE void Datagram:: -add_be_int32(PN_int32 value) { +add_be_int32(int32_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -227,7 +227,7 @@ add_be_int32(PN_int32 value) { * Adds a signed 64-bit big-endian integer to the datagram. */ INLINE void Datagram:: -add_be_int64(PN_int64 value) { +add_be_int64(int64_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -236,7 +236,7 @@ add_be_int64(PN_int64 value) { * Adds an unsigned 16-bit big-endian integer to the datagram. */ INLINE void Datagram:: -add_be_uint16(PN_uint16 value) { +add_be_uint16(uint16_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -245,7 +245,7 @@ add_be_uint16(PN_uint16 value) { * Adds an unsigned 32-bit big-endian integer to the datagram. */ INLINE void Datagram:: -add_be_uint32(PN_uint32 value) { +add_be_uint32(uint32_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -254,7 +254,7 @@ add_be_uint32(PN_uint32 value) { * Adds an unsigned 64-bit big-endian integer to the datagram. */ INLINE void Datagram:: -add_be_uint64(PN_uint64 value) { +add_be_uint64(uint64_t value) { BigEndian s(&value, sizeof(value)); append_data(s.get_data(), sizeof(value)); } @@ -285,10 +285,10 @@ add_be_float64(PN_float64 value) { INLINE void Datagram:: add_string(const string &str) { // The max sendable length for a string is 2^16. - nassertv(str.length() <= (PN_uint16)0xffff); + nassertv(str.length() <= (uint16_t)0xffff); // Strings always are preceded by their length - add_uint16((PN_uint16)str.length()); + add_uint16((uint16_t)str.length()); // Add the string append_data(str); @@ -301,7 +301,7 @@ add_string(const string &str) { INLINE void Datagram:: add_string32(const string &str) { // Strings always are preceded by their length - add_uint32((PN_uint32)str.length()); + add_uint32((uint32_t)str.length()); // Add the string append_data(str); diff --git a/panda/src/express/datagram.cxx b/panda/src/express/datagram.cxx index cf0d442e14..1121953948 100644 --- a/panda/src/express/datagram.cxx +++ b/panda/src/express/datagram.cxx @@ -82,13 +82,13 @@ dump_hex(ostream &out, unsigned int indent) const { void Datagram:: add_wstring(const wstring &str) { // By convention, wstrings are marked with 32-bit lengths. - add_uint32((PN_uint32)str.length()); + add_uint32((uint32_t)str.length()); // Now append each character in the string. We store each code little- // endian, for no real good reason. wstring::const_iterator ci; for (ci = str.begin(); ci != str.end(); ++ci) { - add_uint16((PN_uint16)*ci); + add_uint16((uint16_t)*ci); } } diff --git a/panda/src/express/datagram.h b/panda/src/express/datagram.h index b599fca10b..c2cb3b4c8b 100644 --- a/panda/src/express/datagram.h +++ b/panda/src/express/datagram.h @@ -54,27 +54,27 @@ PUBLISHED: void dump_hex(ostream &out, unsigned int indent=0) const; INLINE void add_bool(bool value); - INLINE void add_int8(PN_int8 value); - INLINE void add_uint8(PN_uint8 value); + INLINE void add_int8(int8_t value); + INLINE void add_uint8(uint8_t value); // The default numeric packing is little-endian. - INLINE void add_int16(PN_int16 value); - INLINE void add_int32(PN_int32 value); - INLINE void add_int64(PN_int64 value); - INLINE void add_uint16(PN_uint16 value); - INLINE void add_uint32(PN_uint32 value); - INLINE void add_uint64(PN_uint64 value); + INLINE void add_int16(int16_t value); + INLINE void add_int32(int32_t value); + INLINE void add_int64(int64_t value); + INLINE void add_uint16(uint16_t value); + INLINE void add_uint32(uint32_t value); + INLINE void add_uint64(uint64_t value); INLINE void add_float32(PN_float32 value); INLINE void add_float64(PN_float64 value); INLINE void add_stdfloat(PN_stdfloat value); // These functions pack numbers big-endian, in case that's desired. - INLINE void add_be_int16(PN_int16 value); - INLINE void add_be_int32(PN_int32 value); - INLINE void add_be_int64(PN_int64 value); - INLINE void add_be_uint16(PN_uint16 value); - INLINE void add_be_uint32(PN_uint32 value); - INLINE void add_be_uint64(PN_uint64 value); + INLINE void add_be_int16(int16_t value); + INLINE void add_be_int32(int32_t value); + INLINE void add_be_int64(int64_t value); + INLINE void add_be_uint16(uint16_t value); + INLINE void add_be_uint32(uint32_t value); + INLINE void add_be_uint64(uint64_t value); INLINE void add_be_float32(PN_float32 value); INLINE void add_be_float64(PN_float64 value); diff --git a/panda/src/express/datagramIterator.I b/panda/src/express/datagramIterator.I index 0e4fff93f4..6f85656b47 100644 --- a/panda/src/express/datagramIterator.I +++ b/panda/src/express/datagramIterator.I @@ -75,14 +75,14 @@ get_bool() { /** * Extracts a signed 8-bit integer. */ -INLINE PN_int8 DatagramIterator:: +INLINE int8_t DatagramIterator:: get_int8() { nassertr(_datagram != (const Datagram *)NULL, 0); // Avoid reading junk data off the end of the datagram: nassertr(_current_index < _datagram->get_length(), 0); // Get the Data: const char *ptr = (const char *)_datagram->get_data(); - PN_int8 tempvar = (PN_int8)ptr[_current_index]; + int8_t tempvar = (int8_t)ptr[_current_index]; ++_current_index; return tempvar; @@ -91,14 +91,14 @@ get_int8() { /** * Extracts an unsigned 8-bit integer. */ -INLINE PN_uint8 DatagramIterator:: +INLINE uint8_t DatagramIterator:: get_uint8() { nassertr(_datagram != (const Datagram *)NULL, 0); // Avoid reading junk data off the end of the datagram: nassertr(_current_index < _datagram->get_length(), 0); // Get the Data: const char *ptr = (const char *)_datagram->get_data(); - PN_uint8 tempvar = (PN_uint8)ptr[_current_index]; + uint8_t tempvar = (uint8_t)ptr[_current_index]; ++_current_index; return tempvar; @@ -107,12 +107,12 @@ get_uint8() { /** * Extracts a signed 16-bit integer. */ -INLINE PN_int16 DatagramIterator:: +INLINE int16_t DatagramIterator:: get_int16() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_int16 tempvar; + int16_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: @@ -126,12 +126,12 @@ get_int16() { /** * Extracts a signed 32-bit integer. */ -INLINE PN_int32 DatagramIterator:: +INLINE int32_t DatagramIterator:: get_int32() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_int32 tempvar; + int32_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: @@ -145,12 +145,12 @@ get_int32() { /** * Extracts a signed 64-bit integer. */ -INLINE PN_int64 DatagramIterator:: +INLINE int64_t DatagramIterator:: get_int64() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_int64 tempvar; + int64_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: @@ -164,12 +164,12 @@ get_int64() { /** * Extracts an unsigned 16-bit integer. */ -INLINE PN_uint16 DatagramIterator:: +INLINE uint16_t DatagramIterator:: get_uint16() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_uint16 tempvar; + uint16_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: @@ -183,12 +183,12 @@ get_uint16() { /** * Extracts an unsigned 32-bit integer. */ -INLINE PN_uint32 DatagramIterator:: +INLINE uint32_t DatagramIterator:: get_uint32() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_uint32 tempvar; + uint32_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: @@ -202,12 +202,12 @@ get_uint32() { /** * Extracts an unsigned 64-bit integer. */ -INLINE PN_uint64 DatagramIterator:: +INLINE uint64_t DatagramIterator:: get_uint64() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_uint64 tempvar; + uint64_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: @@ -274,12 +274,12 @@ get_stdfloat() { /** * Extracts a signed 16-bit big-endian integer. */ -INLINE PN_int16 DatagramIterator:: +INLINE int16_t DatagramIterator:: get_be_int16() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_int16 tempvar; + int16_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: @@ -293,12 +293,12 @@ get_be_int16() { /** * Extracts a signed 32-bit big-endian integer. */ -INLINE PN_int32 DatagramIterator:: +INLINE int32_t DatagramIterator:: get_be_int32() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_int32 tempvar; + int32_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: @@ -312,12 +312,12 @@ get_be_int32() { /** * Extracts a signed 64-bit big-endian integer. */ -INLINE PN_int64 DatagramIterator:: +INLINE int64_t DatagramIterator:: get_be_int64() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_int64 tempvar; + int64_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: @@ -331,12 +331,12 @@ get_be_int64() { /** * Extracts an unsigned 16-bit big-endian integer. */ -INLINE PN_uint16 DatagramIterator:: +INLINE uint16_t DatagramIterator:: get_be_uint16() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_uint16 tempvar; + uint16_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: @@ -350,12 +350,12 @@ get_be_uint16() { /** * Extracts an unsigned 32-bit big-endian integer. */ -INLINE PN_uint32 DatagramIterator:: +INLINE uint32_t DatagramIterator:: get_be_uint32() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_uint32 tempvar; + uint32_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: @@ -369,12 +369,12 @@ get_be_uint32() { /** * Extracts an unsigned 64-bit big-endian integer. */ -INLINE PN_uint64 DatagramIterator:: +INLINE uint64_t DatagramIterator:: get_be_uint64() { nassertr(_datagram != (const Datagram *)NULL, 0); nassertr(_current_index < _datagram->get_length(), 0); - PN_uint64 tempvar; + uint64_t tempvar; // Avoid reading junk data off the end of the datagram: nassertr(_current_index + sizeof(tempvar) <= _datagram->get_length(), 0); // Get the Data: diff --git a/panda/src/express/datagramIterator.cxx b/panda/src/express/datagramIterator.cxx index 3dca573cad..22ac9ecb19 100644 --- a/panda/src/express/datagramIterator.cxx +++ b/panda/src/express/datagramIterator.cxx @@ -22,7 +22,7 @@ TypeHandle DatagramIterator::_type_handle; string DatagramIterator:: get_string() { // First, get the length of the string - PN_uint16 s_len = get_uint16(); + uint16_t s_len = get_uint16(); nassertr(_datagram != (const Datagram *)NULL, ""); nassertr(_current_index + s_len <= _datagram->get_length(), ""); @@ -41,7 +41,7 @@ get_string() { string DatagramIterator:: get_string32() { // First, get the length of the string - PN_uint32 s_len = get_uint32(); + uint32_t s_len = get_uint32(); nassertr(_datagram != (const Datagram *)NULL, ""); nassertr(_current_index + s_len <= _datagram->get_length(), ""); @@ -100,7 +100,7 @@ get_fixed_string(size_t size) { wstring DatagramIterator:: get_wstring() { // First, get the length of the string - PN_uint32 s_len = get_uint32(); + uint32_t s_len = get_uint32(); nassertr(_datagram != (const Datagram *)NULL, wstring()); nassertr(_current_index + s_len * 2 <= _datagram->get_length(), wstring()); diff --git a/panda/src/express/datagramIterator.h b/panda/src/express/datagramIterator.h index a6d1dc0b6e..b3a94c6670 100644 --- a/panda/src/express/datagramIterator.h +++ b/panda/src/express/datagramIterator.h @@ -36,25 +36,25 @@ PUBLISHED: INLINE ~DatagramIterator(); INLINE bool get_bool(); - INLINE PN_int8 get_int8(); - INLINE PN_uint8 get_uint8(); + INLINE int8_t get_int8(); + INLINE uint8_t get_uint8(); - INLINE PN_int16 get_int16(); - INLINE PN_int32 get_int32(); - INLINE PN_int64 get_int64(); - INLINE PN_uint16 get_uint16(); - INLINE PN_uint32 get_uint32(); - INLINE PN_uint64 get_uint64(); + INLINE int16_t get_int16(); + INLINE int32_t get_int32(); + INLINE int64_t get_int64(); + INLINE uint16_t get_uint16(); + INLINE uint32_t get_uint32(); + INLINE uint64_t get_uint64(); INLINE PN_float32 get_float32(); INLINE PN_float64 get_float64(); INLINE PN_stdfloat get_stdfloat(); - INLINE PN_int16 get_be_int16(); - INLINE PN_int32 get_be_int32(); - INLINE PN_int64 get_be_int64(); - INLINE PN_uint16 get_be_uint16(); - INLINE PN_uint32 get_be_uint32(); - INLINE PN_uint64 get_be_uint64(); + INLINE int16_t get_be_int16(); + INLINE int32_t get_be_int32(); + INLINE int64_t get_be_int64(); + INLINE uint16_t get_be_uint16(); + INLINE uint32_t get_be_uint32(); + INLINE uint64_t get_be_uint64(); INLINE PN_float32 get_be_float32(); INLINE PN_float64 get_be_float64(); diff --git a/panda/src/express/globPattern_ext.cxx b/panda/src/express/globPattern_ext.cxx index e6328bc5c0..359c34365f 100644 --- a/panda/src/express/globPattern_ext.cxx +++ b/panda/src/express/globPattern_ext.cxx @@ -25,14 +25,7 @@ match_files(const Filename &cwd) const { PyObject *result = PyList_New(contents.size()); for (size_t i = 0; i < contents.size(); ++i) { - const string &filename = contents[i]; -#if PY_MAJOR_VERSION >= 3 - // This function expects UTF-8. - PyObject *str = PyUnicode_FromStringAndSize(filename.data(), filename.size()); -#else - PyObject *str = PyString_FromStringAndSize(filename.data(), filename.size()); -#endif - PyList_SET_ITEM(result, i, str); + PyList_SET_ITEM(result, i, Dtool_WrapValue(contents[i])); } return result; diff --git a/panda/src/express/hashVal.I b/panda/src/express/hashVal.I index d866e56475..6519915034 100644 --- a/panda/src/express/hashVal.I +++ b/panda/src/express/hashVal.I @@ -184,6 +184,16 @@ INLINE void HashVal:: hash_string(const string &data) { hash_buffer(data.data(), data.length()); } + +/** + * Generates the hash value by hashing the indicated data. This method is + * only defined if we have the OpenSSL library (which provides md5 + * functionality) available. + */ +INLINE void HashVal:: +hash_bytes(const pvector &data) { + hash_buffer((const char *)&data[0], data.size()); +} #endif // HAVE_OPENSSL /** diff --git a/panda/src/express/hashVal.cxx b/panda/src/express/hashVal.cxx index 34a2a3c116..7d52dc5a5e 100644 --- a/panda/src/express/hashVal.cxx +++ b/panda/src/express/hashVal.cxx @@ -258,7 +258,7 @@ hash_buffer(const char *buffer, int length) { * at the indicated buffer and the following 8 positions. */ void HashVal:: -encode_hex(PN_uint32 val, char *buffer) { +encode_hex(uint32_t val, char *buffer) { buffer[0] = tohex(val >> 28); buffer[1] = tohex(val >> 24); buffer[2] = tohex(val >> 20); @@ -273,7 +273,7 @@ encode_hex(PN_uint32 val, char *buffer) { * Decodes the indicated eight-digit hex string into an unsigned integer. */ void HashVal:: -decode_hex(const char *buffer, PN_uint32 &val) { +decode_hex(const char *buffer, uint32_t &val) { unsigned int bytes[8]; for (int i = 0; i < 8; i++) { bytes[i] = fromhex(buffer[i]); diff --git a/panda/src/express/hashVal.h b/panda/src/express/hashVal.h index 3d29fa87af..d0652d1e01 100644 --- a/panda/src/express/hashVal.h +++ b/panda/src/express/hashVal.h @@ -68,16 +68,17 @@ PUBLISHED: bool hash_stream(istream &stream); INLINE void hash_ramfile(const Ramfile &ramfile); INLINE void hash_string(const string &data); + INLINE void hash_bytes(const pvector &data); void hash_buffer(const char *buffer, int length); #endif // HAVE_OPENSSL private: - static void encode_hex(PN_uint32 val, char *buffer); - static void decode_hex(const char *buffer, PN_uint32 &val); + static void encode_hex(uint32_t val, char *buffer); + static void decode_hex(const char *buffer, uint32_t &val); INLINE static char tohex(unsigned int nibble); INLINE static unsigned int fromhex(char digit); - PN_uint32 _hv[4]; + uint32_t _hv[4]; }; INLINE ostream &operator << (ostream &out, const HashVal &hv); diff --git a/panda/src/express/memoryUsage.cxx b/panda/src/express/memoryUsage.cxx index 7c689fd1cd..1aea4fe825 100644 --- a/panda/src/express/memoryUsage.cxx +++ b/panda/src/express/memoryUsage.cxx @@ -460,7 +460,7 @@ MemoryUsage(const MemoryHook ©) : MemoryHook(copy) { _count_memory_usage = false; - PN_int64 max_heap_size = ConfigVariableInt64 + int64_t max_heap_size = ConfigVariableInt64 ("max-heap-size", 0, PRC_DESC("If this is nonzero, it is the maximum number of bytes expected " "to be allocated on the heap before we enter report-memory-usage " diff --git a/panda/src/express/multifile.cxx b/panda/src/express/multifile.cxx index 21befb49dc..c99c83bdb3 100644 --- a/panda/src/express/multifile.cxx +++ b/panda/src/express/multifile.cxx @@ -860,7 +860,7 @@ add_signature(const Multifile::CertChain &cert_chain, EVP_PKEY *pkey) { // Now encode that list of certs to a stream in DER form. stringstream der_stream; StreamWriter der_writer(der_stream); - der_writer.add_uint32((PN_uint32)cert_chain.size()); + der_writer.add_uint32((uint32_t)cert_chain.size()); CertChain::const_iterator ci; for (ci = cert_chain.begin(); ci != cert_chain.end(); ++ci) { @@ -2297,9 +2297,11 @@ read_index() { } // Now read the index out. - _next_index = read->tellg() - _offset; - _next_index = normalize_streampos(_next_index); - read->seekg(_next_index + _offset); + streampos curr_pos = read->tellg() - _offset; + _next_index = normalize_streampos(curr_pos); + if (_next_index > curr_pos) { + read->ignore(_next_index - curr_pos); + } _last_index = 0; _last_data_byte = 0; streampos index_forward; @@ -2334,10 +2336,12 @@ read_index() { } _last_data_byte = max(_last_data_byte, subfile->get_last_byte_pos()); } - streampos curr_pos = normalize_streampos(read->tellg() - _offset); - bytes_skipped = index_forward - curr_pos; - read->seekg(index_forward + _offset); + streampos curr_pos = read->tellg() - _offset; + bytes_skipped = index_forward - normalize_streampos(curr_pos); _next_index = index_forward; + if (_next_index > curr_pos) { + read->ignore(_next_index - curr_pos); + } subfile = new Subfile; index_forward = subfile->read_index(*read, _next_index, this); } diff --git a/panda/src/express/patchfile.cxx b/panda/src/express/patchfile.cxx index b43e58456c..73b04139a0 100644 --- a/panda/src/express/patchfile.cxx +++ b/panda/src/express/patchfile.cxx @@ -61,19 +61,19 @@ const int _v1_header_length = 4 + 2 + 4 + 16 + 4 + 16; */ // Defines -const PN_uint32 Patchfile::_v0_magic_number = 0xfeebfaab; -const PN_uint32 Patchfile::_magic_number = 0xfeebfaac; +const uint32_t Patchfile::_v0_magic_number = 0xfeebfaab; +const uint32_t Patchfile::_magic_number = 0xfeebfaac; // Created version 1 on 11202 to store length and MD5 of original file. To // version 2 on 11202 to store copy offsets as relative. -const PN_uint16 Patchfile::_current_version = 2; +const uint16_t Patchfile::_current_version = 2; -const PN_uint32 Patchfile::_HASH_BITS = 24; -const PN_uint32 Patchfile::_HASHTABLESIZE = PN_uint32(1) << Patchfile::_HASH_BITS; -const PN_uint32 Patchfile::_DEFAULT_FOOTPRINT_LENGTH = 9; // this produced the smallest patch file for libpanda.dll when tested, 12/20/2000 -const PN_uint32 Patchfile::_NULL_VALUE = PN_uint32(0) - 1; -const PN_uint32 Patchfile::_MAX_RUN_LENGTH = (PN_uint32(1) << 16) - 1; -const PN_uint32 Patchfile::_HASH_MASK = (PN_uint32(1) << Patchfile::_HASH_BITS) - 1; +const uint32_t Patchfile::_HASH_BITS = 24; +const uint32_t Patchfile::_HASHTABLESIZE = uint32_t(1) << Patchfile::_HASH_BITS; +const uint32_t Patchfile::_DEFAULT_FOOTPRINT_LENGTH = 9; // this produced the smallest patch file for libpanda.dll when tested, 12/20/2000 +const uint32_t Patchfile::_NULL_VALUE = uint32_t(0) - 1; +const uint32_t Patchfile::_MAX_RUN_LENGTH = (uint32_t(1) << 16) - 1; +const uint32_t Patchfile::_HASH_MASK = (uint32_t(1) << Patchfile::_HASH_BITS) - 1; /** * Create a patch file and initializes internal data @@ -118,7 +118,7 @@ init(PT(Buffer) buffer) { */ Patchfile:: ~Patchfile() { - if (_hash_table != (PN_uint32 *)NULL) { + if (_hash_table != (uint32_t *)NULL) { PANDA_FREE_ARRAY(_hash_table); } @@ -261,9 +261,9 @@ run() { // Now patch the file using the given buffer int buflen; int bytes_read; - PN_uint16 ADD_length; - PN_uint16 COPY_length; - PN_int32 COPY_offset; + uint16_t ADD_length; + uint16_t COPY_length; + int32_t COPY_offset; if (_initiated == false) { express_cat.error() @@ -305,9 +305,9 @@ run() { << _write_stream.tellp() << ")" << endl; } - PN_uint32 bytes_left = (PN_uint32)ADD_length; + uint32_t bytes_left = (uint32_t)ADD_length; while (bytes_left > 0) { - PN_uint32 bytes_this_time = (PN_uint32) min(bytes_left, (PN_uint32) buflen); + uint32_t bytes_this_time = (uint32_t) min(bytes_left, (uint32_t) buflen); _patch_stream->read(_buffer->_buffer, bytes_this_time); if (_patch_stream->fail()) { express_cat.error() @@ -368,10 +368,10 @@ run() { } // read the copy bytes from original file and write them to output - PN_uint32 bytes_left = (PN_uint32)COPY_length; + uint32_t bytes_left = (uint32_t)COPY_length; while (bytes_left > 0) { - PN_uint32 bytes_this_time = (PN_uint32) min(bytes_left, (PN_uint32) buflen); + uint32_t bytes_this_time = (uint32_t) min(bytes_left, (uint32_t) buflen); _origfile_stream->read(_buffer->_buffer, bytes_this_time); if (_origfile_stream->fail()) { express_cat.error() @@ -535,7 +535,7 @@ internal_read_header(const Filename &patch_file) { // check the magic number nassertr(_buffer->get_length() >= _v0_header_length, false); - PN_uint32 magic_number = patch_reader.get_uint32(); + uint32_t magic_number = patch_reader.get_uint32(); if (magic_number != _magic_number && magic_number != _v0_magic_number) { express_cat.error() << "Invalid patch file: " << _patch_file << endl; @@ -555,7 +555,7 @@ internal_read_header(const Filename &patch_file) { if (_version_number >= 1) { // Get the length of the source file. - /*PN_uint32 source_file_length =*/ patch_reader.get_uint32(); + /*uint32_t source_file_length =*/ patch_reader.get_uint32(); // get the MD5 of the source file. _MD5_ofSource.read_stream(patch_reader); @@ -578,22 +578,22 @@ internal_read_header(const Filename &patch_file) { /** * */ -PN_uint32 Patchfile:: +uint32_t Patchfile:: calc_hash(const char *buffer) { #ifdef USE_MD5_FOR_HASHTABLE_INDEX_VALUES HashVal hash; hash.hash_buffer(buffer, _footprint_length); - // cout << PN_uint16(hash.get_value(0)) << " "; + // cout << uint16_t(hash.get_value(0)) << " "; - return PN_uint16(hash.get_value(0)); + return uint16_t(hash.get_value(0)); #else - PN_uint32 hash_value = 0; + uint32_t hash_value = 0; for(int i = 0; i < (int)_footprint_length; i++) { // this is probably not such a good hash. to be replaced --> TRIED MD5, // was not worth it for the execution-time hit on 800Mhz PC - hash_value ^= PN_uint32(*buffer) << ((i * 2) % Patchfile::_HASH_BITS); + hash_value ^= uint32_t(*buffer) << ((i * 2) % Patchfile::_HASH_BITS); buffer++; } @@ -624,10 +624,10 @@ calc_hash(const char *buffer) { * can rapidly produce a list of offsets that all have the same footprint. */ void Patchfile:: -build_hash_link_tables(const char *buffer_orig, PN_uint32 length_orig, - PN_uint32 *hash_table, PN_uint32 *link_table) { +build_hash_link_tables(const char *buffer_orig, uint32_t length_orig, + uint32_t *hash_table, uint32_t *link_table) { - PN_uint32 i; + uint32_t i; // clear hash table for(i = 0; i < _HASHTABLESIZE; i++) { @@ -644,7 +644,7 @@ build_hash_link_tables(const char *buffer_orig, PN_uint32 length_orig, // run through original file and hash each footprint for(i = 0; i < (length_orig - _footprint_length); i++) { - PN_uint32 hash_value = calc_hash(&buffer_orig[i]); + uint32_t hash_value = calc_hash(&buffer_orig[i]); // we must now store this file index in the hash table at the offset of // the hash value @@ -669,7 +669,7 @@ build_hash_link_tables(const char *buffer_orig, PN_uint32 length_orig, hash_table[hash_value] = i; } else { // hash entry is taken, go to the link table - PN_uint32 link_offset = hash_table[hash_value]; + uint32_t link_offset = hash_table[hash_value]; while (_NULL_VALUE != link_table[link_offset]) { link_offset = link_table[link_offset]; @@ -684,9 +684,9 @@ build_hash_link_tables(const char *buffer_orig, PN_uint32 length_orig, * * This function calculates the length of a match between two strings of bytes */ -PN_uint32 Patchfile:: -calc_match_length(const char* buf1, const char* buf2, PN_uint32 max_length, - PN_uint32 min_length) { +uint32_t Patchfile:: +calc_match_length(const char* buf1, const char* buf2, uint32_t max_length, + uint32_t min_length) { // early out: look ahead and sample the end of the minimum range if (min_length > 2) { if (min_length >= max_length) @@ -698,7 +698,7 @@ calc_match_length(const char* buf1, const char* buf2, PN_uint32 max_length, } } - PN_uint32 length = 0; + uint32_t length = 0; while ((length < max_length) && (*buf1 == *buf2)) { buf1++, buf2++, length++; } @@ -711,15 +711,15 @@ calc_match_length(const char* buf1, const char* buf2, PN_uint32 max_length, * matches a string in the new file. */ void Patchfile:: -find_longest_match(PN_uint32 new_pos, PN_uint32 ©_pos, PN_uint16 ©_length, - PN_uint32 *hash_table, PN_uint32 *link_table, const char* buffer_orig, - PN_uint32 length_orig, const char* buffer_new, PN_uint32 length_new) { +find_longest_match(uint32_t new_pos, uint32_t ©_pos, uint16_t ©_length, + uint32_t *hash_table, uint32_t *link_table, const char* buffer_orig, + uint32_t length_orig, const char* buffer_new, uint32_t length_new) { // set length to a safe value copy_length = 0; // get offset of matching string (in orig file) from hash table - PN_uint32 hash_value = calc_hash(&buffer_new[new_pos]); + uint32_t hash_value = calc_hash(&buffer_new[new_pos]); // if no match, bail if (_NULL_VALUE == hash_table[hash_value]) @@ -728,7 +728,7 @@ find_longest_match(PN_uint32 new_pos, PN_uint32 ©_pos, PN_uint16 ©_lengt copy_pos = hash_table[hash_value]; // calc match length - copy_length = (PN_uint16)calc_match_length(&buffer_new[new_pos], + copy_length = (uint16_t)calc_match_length(&buffer_new[new_pos], &buffer_orig[copy_pos], min(min((length_new - new_pos), (length_orig - copy_pos)), @@ -736,12 +736,12 @@ find_longest_match(PN_uint32 new_pos, PN_uint32 ©_pos, PN_uint16 ©_lengt 0); // run through link table, see if we find any longer matches - PN_uint32 match_offset; - PN_uint16 match_length; + uint32_t match_offset; + uint16_t match_length; match_offset = link_table[copy_pos]; while (match_offset != _NULL_VALUE) { - match_length = (PN_uint16)calc_match_length(&buffer_new[new_pos], + match_length = (uint16_t)calc_match_length(&buffer_new[new_pos], &buffer_orig[match_offset], min(min((length_new - new_pos), (length_orig - match_offset)), @@ -763,8 +763,8 @@ find_longest_match(PN_uint32 new_pos, PN_uint32 ©_pos, PN_uint16 ©_lengt * */ void Patchfile:: -emit_ADD(ostream &write_stream, PN_uint32 length, const char* buffer) { - nassertv(length == (PN_uint16)length); //we only write a uint16 +emit_ADD(ostream &write_stream, uint32_t length, const char* buffer) { + nassertv(length == (uint16_t)length); //we only write a uint16 if (express_cat.is_spam()) { express_cat.spam() @@ -773,11 +773,11 @@ emit_ADD(ostream &write_stream, PN_uint32 length, const char* buffer) { // write ADD length StreamWriter patch_writer(write_stream); - patch_writer.add_uint16((PN_uint16)length); + patch_writer.add_uint16((uint16_t)length); // if there are bytes to add, add them if (length > 0) { - patch_writer.append_data(buffer, (PN_uint16)length); + patch_writer.append_data(buffer, (uint16_t)length); } _add_pos += length; @@ -787,10 +787,10 @@ emit_ADD(ostream &write_stream, PN_uint32 length, const char* buffer) { * */ void Patchfile:: -emit_COPY(ostream &write_stream, PN_uint32 length, PN_uint32 copy_pos) { - nassertv(length == (PN_uint16)length); //we only write a uint16 +emit_COPY(ostream &write_stream, uint32_t length, uint32_t copy_pos) { + nassertv(length == (uint16_t)length); //we only write a uint16 - PN_int32 offset = (int)copy_pos - (int)_last_copy_pos; + int32_t offset = (int)copy_pos - (int)_last_copy_pos; if (express_cat.is_spam()) { express_cat.spam() << "COPY: " << length << " bytes from offset " << offset @@ -799,9 +799,9 @@ emit_COPY(ostream &write_stream, PN_uint32 length, PN_uint32 copy_pos) { // write COPY length StreamWriter patch_writer(write_stream); - patch_writer.add_uint16((PN_uint16)length); + patch_writer.add_uint16((uint16_t)length); - if ((PN_uint16)length != 0) { + if ((uint16_t)length != 0) { // write COPY offset patch_writer.add_int32(offset); _last_copy_pos = copy_pos + length; @@ -816,14 +816,14 @@ emit_COPY(ostream &write_stream, PN_uint32 length, PN_uint32 copy_pos) { */ void Patchfile:: emit_add_and_copy(ostream &write_stream, - PN_uint32 add_length, const char *add_buffer, - PN_uint32 copy_length, PN_uint32 copy_pos) { + uint32_t add_length, const char *add_buffer, + uint32_t copy_length, uint32_t copy_pos) { if (add_length == 0 && copy_length == 0) { // Don't accidentally emit a termination code. return; } - static const PN_uint16 max_write = 65535; + static const uint16_t max_write = 65535; while (add_length > max_write) { // Overflow. This chunk is too large to fit into a single ADD block, so // we have to write it as multiple ADDs. @@ -852,8 +852,8 @@ emit_add_and_copy(ostream &write_stream, */ void Patchfile:: cache_add_and_copy(ostream &write_stream, - PN_uint32 add_length, const char *add_buffer, - PN_uint32 copy_length, PN_uint32 copy_pos) { + uint32_t add_length, const char *add_buffer, + uint32_t copy_length, uint32_t copy_pos) { if (add_length != 0) { if (_cache_copy_length != 0) { // Have to flush. @@ -912,7 +912,7 @@ write_header(ostream &write_stream, stream_orig.seekg(0, ios::end); streampos source_file_length = stream_orig.tellg(); - patch_writer.add_uint32((PN_uint32)source_file_length); + patch_writer.add_uint32((uint32_t)source_file_length); // calc MD5 of original file _MD5_ofSource.hash_stream(stream_orig); @@ -926,7 +926,7 @@ write_header(ostream &write_stream, stream_new.seekg(0, ios::end); streampos result_file_length = stream_new.tellg(); - patch_writer.add_uint32((PN_uint32)result_file_length); + patch_writer.add_uint32((uint32_t)result_file_length); // calc MD5 of resultant patched file _MD5_ofResult.hash_stream(stream_new); @@ -958,12 +958,12 @@ write_terminator(ostream &write_stream) { */ bool Patchfile:: compute_file_patches(ostream &write_stream, - PN_uint32 offset_orig, PN_uint32 offset_new, + uint32_t offset_orig, uint32_t offset_new, istream &stream_orig, istream &stream_new) { // read in original file stream_orig.seekg(0, ios::end); nassertr(stream_orig, false); - PN_uint32 source_file_length = stream_orig.tellg(); + uint32_t source_file_length = stream_orig.tellg(); if (express_cat.is_debug()) { express_cat.debug() << "Allocating " << source_file_length << " bytes to read orig\n"; @@ -975,7 +975,7 @@ compute_file_patches(ostream &write_stream, // read in new file stream_new.seekg(0, ios::end); - PN_uint32 result_file_length = stream_new.tellg(); + uint32_t result_file_length = stream_new.tellg(); nassertr(stream_new, false); if (express_cat.is_debug()) { express_cat.debug() @@ -987,12 +987,12 @@ compute_file_patches(ostream &write_stream, stream_new.read(buffer_new, result_file_length); // allocate hashlink tables - if (_hash_table == (PN_uint32 *)NULL) { + if (_hash_table == (uint32_t *)NULL) { if (express_cat.is_debug()) { express_cat.debug() << "Allocating hashtable of size " << _HASHTABLESIZE << " * 4\n"; } - _hash_table = (PN_uint32 *)PANDA_MALLOC_ARRAY(_HASHTABLESIZE * sizeof(PN_uint32)); + _hash_table = (uint32_t *)PANDA_MALLOC_ARRAY(_HASHTABLESIZE * sizeof(uint32_t)); } if (express_cat.is_debug()) { @@ -1000,23 +1000,23 @@ compute_file_patches(ostream &write_stream, << "Allocating linktable of size " << source_file_length << " * 4\n"; } - PN_uint32 *link_table = (PN_uint32 *)PANDA_MALLOC_ARRAY(source_file_length * sizeof(PN_uint32)); + uint32_t *link_table = (uint32_t *)PANDA_MALLOC_ARRAY(source_file_length * sizeof(uint32_t)); // build hash and link tables for original file build_hash_link_tables(buffer_orig, source_file_length, _hash_table, link_table); // run through new file - PN_uint32 new_pos = 0; - PN_uint32 start_pos = new_pos; // this is the position for the start of ADD operations + uint32_t new_pos = 0; + uint32_t start_pos = new_pos; // this is the position for the start of ADD operations - if(((PN_uint32) result_file_length) >= _footprint_length) + if(((uint32_t) result_file_length) >= _footprint_length) { while (new_pos < (result_file_length - _footprint_length)) { // find best match for current position - PN_uint32 COPY_pos; - PN_uint16 COPY_length; + uint32_t COPY_pos; + uint16_t COPY_length; find_longest_match(new_pos, COPY_pos, COPY_length, _hash_table, link_table, buffer_orig, source_file_length, buffer_new, result_file_length); @@ -1036,7 +1036,7 @@ compute_file_patches(ostream &write_stream, } cache_add_and_copy(write_stream, num_skipped, &buffer_new[start_pos], COPY_length, COPY_pos + offset_orig); - new_pos += (PN_uint32)COPY_length; + new_pos += (uint32_t)COPY_length; start_pos = new_pos; } } @@ -1053,7 +1053,7 @@ compute_file_patches(ostream &write_stream, if (start_pos != result_file_length) { // emit ADD for all remaining bytes - PN_uint32 remaining_bytes = result_file_length - start_pos; + uint32_t remaining_bytes = result_file_length - start_pos; cache_add_and_copy(write_stream, remaining_bytes, &buffer_new[start_pos], 0, 0); start_pos += remaining_bytes; @@ -1075,7 +1075,7 @@ compute_file_patches(ostream &write_stream, */ bool Patchfile:: compute_mf_patches(ostream &write_stream, - PN_uint32 offset_orig, PN_uint32 offset_new, + uint32_t offset_orig, uint32_t offset_new, istream &stream_orig, istream &stream_new) { Multifile mf_orig, mf_new; IStreamWrapper stream_origw(stream_orig); @@ -1219,7 +1219,7 @@ read_tar(TarDef &tar, istream &stream) { */ bool Patchfile:: compute_tar_patches(ostream &write_stream, - PN_uint32 offset_orig, PN_uint32 offset_new, + uint32_t offset_orig, uint32_t offset_new, istream &stream_orig, istream &stream_new, TarDef &tar_orig, TarDef &tar_new) { @@ -1424,7 +1424,7 @@ build(Filename file_orig, Filename file_new, Filename patch_name) { bool Patchfile:: do_compute_patches(const Filename &file_orig, const Filename &file_new, ostream &write_stream, - PN_uint32 offset_orig, PN_uint32 offset_new, + uint32_t offset_orig, uint32_t offset_new, istream &stream_orig, istream &stream_new) { nassertr(_add_pos + _cache_add_data.size() + _cache_copy_length == offset_new, false); @@ -1505,7 +1505,7 @@ do_compute_patches(const Filename &file_orig, const Filename &file_new, */ bool Patchfile:: patch_subfile(ostream &write_stream, - PN_uint32 offset_orig, PN_uint32 offset_new, + uint32_t offset_orig, uint32_t offset_new, const Filename &filename, IStreamWrapper &stream_orig, streampos orig_start, streampos orig_end, IStreamWrapper &stream_new, streampos new_start, streampos new_end) { diff --git a/panda/src/express/patchfile.h b/panda/src/express/patchfile.h index eee70c0f21..c67b5a039e 100644 --- a/panda/src/express/patchfile.h +++ b/panda/src/express/patchfile.h @@ -79,23 +79,23 @@ private: private: // stuff for the build operation - void build_hash_link_tables(const char *buffer_orig, PN_uint32 length_orig, - PN_uint32 *hash_table, PN_uint32 *link_table); - PN_uint32 calc_hash(const char *buffer); - void find_longest_match(PN_uint32 new_pos, PN_uint32 ©_pos, PN_uint16 ©_length, - PN_uint32 *hash_table, PN_uint32 *link_table, const char* buffer_orig, - PN_uint32 length_orig, const char* buffer_new, PN_uint32 length_new); - PN_uint32 calc_match_length(const char* buf1, const char* buf2, PN_uint32 max_length, - PN_uint32 min_length); + void build_hash_link_tables(const char *buffer_orig, uint32_t length_orig, + uint32_t *hash_table, uint32_t *link_table); + uint32_t calc_hash(const char *buffer); + void find_longest_match(uint32_t new_pos, uint32_t ©_pos, uint16_t ©_length, + uint32_t *hash_table, uint32_t *link_table, const char* buffer_orig, + uint32_t length_orig, const char* buffer_new, uint32_t length_new); + uint32_t calc_match_length(const char* buf1, const char* buf2, uint32_t max_length, + uint32_t min_length); - void emit_ADD(ostream &write_stream, PN_uint32 length, const char* buffer); - void emit_COPY(ostream &write_stream, PN_uint32 length, PN_uint32 COPY_pos); + void emit_ADD(ostream &write_stream, uint32_t length, const char* buffer); + void emit_COPY(ostream &write_stream, uint32_t length, uint32_t COPY_pos); void emit_add_and_copy(ostream &write_stream, - PN_uint32 add_length, const char *add_buffer, - PN_uint32 copy_length, PN_uint32 copy_pos); + uint32_t add_length, const char *add_buffer, + uint32_t copy_length, uint32_t copy_pos); void cache_add_and_copy(ostream &write_stream, - PN_uint32 add_length, const char *add_buffer, - PN_uint32 copy_length, PN_uint32 copy_pos); + uint32_t add_length, const char *add_buffer, + uint32_t copy_length, uint32_t copy_pos); void cache_flush(ostream &write_stream); void write_header(ostream &write_stream, @@ -103,10 +103,10 @@ private: void write_terminator(ostream &write_stream); bool compute_file_patches(ostream &write_stream, - PN_uint32 offset_orig, PN_uint32 offset_new, + uint32_t offset_orig, uint32_t offset_new, istream &stream_orig, istream &stream_new); bool compute_mf_patches(ostream &write_stream, - PN_uint32 offset_orig, PN_uint32 offset_new, + uint32_t offset_orig, uint32_t offset_new, istream &stream_orig, istream &stream_new); #ifdef HAVE_TAR class TarSubfile { @@ -124,7 +124,7 @@ private: bool read_tar(TarDef &tar, istream &stream); bool compute_tar_patches(ostream &write_stream, - PN_uint32 offset_orig, PN_uint32 offset_new, + uint32_t offset_orig, uint32_t offset_new, istream &stream_orig, istream &stream_new, TarDef &tar_orig, TarDef &tar_new); @@ -140,33 +140,33 @@ private: bool do_compute_patches(const Filename &file_orig, const Filename &file_new, ostream &write_stream, - PN_uint32 offset_orig, PN_uint32 offset_new, + uint32_t offset_orig, uint32_t offset_new, istream &stream_orig, istream &stream_new); bool patch_subfile(ostream &write_stream, - PN_uint32 offset_orig, PN_uint32 offset_new, + uint32_t offset_orig, uint32_t offset_new, const Filename &filename, IStreamWrapper &stream_orig, streampos orig_start, streampos orig_end, IStreamWrapper &stream_new, streampos new_start, streampos new_end); - static const PN_uint32 _HASH_BITS; - static const PN_uint32 _HASHTABLESIZE; - static const PN_uint32 _DEFAULT_FOOTPRINT_LENGTH; - static const PN_uint32 _NULL_VALUE; - static const PN_uint32 _MAX_RUN_LENGTH; - static const PN_uint32 _HASH_MASK; + static const uint32_t _HASH_BITS; + static const uint32_t _HASHTABLESIZE; + static const uint32_t _DEFAULT_FOOTPRINT_LENGTH; + static const uint32_t _NULL_VALUE; + static const uint32_t _MAX_RUN_LENGTH; + static const uint32_t _HASH_MASK; bool _allow_multifile; - PN_uint32 _footprint_length; + uint32_t _footprint_length; - PN_uint32 *_hash_table; + uint32_t *_hash_table; - PN_uint32 _add_pos; - PN_uint32 _last_copy_pos; + uint32_t _add_pos; + uint32_t _last_copy_pos; string _cache_add_data; - PN_uint32 _cache_copy_start; - PN_uint32 _cache_copy_length; + uint32_t _cache_copy_start; + uint32_t _cache_copy_length; private: PT(Buffer) _buffer; // this is the work buffer for apply -- used to prevent virtual memory swapping @@ -174,14 +174,14 @@ private: // async patch apply state variables bool _initiated; - PN_uint16 _version_number; + uint16_t _version_number; HashVal _MD5_ofSource; HashVal _MD5_ofResult; - PN_uint32 _total_bytes_to_process; - PN_uint32 _total_bytes_processed; + uint32_t _total_bytes_to_process; + uint32_t _total_bytes_processed; istream *_patch_stream; pofstream _write_stream; @@ -193,9 +193,9 @@ private: bool _rename_output_to_orig; bool _delete_patchfile; - static const PN_uint32 _v0_magic_number; - static const PN_uint32 _magic_number; - static const PN_uint16 _current_version; + static const uint32_t _v0_magic_number; + static const uint32_t _magic_number; + static const uint16_t _current_version; }; #include "patchfile.I" diff --git a/panda/src/express/pointerTo.I b/panda/src/express/pointerTo.I index b44f4f4ded..a3d842e374 100644 --- a/panda/src/express/pointerTo.I +++ b/panda/src/express/pointerTo.I @@ -15,7 +15,7 @@ * */ template -INLINE PointerTo:: +ALWAYS_INLINE PointerTo:: PointerTo(To *ptr) : PointerToBase(ptr) { } @@ -136,7 +136,7 @@ operator = (const PointerTo ©) { * */ template -INLINE ConstPointerTo:: +ALWAYS_INLINE ConstPointerTo:: ConstPointerTo(const TYPENAME ConstPointerTo::To *ptr) : PointerToBase((TYPENAME ConstPointerTo::To *)ptr) { diff --git a/panda/src/express/pointerTo.h b/panda/src/express/pointerTo.h index 315cdaf2ca..50634f6473 100644 --- a/panda/src/express/pointerTo.h +++ b/panda/src/express/pointerTo.h @@ -58,7 +58,8 @@ class PointerTo : public PointerToBase { public: typedef TYPENAME PointerToBase::To To; PUBLISHED: - INLINE PointerTo(To *ptr = (To *)NULL); + ALWAYS_INLINE PointerTo() DEFAULT_CTOR; + ALWAYS_INLINE PointerTo(To *ptr); INLINE PointerTo(const PointerTo ©); INLINE ~PointerTo(); @@ -119,7 +120,8 @@ class ConstPointerTo : public PointerToBase { public: typedef TYPENAME PointerToBase::To To; PUBLISHED: - INLINE ConstPointerTo(const To *ptr = (const To *)NULL); + ALWAYS_INLINE ConstPointerTo() DEFAULT_CTOR; + ALWAYS_INLINE ConstPointerTo(const To *ptr); INLINE ConstPointerTo(const PointerTo ©); INLINE ConstPointerTo(const ConstPointerTo ©); INLINE ~ConstPointerTo(); diff --git a/panda/src/express/pointerToBase.I b/panda/src/express/pointerToBase.I index 20cac87718..296dc5d3bb 100644 --- a/panda/src/express/pointerToBase.I +++ b/panda/src/express/pointerToBase.I @@ -17,7 +17,15 @@ template INLINE PointerToBase:: PointerToBase(To *ptr) { - reassign(ptr); + _void_ptr = (void *)ptr; + if (ptr != (To *)NULL) { + ptr->ref(); +#ifdef DO_MEMORY_USAGE + if (MemoryUsage::get_track_memory_usage()) { + update_type(ptr); + } +#endif + } } /** @@ -26,7 +34,16 @@ PointerToBase(To *ptr) { template INLINE PointerToBase:: PointerToBase(const PointerToBase ©) { - reassign(copy); + _void_ptr = copy._void_ptr; + if (_void_ptr != NULL) { + To *ptr = (To *)_void_ptr; + ptr->ref(); +#ifdef DO_MEMORY_USAGE + if (MemoryUsage::get_track_memory_usage()) { + update_type(ptr); + } +#endif + } } /** @@ -35,7 +52,10 @@ PointerToBase(const PointerToBase ©) { template INLINE PointerToBase:: ~PointerToBase() { - reassign((To *)NULL); + if (_void_ptr != NULL) { + unref_delete((To *)_void_ptr); + _void_ptr = NULL; + } } #ifdef USE_MOVE_SEMANTICS diff --git a/panda/src/express/pointerToBase.h b/panda/src/express/pointerToBase.h index 3380322e4a..cbafa5587b 100644 --- a/panda/src/express/pointerToBase.h +++ b/panda/src/express/pointerToBase.h @@ -31,6 +31,7 @@ public: typedef T To; protected: + ALWAYS_INLINE PointerToBase() DEFAULT_CTOR; INLINE PointerToBase(To *ptr); INLINE PointerToBase(const PointerToBase ©); INLINE ~PointerToBase(); diff --git a/panda/src/express/trueClock.cxx b/panda/src/express/trueClock.cxx index c3db68bbd9..d2104f0ae0 100644 --- a/panda/src/express/trueClock.cxx +++ b/panda/src/express/trueClock.cxx @@ -90,7 +90,7 @@ get_short_raw_time() { * accurate and seems to lose seconds of time per hour, and (d) someone could * be running a program such as Speed Gear which munges this value anyway. */ - PN_int64 count; + int64_t count; QueryPerformanceCounter((LARGE_INTEGER *)&count); time = (double)(count - _init_count) * _recip_frequency; @@ -114,7 +114,7 @@ typedef BOOL (WINAPI * PFNSETPROCESSAFFINITYMASK)(HANDLE, DWORD_PTR); typedef BOOL (WINAPI * PFNGETPROCESSAFFINITYMASK)(HANDLE, DWORD_PTR*, DWORD_PTR*); bool TrueClock:: -set_cpu_affinity(PN_uint32 mask) const { +set_cpu_affinity(uint32_t mask) const { HMODULE hker = GetModuleHandle("kernel32"); if (hker != 0) { PFNGETPROCESSAFFINITYMASK gp = (PFNGETPROCESSAFFINITYMASK) @@ -163,7 +163,7 @@ TrueClock() { } if (get_use_high_res_clock()) { - PN_int64 int_frequency; + int64_t int_frequency; _has_high_res = (QueryPerformanceFrequency((LARGE_INTEGER *)&int_frequency) != 0); if (_has_high_res) { @@ -223,7 +223,7 @@ TrueClock() { double TrueClock:: correct_time(double time) { // First, get the current time of day measurement. - PN_uint64 int_tod; + uint64_t int_tod; GetSystemTimeAsFileTime((FILETIME *)&int_tod); double tod = (double)(int_tod - _init_tod) * _00000001; @@ -545,7 +545,7 @@ get_short_raw_time() { * */ bool TrueClock:: -set_cpu_affinity(PN_uint32 mask) const { +set_cpu_affinity(uint32_t mask) const { return false; } diff --git a/panda/src/express/trueClock.h b/panda/src/express/trueClock.h index 8b7699da96..45ab097e8b 100644 --- a/panda/src/express/trueClock.h +++ b/panda/src/express/trueClock.h @@ -54,7 +54,7 @@ PUBLISHED: INLINE static TrueClock *get_global_ptr(); - bool set_cpu_affinity(PN_uint32 mask) const; + bool set_cpu_affinity(uint32_t mask) const; protected: TrueClock(); @@ -69,10 +69,10 @@ protected: void set_time_scale(double time, double new_time_scale); bool _has_high_res; - PN_int64 _init_count; + int64_t _init_count; double _frequency, _recip_frequency; int _init_tc; - PN_uint64 _init_tod; + uint64_t _init_tod; // The rest of the data structures in this block are strictly for // implementing paranoid_clock: they are designed to allow us to cross-check diff --git a/panda/src/express/typedef.h b/panda/src/express/typedef.h index 32822ae52d..5030e6d77f 100644 --- a/panda/src/express/typedef.h +++ b/panda/src/express/typedef.h @@ -22,8 +22,8 @@ typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; -typedef PN_int64 longlong; -typedef PN_uint64 ulonglong; +typedef int64_t longlong; +typedef uint64_t ulonglong; #endif diff --git a/panda/src/express/virtualFileSimple.cxx b/panda/src/express/virtualFileSimple.cxx index a900dd514f..a036c0df4b 100644 --- a/panda/src/express/virtualFileSimple.cxx +++ b/panda/src/express/virtualFileSimple.cxx @@ -186,7 +186,7 @@ copy_file(VirtualFile *new_file) { * (which you should eventually delete when you are done reading). Returns * NULL on failure. * - * If auto_unwrap is true, an explicitly-named .pz file is automatically + * If auto_unwrap is true, an explicitly-named .pz/.gz file is automatically * decompressed and the decompressed contents are returned. This is different * than vfs-implicit-pz, which will automatically decompress a file if the * extension .pz is *not* given. @@ -195,7 +195,9 @@ istream *VirtualFileSimple:: open_read_file(bool auto_unwrap) const { // Will we be automatically unwrapping a .pz file? - bool do_uncompress = (_implicit_pz_file || (auto_unwrap && _local_filename.get_extension() == "pz")); + bool do_uncompress = (_implicit_pz_file || + (auto_unwrap && (_local_filename.get_extension() == "pz" || + _local_filename.get_extension() == "gz"))); Filename local_filename(_local_filename); if (do_uncompress) { @@ -364,7 +366,9 @@ bool VirtualFileSimple:: read_file(pvector &result, bool auto_unwrap) const { // Will we be automatically unwrapping a .pz file? - bool do_uncompress = (_implicit_pz_file || (auto_unwrap && _local_filename.get_extension() == "pz")); + bool do_uncompress = (_implicit_pz_file || + (auto_unwrap && (_local_filename.get_extension() == "pz" || + _local_filename.get_extension() == "gz"))); Filename local_filename(_local_filename); if (do_uncompress) { diff --git a/panda/src/express/virtualFileSystem.I b/panda/src/express/virtualFileSystem.I index 53b259c821..3a33e3df9c 100644 --- a/panda/src/express/virtualFileSystem.I +++ b/panda/src/express/virtualFileSystem.I @@ -88,7 +88,7 @@ ls_all(const Filename &filename) const { * Convenience function; returns the entire contents of the indicated file as * a string. * - * If auto_unwrap is true, an explicitly-named .pz file is automatically + * If auto_unwrap is true, an explicitly-named .pz/.gz file is automatically * decompressed and the decompressed contents are returned. This is different * than vfs-implicit-pz, which will automatically decompress a file if the * extension .pz is *not* given. @@ -118,7 +118,7 @@ write_file(const Filename &filename, const string &data, bool auto_wrap) { * file, if it exists and can be read. Returns true on success, false * otherwise. * - * If auto_unwrap is true, an explicitly-named .pz file is automatically + * If auto_unwrap is true, an explicitly-named .pz/.gz file is automatically * decompressed and the decompressed contents are returned. This is different * than vfs-implicit-pz, which will automatically decompress a file if the * extension .pz is *not* given. @@ -134,7 +134,7 @@ read_file(const Filename &filename, string &result, bool auto_unwrap) const { * file, if it exists and can be read. Returns true on success, false * otherwise. * - * If auto_unwrap is true, an explicitly-named .pz file is automatically + * If auto_unwrap is true, an explicitly-named .pz/.gz file is automatically * decompressed and the decompressed contents are returned. This is different * than vfs-implicit-pz, which will automatically decompress a file if the * extension .pz is *not* given. diff --git a/panda/src/express/virtualFileSystem.h b/panda/src/express/virtualFileSystem.h index ea37d9ebe3..22d6316ce7 100644 --- a/panda/src/express/virtualFileSystem.h +++ b/panda/src/express/virtualFileSystem.h @@ -61,6 +61,7 @@ PUBLISHED: int get_num_mounts() const; PT(VirtualFileMount) get_mount(int n) const; MAKE_SEQ(get_mounts, get_num_mounts, get_mount); + MAKE_SEQ_PROPERTY(mounts, get_num_mounts, get_mount); BLOCKING bool chdir(const Filename &new_directory); BLOCKING Filename get_cwd() const; diff --git a/panda/src/express/zStreamBuf.cxx b/panda/src/express/zStreamBuf.cxx index aae6fd0484..c6af03499b 100644 --- a/panda/src/express/zStreamBuf.cxx +++ b/panda/src/express/zStreamBuf.cxx @@ -87,9 +87,9 @@ open_read(istream *source, bool owns_source) { _z_source.opaque = Z_NULL; _z_source.msg = (char *)"no error message"; - int result = inflateInit(&_z_source); + int result = inflateInit2(&_z_source, 32 + 15); if (result < 0) { - show_zlib_error("inflateInit", result, _z_source); + show_zlib_error("inflateInit2", result, _z_source); close_read(); } thread_consider_yield(); @@ -170,6 +170,59 @@ close_write() { } } +/** + * Implements seeking within the stream. ZStreamBuf only allows seeking back + * to the beginning of the stream. + */ +streampos ZStreamBuf:: +seekoff(streamoff off, ios_seekdir dir, ios_openmode which) { + if (which != ios::in) { + // We can only do this with the input stream. + return -1; + } + + // Determine the current position. + size_t n = egptr() - gptr(); + streampos gpos = _z_source.total_out - n; + + // Implement tellg() and seeks to current position. + if ((dir == ios::cur && off == 0) || + (dir == ios::beg && off == gpos)) { + return gpos; + } + + if (off != 0 || dir != ios::beg) { + // We only know how to reposition to the beginning. + return -1; + } + + gbump(n); + + _source->seekg(0, ios::beg); + if (_source->tellg() == (streampos)0) { + _z_source.next_in = Z_NULL; + _z_source.avail_in = 0; + _z_source.next_out = Z_NULL; + _z_source.avail_out = 0; + int result = inflateReset(&_z_source); + if (result < 0) { + show_zlib_error("inflateReset", result, _z_source); + } + return 0; + } + + return -1; +} + +/** + * Implements seeking within the stream. ZStreamBuf only allows seeking back + * to the beginning of the stream. + */ +streampos ZStreamBuf:: +seekpos(streampos pos, ios_openmode which) { + return seekoff(pos, ios::beg, which); +} + /** * Called by the system ostream implementation when its internal buffer is * filled, plus one character. diff --git a/panda/src/express/zStreamBuf.h b/panda/src/express/zStreamBuf.h index 4d0b1aa7d6..a034a76d6c 100644 --- a/panda/src/express/zStreamBuf.h +++ b/panda/src/express/zStreamBuf.h @@ -35,6 +35,9 @@ public: void open_write(ostream *dest, bool owns_dest, int compression_level); void close_write(); + virtual streampos seekoff(streamoff off, ios_seekdir dir, ios_openmode which); + virtual streampos seekpos(streampos pos, ios_openmode which); + protected: virtual int overflow(int c); virtual int sync(); diff --git a/panda/src/ffmpeg/ffmpegAudioCursor.cxx b/panda/src/ffmpeg/ffmpegAudioCursor.cxx index 132f2ff9f9..2f73cff60c 100644 --- a/panda/src/ffmpeg/ffmpegAudioCursor.cxx +++ b/panda/src/ffmpeg/ffmpegAudioCursor.cxx @@ -153,7 +153,7 @@ FfmpegAudioCursor(FfmpegAudio *src) : _packet = new AVPacket; _buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE / 2; - _buffer_alloc = new PN_int16[_buffer_size + 64]; + _buffer_alloc = new int16_t[_buffer_size + 64]; // Allocate enough space for 1024 samples per channel. if ((_packet == 0)||(_buffer_alloc == 0)) { @@ -362,8 +362,8 @@ reload_buffer() { */ void FfmpegAudioCursor:: seek(double t) { - PN_int64 target_ts = (PN_int64)(t / _audio_timebase); - if (target_ts < (PN_int64)(_initial_dts)) { + int64_t target_ts = (int64_t)(t / _audio_timebase); + if (target_ts < (int64_t)(_initial_dts)) { // Attempts to seek before the first packet will fail. target_ts = _initial_dts; } @@ -404,7 +404,7 @@ seek(double t) { * audio will be interleaved. */ void FfmpegAudioCursor:: -read_samples(int n, PN_int16 *data) { +read_samples(int n, int16_t *data) { int desired = n * _audio_channels; while (desired > 0) { diff --git a/panda/src/ffmpeg/ffmpegAudioCursor.h b/panda/src/ffmpeg/ffmpegAudioCursor.h index 6d3ddcffb1..21f79dc62d 100644 --- a/panda/src/ffmpeg/ffmpegAudioCursor.h +++ b/panda/src/ffmpeg/ffmpegAudioCursor.h @@ -48,7 +48,7 @@ PUBLISHED: virtual void seek(double offset); public: - virtual void read_samples(int n, PN_int16 *data); + virtual void read_samples(int n, int16_t *data); protected: void fetch_packet(); @@ -66,9 +66,9 @@ protected: double _audio_timebase; AVFrame *_frame; - PN_int16 *_buffer; + int16_t *_buffer; int _buffer_size; - PN_int16 *_buffer_alloc; + int16_t *_buffer_alloc; int _buffer_head; int _buffer_tail; diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.cxx b/panda/src/ffmpeg/ffmpegVideoCursor.cxx index eb33490384..8affe3c116 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.cxx +++ b/panda/src/ffmpeg/ffmpegVideoCursor.cxx @@ -884,8 +884,8 @@ seek(int frame, bool backward) { */ void FfmpegVideoCursor:: do_seek(int frame, bool backward) { - PN_int64 target_ts = (PN_int64)frame; - if (target_ts < (PN_int64)(_initial_dts)) { + int64_t target_ts = (int64_t)frame; + if (target_ts < (int64_t)(_initial_dts)) { // Attempts to seek before the first packet will fail. target_ts = _initial_dts; } diff --git a/panda/src/framework/pandaFramework.cxx b/panda/src/framework/pandaFramework.cxx index 435be0e348..3703793fac 100644 --- a/panda/src/framework/pandaFramework.cxx +++ b/panda/src/framework/pandaFramework.cxx @@ -31,6 +31,12 @@ #include "transformState.h" #include "renderState.h" +#ifdef LINK_ALL_STATIC +#ifdef HAVE_EGG +#include "pandaegg.h" +#endif +#endif + LoaderOptions PandaFramework::_loader_options; /** @@ -101,10 +107,8 @@ open_framework(int &argc, char **&argv) { // We also want the egg loader. #ifdef HAVE_EGG - extern EXPCL_PANDAEGG void init_libpandaegg(); init_libpandaegg(); #endif - #endif // Let's explicitly make a call to the image type library to ensure it gets diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index a66963ca06..7ac9e89fa2 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -591,7 +591,7 @@ load_model(const NodePath &parent, Filename filename) { bool is_image = false; string extension = filename.get_extension(); #ifdef HAVE_ZLIB - if (extension == "pz") { + if (extension == "pz" || extension == "gz") { extension = Filename(filename.get_basename_wo_extension()).get_extension(); } #endif // HAVE_ZLIB diff --git a/panda/src/gles2gsg/gles2gsg.h b/panda/src/gles2gsg/gles2gsg.h index cd905832a1..f88d40c3fc 100644 --- a/panda/src/gles2gsg/gles2gsg.h +++ b/panda/src/gles2gsg/gles2gsg.h @@ -80,7 +80,6 @@ typedef char GLchar; #define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS #define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT GL_FRAMEBUFFER_INCOMPLETE_FORMATS #define GL_DEPTH_ATTACHMENT_EXT GL_DEPTH_ATTACHMENT -#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0 #define GL_STENCIL_ATTACHMENT_EXT GL_STENCIL_ATTACHMENT #define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES #define GL_DEPTH_STENCIL_EXT GL_DEPTH_STENCIL_OES @@ -88,7 +87,6 @@ typedef char GLchar; #define GL_DEPTH24_STENCIL8_EXT GL_DEPTH24_STENCIL8_OES #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES #define GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT32_OES -#define GL_TEXTURE_3D GL_TEXTURE_3D_OES #define GL_MAX_3D_TEXTURE_SIZE GL_MAX_3D_TEXTURE_SIZE_OES #define GL_SAMPLER_3D GL_SAMPLER_3D_OES #define GL_BGRA GL_BGRA_EXT @@ -120,8 +118,119 @@ typedef char GLchar; #define GL_COMPARE_R_TO_TEXTURE_ARB GL_COMPARE_REF_TO_TEXTURE_EXT #define GL_SAMPLER_2D_SHADOW GL_SAMPLER_2D_SHADOW_EXT #define GL_MAX_DRAW_BUFFERS GL_MAX_DRAW_BUFFERS_NV -#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE -#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE +#define GL_SRC1_COLOR GL_SRC1_COLOR_EXT +#define GL_ONE_MINUS_SRC1_COLOR GL_ONE_MINUS_SRC1_COLOR_EXT +#define GL_SRC1_ALPHA GL_SRC1_ALPHA_EXT +#define GL_ONE_MINUS_SRC1_ALPHA GL_ONE_MINUS_SRC1_ALPHA_EXT + +#define GL_DEBUG_OUTPUT_SYNCHRONOUS GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR +#define GL_DEBUG_TYPE_PERFORMANCE GL_DEBUG_TYPE_PERFORMANCE_KHR +#define GL_DEBUG_SEVERITY_HIGH GL_DEBUG_SEVERITY_HIGH_KHR +#define GL_DEBUG_SEVERITY_MEDIUM GL_DEBUG_SEVERITY_MEDIUM_KHR +#define GL_DEBUG_SEVERITY_LOW GL_DEBUG_SEVERITY_LOW_KHR +#define GL_DEBUG_SEVERITY_NOTIFICATION GL_DEBUG_SEVERITY_NOTIFICATION_KHR +#define GL_BUFFER GL_BUFFER_KHR +#define GL_SHADER GL_SHADER_KHR +#define GL_PROGRAM GL_PROGRAM_KHR +#define GL_DEBUG_OUTPUT GL_DEBUG_OUTPUT_KHR + +// For GLES 3 compat - need a better solution for this +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x1 +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x2 +#define GL_UNIFORM_BARRIER_BIT 0x4 +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x8 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x20 +#define GL_COMMAND_BARRIER_BIT 0x40 +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x80 +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x100 +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x200 +#define GL_FRAMEBUFFER_BARRIER_BIT 0x400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x1000 +#define GL_HALF_FLOAT 0x140B +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_RGB10_A2 0x8059 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_NUM_EXTENSIONS 0x821D +#define GL_RG_INTEGER 0x8228 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_RED_INTEGER 0x8D94 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_MAX_IMAGE_UNITS 0x8F38 +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 +#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF #undef SUPPORT_IMMEDIATE_MODE #define APIENTRY diff --git a/panda/src/gles2gsg/panda_esgl2ext.h b/panda/src/gles2gsg/panda_esgl2ext.h index 7e6ff9c32a..6d5258fff0 100644 --- a/panda/src/gles2gsg/panda_esgl2ext.h +++ b/panda/src/gles2gsg/panda_esgl2ext.h @@ -1,1533 +1,1851 @@ #ifndef __panda_esgl2ext_h_ -#define __panda_esgl2ext_h_ - -/* $Revision$ on $Date$ */ +#define __panda_esgl2ext_h_ 1 #ifdef __cplusplus extern "C" { #endif /* - * This document is licensed under the SGI Free Software B License Version - * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . - */ +** Copyright (c) 2013-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ +/* +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.opengl.org/registry/ +** +** Khronos $Revision: 32518 $ on $Date: 2016-03-11 02:42:11 -0800 (Fri, 11 Mar 2016) $ +*/ #ifndef GL_APIENTRYP -# define GL_APIENTRYP GL_APIENTRY* +#define GL_APIENTRYP GL_APIENTRY* #endif -/*------------------------------------------------------------------------* - * OES extension tokens - *------------------------------------------------------------------------*/ +/* Generated on date 20160311 */ -/* GL_OES_compressed_ETC1_RGB8_texture */ -#ifndef GL_OES_compressed_ETC1_RGB8_texture -#define GL_ETC1_RGB8_OES 0x8D64 +/* Generated C header for: + * API: gles2 + * Profile: common + * Versions considered: 2\.[0-9] + * Versions emitted: _nomatch_^ + * Default extensions included: gles2 + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef GL_KHR_blend_equation_advanced +#define GL_KHR_blend_equation_advanced 1 +#define GL_MULTIPLY_KHR 0x9294 +#define GL_SCREEN_KHR 0x9295 +#define GL_OVERLAY_KHR 0x9296 +#define GL_DARKEN_KHR 0x9297 +#define GL_LIGHTEN_KHR 0x9298 +#define GL_COLORDODGE_KHR 0x9299 +#define GL_COLORBURN_KHR 0x929A +#define GL_HARDLIGHT_KHR 0x929B +#define GL_SOFTLIGHT_KHR 0x929C +#define GL_DIFFERENCE_KHR 0x929E +#define GL_EXCLUSION_KHR 0x92A0 +#define GL_HSL_HUE_KHR 0x92AD +#define GL_HSL_SATURATION_KHR 0x92AE +#define GL_HSL_COLOR_KHR 0x92AF +#define GL_HSL_LUMINOSITY_KHR 0x92B0 +typedef void (GL_APIENTRYP PFNGLBLENDBARRIERKHRPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBlendBarrierKHR (void); #endif +#endif /* GL_KHR_blend_equation_advanced */ -/* GL_OES_compressed_paletted_texture */ -#ifndef GL_OES_compressed_paletted_texture -#define GL_PALETTE4_RGB8_OES 0x8B90 -#define GL_PALETTE4_RGBA8_OES 0x8B91 -#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 -#define GL_PALETTE4_RGBA4_OES 0x8B93 -#define GL_PALETTE4_RGB5_A1_OES 0x8B94 -#define GL_PALETTE8_RGB8_OES 0x8B95 -#define GL_PALETTE8_RGBA8_OES 0x8B96 -#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 -#define GL_PALETTE8_RGBA4_OES 0x8B98 -#define GL_PALETTE8_RGB5_A1_OES 0x8B99 -#endif +#ifndef GL_KHR_blend_equation_advanced_coherent +#define GL_KHR_blend_equation_advanced_coherent 1 +#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285 +#endif /* GL_KHR_blend_equation_advanced_coherent */ -/* GL_OES_depth24 */ -#ifndef GL_OES_depth24 -#define GL_DEPTH_COMPONENT24_OES 0x81A6 -#endif - -/* GL_OES_depth32 */ -#ifndef GL_OES_depth32 -#define GL_DEPTH_COMPONENT32_OES 0x81A7 -#endif - -/* GL_OES_depth_texture */ -/* No new tokens introduced by this extension. */ - -/* GL_OES_EGL_image */ -#ifndef GL_OES_EGL_image -typedef void* GLeglImageOES; -#endif - -/* GL_OES_EGL_image_external */ -#ifndef GL_OES_EGL_image_external -/* GLeglImageOES defined in GL_OES_EGL_image already. */ -#define GL_TEXTURE_EXTERNAL_OES 0x8D65 -#define GL_SAMPLER_EXTERNAL_OES 0x8D66 -#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67 -#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68 -#endif - -/* GL_OES_element_index_uint */ -#ifndef GL_OES_element_index_uint -#define GL_UNSIGNED_INT 0x1405 -#endif - -/* GL_OES_get_program_binary */ -#ifndef GL_OES_get_program_binary -#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741 -#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE -#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF -#endif - -/* GL_OES_mapbuffer */ -#ifndef GL_OES_mapbuffer -#define GL_WRITE_ONLY_OES 0x88B9 -#define GL_BUFFER_ACCESS_OES 0x88BB -#define GL_BUFFER_MAPPED_OES 0x88BC -#define GL_BUFFER_MAP_POINTER_OES 0x88BD -#endif - -/* GL_OES_packed_depth_stencil */ -#ifndef GL_OES_packed_depth_stencil -#define GL_DEPTH_STENCIL_OES 0x84F9 -#define GL_UNSIGNED_INT_24_8_OES 0x84FA -#define GL_DEPTH24_STENCIL8_OES 0x88F0 -#endif - -/* GL_OES_required_internalformat */ -#ifndef GL_OES_required_internalformat -#define GL_ALPHA8_OES 0x803C -#define GL_DEPTH_COMPONENT16_OES 0x81A5 -/* reuse GL_DEPTH_COMPONENT24_OES */ -/* reuse GL_DEPTH24_STENCIL8_OES */ -/* reuse GL_DEPTH_COMPONENT32_OES */ -#define GL_LUMINANCE4_ALPHA4_OES 0x8043 -#define GL_LUMINANCE8_ALPHA8_OES 0x8045 -#define GL_LUMINANCE8_OES 0x8040 -#define GL_RGBA4_OES 0x8056 -#define GL_RGB5_A1_OES 0x8057 -#define GL_RGB565_OES 0x8D62 -/* reuse GL_RGB8_OES */ -/* reuse GL_RGBA8_OES */ -/* reuse GL_RGB10_EXT */ -/* reuse GL_RGB10_A2_EXT */ -#endif - -/* GL_OES_rgb8_rgba8 */ -#ifndef GL_OES_rgb8_rgba8 -#define GL_RGB8_OES 0x8051 -#define GL_RGBA8_OES 0x8058 -#endif - -/* GL_OES_standard_derivatives */ -#ifndef GL_OES_standard_derivatives -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B -#endif - -/* GL_OES_stencil1 */ -#ifndef GL_OES_stencil1 -#define GL_STENCIL_INDEX1_OES 0x8D46 -#endif - -/* GL_OES_stencil4 */ -#ifndef GL_OES_stencil4 -#define GL_STENCIL_INDEX4_OES 0x8D47 -#endif - -#ifndef GL_OES_surfaceless_context -#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219 -#endif - -/* GL_OES_texture_3D */ -#ifndef GL_OES_texture_3D -#define GL_TEXTURE_WRAP_R_OES 0x8072 -#define GL_TEXTURE_3D_OES 0x806F -#define GL_TEXTURE_BINDING_3D_OES 0x806A -#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073 -#define GL_SAMPLER_3D_OES 0x8B5F -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4 -#endif - -/* GL_OES_texture_float */ -/* No new tokens introduced by this extension. */ - -/* GL_OES_texture_float_linear */ -/* No new tokens introduced by this extension. */ - -/* GL_OES_texture_half_float */ -#ifndef GL_OES_texture_half_float -#define GL_HALF_FLOAT_OES 0x8D61 -#endif - -/* GL_OES_texture_half_float_linear */ -/* No new tokens introduced by this extension. */ - -/* GL_OES_texture_npot */ -/* No new tokens introduced by this extension. */ - -/* GL_OES_vertex_array_object */ -#ifndef GL_OES_vertex_array_object -#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5 -#endif - -/* GL_OES_vertex_half_float */ -/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */ - -/* GL_OES_vertex_type_10_10_10_2 */ -#ifndef GL_OES_vertex_type_10_10_10_2 -#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6 -#define GL_INT_10_10_10_2_OES 0x8DF7 -#endif - -/*------------------------------------------------------------------------* - * KHR extension tokens - *------------------------------------------------------------------------*/ +#ifndef GL_KHR_context_flush_control +#define GL_KHR_context_flush_control 1 +#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB +#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC +#endif /* GL_KHR_context_flush_control */ #ifndef GL_KHR_debug -typedef void (GL_APIENTRYP GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam); -#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 -#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 -#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 -#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 -#define GL_DEBUG_SOURCE_API 0x8246 -#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 -#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 -#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 -#define GL_DEBUG_SOURCE_APPLICATION 0x824A -#define GL_DEBUG_SOURCE_OTHER 0x824B -#define GL_DEBUG_TYPE_ERROR 0x824C -#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D -#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E -#define GL_DEBUG_TYPE_PORTABILITY 0x824F -#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 -#define GL_DEBUG_TYPE_OTHER 0x8251 -#define GL_DEBUG_TYPE_MARKER 0x8268 -#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 -#define GL_DEBUG_TYPE_POP_GROUP 0x826A -#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B -#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C -#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D -#define GL_BUFFER 0x82E0 -#define GL_SHADER 0x82E1 -#define GL_PROGRAM 0x82E2 -#define GL_QUERY 0x82E3 -/* PROGRAM_PIPELINE only in GL */ -#define GL_SAMPLER 0x82E6 -/* DISPLAY_LIST only in GL */ -#define GL_MAX_LABEL_LENGTH 0x82E8 -#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 -#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 -#define GL_DEBUG_LOGGED_MESSAGES 0x9145 -#define GL_DEBUG_SEVERITY_HIGH 0x9146 -#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 -#define GL_DEBUG_SEVERITY_LOW 0x9148 -#define GL_DEBUG_OUTPUT 0x92E0 -#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 -#define GL_STACK_OVERFLOW 0x0503 -#define GL_STACK_UNDERFLOW 0x0504 +#define GL_KHR_debug 1 +typedef void (GL_APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +#define GL_SAMPLER 0x82E6 +#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245 +#define GL_DEBUG_SOURCE_API_KHR 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A +#define GL_DEBUG_SOURCE_OTHER_KHR 0x824B +#define GL_DEBUG_TYPE_ERROR_KHR 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E +#define GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250 +#define GL_DEBUG_TYPE_OTHER_KHR 0x8251 +#define GL_DEBUG_TYPE_MARKER_KHR 0x8268 +#define GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269 +#define GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A +#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C +#define GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D +#define GL_BUFFER_KHR 0x82E0 +#define GL_SHADER_KHR 0x82E1 +#define GL_PROGRAM_KHR 0x82E2 +#define GL_VERTEX_ARRAY_KHR 0x8074 +#define GL_QUERY_KHR 0x82E3 +#define GL_PROGRAM_PIPELINE_KHR 0x82E4 +#define GL_SAMPLER_KHR 0x82E6 +#define GL_MAX_LABEL_LENGTH_KHR 0x82E8 +#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_KHR 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147 +#define GL_DEBUG_SEVERITY_LOW_KHR 0x9148 +#define GL_DEBUG_OUTPUT_KHR 0x92E0 +#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002 +#define GL_STACK_OVERFLOW_KHR 0x0503 +#define GL_STACK_UNDERFLOW_KHR 0x0504 +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKKHRPROC) (GLDEBUGPROCKHR callback, const void *userParam); +typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPKHRPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); +typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPKHRPROC) (void); +typedef void (GL_APIENTRYP PFNGLOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETPOINTERVKHRPROC) (GLenum pname, void **params); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDebugMessageControlKHR (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +GL_APICALL void GL_APIENTRY glDebugMessageInsertKHR (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +GL_APICALL void GL_APIENTRY glDebugMessageCallbackKHR (GLDEBUGPROCKHR callback, const void *userParam); +GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLogKHR (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +GL_APICALL void GL_APIENTRY glPushDebugGroupKHR (GLenum source, GLuint id, GLsizei length, const GLchar *message); +GL_APICALL void GL_APIENTRY glPopDebugGroupKHR (void); +GL_APICALL void GL_APIENTRY glObjectLabelKHR (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +GL_APICALL void GL_APIENTRY glGetObjectLabelKHR (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +GL_APICALL void GL_APIENTRY glObjectPtrLabelKHR (const void *ptr, GLsizei length, const GLchar *label); +GL_APICALL void GL_APIENTRY glGetObjectPtrLabelKHR (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +GL_APICALL void GL_APIENTRY glGetPointervKHR (GLenum pname, void **params); #endif +#endif /* GL_KHR_debug */ + +#ifndef GL_KHR_no_error +#define GL_KHR_no_error 1 +#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008 +#endif /* GL_KHR_no_error */ + +#ifndef GL_KHR_robust_buffer_access_behavior +#define GL_KHR_robust_buffer_access_behavior 1 +#endif /* GL_KHR_robust_buffer_access_behavior */ + +#ifndef GL_KHR_robustness +#define GL_KHR_robustness 1 +#define GL_CONTEXT_ROBUST_ACCESS_KHR 0x90F3 +#define GL_LOSE_CONTEXT_ON_RESET_KHR 0x8252 +#define GL_GUILTY_CONTEXT_RESET_KHR 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_KHR 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_KHR 0x8255 +#define GL_RESET_NOTIFICATION_STRATEGY_KHR 0x8256 +#define GL_NO_RESET_NOTIFICATION_KHR 0x8261 +#define GL_CONTEXT_LOST_KHR 0x0507 +typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC) (void); +typedef void (GL_APIENTRYP PFNGLREADNPIXELSKHRPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void); +GL_APICALL void GL_APIENTRY glReadnPixelsKHR (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +GL_APICALL void GL_APIENTRY glGetnUniformfvKHR (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetnUniformivKHR (GLuint program, GLint location, GLsizei bufSize, GLint *params); +GL_APICALL void GL_APIENTRY glGetnUniformuivKHR (GLuint program, GLint location, GLsizei bufSize, GLuint *params); +#endif +#endif /* GL_KHR_robustness */ + +#ifndef GL_KHR_texture_compression_astc_hdr +#define GL_KHR_texture_compression_astc_hdr 1 +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD +#endif /* GL_KHR_texture_compression_astc_hdr */ #ifndef GL_KHR_texture_compression_astc_ldr -#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 -#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 -#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 -#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 -#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 -#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 -#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 -#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 -#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 -#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 -#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA -#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB -#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC -#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD -#endif +#define GL_KHR_texture_compression_astc_ldr 1 +#endif /* GL_KHR_texture_compression_astc_ldr */ -/*------------------------------------------------------------------------* - * AMD extension tokens - *------------------------------------------------------------------------*/ +#ifndef GL_KHR_texture_compression_astc_sliced_3d +#define GL_KHR_texture_compression_astc_sliced_3d 1 +#endif /* GL_KHR_texture_compression_astc_sliced_3d */ -/* GL_AMD_compressed_3DC_texture */ -#ifndef GL_AMD_compressed_3DC_texture -#define GL_3DC_X_AMD 0x87F9 -#define GL_3DC_XY_AMD 0x87FA -#endif - -/* GL_AMD_compressed_ATC_texture */ -#ifndef GL_AMD_compressed_ATC_texture -#define GL_ATC_RGB_AMD 0x8C92 -#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 -#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE -#endif - -/* GL_AMD_performance_monitor */ -#ifndef GL_AMD_performance_monitor -#define GL_COUNTER_TYPE_AMD 0x8BC0 -#define GL_COUNTER_RANGE_AMD 0x8BC1 -#define GL_UNSIGNED_INT64_AMD 0x8BC2 -#define GL_PERCENTAGE_AMD 0x8BC3 -#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 -#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 -#define GL_PERFMON_RESULT_AMD 0x8BC6 -#endif - -/* GL_AMD_program_binary_Z400 */ -#ifndef GL_AMD_program_binary_Z400 -#define GL_Z400_BINARY_AMD 0x8740 -#endif - -/*------------------------------------------------------------------------* - * ANGLE extension tokens - *------------------------------------------------------------------------*/ - -/* GL_ANGLE_framebuffer_blit */ -#ifndef GL_ANGLE_framebuffer_blit -#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8 -#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9 -#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6 -#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA -#endif - -/* GL_ANGLE_framebuffer_multisample */ -#ifndef GL_ANGLE_framebuffer_multisample -#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56 -#define GL_MAX_SAMPLES_ANGLE 0x8D57 -#endif - -/* GL_ANGLE_instanced_arrays */ -#ifndef GL_ANGLE_instanced_arrays -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE -#endif - -/* GL_ANGLE_pack_reverse_row_order */ -#ifndef GL_ANGLE_pack_reverse_row_order -#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4 -#endif - -/* GL_ANGLE_texture_compression_dxt3 */ -#ifndef GL_ANGLE_texture_compression_dxt3 -#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2 -#endif - -/* GL_ANGLE_texture_compression_dxt5 */ -#ifndef GL_ANGLE_texture_compression_dxt5 -#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3 -#endif - -/* GL_ANGLE_texture_usage */ -#ifndef GL_ANGLE_texture_usage -#define GL_TEXTURE_USAGE_ANGLE 0x93A2 -#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3 -#endif - -/* GL_ANGLE_translated_shader_source */ -#ifndef GL_ANGLE_translated_shader_source -#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 -#endif - -/*------------------------------------------------------------------------* - * APPLE extension tokens - *------------------------------------------------------------------------*/ - -/* GL_APPLE_copy_texture_levels */ -/* No new tokens introduced by this extension. */ - -/* GL_APPLE_framebuffer_multisample */ -#ifndef GL_APPLE_framebuffer_multisample -#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56 -#define GL_MAX_SAMPLES_APPLE 0x8D57 -#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8 -#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9 -#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6 -#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA -#endif - -/* GL_APPLE_rgb_422 */ -#ifndef GL_APPLE_rgb_422 -#define GL_RGB_422_APPLE 0x8A1F -#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA -#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB -#endif - -/* GL_APPLE_sync */ -#ifndef GL_APPLE_sync - -#ifndef __gl3_h_ -/* These types are defined with reference to - * in the Apple extension spec, but here we use the Khronos - * portable types in khrplatform.h, and assume those types - * are always defined. - * If any other extensions using these types are defined, - * the typedefs must move out of this block and be shared. - */ -typedef khronos_int64_t GLint64; -typedef khronos_uint64_t GLuint64; -typedef struct __GLsync *GLsync; -#endif - -#define GL_SYNC_OBJECT_APPLE 0x8A53 -#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111 -#define GL_OBJECT_TYPE_APPLE 0x9112 -#define GL_SYNC_CONDITION_APPLE 0x9113 -#define GL_SYNC_STATUS_APPLE 0x9114 -#define GL_SYNC_FLAGS_APPLE 0x9115 -#define GL_SYNC_FENCE_APPLE 0x9116 -#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117 -#define GL_UNSIGNALED_APPLE 0x9118 -#define GL_SIGNALED_APPLE 0x9119 -#define GL_ALREADY_SIGNALED_APPLE 0x911A -#define GL_TIMEOUT_EXPIRED_APPLE 0x911B -#define GL_CONDITION_SATISFIED_APPLE 0x911C -#define GL_WAIT_FAILED_APPLE 0x911D -#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001 -#define GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFFull -#endif - -/* GL_APPLE_texture_format_BGRA8888 */ -#ifndef GL_APPLE_texture_format_BGRA8888 -#define GL_BGRA_EXT 0x80E1 -#endif - -/* GL_APPLE_texture_max_level */ -#ifndef GL_APPLE_texture_max_level -#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D -#endif - -/*------------------------------------------------------------------------* - * ARM extension tokens - *------------------------------------------------------------------------*/ - -/* GL_ARM_mali_program_binary */ -#ifndef GL_ARM_mali_program_binary -#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61 -#endif - -/* GL_ARM_mali_shader_binary */ -#ifndef GL_ARM_mali_shader_binary -#define GL_MALI_SHADER_BINARY_ARM 0x8F60 -#endif - -/* GL_ARM_rgba8 */ -/* No new tokens introduced by this extension. */ - -/*------------------------------------------------------------------------* - * EXT extension tokens - *------------------------------------------------------------------------*/ - -/* GL_EXT_blend_minmax */ -#ifndef GL_EXT_blend_minmax -#define GL_MIN_EXT 0x8007 -#define GL_MAX_EXT 0x8008 -#endif - -/* GL_EXT_color_buffer_half_float */ -#ifndef GL_EXT_color_buffer_half_float -#define GL_RGBA16F_EXT 0x881A -#define GL_RGB16F_EXT 0x881B -#define GL_RG16F_EXT 0x822F -#define GL_R16F_EXT 0x822D -#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211 -#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17 -#endif - -/* GL_EXT_debug_label */ -#ifndef GL_EXT_debug_label -#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F -#define GL_PROGRAM_OBJECT_EXT 0x8B40 -#define GL_SHADER_OBJECT_EXT 0x8B48 -#define GL_BUFFER_OBJECT_EXT 0x9151 -#define GL_QUERY_OBJECT_EXT 0x9153 -#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154 -#endif - -/* GL_EXT_debug_marker */ -/* No new tokens introduced by this extension. */ - -/* GL_EXT_discard_framebuffer */ -#ifndef GL_EXT_discard_framebuffer -#define GL_COLOR_EXT 0x1800 -#define GL_DEPTH_EXT 0x1801 -#define GL_STENCIL_EXT 0x1802 -#endif - -/* GL_EXT_map_buffer_range */ -#ifndef GL_EXT_map_buffer_range -#define GL_MAP_READ_BIT_EXT 0x0001 -#define GL_MAP_WRITE_BIT_EXT 0x0002 -#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004 -#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008 -#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010 -#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020 -#endif - -/* GL_EXT_multisampled_render_to_texture */ -#ifndef GL_EXT_multisampled_render_to_texture -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C -/* reuse values from GL_EXT_framebuffer_multisample (desktop extension) */ -#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 -#define GL_MAX_SAMPLES_EXT 0x8D57 -#endif - -/* GL_EXT_multiview_draw_buffers */ -#ifndef GL_EXT_multiview_draw_buffers -#define GL_COLOR_ATTACHMENT_EXT 0x90F0 -#define GL_MULTIVIEW_EXT 0x90F1 -#define GL_DRAW_BUFFER_EXT 0x0C01 -#define GL_READ_BUFFER_EXT 0x0C02 -#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2 -#endif - -/* GL_EXT_multi_draw_arrays */ -/* No new tokens introduced by this extension. */ - -/* GL_EXT_occlusion_query_boolean */ -#ifndef GL_EXT_occlusion_query_boolean -#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F -#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A -#define GL_CURRENT_QUERY_EXT 0x8865 -#define GL_QUERY_RESULT_EXT 0x8866 -#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867 -#endif - -/* GL_EXT_read_format_bgra */ -#ifndef GL_EXT_read_format_bgra -#define GL_BGRA_EXT 0x80E1 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366 -#endif - -/* GL_EXT_robustness */ -#ifndef GL_EXT_robustness -/* reuse GL_NO_ERROR */ -#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253 -#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254 -#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255 -#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3 -#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256 -#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252 -#define GL_NO_RESET_NOTIFICATION_EXT 0x8261 -#endif - -/* GL_EXT_separate_shader_objects */ -#ifndef GL_EXT_separate_shader_objects -#define GL_VERTEX_SHADER_BIT_EXT 0x00000001 -#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002 -#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF -#define GL_PROGRAM_SEPARABLE_EXT 0x8258 -#define GL_ACTIVE_PROGRAM_EXT 0x8259 -#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A -#endif - -/* GL_EXT_shader_framebuffer_fetch */ -#ifndef GL_EXT_shader_framebuffer_fetch -#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 -#endif - -/* GL_EXT_shader_texture_lod */ -/* No new tokens introduced by this extension. */ - -/* GL_EXT_shadow_samplers */ -#ifndef GL_EXT_shadow_samplers -#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C -#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D -#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E -#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62 -#endif - -/* GL_EXT_sRGB */ -#ifndef GL_EXT_sRGB -#define GL_SRGB_EXT 0x8C40 -#define GL_SRGB_ALPHA_EXT 0x8C42 -#define GL_SRGB8_ALPHA8_EXT 0x8C43 -#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210 -#endif - -/* GL_EXT_texture_compression_dxt1 */ -#ifndef GL_EXT_texture_compression_dxt1 -#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#endif - -/* GL_EXT_texture_filter_anisotropic */ -#ifndef GL_EXT_texture_filter_anisotropic -#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF -#endif - -/* GL_EXT_texture_format_BGRA8888 */ -#ifndef GL_EXT_texture_format_BGRA8888 -#define GL_BGRA_EXT 0x80E1 -#endif - -/* GL_EXT_texture_rg */ -#ifndef GL_EXT_texture_rg -#define GL_RED_EXT 0x1903 -#define GL_RG_EXT 0x8227 -#define GL_R8_EXT 0x8229 -#define GL_RG8_EXT 0x822B -#endif - -/* GL_EXT_texture_storage */ -#ifndef GL_EXT_texture_storage -#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F -#define GL_ALPHA8_EXT 0x803C -#define GL_LUMINANCE8_EXT 0x8040 -#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 -#define GL_RGBA32F_EXT 0x8814 -#define GL_RGB32F_EXT 0x8815 -#define GL_ALPHA32F_EXT 0x8816 -#define GL_LUMINANCE32F_EXT 0x8818 -#define GL_LUMINANCE_ALPHA32F_EXT 0x8819 -/* reuse GL_RGBA16F_EXT */ -/* reuse GL_RGB16F_EXT */ -#define GL_ALPHA16F_EXT 0x881C -#define GL_LUMINANCE16F_EXT 0x881E -#define GL_LUMINANCE_ALPHA16F_EXT 0x881F -#define GL_RGB10_A2_EXT 0x8059 -#define GL_RGB10_EXT 0x8052 -#define GL_BGRA8_EXT 0x93A1 -#define GL_R8_EXT 0x8229 -#define GL_RG8_EXT 0x822B -#define GL_R32F_EXT 0x822E -#define GL_RG32F_EXT 0x8230 -#define GL_R16F_EXT 0x822D -#define GL_RG16F_EXT 0x822F -#endif - -/* GL_EXT_texture_type_2_10_10_10_REV */ -#ifndef GL_EXT_texture_type_2_10_10_10_REV -#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368 -#endif - -/* GL_EXT_unpack_subimage */ -#ifndef GL_EXT_unpack_subimage -#define GL_UNPACK_ROW_LENGTH 0x0CF2 -#define GL_UNPACK_SKIP_ROWS 0x0CF3 -#define GL_UNPACK_SKIP_PIXELS 0x0CF4 -#endif - -/*------------------------------------------------------------------------* - * DMP extension tokens - *------------------------------------------------------------------------*/ - -/* GL_DMP_shader_binary */ -#ifndef GL_DMP_shader_binary -#define GL_SHADER_BINARY_DMP 0x9250 -#endif - -/*------------------------------------------------------------------------* - * FJ extension tokens - *------------------------------------------------------------------------*/ - -/* GL_FJ_shader_binary_GCCSO */ -#ifndef GL_FJ_shader_binary_GCCSO -#define GCCSO_SHADER_BINARY_FJ 0x9260 -#endif - -/*------------------------------------------------------------------------* - * IMG extension tokens - *------------------------------------------------------------------------*/ - -/* GL_IMG_program_binary */ -#ifndef GL_IMG_program_binary -#define GL_SGX_PROGRAM_BINARY_IMG 0x9130 -#endif - -/* GL_IMG_read_format */ -#ifndef GL_IMG_read_format -#define GL_BGRA_IMG 0x80E1 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365 -#endif - -/* GL_IMG_shader_binary */ -#ifndef GL_IMG_shader_binary -#define GL_SGX_BINARY_IMG 0x8C0A -#endif - -/* GL_IMG_texture_compression_pvrtc */ -#ifndef GL_IMG_texture_compression_pvrtc -#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 -#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 -#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 -#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 -#endif - -/* GL_IMG_multisampled_render_to_texture */ -#ifndef GL_IMG_multisampled_render_to_texture -#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133 -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134 -#define GL_MAX_SAMPLES_IMG 0x9135 -#define GL_TEXTURE_SAMPLES_IMG 0x9136 -#endif - -/*------------------------------------------------------------------------* - * NV extension tokens - *------------------------------------------------------------------------*/ - -/* GL_NV_coverage_sample */ -#ifndef GL_NV_coverage_sample -#define GL_COVERAGE_COMPONENT_NV 0x8ED0 -#define GL_COVERAGE_COMPONENT4_NV 0x8ED1 -#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2 -#define GL_COVERAGE_BUFFERS_NV 0x8ED3 -#define GL_COVERAGE_SAMPLES_NV 0x8ED4 -#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5 -#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6 -#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7 -#define GL_COVERAGE_BUFFER_BIT_NV 0x8000 -#endif - -/* GL_NV_depth_nonlinear */ -#ifndef GL_NV_depth_nonlinear -#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C -#endif - -/* GL_NV_draw_buffers */ -#ifndef GL_NV_draw_buffers -#define GL_MAX_DRAW_BUFFERS_NV 0x8824 -#define GL_DRAW_BUFFER0_NV 0x8825 -#define GL_DRAW_BUFFER1_NV 0x8826 -#define GL_DRAW_BUFFER2_NV 0x8827 -#define GL_DRAW_BUFFER3_NV 0x8828 -#define GL_DRAW_BUFFER4_NV 0x8829 -#define GL_DRAW_BUFFER5_NV 0x882A -#define GL_DRAW_BUFFER6_NV 0x882B -#define GL_DRAW_BUFFER7_NV 0x882C -#define GL_DRAW_BUFFER8_NV 0x882D -#define GL_DRAW_BUFFER9_NV 0x882E -#define GL_DRAW_BUFFER10_NV 0x882F -#define GL_DRAW_BUFFER11_NV 0x8830 -#define GL_DRAW_BUFFER12_NV 0x8831 -#define GL_DRAW_BUFFER13_NV 0x8832 -#define GL_DRAW_BUFFER14_NV 0x8833 -#define GL_DRAW_BUFFER15_NV 0x8834 -#define GL_COLOR_ATTACHMENT0_NV 0x8CE0 -#define GL_COLOR_ATTACHMENT1_NV 0x8CE1 -#define GL_COLOR_ATTACHMENT2_NV 0x8CE2 -#define GL_COLOR_ATTACHMENT3_NV 0x8CE3 -#define GL_COLOR_ATTACHMENT4_NV 0x8CE4 -#define GL_COLOR_ATTACHMENT5_NV 0x8CE5 -#define GL_COLOR_ATTACHMENT6_NV 0x8CE6 -#define GL_COLOR_ATTACHMENT7_NV 0x8CE7 -#define GL_COLOR_ATTACHMENT8_NV 0x8CE8 -#define GL_COLOR_ATTACHMENT9_NV 0x8CE9 -#define GL_COLOR_ATTACHMENT10_NV 0x8CEA -#define GL_COLOR_ATTACHMENT11_NV 0x8CEB -#define GL_COLOR_ATTACHMENT12_NV 0x8CEC -#define GL_COLOR_ATTACHMENT13_NV 0x8CED -#define GL_COLOR_ATTACHMENT14_NV 0x8CEE -#define GL_COLOR_ATTACHMENT15_NV 0x8CEF -#endif - -/* GL_NV_fbo_color_attachments */ -#ifndef GL_NV_fbo_color_attachments -#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF -/* GL_COLOR_ATTACHMENT{0-15}_NV defined in GL_NV_draw_buffers already. */ -#endif - -/* GL_NV_fence */ -#ifndef GL_NV_fence -#define GL_ALL_COMPLETED_NV 0x84F2 -#define GL_FENCE_STATUS_NV 0x84F3 -#define GL_FENCE_CONDITION_NV 0x84F4 -#endif - -/* GL_NV_read_buffer */ -#ifndef GL_NV_read_buffer -#define GL_READ_BUFFER_NV 0x0C02 -#endif - -/* GL_NV_read_buffer_front */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_read_depth */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_read_depth_stencil */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_read_stencil */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_texture_compression_s3tc_update */ -/* No new tokens introduced by this extension. */ - -/* GL_NV_texture_npot_2D_mipmap */ -/* No new tokens introduced by this extension. */ - -/*------------------------------------------------------------------------* - * QCOM extension tokens - *------------------------------------------------------------------------*/ - -/* GL_QCOM_alpha_test */ -#ifndef GL_QCOM_alpha_test -#define GL_ALPHA_TEST_QCOM 0x0BC0 -#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 -#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 -#endif - -/* GL_QCOM_binning_control */ -#ifndef GL_QCOM_binning_control -#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0 -#define GL_CPU_OPTIMIZED_QCOM 0x8FB1 -#define GL_GPU_OPTIMIZED_QCOM 0x8FB2 -#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3 -#endif - -/* GL_QCOM_driver_control */ -/* No new tokens introduced by this extension. */ - -/* GL_QCOM_extended_get */ -#ifndef GL_QCOM_extended_get -#define GL_TEXTURE_WIDTH_QCOM 0x8BD2 -#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3 -#define GL_TEXTURE_DEPTH_QCOM 0x8BD4 -#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5 -#define GL_TEXTURE_FORMAT_QCOM 0x8BD6 -#define GL_TEXTURE_TYPE_QCOM 0x8BD7 -#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8 -#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9 -#define GL_TEXTURE_TARGET_QCOM 0x8BDA -#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB -#define GL_STATE_RESTORE 0x8BDC -#endif - -/* GL_QCOM_extended_get2 */ -/* No new tokens introduced by this extension. */ - -/* GL_QCOM_perfmon_global_mode */ -#ifndef GL_QCOM_perfmon_global_mode -#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0 -#endif - -/* GL_QCOM_writeonly_rendering */ -#ifndef GL_QCOM_writeonly_rendering -#define GL_WRITEONLY_RENDERING_QCOM 0x8823 -#endif - -/* GL_QCOM_tiled_rendering */ -#ifndef GL_QCOM_tiled_rendering -#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001 -#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002 -#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004 -#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008 -#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010 -#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020 -#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040 -#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080 -#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100 -#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200 -#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400 -#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800 -#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000 -#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000 -#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000 -#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000 -#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000 -#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000 -#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000 -#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000 -#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000 -#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000 -#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000 -#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000 -#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000 -#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000 -#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000 -#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000 -#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000 -#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000 -#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000 -#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000 -#endif - -/*------------------------------------------------------------------------* - * VIV extension tokens - *------------------------------------------------------------------------*/ - -/* GL_VIV_shader_binary */ -#ifndef GL_VIV_shader_binary -#define GL_SHADER_BINARY_VIV 0x8FC4 -#endif - -/*------------------------------------------------------------------------* - * End of extension tokens, start of corresponding extension functions - *------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------* - * OES extension functions - *------------------------------------------------------------------------*/ - -/* GL_OES_compressed_ETC1_RGB8_texture */ -#ifndef GL_OES_compressed_ETC1_RGB8_texture -#define GL_OES_compressed_ETC1_RGB8_texture 1 -#endif - -/* GL_OES_compressed_paletted_texture */ -#ifndef GL_OES_compressed_paletted_texture -#define GL_OES_compressed_paletted_texture 1 -#endif - -/* GL_OES_depth24 */ -#ifndef GL_OES_depth24 -#define GL_OES_depth24 1 -#endif - -/* GL_OES_depth32 */ -#ifndef GL_OES_depth32 -#define GL_OES_depth32 1 -#endif - -/* GL_OES_depth_texture */ -#ifndef GL_OES_depth_texture -#define GL_OES_depth_texture 1 -#endif - -/* GL_OES_EGL_image */ #ifndef GL_OES_EGL_image #define GL_OES_EGL_image 1 +typedef void *GLeglImageOES; +typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); +typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image); GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image); #endif -typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); -typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); -#endif +#endif /* GL_OES_EGL_image */ -/* GL_OES_EGL_image_external */ #ifndef GL_OES_EGL_image_external #define GL_OES_EGL_image_external 1 -/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */ -#endif +#define GL_TEXTURE_EXTERNAL_OES 0x8D65 +#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67 +#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68 +#define GL_SAMPLER_EXTERNAL_OES 0x8D66 +#endif /* GL_OES_EGL_image_external */ + +#ifndef GL_OES_EGL_image_external_essl3 +#define GL_OES_EGL_image_external_essl3 1 +#endif /* GL_OES_EGL_image_external_essl3 */ + +#ifndef GL_OES_compressed_ETC1_RGB8_sub_texture +#define GL_OES_compressed_ETC1_RGB8_sub_texture 1 +#endif /* GL_OES_compressed_ETC1_RGB8_sub_texture */ + +#ifndef GL_OES_compressed_ETC1_RGB8_texture +#define GL_OES_compressed_ETC1_RGB8_texture 1 +#define GL_ETC1_RGB8_OES 0x8D64 +#endif /* GL_OES_compressed_ETC1_RGB8_texture */ + +#ifndef GL_OES_compressed_paletted_texture +#define GL_OES_compressed_paletted_texture 1 +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 +#endif /* GL_OES_compressed_paletted_texture */ + +#ifndef GL_OES_copy_image +#define GL_OES_copy_image 1 +typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAOESPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glCopyImageSubDataOES (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +#endif +#endif /* GL_OES_copy_image */ + +#ifndef GL_OES_depth24 +#define GL_OES_depth24 1 +#define GL_DEPTH_COMPONENT24_OES 0x81A6 +#endif /* GL_OES_depth24 */ + +#ifndef GL_OES_depth32 +#define GL_OES_depth32 1 +#define GL_DEPTH_COMPONENT32_OES 0x81A7 +#endif /* GL_OES_depth32 */ + +#ifndef GL_OES_depth_texture +#define GL_OES_depth_texture 1 +#endif /* GL_OES_depth_texture */ + +#ifndef GL_OES_draw_buffers_indexed +#define GL_OES_draw_buffers_indexed 1 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +typedef void (GL_APIENTRYP PFNGLENABLEIOESPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP PFNGLDISABLEIOESPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIOESPROC) (GLuint buf, GLenum mode); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIOESPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCIOESPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIOESPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GL_APIENTRYP PFNGLCOLORMASKIOESPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIOESPROC) (GLenum target, GLuint index); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glEnableiOES (GLenum target, GLuint index); +GL_APICALL void GL_APIENTRY glDisableiOES (GLenum target, GLuint index); +GL_APICALL void GL_APIENTRY glBlendEquationiOES (GLuint buf, GLenum mode); +GL_APICALL void GL_APIENTRY glBlendEquationSeparateiOES (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +GL_APICALL void GL_APIENTRY glBlendFunciOES (GLuint buf, GLenum src, GLenum dst); +GL_APICALL void GL_APIENTRY glBlendFuncSeparateiOES (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +GL_APICALL void GL_APIENTRY glColorMaskiOES (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +GL_APICALL GLboolean GL_APIENTRY glIsEnablediOES (GLenum target, GLuint index); +#endif +#endif /* GL_OES_draw_buffers_indexed */ + +#ifndef GL_OES_draw_elements_base_vertex +#define GL_OES_draw_elements_base_vertex 1 +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexOES (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexOES (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); +#endif +#endif /* GL_OES_draw_elements_base_vertex */ -/* GL_OES_element_index_uint */ #ifndef GL_OES_element_index_uint #define GL_OES_element_index_uint 1 -#endif +#endif /* GL_OES_element_index_uint */ -/* GL_OES_fbo_render_mipmap */ #ifndef GL_OES_fbo_render_mipmap #define GL_OES_fbo_render_mipmap 1 -#endif +#endif /* GL_OES_fbo_render_mipmap */ -/* GL_OES_fragment_precision_high */ #ifndef GL_OES_fragment_precision_high #define GL_OES_fragment_precision_high 1 -#endif +#endif /* GL_OES_fragment_precision_high */ + +#ifndef GL_OES_geometry_point_size +#define GL_OES_geometry_point_size 1 +#endif /* GL_OES_geometry_point_size */ + +#ifndef GL_OES_geometry_shader +#define GL_OES_geometry_shader 1 +#define GL_GEOMETRY_SHADER_OES 0x8DD9 +#define GL_GEOMETRY_SHADER_BIT_OES 0x00000004 +#define GL_GEOMETRY_LINKED_VERTICES_OUT_OES 0x8916 +#define GL_GEOMETRY_LINKED_INPUT_TYPE_OES 0x8917 +#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES 0x8918 +#define GL_GEOMETRY_SHADER_INVOCATIONS_OES 0x887F +#define GL_LAYER_PROVOKING_VERTEX_OES 0x825E +#define GL_LINES_ADJACENCY_OES 0x000A +#define GL_LINE_STRIP_ADJACENCY_OES 0x000B +#define GL_TRIANGLES_ADJACENCY_OES 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY_OES 0x000D +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8DDF +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES 0x8A2C +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8A32 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES 0x9124 +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES 0x8DE1 +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES 0x8E5A +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES 0x8C29 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES 0x92CF +#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES 0x92D5 +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES 0x90CD +#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES 0x90D7 +#define GL_FIRST_VERTEX_CONVENTION_OES 0x8E4D +#define GL_LAST_VERTEX_CONVENTION_OES 0x8E4E +#define GL_UNDEFINED_VERTEX_OES 0x8260 +#define GL_PRIMITIVES_GENERATED_OES 0x8C87 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS_OES 0x9312 +#define GL_MAX_FRAMEBUFFER_LAYERS_OES 0x9317 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES 0x8DA8 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES 0x8DA7 +#define GL_REFERENCED_BY_GEOMETRY_SHADER_OES 0x9309 +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREOESPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glFramebufferTextureOES (GLenum target, GLenum attachment, GLuint texture, GLint level); +#endif +#endif /* GL_OES_geometry_shader */ -/* GL_OES_get_program_binary */ #ifndef GL_OES_get_program_binary #define GL_OES_get_program_binary 1 +#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE +#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF +typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length); #ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); -GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length); -#endif -typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); -typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length); +GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const void *binary, GLint length); #endif +#endif /* GL_OES_get_program_binary */ + +#ifndef GL_OES_gpu_shader5 +#define GL_OES_gpu_shader5 1 +#endif /* GL_OES_gpu_shader5 */ -/* GL_OES_mapbuffer */ #ifndef GL_OES_mapbuffer #define GL_OES_mapbuffer 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access); -GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target); -GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid** params); -#endif -typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access); +#define GL_WRITE_ONLY_OES 0x88B9 +#define GL_BUFFER_ACCESS_OES 0x88BB +#define GL_BUFFER_MAPPED_OES 0x88BC +#define GL_BUFFER_MAP_POINTER_OES 0x88BD +typedef void *(GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access); typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target); -typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid** params); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void **params); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void *GL_APIENTRY glMapBufferOES (GLenum target, GLenum access); +GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target); +GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, void **params); #endif +#endif /* GL_OES_mapbuffer */ -/* GL_OES_packed_depth_stencil */ #ifndef GL_OES_packed_depth_stencil #define GL_OES_packed_depth_stencil 1 -#endif +#define GL_DEPTH_STENCIL_OES 0x84F9 +#define GL_UNSIGNED_INT_24_8_OES 0x84FA +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#endif /* GL_OES_packed_depth_stencil */ + +#ifndef GL_OES_primitive_bounding_box +#define GL_OES_primitive_bounding_box 1 +#define GL_PRIMITIVE_BOUNDING_BOX_OES 0x92BE +typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXOESPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glPrimitiveBoundingBoxOES (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +#endif +#endif /* GL_OES_primitive_bounding_box */ -/* GL_OES_required_internalformat */ #ifndef GL_OES_required_internalformat #define GL_OES_required_internalformat 1 -#endif +#define GL_ALPHA8_OES 0x803C +#define GL_DEPTH_COMPONENT16_OES 0x81A5 +#define GL_LUMINANCE4_ALPHA4_OES 0x8043 +#define GL_LUMINANCE8_ALPHA8_OES 0x8045 +#define GL_LUMINANCE8_OES 0x8040 +#define GL_RGBA4_OES 0x8056 +#define GL_RGB5_A1_OES 0x8057 +#define GL_RGB565_OES 0x8D62 +#define GL_RGB8_OES 0x8051 +#define GL_RGBA8_OES 0x8058 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB10_A2_EXT 0x8059 +#endif /* GL_OES_required_internalformat */ -/* GL_OES_rgb8_rgba8 */ #ifndef GL_OES_rgb8_rgba8 #define GL_OES_rgb8_rgba8 1 -#endif +#endif /* GL_OES_rgb8_rgba8 */ + +#ifndef GL_OES_sample_shading +#define GL_OES_sample_shading 1 +#define GL_SAMPLE_SHADING_OES 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE_OES 0x8C37 +typedef void (GL_APIENTRYP PFNGLMINSAMPLESHADINGOESPROC) (GLfloat value); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glMinSampleShadingOES (GLfloat value); +#endif +#endif /* GL_OES_sample_shading */ + +#ifndef GL_OES_sample_variables +#define GL_OES_sample_variables 1 +#endif /* GL_OES_sample_variables */ + +#ifndef GL_OES_shader_image_atomic +#define GL_OES_shader_image_atomic 1 +#endif /* GL_OES_shader_image_atomic */ + +#ifndef GL_OES_shader_io_blocks +#define GL_OES_shader_io_blocks 1 +#endif /* GL_OES_shader_io_blocks */ + +#ifndef GL_OES_shader_multisample_interpolation +#define GL_OES_shader_multisample_interpolation 1 +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5C +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES 0x8E5D +#endif /* GL_OES_shader_multisample_interpolation */ -/* GL_OES_standard_derivatives */ #ifndef GL_OES_standard_derivatives #define GL_OES_standard_derivatives 1 -#endif +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B +#endif /* GL_OES_standard_derivatives */ -/* GL_OES_stencil1 */ #ifndef GL_OES_stencil1 #define GL_OES_stencil1 1 -#endif +#define GL_STENCIL_INDEX1_OES 0x8D46 +#endif /* GL_OES_stencil1 */ -/* GL_OES_stencil4 */ #ifndef GL_OES_stencil4 #define GL_OES_stencil4 1 -#endif +#define GL_STENCIL_INDEX4_OES 0x8D47 +#endif /* GL_OES_stencil4 */ #ifndef GL_OES_surfaceless_context #define GL_OES_surfaceless_context 1 -#endif +#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219 +#endif /* GL_OES_surfaceless_context */ + +#ifndef GL_OES_tessellation_point_size +#define GL_OES_tessellation_point_size 1 +#endif /* GL_OES_tessellation_point_size */ + +#ifndef GL_OES_tessellation_shader +#define GL_OES_tessellation_shader 1 +#define GL_PATCHES_OES 0x000E +#define GL_PATCH_VERTICES_OES 0x8E72 +#define GL_TESS_CONTROL_OUTPUT_VERTICES_OES 0x8E75 +#define GL_TESS_GEN_MODE_OES 0x8E76 +#define GL_TESS_GEN_SPACING_OES 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER_OES 0x8E78 +#define GL_TESS_GEN_POINT_MODE_OES 0x8E79 +#define GL_ISOLINES_OES 0x8E7A +#define GL_QUADS_OES 0x0007 +#define GL_FRACTIONAL_ODD_OES 0x8E7B +#define GL_FRACTIONAL_EVEN_OES 0x8E7C +#define GL_MAX_PATCH_VERTICES_OES 0x8E7D +#define GL_MAX_TESS_GEN_LEVEL_OES 0x8E7E +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E7F +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E80 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES 0x8E81 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES 0x8E82 +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES 0x8E83 +#define GL_MAX_TESS_PATCH_COMPONENTS_OES 0x8E84 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES 0x8E85 +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES 0x8E86 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES 0x8E89 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES 0x8E8A +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES 0x886C +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES 0x886D +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E1F +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES 0x92CD +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES 0x92CE +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES 0x92D3 +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES 0x92D4 +#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES 0x90CB +#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES 0x90CC +#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES 0x90D8 +#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES 0x90D9 +#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES 0x8221 +#define GL_IS_PER_PATCH_OES 0x92E7 +#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES 0x9307 +#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES 0x9308 +#define GL_TESS_CONTROL_SHADER_OES 0x8E88 +#define GL_TESS_EVALUATION_SHADER_OES 0x8E87 +#define GL_TESS_CONTROL_SHADER_BIT_OES 0x00000008 +#define GL_TESS_EVALUATION_SHADER_BIT_OES 0x00000010 +typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIOESPROC) (GLenum pname, GLint value); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glPatchParameteriOES (GLenum pname, GLint value); +#endif +#endif /* GL_OES_tessellation_shader */ -/* GL_OES_texture_3D */ #ifndef GL_OES_texture_3D #define GL_OES_texture_3D 1 +#define GL_TEXTURE_WRAP_R_OES 0x8072 +#define GL_TEXTURE_3D_OES 0x806F +#define GL_TEXTURE_BINDING_3D_OES 0x806A +#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073 +#define GL_SAMPLER_3D_OES 0x8B5F +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4 +typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); #ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); -GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); -GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); #endif -typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); -typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); -typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); -typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); -typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -#endif +#endif /* GL_OES_texture_3D */ + +#ifndef GL_OES_texture_border_clamp +#define GL_OES_texture_border_clamp 1 +#define GL_TEXTURE_BORDER_COLOR_OES 0x1004 +#define GL_CLAMP_TO_BORDER_OES 0x812D +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, const GLuint *params); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, const GLuint *param); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, GLuint *params); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTexParameterIivOES (GLenum target, GLenum pname, const GLint *params); +GL_APICALL void GL_APIENTRY glTexParameterIuivOES (GLenum target, GLenum pname, const GLuint *params); +GL_APICALL void GL_APIENTRY glGetTexParameterIivOES (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetTexParameterIuivOES (GLenum target, GLenum pname, GLuint *params); +GL_APICALL void GL_APIENTRY glSamplerParameterIivOES (GLuint sampler, GLenum pname, const GLint *param); +GL_APICALL void GL_APIENTRY glSamplerParameterIuivOES (GLuint sampler, GLenum pname, const GLuint *param); +GL_APICALL void GL_APIENTRY glGetSamplerParameterIivOES (GLuint sampler, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivOES (GLuint sampler, GLenum pname, GLuint *params); +#endif +#endif /* GL_OES_texture_border_clamp */ + +#ifndef GL_OES_texture_buffer +#define GL_OES_texture_buffer 1 +#define GL_TEXTURE_BUFFER_OES 0x8C2A +#define GL_TEXTURE_BUFFER_BINDING_OES 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_OES 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_OES 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES 0x8C2D +#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES 0x919F +#define GL_SAMPLER_BUFFER_OES 0x8DC2 +#define GL_INT_SAMPLER_BUFFER_OES 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_OES 0x8DD8 +#define GL_IMAGE_BUFFER_OES 0x9051 +#define GL_INT_IMAGE_BUFFER_OES 0x905C +#define GL_UNSIGNED_INT_IMAGE_BUFFER_OES 0x9067 +#define GL_TEXTURE_BUFFER_OFFSET_OES 0x919D +#define GL_TEXTURE_BUFFER_SIZE_OES 0x919E +typedef void (GL_APIENTRYP PFNGLTEXBUFFEROESPROC) (GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEOESPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTexBufferOES (GLenum target, GLenum internalformat, GLuint buffer); +GL_APICALL void GL_APIENTRY glTexBufferRangeOES (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +#endif +#endif /* GL_OES_texture_buffer */ + +#ifndef GL_OES_texture_compression_astc +#define GL_OES_texture_compression_astc 1 +#define GL_COMPRESSED_RGBA_ASTC_3x3x3_OES 0x93C0 +#define GL_COMPRESSED_RGBA_ASTC_4x3x3_OES 0x93C1 +#define GL_COMPRESSED_RGBA_ASTC_4x4x3_OES 0x93C2 +#define GL_COMPRESSED_RGBA_ASTC_4x4x4_OES 0x93C3 +#define GL_COMPRESSED_RGBA_ASTC_5x4x4_OES 0x93C4 +#define GL_COMPRESSED_RGBA_ASTC_5x5x4_OES 0x93C5 +#define GL_COMPRESSED_RGBA_ASTC_5x5x5_OES 0x93C6 +#define GL_COMPRESSED_RGBA_ASTC_6x5x5_OES 0x93C7 +#define GL_COMPRESSED_RGBA_ASTC_6x6x5_OES 0x93C8 +#define GL_COMPRESSED_RGBA_ASTC_6x6x6_OES 0x93C9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES 0x93E0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES 0x93E1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES 0x93E2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES 0x93E3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES 0x93E4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES 0x93E5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES 0x93E6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES 0x93E7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES 0x93E8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES 0x93E9 +#endif /* GL_OES_texture_compression_astc */ + +#ifndef GL_OES_texture_cube_map_array +#define GL_OES_texture_cube_map_array 1 +#define GL_TEXTURE_CUBE_MAP_ARRAY_OES 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES 0x900A +#define GL_SAMPLER_CUBE_MAP_ARRAY_OES 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900F +#define GL_IMAGE_CUBE_MAP_ARRAY_OES 0x9054 +#define GL_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x905F +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x906A +#endif /* GL_OES_texture_cube_map_array */ -/* GL_OES_texture_float */ #ifndef GL_OES_texture_float #define GL_OES_texture_float 1 -#endif +#endif /* GL_OES_texture_float */ -/* GL_OES_texture_float_linear */ #ifndef GL_OES_texture_float_linear #define GL_OES_texture_float_linear 1 -#endif +#endif /* GL_OES_texture_float_linear */ -/* GL_OES_texture_half_float */ #ifndef GL_OES_texture_half_float #define GL_OES_texture_half_float 1 -#endif +#define GL_HALF_FLOAT_OES 0x8D61 +#endif /* GL_OES_texture_half_float */ -/* GL_OES_texture_half_float_linear */ #ifndef GL_OES_texture_half_float_linear #define GL_OES_texture_half_float_linear 1 -#endif +#endif /* GL_OES_texture_half_float_linear */ -/* GL_OES_texture_npot */ #ifndef GL_OES_texture_npot #define GL_OES_texture_npot 1 -#endif +#endif /* GL_OES_texture_npot */ + +#ifndef GL_OES_texture_stencil8 +#define GL_OES_texture_stencil8 1 +#define GL_STENCIL_INDEX_OES 0x1901 +#define GL_STENCIL_INDEX8_OES 0x8D48 +#endif /* GL_OES_texture_stencil8 */ + +#ifndef GL_OES_texture_storage_multisample_2d_array +#define GL_OES_texture_storage_multisample_2d_array 1 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES 0x9102 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES 0x9105 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910D +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTexStorage3DMultisampleOES (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +#endif +#endif /* GL_OES_texture_storage_multisample_2d_array */ + +#ifndef GL_OES_texture_view +#define GL_OES_texture_view 1 +#define GL_TEXTURE_VIEW_MIN_LEVEL_OES 0x82DB +#define GL_TEXTURE_VIEW_NUM_LEVELS_OES 0x82DC +#define GL_TEXTURE_VIEW_MIN_LAYER_OES 0x82DD +#define GL_TEXTURE_VIEW_NUM_LAYERS_OES 0x82DE +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF +typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWOESPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTextureViewOES (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +#endif +#endif /* GL_OES_texture_view */ -/* GL_OES_vertex_array_object */ #ifndef GL_OES_vertex_array_object #define GL_OES_vertex_array_object 1 +#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5 +typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array); +typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays); +typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays); +typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array); GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays); GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays); GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array); #endif -typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array); -typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays); -typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays); -typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array); -#endif +#endif /* GL_OES_vertex_array_object */ -/* GL_OES_vertex_half_float */ #ifndef GL_OES_vertex_half_float #define GL_OES_vertex_half_float 1 -#endif +#endif /* GL_OES_vertex_half_float */ -/* GL_OES_vertex_type_10_10_10_2 */ #ifndef GL_OES_vertex_type_10_10_10_2 #define GL_OES_vertex_type_10_10_10_2 1 -#endif +#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6 +#define GL_INT_10_10_10_2_OES 0x8DF7 +#endif /* GL_OES_vertex_type_10_10_10_2 */ -/*------------------------------------------------------------------------* - * KHR extension functions - *------------------------------------------------------------------------*/ - -#ifndef GL_KHR_debug -#define GL_KHR_debug 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -GL_APICALL void GL_APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); -GL_APICALL void GL_APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam); -GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); -GL_APICALL void GL_APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message); -GL_APICALL void GL_APIENTRY glPopDebugGroup (void); -GL_APICALL void GL_APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); -GL_APICALL void GL_APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); -GL_APICALL void GL_APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label); -GL_APICALL void GL_APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); -GL_APICALL void GL_APIENTRY glGetPointerv (GLenum pname, void **params); -#endif -typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); -typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam); -typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); -typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); -typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void); -typedef void (GL_APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); -typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETPOINTERVPROC) (GLenum pname, void **params); -#endif - -#ifndef GL_KHR_texture_compression_astc_ldr -#define GL_KHR_texture_compression_astc_ldr 1 -#endif - - -/*------------------------------------------------------------------------* - * AMD extension functions - *------------------------------------------------------------------------*/ - -/* GL_AMD_compressed_3DC_texture */ #ifndef GL_AMD_compressed_3DC_texture #define GL_AMD_compressed_3DC_texture 1 -#endif +#define GL_3DC_X_AMD 0x87F9 +#define GL_3DC_XY_AMD 0x87FA +#endif /* GL_AMD_compressed_3DC_texture */ -/* GL_AMD_compressed_ATC_texture */ #ifndef GL_AMD_compressed_ATC_texture #define GL_AMD_compressed_ATC_texture 1 -#endif +#define GL_ATC_RGB_AMD 0x8C92 +#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 +#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE +#endif /* GL_AMD_compressed_ATC_texture */ -/* AMD_performance_monitor */ #ifndef GL_AMD_performance_monitor #define GL_AMD_performance_monitor 1 +#define GL_COUNTER_TYPE_AMD 0x8BC0 +#define GL_COUNTER_RANGE_AMD 0x8BC1 +#define GL_UNSIGNED_INT64_AMD 0x8BC2 +#define GL_PERCENTAGE_AMD 0x8BC3 +#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 +#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 +#define GL_PERFMON_RESULT_AMD 0x8BC6 +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data); +typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList); +typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups); GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); -GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data); GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors); GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors); -GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList); +GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList); GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor); GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor); GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); #endif -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data); -typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); -typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); -typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList); -typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); -typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); -#endif +#endif /* GL_AMD_performance_monitor */ -/* GL_AMD_program_binary_Z400 */ #ifndef GL_AMD_program_binary_Z400 #define GL_AMD_program_binary_Z400 1 -#endif +#define GL_Z400_BINARY_AMD 0x8740 +#endif /* GL_AMD_program_binary_Z400 */ -/*------------------------------------------------------------------------* - * ANGLE extension functions - *------------------------------------------------------------------------*/ +#ifndef GL_ANDROID_extension_pack_es31a +#define GL_ANDROID_extension_pack_es31a 1 +#endif /* GL_ANDROID_extension_pack_es31a */ + +#ifndef GL_ANGLE_depth_texture +#define GL_ANGLE_depth_texture 1 +#endif /* GL_ANGLE_depth_texture */ -/* GL_ANGLE_framebuffer_blit */ #ifndef GL_ANGLE_framebuffer_blit #define GL_ANGLE_framebuffer_blit 1 +#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA +typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); #endif -typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -#endif +#endif /* GL_ANGLE_framebuffer_blit */ -/* GL_ANGLE_framebuffer_multisample */ #ifndef GL_ANGLE_framebuffer_multisample #define GL_ANGLE_framebuffer_multisample 1 +#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56 +#define GL_MAX_SAMPLES_ANGLE 0x8D57 +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); #endif -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -#endif +#endif /* GL_ANGLE_framebuffer_multisample */ -#ifndef GL_ANGLE_instanced_arrays +#ifndef GL_ANGLE_instanced_arrays #define GL_ANGLE_instanced_arrays 1 +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount); GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor); #endif -typedef void (GL_APIENTRYP PFLGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -typedef void (GL_APIENTRYP PFLGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); -typedef void (GL_APIENTRYP PFLGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor); -#endif +#endif /* GL_ANGLE_instanced_arrays */ -/* GL_ANGLE_pack_reverse_row_order */ -#ifndef GL_ANGLE_pack_reverse_row_order +#ifndef GL_ANGLE_pack_reverse_row_order #define GL_ANGLE_pack_reverse_row_order 1 -#endif +#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4 +#endif /* GL_ANGLE_pack_reverse_row_order */ -/* GL_ANGLE_texture_compression_dxt3 */ -#ifndef GL_ANGLE_texture_compression_dxt3 +#ifndef GL_ANGLE_program_binary +#define GL_ANGLE_program_binary 1 +#define GL_PROGRAM_BINARY_ANGLE 0x93A6 +#endif /* GL_ANGLE_program_binary */ + +#ifndef GL_ANGLE_texture_compression_dxt3 #define GL_ANGLE_texture_compression_dxt3 1 -#endif +#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2 +#endif /* GL_ANGLE_texture_compression_dxt3 */ -/* GL_ANGLE_texture_compression_dxt5 */ -#ifndef GL_ANGLE_texture_compression_dxt5 +#ifndef GL_ANGLE_texture_compression_dxt5 #define GL_ANGLE_texture_compression_dxt5 1 -#endif +#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3 +#endif /* GL_ANGLE_texture_compression_dxt5 */ -/* GL_ANGLE_texture_usage */ -#ifndef GL_ANGLE_texture_usage +#ifndef GL_ANGLE_texture_usage #define GL_ANGLE_texture_usage 1 -#endif +#define GL_TEXTURE_USAGE_ANGLE 0x93A2 +#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3 +#endif /* GL_ANGLE_texture_usage */ -#ifndef GL_ANGLE_translated_shader_source +#ifndef GL_ANGLE_translated_shader_source #define GL_ANGLE_translated_shader_source 1 +#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 +typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); #endif -typedef void (GL_APIENTRYP PFLGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); -#endif +#endif /* GL_ANGLE_translated_shader_source */ -/*------------------------------------------------------------------------* - * APPLE extension functions - *------------------------------------------------------------------------*/ +#ifndef GL_APPLE_clip_distance +#define GL_APPLE_clip_distance 1 +#define GL_MAX_CLIP_DISTANCES_APPLE 0x0D32 +#define GL_CLIP_DISTANCE0_APPLE 0x3000 +#define GL_CLIP_DISTANCE1_APPLE 0x3001 +#define GL_CLIP_DISTANCE2_APPLE 0x3002 +#define GL_CLIP_DISTANCE3_APPLE 0x3003 +#define GL_CLIP_DISTANCE4_APPLE 0x3004 +#define GL_CLIP_DISTANCE5_APPLE 0x3005 +#define GL_CLIP_DISTANCE6_APPLE 0x3006 +#define GL_CLIP_DISTANCE7_APPLE 0x3007 +#endif /* GL_APPLE_clip_distance */ + +#ifndef GL_APPLE_color_buffer_packed_float +#define GL_APPLE_color_buffer_packed_float 1 +#endif /* GL_APPLE_color_buffer_packed_float */ -/* GL_APPLE_copy_texture_levels */ #ifndef GL_APPLE_copy_texture_levels #define GL_APPLE_copy_texture_levels 1 +typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount); #endif -typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount); -#endif +#endif /* GL_APPLE_copy_texture_levels */ -/* GL_APPLE_framebuffer_multisample */ #ifndef GL_APPLE_framebuffer_multisample #define GL_APPLE_framebuffer_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum, GLsizei, GLenum, GLsizei, GLsizei); -GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void); -#endif /* GL_GLEXT_PROTOTYPES */ +#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56 +#define GL_MAX_SAMPLES_APPLE 0x8D57 +#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void); #endif +#endif /* GL_APPLE_framebuffer_multisample */ -/* GL_APPLE_rgb_422 */ #ifndef GL_APPLE_rgb_422 #define GL_APPLE_rgb_422 1 -#endif +#define GL_RGB_422_APPLE 0x8A1F +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#define GL_RGB_RAW_422_APPLE 0x8A51 +#endif /* GL_APPLE_rgb_422 */ -/* GL_APPLE_sync */ -#ifndef GL_APPLE_sync -#define GL_APPLE_sync 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags); -GL_APICALL GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync); -GL_APICALL void GL_APIENTRY glDeleteSyncAPPLE (GLsync sync); -GL_APICALL GLenum GL_APIENTRY glClientWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params); -GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -#endif -typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags); -typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync); -typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync); -typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); -typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); -typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params); -typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -#endif - -/* GL_APPLE_texture_format_BGRA8888 */ #ifndef GL_APPLE_texture_format_BGRA8888 #define GL_APPLE_texture_format_BGRA8888 1 -#endif +#define GL_BGRA_EXT 0x80E1 +#define GL_BGRA8_EXT 0x93A1 +#endif /* GL_APPLE_texture_format_BGRA8888 */ -/* GL_APPLE_texture_max_level */ #ifndef GL_APPLE_texture_max_level #define GL_APPLE_texture_max_level 1 -#endif +#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D +#endif /* GL_APPLE_texture_max_level */ -/*------------------------------------------------------------------------* - * ARM extension functions - *------------------------------------------------------------------------*/ +#ifndef GL_APPLE_texture_packed_float +#define GL_APPLE_texture_packed_float 1 +#define GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE 0x8C3B +#define GL_UNSIGNED_INT_5_9_9_9_REV_APPLE 0x8C3E +#define GL_R11F_G11F_B10F_APPLE 0x8C3A +#define GL_RGB9_E5_APPLE 0x8C3D +#endif /* GL_APPLE_texture_packed_float */ -/* GL_ARM_mali_program_binary */ #ifndef GL_ARM_mali_program_binary #define GL_ARM_mali_program_binary 1 -#endif +#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61 +#endif /* GL_ARM_mali_program_binary */ -/* GL_ARM_mali_shader_binary */ #ifndef GL_ARM_mali_shader_binary #define GL_ARM_mali_shader_binary 1 -#endif +#define GL_MALI_SHADER_BINARY_ARM 0x8F60 +#endif /* GL_ARM_mali_shader_binary */ -/* GL_ARM_rgba8 */ #ifndef GL_ARM_rgba8 #define GL_ARM_rgba8 1 +#endif /* GL_ARM_rgba8 */ + +#ifndef GL_ARM_shader_framebuffer_fetch +#define GL_ARM_shader_framebuffer_fetch 1 +#define GL_FETCH_PER_SAMPLE_ARM 0x8F65 +#define GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM 0x8F66 +#endif /* GL_ARM_shader_framebuffer_fetch */ + +#ifndef GL_ARM_shader_framebuffer_fetch_depth_stencil +#define GL_ARM_shader_framebuffer_fetch_depth_stencil 1 +#endif /* GL_ARM_shader_framebuffer_fetch_depth_stencil */ + +#ifndef GL_DMP_program_binary +#define GL_DMP_program_binary 1 +#define GL_SMAPHS30_PROGRAM_BINARY_DMP 0x9251 +#define GL_SMAPHS_PROGRAM_BINARY_DMP 0x9252 +#define GL_DMP_PROGRAM_BINARY_DMP 0x9253 +#endif /* GL_DMP_program_binary */ + +#ifndef GL_DMP_shader_binary +#define GL_DMP_shader_binary 1 +#define GL_SHADER_BINARY_DMP 0x9250 +#endif /* GL_DMP_shader_binary */ + +#ifndef GL_EXT_YUV_target +#define GL_EXT_YUV_target 1 +#define GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT 0x8BE7 +#endif /* GL_EXT_YUV_target */ + +#ifndef GL_EXT_base_instance +#define GL_EXT_base_instance 1 +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawArraysInstancedBaseInstanceEXT (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); #endif +#endif /* GL_EXT_base_instance */ -/*------------------------------------------------------------------------* - * EXT extension functions - *------------------------------------------------------------------------*/ +#ifndef GL_EXT_blend_func_extended +#define GL_EXT_blend_func_extended 1 +#define GL_SRC1_COLOR_EXT 0x88F9 +#define GL_SRC1_ALPHA_EXT 0x8589 +#define GL_ONE_MINUS_SRC1_COLOR_EXT 0x88FA +#define GL_ONE_MINUS_SRC1_ALPHA_EXT 0x88FB +#define GL_SRC_ALPHA_SATURATE_EXT 0x0308 +#define GL_LOCATION_INDEX_EXT 0x930F +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT 0x88FC +typedef void (GL_APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); +typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATAINDEXEXTPROC) (GLuint program, const GLchar *name); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBindFragDataLocationIndexedEXT (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); +GL_APICALL void GL_APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name); +GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocationIndexEXT (GLuint program, GLenum programInterface, const GLchar *name); +GL_APICALL GLint GL_APIENTRY glGetFragDataIndexEXT (GLuint program, const GLchar *name); +#endif +#endif /* GL_EXT_blend_func_extended */ -/* GL_EXT_blend_minmax */ #ifndef GL_EXT_blend_minmax #define GL_EXT_blend_minmax 1 -#endif +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#endif /* GL_EXT_blend_minmax */ + +#ifndef GL_EXT_buffer_storage +#define GL_EXT_buffer_storage 1 +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_PERSISTENT_BIT_EXT 0x0040 +#define GL_MAP_COHERENT_BIT_EXT 0x0080 +#define GL_DYNAMIC_STORAGE_BIT_EXT 0x0100 +#define GL_CLIENT_STORAGE_BIT_EXT 0x0200 +#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000 +#define GL_BUFFER_IMMUTABLE_STORAGE_EXT 0x821F +#define GL_BUFFER_STORAGE_FLAGS_EXT 0x8220 +typedef void (GL_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBufferStorageEXT (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); +#endif +#endif /* GL_EXT_buffer_storage */ + +#ifndef GL_EXT_color_buffer_float +#define GL_EXT_color_buffer_float 1 +#endif /* GL_EXT_color_buffer_float */ -/* GL_EXT_color_buffer_half_float */ #ifndef GL_EXT_color_buffer_half_float #define GL_EXT_color_buffer_half_float 1 -#endif +#define GL_RGBA16F_EXT 0x881A +#define GL_RGB16F_EXT 0x881B +#define GL_RG16F_EXT 0x822F +#define GL_R16F_EXT 0x822D +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211 +#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17 +#endif /* GL_EXT_color_buffer_half_float */ + +#ifndef GL_EXT_copy_image +#define GL_EXT_copy_image 1 +typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAEXTPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glCopyImageSubDataEXT (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +#endif +#endif /* GL_EXT_copy_image */ -/* GL_EXT_debug_label */ #ifndef GL_EXT_debug_label #define GL_EXT_debug_label 1 +#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F +#define GL_PROGRAM_OBJECT_EXT 0x8B40 +#define GL_SHADER_OBJECT_EXT 0x8B48 +#define GL_BUFFER_OBJECT_EXT 0x9151 +#define GL_QUERY_OBJECT_EXT 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154 +#define GL_TRANSFORM_FEEDBACK 0x8E22 +typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label); GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); #endif -typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); -#endif +#endif /* GL_EXT_debug_label */ -/* GL_EXT_debug_marker */ #ifndef GL_EXT_debug_marker #define GL_EXT_debug_marker 1 +typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker); GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker); GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void); #endif -typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker); -typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker); -typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void); -#endif +#endif /* GL_EXT_debug_marker */ -/* GL_EXT_discard_framebuffer */ #ifndef GL_EXT_discard_framebuffer #define GL_EXT_discard_framebuffer 1 +#define GL_COLOR_EXT 0x1800 +#define GL_DEPTH_EXT 0x1801 +#define GL_STENCIL_EXT 0x1802 +typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments); #endif -typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); -#endif +#endif /* GL_EXT_discard_framebuffer */ -/* GL_EXT_map_buffer_range */ -#ifndef GL_EXT_map_buffer_range -#define GL_EXT_map_buffer_range 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length); -#endif -typedef void* (GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length); -#endif - -/* GL_EXT_multisampled_render_to_texture */ -#ifndef GL_EXT_multisampled_render_to_texture -#define GL_EXT_multisampled_render_to_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum, GLsizei, GLenum, GLsizei, GLsizei); -GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei); -#endif -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); -#endif - -/* GL_EXT_multiview_draw_buffers */ -#ifndef GL_EXT_multiview_draw_buffers -#define GL_EXT_multiview_draw_buffers 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index); -GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices); -GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data); -#endif -typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index); -typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices); -typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data); -#endif - -#ifndef GL_EXT_multi_draw_arrays -#define GL_EXT_multi_draw_arrays 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei); -GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); -typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); -#endif - -/* GL_EXT_occlusion_query_boolean */ -#ifndef GL_EXT_occlusion_query_boolean -#define GL_EXT_occlusion_query_boolean 1 +#ifndef GL_EXT_disjoint_timer_query +#define GL_EXT_disjoint_timer_query 1 +#define GL_QUERY_COUNTER_BITS_EXT 0x8864 +#define GL_CURRENT_QUERY_EXT 0x8865 +#define GL_QUERY_RESULT_EXT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867 +#define GL_TIME_ELAPSED_EXT 0x88BF +#define GL_TIMESTAMP_EXT 0x8E28 +#define GL_GPU_DISJOINT_EXT 0x8FBB +typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids); +typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id); +typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id); +typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLQUERYCOUNTEREXTPROC) (GLuint id, GLenum target); +typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTIVEXTPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params); +//typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64 *params); +//typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64 *params); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids); GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids); GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id); GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id); GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target); +GL_APICALL void GL_APIENTRY glQueryCounterEXT (GLuint id, GLenum target); GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetQueryObjectivEXT (GLuint id, GLenum pname, GLint *params); GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params); +//GL_APICALL void GL_APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64 *params); +//GL_APICALL void GL_APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64 *params); #endif -typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids); -typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids); -typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id); -typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id); -typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target); -typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params); -#endif +#endif /* GL_EXT_disjoint_timer_query */ + +#ifndef GL_EXT_draw_buffers +#define GL_EXT_draw_buffers 1 +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_MAX_DRAW_BUFFERS_EXT 0x8824 +#define GL_DRAW_BUFFER0_EXT 0x8825 +#define GL_DRAW_BUFFER1_EXT 0x8826 +#define GL_DRAW_BUFFER2_EXT 0x8827 +#define GL_DRAW_BUFFER3_EXT 0x8828 +#define GL_DRAW_BUFFER4_EXT 0x8829 +#define GL_DRAW_BUFFER5_EXT 0x882A +#define GL_DRAW_BUFFER6_EXT 0x882B +#define GL_DRAW_BUFFER7_EXT 0x882C +#define GL_DRAW_BUFFER8_EXT 0x882D +#define GL_DRAW_BUFFER9_EXT 0x882E +#define GL_DRAW_BUFFER10_EXT 0x882F +#define GL_DRAW_BUFFER11_EXT 0x8830 +#define GL_DRAW_BUFFER12_EXT 0x8831 +#define GL_DRAW_BUFFER13_EXT 0x8832 +#define GL_DRAW_BUFFER14_EXT 0x8833 +#define GL_DRAW_BUFFER15_EXT 0x8834 +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs); +#endif +#endif /* GL_EXT_draw_buffers */ + +#ifndef GL_EXT_draw_buffers_indexed +#define GL_EXT_draw_buffers_indexed 1 +typedef void (GL_APIENTRYP PFNGLENABLEIEXTPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP PFNGLDISABLEIEXTPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIEXTPROC) (GLuint buf, GLenum mode); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIEXTPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCIEXTPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIEXTPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GL_APIENTRYP PFNGLCOLORMASKIEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIEXTPROC) (GLenum target, GLuint index); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glEnableiEXT (GLenum target, GLuint index); +GL_APICALL void GL_APIENTRY glDisableiEXT (GLenum target, GLuint index); +GL_APICALL void GL_APIENTRY glBlendEquationiEXT (GLuint buf, GLenum mode); +GL_APICALL void GL_APIENTRY glBlendEquationSeparateiEXT (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +GL_APICALL void GL_APIENTRY glBlendFunciEXT (GLuint buf, GLenum src, GLenum dst); +GL_APICALL void GL_APIENTRY glBlendFuncSeparateiEXT (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +GL_APICALL void GL_APIENTRY glColorMaskiEXT (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +GL_APICALL GLboolean GL_APIENTRY glIsEnablediEXT (GLenum target, GLuint index); +#endif +#endif /* GL_EXT_draw_buffers_indexed */ + +#ifndef GL_EXT_draw_elements_base_vertex +#define GL_EXT_draw_elements_base_vertex 1 +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); +#endif +#endif /* GL_EXT_draw_elements_base_vertex */ + +#ifndef GL_EXT_draw_instanced +#define GL_EXT_draw_instanced 1 +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#endif +#endif /* GL_EXT_draw_instanced */ + +#ifndef GL_EXT_float_blend +#define GL_EXT_float_blend 1 +#endif /* GL_EXT_float_blend */ + +#ifndef GL_EXT_geometry_point_size +#define GL_EXT_geometry_point_size 1 +#endif /* GL_EXT_geometry_point_size */ + +#ifndef GL_EXT_geometry_shader +#define GL_EXT_geometry_shader 1 +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 +#define GL_GEOMETRY_SHADER_BIT_EXT 0x00000004 +#define GL_GEOMETRY_LINKED_VERTICES_OUT_EXT 0x8916 +#define GL_GEOMETRY_LINKED_INPUT_TYPE_EXT 0x8917 +#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT 0x8918 +#define GL_GEOMETRY_SHADER_INVOCATIONS_EXT 0x887F +#define GL_LAYER_PROVOKING_VERTEX_EXT 0x825E +#define GL_LINES_ADJACENCY_EXT 0x000A +#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B +#define GL_TRIANGLES_ADJACENCY_EXT 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT 0x8A2C +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8A32 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT 0x9124 +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT 0x8E5A +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT 0x92CF +#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT 0x92D5 +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT 0x90CD +#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT 0x90D7 +#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D +#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E +#define GL_UNDEFINED_VERTEX_EXT 0x8260 +#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT 0x9312 +#define GL_MAX_FRAMEBUFFER_LAYERS_EXT 0x9317 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_REFERENCED_BY_GEOMETRY_SHADER_EXT 0x9309 +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level); +#endif +#endif /* GL_EXT_geometry_shader */ + +#ifndef GL_EXT_gpu_shader5 +#define GL_EXT_gpu_shader5 1 +#endif /* GL_EXT_gpu_shader5 */ + +#ifndef GL_EXT_instanced_arrays +#define GL_EXT_instanced_arrays 1 +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_EXT 0x88FE +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glVertexAttribDivisorEXT (GLuint index, GLuint divisor); +#endif +#endif /* GL_EXT_instanced_arrays */ + +#ifndef GL_EXT_map_buffer_range +#define GL_EXT_map_buffer_range 1 +#define GL_MAP_READ_BIT_EXT 0x0001 +#define GL_MAP_WRITE_BIT_EXT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020 +typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void *GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length); +#endif +#endif /* GL_EXT_map_buffer_range */ + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 +typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount); +#endif +#endif /* GL_EXT_multi_draw_arrays */ + +#ifndef GL_EXT_multi_draw_indirect +#define GL_EXT_multi_draw_indirect 1 +typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); +typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glMultiDrawArraysIndirectEXT (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); +GL_APICALL void GL_APIENTRY glMultiDrawElementsIndirectEXT (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride); +#endif +#endif /* GL_EXT_multi_draw_indirect */ + +#ifndef GL_EXT_multisampled_compatibility +#define GL_EXT_multisampled_compatibility 1 +#define GL_MULTISAMPLE_EXT 0x809D +#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F +#endif /* GL_EXT_multisampled_compatibility */ + +#ifndef GL_EXT_multisampled_render_to_texture +#define GL_EXT_multisampled_render_to_texture 1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); +#endif +#endif /* GL_EXT_multisampled_render_to_texture */ + +#ifndef GL_EXT_multiview_draw_buffers +#define GL_EXT_multiview_draw_buffers 1 +#define GL_COLOR_ATTACHMENT_EXT 0x90F0 +#define GL_MULTIVIEW_EXT 0x90F1 +#define GL_DRAW_BUFFER_EXT 0x0C01 +#define GL_READ_BUFFER_EXT 0x0C02 +#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2 +typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index); +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices); +typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index); +GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices); +GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data); +#endif +#endif /* GL_EXT_multiview_draw_buffers */ + +#ifndef GL_EXT_occlusion_query_boolean +#define GL_EXT_occlusion_query_boolean 1 +#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A +#endif /* GL_EXT_occlusion_query_boolean */ + +#ifndef GL_EXT_polygon_offset_clamp +#define GL_EXT_polygon_offset_clamp 1 +#define GL_POLYGON_OFFSET_CLAMP_EXT 0x8E1B +typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETCLAMPEXTPROC) (GLfloat factor, GLfloat units, GLfloat clamp); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glPolygonOffsetClampEXT (GLfloat factor, GLfloat units, GLfloat clamp); +#endif +#endif /* GL_EXT_polygon_offset_clamp */ + +#ifndef GL_EXT_post_depth_coverage +#define GL_EXT_post_depth_coverage 1 +#endif /* GL_EXT_post_depth_coverage */ + +#ifndef GL_EXT_primitive_bounding_box +#define GL_EXT_primitive_bounding_box 1 +#define GL_PRIMITIVE_BOUNDING_BOX_EXT 0x92BE +typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXEXTPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glPrimitiveBoundingBoxEXT (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +#endif +#endif /* GL_EXT_primitive_bounding_box */ + +#ifndef GL_EXT_pvrtc_sRGB +#define GL_EXT_pvrtc_sRGB 1 +#define GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54 +#define GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55 +#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56 +#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57 +#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG 0x93F0 +#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG 0x93F1 +#endif /* GL_EXT_pvrtc_sRGB */ + +#ifndef GL_EXT_raster_multisample +#define GL_EXT_raster_multisample 1 +#define GL_RASTER_MULTISAMPLE_EXT 0x9327 +#define GL_RASTER_SAMPLES_EXT 0x9328 +#define GL_MAX_RASTER_SAMPLES_EXT 0x9329 +#define GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT 0x932A +#define GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT 0x932B +#define GL_EFFECTIVE_RASTER_SAMPLES_EXT 0x932C +typedef void (GL_APIENTRYP PFNGLRASTERSAMPLESEXTPROC) (GLuint samples, GLboolean fixedsamplelocations); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRasterSamplesEXT (GLuint samples, GLboolean fixedsamplelocations); +#endif +#endif /* GL_EXT_raster_multisample */ -/* GL_EXT_read_format_bgra */ #ifndef GL_EXT_read_format_bgra #define GL_EXT_read_format_bgra 1 -#endif +#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366 +#endif /* GL_EXT_read_format_bgra */ + +#ifndef GL_EXT_render_snorm +#define GL_EXT_render_snorm 1 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM_EXT 0x8F98 +#define GL_RG16_SNORM_EXT 0x8F99 +#define GL_RGBA16_SNORM_EXT 0x8F9B +#endif /* GL_EXT_render_snorm */ -/* GL_EXT_robustness */ #ifndef GL_EXT_robustness #define GL_EXT_robustness 1 +#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255 +#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3 +#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256 +#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252 +#define GL_NO_RESET_NOTIFICATION_EXT 0x8261 +typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void); +typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void); GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); -GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, float *params); +GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params); #endif -typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void); -typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); -typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, float *params); -typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); -#endif +#endif /* GL_EXT_robustness */ + +#ifndef GL_EXT_sRGB +#define GL_EXT_sRGB 1 +#define GL_SRGB_EXT 0x8C40 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210 +#endif /* GL_EXT_sRGB */ + +#ifndef GL_EXT_sRGB_write_control +#define GL_EXT_sRGB_write_control 1 +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 +#endif /* GL_EXT_sRGB_write_control */ -/* GL_EXT_separate_shader_objects */ #ifndef GL_EXT_separate_shader_objects #define GL_EXT_separate_shader_objects 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program); -GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program); -GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings); -GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline); -GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines); -GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines); -GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline); -GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value); -GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint x); -GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint x, GLint y); -GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z); -GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); -GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat x); -GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat x, GLfloat y); -GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); -GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline); -GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -#endif -typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program); +#define GL_ACTIVE_PROGRAM_EXT 0x8259 +#define GL_VERTEX_SHADER_BIT_EXT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002 +#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF +#define GL_PROGRAM_SEPARABLE_EXT 0x8258 +#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program); -typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings); typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline); +typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings); typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines); typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params); typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline); typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); -typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program); typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline); -typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program); +GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline); +GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings); +GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines); +GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines); +GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params); +GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline); +GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value); +GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat v0); +GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint v0); +GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1); +GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint v0, GLint v1); +GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program); +GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline); +GL_APICALL void GL_APIENTRY glProgramUniform1uiEXT (GLuint program, GLint location, GLuint v0); +GL_APICALL void GL_APIENTRY glProgramUniform2uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1); +GL_APICALL void GL_APIENTRY glProgramUniform3uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +GL_APICALL void GL_APIENTRY glProgramUniform4uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void GL_APIENTRY glProgramUniform1uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniform2uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniform3uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniform4uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); #endif +#endif /* GL_EXT_separate_shader_objects */ -/* GL_EXT_shader_framebuffer_fetch */ #ifndef GL_EXT_shader_framebuffer_fetch #define GL_EXT_shader_framebuffer_fetch 1 -#endif +#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 +#endif /* GL_EXT_shader_framebuffer_fetch */ + +#ifndef GL_EXT_shader_group_vote +#define GL_EXT_shader_group_vote 1 +#endif /* GL_EXT_shader_group_vote */ + +#ifndef GL_EXT_shader_implicit_conversions +#define GL_EXT_shader_implicit_conversions 1 +#endif /* GL_EXT_shader_implicit_conversions */ + +#ifndef GL_EXT_shader_integer_mix +#define GL_EXT_shader_integer_mix 1 +#endif /* GL_EXT_shader_integer_mix */ + +#ifndef GL_EXT_shader_io_blocks +#define GL_EXT_shader_io_blocks 1 +#endif /* GL_EXT_shader_io_blocks */ + +#ifndef GL_EXT_shader_pixel_local_storage +#define GL_EXT_shader_pixel_local_storage 1 +#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63 +#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT 0x8F67 +#define GL_SHADER_PIXEL_LOCAL_STORAGE_EXT 0x8F64 +#endif /* GL_EXT_shader_pixel_local_storage */ + +#ifndef GL_EXT_shader_pixel_local_storage2 +#define GL_EXT_shader_pixel_local_storage2 1 +#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT 0x9650 +#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT 0x9651 +#define GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT 0x9652 +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) (GLuint target, GLsizei size); +typedef GLsizei (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) (GLuint target); +typedef void (GL_APIENTRYP PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC) (GLsizei offset, GLsizei n, const GLuint *values); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glFramebufferPixelLocalStorageSizeEXT (GLuint target, GLsizei size); +GL_APICALL GLsizei GL_APIENTRY glGetFramebufferPixelLocalStorageSizeEXT (GLuint target); +GL_APICALL void GL_APIENTRY glClearPixelLocalStorageuiEXT (GLsizei offset, GLsizei n, const GLuint *values); +#endif +#endif /* GL_EXT_shader_pixel_local_storage2 */ -/* GL_EXT_shader_texture_lod */ #ifndef GL_EXT_shader_texture_lod #define GL_EXT_shader_texture_lod 1 -#endif +#endif /* GL_EXT_shader_texture_lod */ -/* GL_EXT_shadow_samplers */ #ifndef GL_EXT_shadow_samplers #define GL_EXT_shadow_samplers 1 -#endif +#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C +#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D +#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E +#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62 +#endif /* GL_EXT_shadow_samplers */ -/* GL_EXT_sRGB */ -#ifndef GL_EXT_sRGB -#define GL_EXT_sRGB 1 +#ifndef GL_EXT_sparse_texture +#define GL_EXT_sparse_texture 1 +#define GL_TEXTURE_SPARSE_EXT 0x91A6 +#define GL_VIRTUAL_PAGE_SIZE_INDEX_EXT 0x91A7 +#define GL_NUM_SPARSE_LEVELS_EXT 0x91AA +#define GL_NUM_VIRTUAL_PAGE_SIZES_EXT 0x91A8 +#define GL_VIRTUAL_PAGE_SIZE_X_EXT 0x9195 +#define GL_VIRTUAL_PAGE_SIZE_Y_EXT 0x9196 +#define GL_VIRTUAL_PAGE_SIZE_Z_EXT 0x9197 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_3D 0x806F +#define GL_MAX_SPARSE_TEXTURE_SIZE_EXT 0x9198 +#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT 0x9199 +#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT 0x919A +#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT 0x91A9 +typedef void (GL_APIENTRYP PFNGLTEXPAGECOMMITMENTEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTexPageCommitmentEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); #endif +#endif /* GL_EXT_sparse_texture */ + +#ifndef GL_EXT_tessellation_point_size +#define GL_EXT_tessellation_point_size 1 +#endif /* GL_EXT_tessellation_point_size */ + +#ifndef GL_EXT_tessellation_shader +#define GL_EXT_tessellation_shader 1 +#define GL_PATCHES_EXT 0x000E +#define GL_PATCH_VERTICES_EXT 0x8E72 +#define GL_TESS_CONTROL_OUTPUT_VERTICES_EXT 0x8E75 +#define GL_TESS_GEN_MODE_EXT 0x8E76 +#define GL_TESS_GEN_SPACING_EXT 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER_EXT 0x8E78 +#define GL_TESS_GEN_POINT_MODE_EXT 0x8E79 +#define GL_ISOLINES_EXT 0x8E7A +#define GL_QUADS_EXT 0x0007 +#define GL_FRACTIONAL_ODD_EXT 0x8E7B +#define GL_FRACTIONAL_EVEN_EXT 0x8E7C +#define GL_MAX_PATCH_VERTICES_EXT 0x8E7D +#define GL_MAX_TESS_GEN_LEVEL_EXT 0x8E7E +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E7F +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E80 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT 0x8E81 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT 0x8E82 +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT 0x8E83 +#define GL_MAX_TESS_PATCH_COMPONENTS_EXT 0x8E84 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT 0x8E85 +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT 0x8E86 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT 0x8E89 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT 0x8E8A +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT 0x886C +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT 0x886D +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E1F +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT 0x92CD +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT 0x92CE +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT 0x92D3 +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT 0x92D4 +#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT 0x90CB +#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT 0x90CC +#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT 0x90D8 +#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT 0x90D9 +#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221 +#define GL_IS_PER_PATCH_EXT 0x92E7 +#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT 0x9307 +#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT 0x9308 +#define GL_TESS_CONTROL_SHADER_EXT 0x8E88 +#define GL_TESS_EVALUATION_SHADER_EXT 0x8E87 +#define GL_TESS_CONTROL_SHADER_BIT_EXT 0x00000008 +#define GL_TESS_EVALUATION_SHADER_BIT_EXT 0x00000010 +typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIEXTPROC) (GLenum pname, GLint value); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glPatchParameteriEXT (GLenum pname, GLint value); +#endif +#endif /* GL_EXT_tessellation_shader */ + +#ifndef GL_EXT_texture_border_clamp +#define GL_EXT_texture_border_clamp 1 +#define GL_TEXTURE_BORDER_COLOR_EXT 0x1004 +#define GL_CLAMP_TO_BORDER_EXT 0x812D +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, const GLuint *param); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, GLuint *params); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTexParameterIivEXT (GLenum target, GLenum pname, const GLint *params); +GL_APICALL void GL_APIENTRY glTexParameterIuivEXT (GLenum target, GLenum pname, const GLuint *params); +GL_APICALL void GL_APIENTRY glGetTexParameterIivEXT (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetTexParameterIuivEXT (GLenum target, GLenum pname, GLuint *params); +GL_APICALL void GL_APIENTRY glSamplerParameterIivEXT (GLuint sampler, GLenum pname, const GLint *param); +GL_APICALL void GL_APIENTRY glSamplerParameterIuivEXT (GLuint sampler, GLenum pname, const GLuint *param); +GL_APICALL void GL_APIENTRY glGetSamplerParameterIivEXT (GLuint sampler, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivEXT (GLuint sampler, GLenum pname, GLuint *params); +#endif +#endif /* GL_EXT_texture_border_clamp */ + +#ifndef GL_EXT_texture_buffer +#define GL_EXT_texture_buffer 1 +#define GL_TEXTURE_BUFFER_EXT 0x8C2A +#define GL_TEXTURE_BUFFER_BINDING_EXT 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D +#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT 0x919F +#define GL_SAMPLER_BUFFER_EXT 0x8DC2 +#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 +#define GL_IMAGE_BUFFER_EXT 0x9051 +#define GL_INT_IMAGE_BUFFER_EXT 0x905C +#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067 +#define GL_TEXTURE_BUFFER_OFFSET_EXT 0x919D +#define GL_TEXTURE_BUFFER_SIZE_EXT 0x919E +typedef void (GL_APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEEXTPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint buffer); +GL_APICALL void GL_APIENTRY glTexBufferRangeEXT (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +#endif +#endif /* GL_EXT_texture_buffer */ -/* GL_EXT_texture_compression_dxt1 */ #ifndef GL_EXT_texture_compression_dxt1 #define GL_EXT_texture_compression_dxt1 1 -#endif +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#endif /* GL_EXT_texture_compression_dxt1 */ + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_EXT_texture_compression_s3tc 1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#endif /* GL_EXT_texture_compression_s3tc */ + +#ifndef GL_EXT_texture_cube_map_array +#define GL_EXT_texture_cube_map_array 1 +#define GL_TEXTURE_CUBE_MAP_ARRAY_EXT 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT 0x900A +#define GL_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900F +#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054 +#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A +#endif /* GL_EXT_texture_cube_map_array */ -/* GL_EXT_texture_filter_anisotropic */ #ifndef GL_EXT_texture_filter_anisotropic #define GL_EXT_texture_filter_anisotropic 1 -#endif +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif /* GL_EXT_texture_filter_anisotropic */ + +#ifndef GL_EXT_texture_filter_minmax +#define GL_EXT_texture_filter_minmax 1 +#endif /* GL_EXT_texture_filter_minmax */ -/* GL_EXT_texture_format_BGRA8888 */ #ifndef GL_EXT_texture_format_BGRA8888 #define GL_EXT_texture_format_BGRA8888 1 -#endif +#endif /* GL_EXT_texture_format_BGRA8888 */ + +#ifndef GL_EXT_texture_norm16 +#define GL_EXT_texture_norm16 1 +#define GL_R16_EXT 0x822A +#define GL_RG16_EXT 0x822C +#define GL_RGBA16_EXT 0x805B +#define GL_RGB16_EXT 0x8054 +#define GL_RGB16_SNORM_EXT 0x8F9A +#endif /* GL_EXT_texture_norm16 */ -/* GL_EXT_texture_rg */ #ifndef GL_EXT_texture_rg #define GL_EXT_texture_rg 1 -#endif +#define GL_RED_EXT 0x1903 +#define GL_RG_EXT 0x8227 +#define GL_R8_EXT 0x8229 +#define GL_RG8_EXT 0x822B +#endif /* GL_EXT_texture_rg */ + +#ifndef GL_EXT_texture_sRGB_R8 +#define GL_EXT_texture_sRGB_R8 1 +#define GL_SR8_EXT 0x8FBD +#endif /* GL_EXT_texture_sRGB_R8 */ + +#ifndef GL_EXT_texture_sRGB_RG8 +#define GL_EXT_texture_sRGB_RG8 1 +#define GL_SRG8_EXT 0x8FBE +#endif /* GL_EXT_texture_sRGB_RG8 */ + +#ifndef GL_EXT_texture_sRGB_decode +#define GL_EXT_texture_sRGB_decode 1 +#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 +#define GL_DECODE_EXT 0x8A49 +#define GL_SKIP_DECODE_EXT 0x8A4A +#endif /* GL_EXT_texture_sRGB_decode */ -/* GL_EXT_texture_storage */ #ifndef GL_EXT_texture_storage #define GL_EXT_texture_storage 1 +#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F +#define GL_ALPHA8_EXT 0x803C +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_RGBA32F_EXT 0x8814 +#define GL_RGB32F_EXT 0x8815 +#define GL_ALPHA32F_EXT 0x8816 +#define GL_LUMINANCE32F_EXT 0x8818 +#define GL_LUMINANCE_ALPHA32F_EXT 0x8819 +#define GL_ALPHA16F_EXT 0x881C +#define GL_LUMINANCE16F_EXT 0x881E +#define GL_LUMINANCE_ALPHA16F_EXT 0x881F +#define GL_R32F_EXT 0x822E +#define GL_RG32F_EXT 0x8230 +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); @@ -1536,123 +1854,345 @@ GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); #endif -typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); -typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); -typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -#endif +#endif /* GL_EXT_texture_storage */ -/* GL_EXT_texture_type_2_10_10_10_REV */ #ifndef GL_EXT_texture_type_2_10_10_10_REV #define GL_EXT_texture_type_2_10_10_10_REV 1 -#endif +#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368 +#endif /* GL_EXT_texture_type_2_10_10_10_REV */ + +#ifndef GL_EXT_texture_view +#define GL_EXT_texture_view 1 +#define GL_TEXTURE_VIEW_MIN_LEVEL_EXT 0x82DB +#define GL_TEXTURE_VIEW_NUM_LEVELS_EXT 0x82DC +#define GL_TEXTURE_VIEW_MIN_LAYER_EXT 0x82DD +#define GL_TEXTURE_VIEW_NUM_LAYERS_EXT 0x82DE +typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWEXTPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTextureViewEXT (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +#endif +#endif /* GL_EXT_texture_view */ -/* GL_EXT_unpack_subimage */ #ifndef GL_EXT_unpack_subimage #define GL_EXT_unpack_subimage 1 -#endif +#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2 +#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4 +#endif /* GL_EXT_unpack_subimage */ -/*------------------------------------------------------------------------* - * DMP extension functions - *------------------------------------------------------------------------*/ - -/* GL_DMP_shader_binary */ -#ifndef GL_DMP_shader_binary -#define GL_DMP_shader_binary 1 -#endif - -/*------------------------------------------------------------------------* - * FJ extension functions - *------------------------------------------------------------------------*/ - -/* GL_FJ_shader_binary_GCCSO */ #ifndef GL_FJ_shader_binary_GCCSO #define GL_FJ_shader_binary_GCCSO 1 +#define GL_GCCSO_SHADER_BINARY_FJ 0x9260 +#endif /* GL_FJ_shader_binary_GCCSO */ + +#ifndef GL_IMG_framebuffer_downsample +#define GL_IMG_framebuffer_downsample 1 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG 0x913C +#define GL_NUM_DOWNSAMPLE_SCALES_IMG 0x913D +#define GL_DOWNSAMPLE_SCALES_IMG 0x913E +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG 0x913F +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DDOWNSAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint xscale, GLint yscale); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERDOWNSAMPLEIMGPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer, GLint xscale, GLint yscale); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glFramebufferTexture2DDownsampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint xscale, GLint yscale); +GL_APICALL void GL_APIENTRY glFramebufferTextureLayerDownsampleIMG (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer, GLint xscale, GLint yscale); #endif +#endif /* GL_IMG_framebuffer_downsample */ -/*------------------------------------------------------------------------* - * IMG extension functions - *------------------------------------------------------------------------*/ - -/* GL_IMG_program_binary */ -#ifndef GL_IMG_program_binary -#define GL_IMG_program_binary 1 -#endif - -/* GL_IMG_read_format */ -#ifndef GL_IMG_read_format -#define GL_IMG_read_format 1 -#endif - -/* GL_IMG_shader_binary */ -#ifndef GL_IMG_shader_binary -#define GL_IMG_shader_binary 1 -#endif - -/* GL_IMG_texture_compression_pvrtc */ -#ifndef GL_IMG_texture_compression_pvrtc -#define GL_IMG_texture_compression_pvrtc 1 -#endif - -/* GL_IMG_multisampled_render_to_texture */ #ifndef GL_IMG_multisampled_render_to_texture #define GL_IMG_multisampled_render_to_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei); -GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei); -#endif +#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134 +#define GL_MAX_SAMPLES_IMG 0x9135 +#define GL_TEXTURE_SAMPLES_IMG 0x9136 typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); #endif +#endif /* GL_IMG_multisampled_render_to_texture */ -/*------------------------------------------------------------------------* - * NV extension functions - *------------------------------------------------------------------------*/ +#ifndef GL_IMG_program_binary +#define GL_IMG_program_binary 1 +#define GL_SGX_PROGRAM_BINARY_IMG 0x9130 +#endif /* GL_IMG_program_binary */ + +#ifndef GL_IMG_read_format +#define GL_IMG_read_format 1 +#define GL_BGRA_IMG 0x80E1 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365 +#endif /* GL_IMG_read_format */ + +#ifndef GL_IMG_shader_binary +#define GL_IMG_shader_binary 1 +#define GL_SGX_BINARY_IMG 0x8C0A +#endif /* GL_IMG_shader_binary */ + +#ifndef GL_IMG_texture_compression_pvrtc +#define GL_IMG_texture_compression_pvrtc 1 +#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 +#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 +#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 +#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 +#endif /* GL_IMG_texture_compression_pvrtc */ + +#ifndef GL_IMG_texture_compression_pvrtc2 +#define GL_IMG_texture_compression_pvrtc2 1 +#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137 +#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138 +#endif /* GL_IMG_texture_compression_pvrtc2 */ + +#ifndef GL_IMG_texture_filter_cubic +#define GL_IMG_texture_filter_cubic 1 +#define GL_CUBIC_IMG 0x9139 +#define GL_CUBIC_MIPMAP_NEAREST_IMG 0x913A +#define GL_CUBIC_MIPMAP_LINEAR_IMG 0x913B +#endif /* GL_IMG_texture_filter_cubic */ + +#ifndef GL_INTEL_framebuffer_CMAA +#define GL_INTEL_framebuffer_CMAA 1 +typedef void (GL_APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glApplyFramebufferAttachmentCMAAINTEL (void); +#endif +#endif /* GL_INTEL_framebuffer_CMAA */ + +#ifndef GL_INTEL_performance_query +#define GL_INTEL_performance_query 1 +#define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000 +#define GL_PERFQUERY_GLOBAL_CONTEXT_INTEL 0x00000001 +#define GL_PERFQUERY_WAIT_INTEL 0x83FB +#define GL_PERFQUERY_FLUSH_INTEL 0x83FA +#define GL_PERFQUERY_DONOT_FLUSH_INTEL 0x83F9 +#define GL_PERFQUERY_COUNTER_EVENT_INTEL 0x94F0 +#define GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL 0x94F1 +#define GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL 0x94F2 +#define GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL 0x94F3 +#define GL_PERFQUERY_COUNTER_RAW_INTEL 0x94F4 +#define GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL 0x94F5 +#define GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL 0x94F8 +#define GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL 0x94F9 +#define GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL 0x94FA +#define GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL 0x94FB +#define GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL 0x94FC +#define GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL 0x94FD +#define GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL 0x94FE +#define GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL 0x94FF +#define GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL 0x9500 +typedef void (GL_APIENTRYP PFNGLBEGINPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (GL_APIENTRYP PFNGLCREATEPERFQUERYINTELPROC) (GLuint queryId, GLuint *queryHandle); +typedef void (GL_APIENTRYP PFNGLDELETEPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (GL_APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (GL_APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId); +typedef void (GL_APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId); +//typedef void (GL_APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); +typedef void (GL_APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten); +typedef void (GL_APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId); +typedef void (GL_APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBeginPerfQueryINTEL (GLuint queryHandle); +GL_APICALL void GL_APIENTRY glCreatePerfQueryINTEL (GLuint queryId, GLuint *queryHandle); +GL_APICALL void GL_APIENTRY glDeletePerfQueryINTEL (GLuint queryHandle); +GL_APICALL void GL_APIENTRY glEndPerfQueryINTEL (GLuint queryHandle); +GL_APICALL void GL_APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId); +GL_APICALL void GL_APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId); +//GL_APICALL void GL_APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); +GL_APICALL void GL_APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten); +GL_APICALL void GL_APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId); +GL_APICALL void GL_APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); +#endif +#endif /* GL_INTEL_performance_query */ + +#ifndef GL_NV_blend_equation_advanced +#define GL_NV_blend_equation_advanced 1 +#define GL_BLEND_OVERLAP_NV 0x9281 +#define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280 +#define GL_BLUE_NV 0x1905 +#define GL_COLORBURN_NV 0x929A +#define GL_COLORDODGE_NV 0x9299 +#define GL_CONJOINT_NV 0x9284 +#define GL_CONTRAST_NV 0x92A1 +#define GL_DARKEN_NV 0x9297 +#define GL_DIFFERENCE_NV 0x929E +#define GL_DISJOINT_NV 0x9283 +#define GL_DST_ATOP_NV 0x928F +#define GL_DST_IN_NV 0x928B +#define GL_DST_NV 0x9287 +#define GL_DST_OUT_NV 0x928D +#define GL_DST_OVER_NV 0x9289 +#define GL_EXCLUSION_NV 0x92A0 +#define GL_GREEN_NV 0x1904 +#define GL_HARDLIGHT_NV 0x929B +#define GL_HARDMIX_NV 0x92A9 +#define GL_HSL_COLOR_NV 0x92AF +#define GL_HSL_HUE_NV 0x92AD +#define GL_HSL_LUMINOSITY_NV 0x92B0 +#define GL_HSL_SATURATION_NV 0x92AE +#define GL_INVERT_OVG_NV 0x92B4 +#define GL_INVERT_RGB_NV 0x92A3 +#define GL_LIGHTEN_NV 0x9298 +#define GL_LINEARBURN_NV 0x92A5 +#define GL_LINEARDODGE_NV 0x92A4 +#define GL_LINEARLIGHT_NV 0x92A7 +#define GL_MINUS_CLAMPED_NV 0x92B3 +#define GL_MINUS_NV 0x929F +#define GL_MULTIPLY_NV 0x9294 +#define GL_OVERLAY_NV 0x9296 +#define GL_PINLIGHT_NV 0x92A8 +#define GL_PLUS_CLAMPED_ALPHA_NV 0x92B2 +#define GL_PLUS_CLAMPED_NV 0x92B1 +#define GL_PLUS_DARKER_NV 0x9292 +#define GL_PLUS_NV 0x9291 +#define GL_RED_NV 0x1903 +#define GL_SCREEN_NV 0x9295 +#define GL_SOFTLIGHT_NV 0x929C +#define GL_SRC_ATOP_NV 0x928E +#define GL_SRC_IN_NV 0x928A +#define GL_SRC_NV 0x9286 +#define GL_SRC_OUT_NV 0x928C +#define GL_SRC_OVER_NV 0x9288 +#define GL_UNCORRELATED_NV 0x9282 +#define GL_VIVIDLIGHT_NV 0x92A6 +#define GL_XOR_NV 0x1506 +typedef void (GL_APIENTRYP PFNGLBLENDPARAMETERINVPROC) (GLenum pname, GLint value); +typedef void (GL_APIENTRYP PFNGLBLENDBARRIERNVPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBlendParameteriNV (GLenum pname, GLint value); +GL_APICALL void GL_APIENTRY glBlendBarrierNV (void); +#endif +#endif /* GL_NV_blend_equation_advanced */ + +#ifndef GL_NV_blend_equation_advanced_coherent +#define GL_NV_blend_equation_advanced_coherent 1 +#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285 +#endif /* GL_NV_blend_equation_advanced_coherent */ + +#ifndef GL_NV_conditional_render +#define GL_NV_conditional_render 1 +#define GL_QUERY_WAIT_NV 0x8E13 +#define GL_QUERY_NO_WAIT_NV 0x8E14 +#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 +typedef void (GL_APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode); +typedef void (GL_APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode); +GL_APICALL void GL_APIENTRY glEndConditionalRenderNV (void); +#endif +#endif /* GL_NV_conditional_render */ + +#ifndef GL_NV_conservative_raster +#define GL_NV_conservative_raster 1 +#define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346 +#define GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV 0x9347 +#define GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV 0x9348 +#define GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV 0x9349 +typedef void (GL_APIENTRYP PFNGLSUBPIXELPRECISIONBIASNVPROC) (GLuint xbits, GLuint ybits); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybits); +#endif +#endif /* GL_NV_conservative_raster */ + +#ifndef GL_NV_copy_buffer +#define GL_NV_copy_buffer 1 +#define GL_COPY_READ_BUFFER_NV 0x8F36 +#define GL_COPY_WRITE_BUFFER_NV 0x8F37 +typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATANVPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glCopyBufferSubDataNV (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +#endif +#endif /* GL_NV_copy_buffer */ -/* GL_NV_coverage_sample */ #ifndef GL_NV_coverage_sample #define GL_NV_coverage_sample 1 +#define GL_COVERAGE_COMPONENT_NV 0x8ED0 +#define GL_COVERAGE_COMPONENT4_NV 0x8ED1 +#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2 +#define GL_COVERAGE_BUFFERS_NV 0x8ED3 +#define GL_COVERAGE_SAMPLES_NV 0x8ED4 +#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5 +#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6 +#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7 +#define GL_COVERAGE_BUFFER_BIT_NV 0x00008000 +typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask); +typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask); GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation); #endif -typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask); -typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation); -#endif +#endif /* GL_NV_coverage_sample */ -/* GL_NV_depth_nonlinear */ #ifndef GL_NV_depth_nonlinear #define GL_NV_depth_nonlinear 1 -#endif +#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C +#endif /* GL_NV_depth_nonlinear */ -/* GL_NV_draw_buffers */ #ifndef GL_NV_draw_buffers #define GL_NV_draw_buffers 1 +#define GL_MAX_DRAW_BUFFERS_NV 0x8824 +#define GL_DRAW_BUFFER0_NV 0x8825 +#define GL_DRAW_BUFFER1_NV 0x8826 +#define GL_DRAW_BUFFER2_NV 0x8827 +#define GL_DRAW_BUFFER3_NV 0x8828 +#define GL_DRAW_BUFFER4_NV 0x8829 +#define GL_DRAW_BUFFER5_NV 0x882A +#define GL_DRAW_BUFFER6_NV 0x882B +#define GL_DRAW_BUFFER7_NV 0x882C +#define GL_DRAW_BUFFER8_NV 0x882D +#define GL_DRAW_BUFFER9_NV 0x882E +#define GL_DRAW_BUFFER10_NV 0x882F +#define GL_DRAW_BUFFER11_NV 0x8830 +#define GL_DRAW_BUFFER12_NV 0x8831 +#define GL_DRAW_BUFFER13_NV 0x8832 +#define GL_DRAW_BUFFER14_NV 0x8833 +#define GL_DRAW_BUFFER15_NV 0x8834 +#define GL_COLOR_ATTACHMENT0_NV 0x8CE0 +#define GL_COLOR_ATTACHMENT1_NV 0x8CE1 +#define GL_COLOR_ATTACHMENT2_NV 0x8CE2 +#define GL_COLOR_ATTACHMENT3_NV 0x8CE3 +#define GL_COLOR_ATTACHMENT4_NV 0x8CE4 +#define GL_COLOR_ATTACHMENT5_NV 0x8CE5 +#define GL_COLOR_ATTACHMENT6_NV 0x8CE6 +#define GL_COLOR_ATTACHMENT7_NV 0x8CE7 +#define GL_COLOR_ATTACHMENT8_NV 0x8CE8 +#define GL_COLOR_ATTACHMENT9_NV 0x8CE9 +#define GL_COLOR_ATTACHMENT10_NV 0x8CEA +#define GL_COLOR_ATTACHMENT11_NV 0x8CEB +#define GL_COLOR_ATTACHMENT12_NV 0x8CEC +#define GL_COLOR_ATTACHMENT13_NV 0x8CED +#define GL_COLOR_ATTACHMENT14_NV 0x8CEE +#define GL_COLOR_ATTACHMENT15_NV 0x8CEF +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs); #endif -typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs); -#endif +#endif /* GL_NV_draw_buffers */ + +#ifndef GL_NV_draw_instanced +#define GL_NV_draw_instanced 1 +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDNVPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDNVPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawArraysInstancedNV (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#endif +#endif /* GL_NV_draw_instanced */ + +#ifndef GL_NV_explicit_attrib_location +#define GL_NV_explicit_attrib_location 1 +#endif /* GL_NV_explicit_attrib_location */ -/* GL_NV_fbo_color_attachments */ #ifndef GL_NV_fbo_color_attachments #define GL_NV_fbo_color_attachments 1 -#endif +#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF +#endif /* GL_NV_fbo_color_attachments */ -/* GL_NV_fence */ #ifndef GL_NV_fence #define GL_NV_fence 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei, const GLuint *); -GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei, GLuint *); -GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint); -GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint); -GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *); -GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint); -GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint, GLenum); -#endif +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence); @@ -1660,83 +2200,636 @@ typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence); typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences); +GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences); +GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint fence); +GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint fence); +GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint fence); +GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition); #endif +#endif /* GL_NV_fence */ + +#ifndef GL_NV_fill_rectangle +#define GL_NV_fill_rectangle 1 +#define GL_FILL_RECTANGLE_NV 0x933C +#endif /* GL_NV_fill_rectangle */ + +#ifndef GL_NV_fragment_coverage_to_color +#define GL_NV_fragment_coverage_to_color 1 +#define GL_FRAGMENT_COVERAGE_TO_COLOR_NV 0x92DD +#define GL_FRAGMENT_COVERAGE_COLOR_NV 0x92DE +typedef void (GL_APIENTRYP PFNGLFRAGMENTCOVERAGECOLORNVPROC) (GLuint color); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glFragmentCoverageColorNV (GLuint color); +#endif +#endif /* GL_NV_fragment_coverage_to_color */ + +#ifndef GL_NV_fragment_shader_interlock +#define GL_NV_fragment_shader_interlock 1 +#endif /* GL_NV_fragment_shader_interlock */ + +#ifndef GL_NV_framebuffer_blit +#define GL_NV_framebuffer_blit 1 +#define GL_READ_FRAMEBUFFER_NV 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_NV 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_NV 0x8CAA +typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBlitFramebufferNV (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif +#endif /* GL_NV_framebuffer_blit */ + +#ifndef GL_NV_framebuffer_mixed_samples +#define GL_NV_framebuffer_mixed_samples 1 +#define GL_COVERAGE_MODULATION_TABLE_NV 0x9331 +#define GL_COLOR_SAMPLES_NV 0x8E20 +#define GL_DEPTH_SAMPLES_NV 0x932D +#define GL_STENCIL_SAMPLES_NV 0x932E +#define GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV 0x932F +#define GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV 0x9330 +#define GL_COVERAGE_MODULATION_NV 0x9332 +#define GL_COVERAGE_MODULATION_TABLE_SIZE_NV 0x9333 +typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONTABLENVPROC) (GLsizei n, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLGETCOVERAGEMODULATIONTABLENVPROC) (GLsizei bufsize, GLfloat *v); +typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONNVPROC) (GLenum components); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glCoverageModulationTableNV (GLsizei n, const GLfloat *v); +GL_APICALL void GL_APIENTRY glGetCoverageModulationTableNV (GLsizei bufsize, GLfloat *v); +GL_APICALL void GL_APIENTRY glCoverageModulationNV (GLenum components); +#endif +#endif /* GL_NV_framebuffer_mixed_samples */ + +#ifndef GL_NV_framebuffer_multisample +#define GL_NV_framebuffer_multisample 1 +#define GL_RENDERBUFFER_SAMPLES_NV 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56 +#define GL_MAX_SAMPLES_NV 0x8D57 +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLENVPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif +#endif /* GL_NV_framebuffer_multisample */ + +#ifndef GL_NV_generate_mipmap_sRGB +#define GL_NV_generate_mipmap_sRGB 1 +#endif /* GL_NV_generate_mipmap_sRGB */ + +#ifndef GL_NV_geometry_shader_passthrough +#define GL_NV_geometry_shader_passthrough 1 +#endif /* GL_NV_geometry_shader_passthrough */ + +#ifndef GL_NV_image_formats +#define GL_NV_image_formats 1 +#endif /* GL_NV_image_formats */ + +#ifndef GL_NV_instanced_arrays +#define GL_NV_instanced_arrays 1 +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORNVPROC) (GLuint index, GLuint divisor); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint divisor); +#endif +#endif /* GL_NV_instanced_arrays */ + +#ifndef GL_NV_internalformat_sample_query +#define GL_NV_internalformat_sample_query 1 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_MULTISAMPLES_NV 0x9371 +#define GL_SUPERSAMPLE_SCALE_X_NV 0x9372 +#define GL_SUPERSAMPLE_SCALE_Y_NV 0x9373 +#define GL_CONFORMANT_NV 0x9374 +typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params); +#endif +#endif /* GL_NV_internalformat_sample_query */ + +#ifndef GL_NV_non_square_matrices +#define GL_NV_non_square_matrices 1 +#define GL_FLOAT_MAT2x3_NV 0x8B65 +#define GL_FLOAT_MAT2x4_NV 0x8B66 +#define GL_FLOAT_MAT3x2_NV 0x8B67 +#define GL_FLOAT_MAT3x4_NV 0x8B68 +#define GL_FLOAT_MAT4x2_NV 0x8B69 +#define GL_FLOAT_MAT4x3_NV 0x8B6A +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glUniformMatrix2x3fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x2fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix2x4fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x2fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x4fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x3fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +#endif +#endif /* GL_NV_non_square_matrices */ + +#ifndef GL_NV_path_rendering +#define GL_NV_path_rendering 1 +#define GL_PATH_FORMAT_SVG_NV 0x9070 +#define GL_PATH_FORMAT_PS_NV 0x9071 +#define GL_STANDARD_FONT_NAME_NV 0x9072 +#define GL_SYSTEM_FONT_NAME_NV 0x9073 +#define GL_FILE_NAME_NV 0x9074 +#define GL_PATH_STROKE_WIDTH_NV 0x9075 +#define GL_PATH_END_CAPS_NV 0x9076 +#define GL_PATH_INITIAL_END_CAP_NV 0x9077 +#define GL_PATH_TERMINAL_END_CAP_NV 0x9078 +#define GL_PATH_JOIN_STYLE_NV 0x9079 +#define GL_PATH_MITER_LIMIT_NV 0x907A +#define GL_PATH_DASH_CAPS_NV 0x907B +#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C +#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D +#define GL_PATH_DASH_OFFSET_NV 0x907E +#define GL_PATH_CLIENT_LENGTH_NV 0x907F +#define GL_PATH_FILL_MODE_NV 0x9080 +#define GL_PATH_FILL_MASK_NV 0x9081 +#define GL_PATH_FILL_COVER_MODE_NV 0x9082 +#define GL_PATH_STROKE_COVER_MODE_NV 0x9083 +#define GL_PATH_STROKE_MASK_NV 0x9084 +#define GL_COUNT_UP_NV 0x9088 +#define GL_COUNT_DOWN_NV 0x9089 +#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A +#define GL_CONVEX_HULL_NV 0x908B +#define GL_BOUNDING_BOX_NV 0x908D +#define GL_TRANSLATE_X_NV 0x908E +#define GL_TRANSLATE_Y_NV 0x908F +#define GL_TRANSLATE_2D_NV 0x9090 +#define GL_TRANSLATE_3D_NV 0x9091 +#define GL_AFFINE_2D_NV 0x9092 +#define GL_AFFINE_3D_NV 0x9094 +#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096 +#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098 +#define GL_UTF8_NV 0x909A +#define GL_UTF16_NV 0x909B +#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C +#define GL_PATH_COMMAND_COUNT_NV 0x909D +#define GL_PATH_COORD_COUNT_NV 0x909E +#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F +#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0 +#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1 +#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2 +#define GL_SQUARE_NV 0x90A3 +#define GL_ROUND_NV 0x90A4 +#define GL_TRIANGULAR_NV 0x90A5 +#define GL_BEVEL_NV 0x90A6 +#define GL_MITER_REVERT_NV 0x90A7 +#define GL_MITER_TRUNCATE_NV 0x90A8 +#define GL_SKIP_MISSING_GLYPH_NV 0x90A9 +#define GL_USE_MISSING_GLYPH_NV 0x90AA +#define GL_PATH_ERROR_POSITION_NV 0x90AB +#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD +#define GL_ADJACENT_PAIRS_NV 0x90AE +#define GL_FIRST_TO_REST_NV 0x90AF +#define GL_PATH_GEN_MODE_NV 0x90B0 +#define GL_PATH_GEN_COEFF_NV 0x90B1 +#define GL_PATH_GEN_COMPONENTS_NV 0x90B3 +#define GL_PATH_STENCIL_FUNC_NV 0x90B7 +#define GL_PATH_STENCIL_REF_NV 0x90B8 +#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9 +#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD +#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE +#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF +#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4 +#define GL_MOVE_TO_RESETS_NV 0x90B5 +#define GL_MOVE_TO_CONTINUES_NV 0x90B6 +#define GL_CLOSE_PATH_NV 0x00 +#define GL_MOVE_TO_NV 0x02 +#define GL_RELATIVE_MOVE_TO_NV 0x03 +#define GL_LINE_TO_NV 0x04 +#define GL_RELATIVE_LINE_TO_NV 0x05 +#define GL_HORIZONTAL_LINE_TO_NV 0x06 +#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07 +#define GL_VERTICAL_LINE_TO_NV 0x08 +#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09 +#define GL_QUADRATIC_CURVE_TO_NV 0x0A +#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B +#define GL_CUBIC_CURVE_TO_NV 0x0C +#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D +#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E +#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F +#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10 +#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11 +#define GL_SMALL_CCW_ARC_TO_NV 0x12 +#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13 +#define GL_SMALL_CW_ARC_TO_NV 0x14 +#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15 +#define GL_LARGE_CCW_ARC_TO_NV 0x16 +#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17 +#define GL_LARGE_CW_ARC_TO_NV 0x18 +#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19 +#define GL_RESTART_PATH_NV 0xF0 +#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2 +#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4 +#define GL_RECT_NV 0xF6 +#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8 +#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA +#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC +#define GL_ARC_TO_NV 0xFE +#define GL_RELATIVE_ARC_TO_NV 0xFF +#define GL_BOLD_BIT_NV 0x01 +#define GL_ITALIC_BIT_NV 0x02 +#define GL_GLYPH_WIDTH_BIT_NV 0x01 +#define GL_GLYPH_HEIGHT_BIT_NV 0x02 +#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04 +#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08 +#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10 +#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20 +#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40 +#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80 +#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100 +#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000 +#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000 +#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000 +#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000 +#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000 +#define GL_FONT_ASCENDER_BIT_NV 0x00200000 +#define GL_FONT_DESCENDER_BIT_NV 0x00400000 +#define GL_FONT_HEIGHT_BIT_NV 0x00800000 +#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000 +#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000 +#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000 +#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000 +#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000 +#define GL_ROUNDED_RECT_NV 0xE8 +#define GL_RELATIVE_ROUNDED_RECT_NV 0xE9 +#define GL_ROUNDED_RECT2_NV 0xEA +#define GL_RELATIVE_ROUNDED_RECT2_NV 0xEB +#define GL_ROUNDED_RECT4_NV 0xEC +#define GL_RELATIVE_ROUNDED_RECT4_NV 0xED +#define GL_ROUNDED_RECT8_NV 0xEE +#define GL_RELATIVE_ROUNDED_RECT8_NV 0xEF +#define GL_RELATIVE_RECT_NV 0xF7 +#define GL_FONT_GLYPHS_AVAILABLE_NV 0x9368 +#define GL_FONT_TARGET_UNAVAILABLE_NV 0x9369 +#define GL_FONT_UNAVAILABLE_NV 0x936A +#define GL_FONT_UNINTELLIGIBLE_NV 0x936B +#define GL_CONIC_CURVE_TO_NV 0x1A +#define GL_RELATIVE_CONIC_CURVE_TO_NV 0x1B +#define GL_FONT_NUM_GLYPH_INDICES_BIT_NV 0x20000000 +#define GL_STANDARD_FONT_FORMAT_NV 0x936C +#define GL_PATH_PROJECTION_NV 0x1701 +#define GL_PATH_MODELVIEW_NV 0x1700 +#define GL_PATH_MODELVIEW_STACK_DEPTH_NV 0x0BA3 +#define GL_PATH_MODELVIEW_MATRIX_NV 0x0BA6 +#define GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36 +#define GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3 +#define GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4 +#define GL_PATH_PROJECTION_MATRIX_NV 0x0BA7 +#define GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38 +#define GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4 +#define GL_FRAGMENT_INPUT_NV 0x936D +typedef GLuint (GL_APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range); +typedef void (GL_APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range); +typedef GLboolean (GL_APIENTRYP PFNGLISPATHNVPROC) (GLuint path); +typedef void (GL_APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (GL_APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (GL_APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (GL_APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (GL_APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString); +typedef void (GL_APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef void (GL_APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef void (GL_APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights); +typedef void (GL_APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath); +typedef void (GL_APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight); +typedef void (GL_APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues); +typedef void (GL_APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value); +typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value); +typedef void (GL_APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray); +typedef void (GL_APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask); +typedef void (GL_APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units); +typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues); +typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues); +typedef void (GL_APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func); +typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode); +typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode); +typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value); +typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value); +typedef void (GL_APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands); +typedef void (GL_APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords); +typedef void (GL_APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray); +typedef void (GL_APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics); +typedef void (GL_APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics); +typedef void (GL_APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing); +typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y); +typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y); +typedef GLfloat (GL_APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments); +typedef GLboolean (GL_APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY); +typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X2FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (GL_APIENTRYP PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X2FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (GL_APIENTRYP PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); +typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode); +typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode); +typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]); +typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef GLenum (GL_APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef void (GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL GLuint GL_APIENTRY glGenPathsNV (GLsizei range); +GL_APICALL void GL_APIENTRY glDeletePathsNV (GLuint path, GLsizei range); +GL_APICALL GLboolean GL_APIENTRY glIsPathNV (GLuint path); +GL_APICALL void GL_APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +GL_APICALL void GL_APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords); +GL_APICALL void GL_APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +GL_APICALL void GL_APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords); +GL_APICALL void GL_APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString); +GL_APICALL void GL_APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +GL_APICALL void GL_APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +GL_APICALL void GL_APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights); +GL_APICALL void GL_APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath); +GL_APICALL void GL_APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight); +GL_APICALL void GL_APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues); +GL_APICALL void GL_APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value); +GL_APICALL void GL_APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value); +GL_APICALL void GL_APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value); +GL_APICALL void GL_APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value); +GL_APICALL void GL_APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray); +GL_APICALL void GL_APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units); +GL_APICALL void GL_APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues); +GL_APICALL void GL_APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues); +GL_APICALL void GL_APIENTRY glPathCoverDepthFuncNV (GLenum func); +GL_APICALL void GL_APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode); +GL_APICALL void GL_APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode); +GL_APICALL void GL_APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +GL_APICALL void GL_APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value); +GL_APICALL void GL_APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value); +GL_APICALL void GL_APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands); +GL_APICALL void GL_APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords); +GL_APICALL void GL_APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray); +GL_APICALL void GL_APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics); +GL_APICALL void GL_APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics); +GL_APICALL void GL_APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing); +GL_APICALL GLboolean GL_APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y); +GL_APICALL GLboolean GL_APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y); +GL_APICALL GLfloat GL_APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments); +GL_APICALL GLboolean GL_APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY); +GL_APICALL void GL_APIENTRY glMatrixLoad3x2fNV (GLenum matrixMode, const GLfloat *m); +GL_APICALL void GL_APIENTRY glMatrixLoad3x3fNV (GLenum matrixMode, const GLfloat *m); +GL_APICALL void GL_APIENTRY glMatrixLoadTranspose3x3fNV (GLenum matrixMode, const GLfloat *m); +GL_APICALL void GL_APIENTRY glMatrixMult3x2fNV (GLenum matrixMode, const GLfloat *m); +GL_APICALL void GL_APIENTRY glMatrixMult3x3fNV (GLenum matrixMode, const GLfloat *m); +GL_APICALL void GL_APIENTRY glMatrixMultTranspose3x3fNV (GLenum matrixMode, const GLfloat *m); +GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode); +GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode); +GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]); +GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +GL_APICALL GLenum GL_APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs); +GL_APICALL void GL_APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params); +#endif +#endif /* GL_NV_path_rendering */ + +#ifndef GL_NV_path_rendering_shared_edge +#define GL_NV_path_rendering_shared_edge 1 +#define GL_SHARED_EDGE_NV 0xC0 +#endif /* GL_NV_path_rendering_shared_edge */ + +#ifndef GL_NV_polygon_mode +#define GL_NV_polygon_mode 1 +#define GL_POLYGON_MODE_NV 0x0B40 +#define GL_POLYGON_OFFSET_POINT_NV 0x2A01 +#define GL_POLYGON_OFFSET_LINE_NV 0x2A02 +#define GL_POINT_NV 0x1B00 +#define GL_LINE_NV 0x1B01 +#define GL_FILL_NV 0x1B02 +typedef void (GL_APIENTRYP PFNGLPOLYGONMODENVPROC) (GLenum face, GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glPolygonModeNV (GLenum face, GLenum mode); +#endif +#endif /* GL_NV_polygon_mode */ -/* GL_NV_read_buffer */ #ifndef GL_NV_read_buffer #define GL_NV_read_buffer 1 +#define GL_READ_BUFFER_NV 0x0C02 +typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode); #endif -typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode); -#endif +#endif /* GL_NV_read_buffer */ -/* GL_NV_read_buffer_front */ #ifndef GL_NV_read_buffer_front #define GL_NV_read_buffer_front 1 -#endif +#endif /* GL_NV_read_buffer_front */ -/* GL_NV_read_depth */ #ifndef GL_NV_read_depth #define GL_NV_read_depth 1 -#endif +#endif /* GL_NV_read_depth */ -/* GL_NV_read_depth_stencil */ #ifndef GL_NV_read_depth_stencil #define GL_NV_read_depth_stencil 1 -#endif +#endif /* GL_NV_read_depth_stencil */ -/* GL_NV_read_stencil */ #ifndef GL_NV_read_stencil #define GL_NV_read_stencil 1 -#endif +#endif /* GL_NV_read_stencil */ + +#ifndef GL_NV_sRGB_formats +#define GL_NV_sRGB_formats 1 +#define GL_SLUMINANCE_NV 0x8C46 +#define GL_SLUMINANCE_ALPHA_NV 0x8C44 +#define GL_SRGB8_NV 0x8C41 +#define GL_SLUMINANCE8_NV 0x8C47 +#define GL_SLUMINANCE8_ALPHA8_NV 0x8C45 +#define GL_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F +#define GL_ETC1_SRGB8_NV 0x88EE +#endif /* GL_NV_sRGB_formats */ + +#ifndef GL_NV_sample_locations +#define GL_NV_sample_locations 1 +#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D +#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV 0x933E +#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV 0x933F +#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV 0x9340 +#define GL_SAMPLE_LOCATION_NV 0x8E50 +#define GL_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9341 +#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV 0x9342 +#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV 0x9343 +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLRESOLVEDEPTHVALUESNVPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glFramebufferSampleLocationsfvNV (GLenum target, GLuint start, GLsizei count, const GLfloat *v); +GL_APICALL void GL_APIENTRY glNamedFramebufferSampleLocationsfvNV (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); +GL_APICALL void GL_APIENTRY glResolveDepthValuesNV (void); +#endif +#endif /* GL_NV_sample_locations */ + +#ifndef GL_NV_sample_mask_override_coverage +#define GL_NV_sample_mask_override_coverage 1 +#endif /* GL_NV_sample_mask_override_coverage */ + +#ifndef GL_NV_shader_noperspective_interpolation +#define GL_NV_shader_noperspective_interpolation 1 +#endif /* GL_NV_shader_noperspective_interpolation */ + +#ifndef GL_NV_shadow_samplers_array +#define GL_NV_shadow_samplers_array 1 +#define GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4 +#endif /* GL_NV_shadow_samplers_array */ + +#ifndef GL_NV_shadow_samplers_cube +#define GL_NV_shadow_samplers_cube 1 +#define GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5 +#endif /* GL_NV_shadow_samplers_cube */ + +#ifndef GL_NV_texture_border_clamp +#define GL_NV_texture_border_clamp 1 +#define GL_TEXTURE_BORDER_COLOR_NV 0x1004 +#define GL_CLAMP_TO_BORDER_NV 0x812D +#endif /* GL_NV_texture_border_clamp */ -/* GL_NV_texture_compression_s3tc_update */ #ifndef GL_NV_texture_compression_s3tc_update #define GL_NV_texture_compression_s3tc_update 1 -#endif +#endif /* GL_NV_texture_compression_s3tc_update */ -/* GL_NV_texture_npot_2D_mipmap */ #ifndef GL_NV_texture_npot_2D_mipmap #define GL_NV_texture_npot_2D_mipmap 1 +#endif /* GL_NV_texture_npot_2D_mipmap */ + +#ifndef GL_NV_viewport_array +#define GL_NV_viewport_array 1 +#define GL_MAX_VIEWPORTS_NV 0x825B +#define GL_VIEWPORT_SUBPIXEL_BITS_NV 0x825C +#define GL_VIEWPORT_BOUNDS_RANGE_NV 0x825D +#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV 0x825F +typedef void (GL_APIENTRYP PFNGLVIEWPORTARRAYVNVPROC) (GLuint first, GLsizei count, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFVNVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLSCISSORARRAYVNVPROC) (GLuint first, GLsizei count, const GLint *v); +typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDNVPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDVNVPROC) (GLuint index, const GLint *v); +typedef void (GL_APIENTRYP PFNGLDEPTHRANGEARRAYFVNVPROC) (GLuint first, GLsizei count, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLDEPTHRANGEINDEXEDFNVPROC) (GLuint index, GLfloat n, GLfloat f); +typedef void (GL_APIENTRYP PFNGLGETFLOATI_VNVPROC) (GLenum target, GLuint index, GLfloat *data); +typedef void (GL_APIENTRYP PFNGLENABLEINVPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP PFNGLDISABLEINVPROC) (GLenum target, GLuint index); +typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDINVPROC) (GLenum target, GLuint index); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glViewportArrayvNV (GLuint first, GLsizei count, const GLfloat *v); +GL_APICALL void GL_APIENTRY glViewportIndexedfNV (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +GL_APICALL void GL_APIENTRY glViewportIndexedfvNV (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glScissorArrayvNV (GLuint first, GLsizei count, const GLint *v); +GL_APICALL void GL_APIENTRY glScissorIndexedNV (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glScissorIndexedvNV (GLuint index, const GLint *v); +GL_APICALL void GL_APIENTRY glDepthRangeArrayfvNV (GLuint first, GLsizei count, const GLfloat *v); +GL_APICALL void GL_APIENTRY glDepthRangeIndexedfNV (GLuint index, GLfloat n, GLfloat f); +GL_APICALL void GL_APIENTRY glGetFloati_vNV (GLenum target, GLuint index, GLfloat *data); +GL_APICALL void GL_APIENTRY glEnableiNV (GLenum target, GLuint index); +GL_APICALL void GL_APIENTRY glDisableiNV (GLenum target, GLuint index); +GL_APICALL GLboolean GL_APIENTRY glIsEnablediNV (GLenum target, GLuint index); #endif +#endif /* GL_NV_viewport_array */ -/*------------------------------------------------------------------------* - * QCOM extension functions - *------------------------------------------------------------------------*/ +#ifndef GL_NV_viewport_array2 +#define GL_NV_viewport_array2 1 +#endif /* GL_NV_viewport_array2 */ + +#ifndef GL_OVR_multiview +#define GL_OVR_multiview 1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632 +#define GL_MAX_VIEWS_OVR 0x9631 +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +#endif +#endif /* GL_OVR_multiview */ + +#ifndef GL_OVR_multiview2 +#define GL_OVR_multiview2 1 +#endif /* GL_OVR_multiview2 */ + +#ifndef GL_OVR_multiview_multisampled_render_to_texture +#define GL_OVR_multiview_multisampled_render_to_texture 1 +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews); +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glFramebufferTextureMultisampleMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews); +#endif +#endif /* GL_OVR_multiview_multisampled_render_to_texture */ -/* GL_QCOM_alpha_test */ #ifndef GL_QCOM_alpha_test #define GL_QCOM_alpha_test 1 +#define GL_ALPHA_TEST_QCOM 0x0BC0 +#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 +#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 +typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref); #endif -typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); -#endif +#endif /* GL_QCOM_alpha_test */ -/* GL_QCOM_binning_control */ #ifndef GL_QCOM_binning_control #define GL_QCOM_binning_control 1 -#endif +#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0 +#define GL_CPU_OPTIMIZED_QCOM 0x8FB1 +#define GL_GPU_OPTIMIZED_QCOM 0x8FB2 +#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3 +#endif /* GL_QCOM_binning_control */ -/* GL_QCOM_driver_control */ #ifndef GL_QCOM_driver_control #define GL_QCOM_driver_control 1 +typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls); +typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString); +typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); +typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls); GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString); GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl); GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl); #endif -typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls); -typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString); -typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); -typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); -#endif +#endif /* GL_QCOM_driver_control */ -/* GL_QCOM_extended_get */ #ifndef GL_QCOM_extended_get #define GL_QCOM_extended_get 1 +#define GL_TEXTURE_WIDTH_QCOM 0x8BD2 +#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3 +#define GL_TEXTURE_DEPTH_QCOM 0x8BD4 +#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5 +#define GL_TEXTURE_FORMAT_QCOM 0x8BD6 +#define GL_TEXTURE_TYPE_QCOM 0x8BD7 +#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8 +#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9 +#define GL_TEXTURE_TARGET_QCOM 0x8BDA +#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB +#define GL_STATE_RESTORE 0x8BDC +typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures); +typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers); +typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers); +typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers); +typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels); +typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, void **params); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures); GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers); @@ -1744,66 +2837,84 @@ GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GL GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers); GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params); GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels); -GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params); -#endif -typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures); -typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers); -typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers); -typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers); -typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param); -typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels); -typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params); +GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels); +GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, void **params); #endif +#endif /* GL_QCOM_extended_get */ -/* GL_QCOM_extended_get2 */ #ifndef GL_QCOM_extended_get2 #define GL_QCOM_extended_get2 1 +typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders); +typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms); +typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders); GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms); GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program); GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length); #endif -typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders); -typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms); -typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program); -typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length); -#endif +#endif /* GL_QCOM_extended_get2 */ -/* GL_QCOM_perfmon_global_mode */ #ifndef GL_QCOM_perfmon_global_mode #define GL_QCOM_perfmon_global_mode 1 -#endif +#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0 +#endif /* GL_QCOM_perfmon_global_mode */ -/* GL_QCOM_writeonly_rendering */ -#ifndef GL_QCOM_writeonly_rendering -#define GL_QCOM_writeonly_rendering 1 -#endif - -/* GL_QCOM_tiled_rendering */ #ifndef GL_QCOM_tiled_rendering #define GL_QCOM_tiled_rendering 1 +#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001 +#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002 +#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004 +#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008 +#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010 +#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020 +#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040 +#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080 +#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100 +#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200 +#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400 +#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800 +#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000 +#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000 +#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000 +#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000 +#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000 +#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000 +#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000 +#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000 +#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000 +#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000 +#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000 +#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000 +#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000 +#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000 +#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000 +#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000 +#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000 +#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000 +#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000 +#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000 +typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); +typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask); #ifdef GL_GLEXT_PROTOTYPES GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask); #endif -typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); -typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask); -#endif +#endif /* GL_QCOM_tiled_rendering */ -/*------------------------------------------------------------------------* - * VIV extension tokens - *------------------------------------------------------------------------*/ +#ifndef GL_QCOM_writeonly_rendering +#define GL_QCOM_writeonly_rendering 1 +#define GL_WRITEONLY_RENDERING_QCOM 0x8823 +#endif /* GL_QCOM_writeonly_rendering */ -/* GL_VIV_shader_binary */ #ifndef GL_VIV_shader_binary #define GL_VIV_shader_binary 1 -#endif +#define GL_SHADER_BINARY_VIV 0x8FC4 +#endif /* GL_VIV_shader_binary */ #ifdef __cplusplus } #endif -#endif /* __gl2ext_h_ */ +#endif diff --git a/panda/src/glesgsg/glesgsg.h b/panda/src/glesgsg/glesgsg.h index 40b4722b22..416e5737cb 100644 --- a/panda/src/glesgsg/glesgsg.h +++ b/panda/src/glesgsg/glesgsg.h @@ -73,6 +73,7 @@ #define GL_RENDERBUFFER_ALPHA_SIZE_EXT GL_RENDERBUFFER_ALPHA_SIZE_OES #define GL_RENDERBUFFER_DEPTH_SIZE_EXT GL_RENDERBUFFER_DEPTH_SIZE_OES #define GL_RENDERBUFFER_STENCIL_SIZE_EXT GL_RENDERBUFFER_STENCIL_SIZE_OES +#define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES #define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER_OES #define GL_DRAW_FRAMEBUFFER_EXT GL_FRAMEBUFFER_OES #define GL_READ_FRAMEBUFFER_EXT GL_FRAMEBUFFER_OES @@ -119,6 +120,17 @@ #define GL_LUMINANCE8 GL_LUMINANCE8_EXT #define GL_LUMINANCE8_ALPHA8 GL_LUMINANCE8_ALPHA8_EXT #define GL_MAX_VERTEX_UNITS_ARB GL_MAX_VERTEX_UNITS_OES +#define GL_TEXTURE_MAX_LEVEL GL_TEXTURE_MAX_LEVEL_APPLE + +// These aren't technically part of OpenGL ES 1.0, but some implementations +// nonetheless implement it. +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_OUTPUT 0x92E0 #undef SUPPORT_IMMEDIATE_MODE #define APIENTRY diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index b750233520..7e055364e4 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -252,7 +252,7 @@ begin_frame(FrameMode mode, Thread *current_thread) { // In case of multisample rendering, we don't need to issue the barrier // until we call glBlitFramebuffer. -#ifndef OPENGLES +#ifndef OPENGLES_1 if (gl_enable_memory_barriers && _fbo_multisample == 0) { CLP(GraphicsStateGuardian) *glgsg; DCAST_INTO_R(glgsg, _gsg, false); @@ -526,7 +526,6 @@ rebuild_bitplanes() { } glgsg->bind_fbo(_fbo[layer]); -#ifndef OPENGLES if (glgsg->_use_object_labels) { // Assign a label for OpenGL to use when displaying debug messages. if (num_fbos > 1) { @@ -538,7 +537,6 @@ rebuild_bitplanes() { glgsg->_glObjectLabel(GL_FRAMEBUFFER, _fbo[layer], _name.size(), _name.data()); } } -#endif // For all slots, update the slot. if (_use_depth_stencil) { @@ -591,7 +589,7 @@ rebuild_bitplanes() { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } -#ifndef OPENGLES +#ifndef OPENGLES_1 } else if (glgsg->_supports_empty_framebuffer) { // Set the "default" width and height, which is required to have an FBO // without any attachments. @@ -751,12 +749,10 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, _fb_properties.setup_color_texture(tex); } -#ifndef OPENGLES GLenum target = glgsg->get_texture_target(tex->get_texture_type()); if (target == GL_TEXTURE_CUBE_MAP) { target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; } -#endif if (attachpoint == GL_DEPTH_ATTACHMENT_EXT) { GLCAT.debug() << "Binding texture " << *tex << " to depth attachment.\n"; @@ -815,7 +811,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, GLuint gl_format = GL_RGBA4; switch (slot) { case RTP_depth_stencil: - gl_format = GL_DEPTH_STENCIL_OES; + gl_format = GL_DEPTH24_STENCIL8_OES; break; case RTP_depth: if (_fb_properties.get_depth_bits() > 24 && glgsg->_supports_depth32) { @@ -906,7 +902,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, } } else { if (_fb_properties.get_color_bits() > 16 * 3) { - gl_format = GL_RGBA32F_ARB; + gl_format = GL_RGB32F_ARB; } else if (_fb_properties.get_color_bits() > 8 * 3) { gl_format = GL_RGB16_EXT; } else { @@ -924,11 +920,11 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, } } else { if (_fb_properties.get_color_bits() > 16 * 3) { - gl_format = GL_RGB32F_ARB; + gl_format = GL_RGBA32F_ARB; } else if (_fb_properties.get_color_bits() > 8 * 3) { - gl_format = GL_RGB16_EXT; + gl_format = GL_RGBA16_EXT; } else { - gl_format = GL_RGB; + gl_format = GL_RGBA; } } } @@ -1094,7 +1090,6 @@ bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane slot, GL_RENDERBUFFER_EXT, _rbm[slot]); } } else { - Texture *Tex = attach[slot]; GLuint gl_format = GL_RGBA; #ifndef OPENGLES switch (slot) { @@ -1191,9 +1186,7 @@ attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) { glgsg->_glFramebufferTexture3D(GL_FRAMEBUFFER_EXT, attachpoint, target, gtc->_index, 0, layer); break; -#endif -#ifndef OPENGLES - case GL_TEXTURE_2D_ARRAY_EXT: + case GL_TEXTURE_2D_ARRAY: glgsg->_glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, attachpoint, gtc->_index, 0, layer); break; @@ -1729,7 +1722,7 @@ resolve_multisamples() { PStatGPUTimer timer(glgsg, _resolve_multisample_pcollector); -#ifndef OPENGLES +#ifndef OPENGLES_1 if (gl_enable_memory_barriers) { // Issue memory barriers as necessary to make sure that the texture memory // is synchronized before we blit to it. diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.I b/panda/src/glstuff/glGraphicsStateGuardian_src.I index a1fa34dd4a..221aff21b9 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.I +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.I @@ -189,6 +189,8 @@ INLINE bool CLP(GraphicsStateGuardian):: is_at_least_gles_version(int major_version, int minor_version) const { #ifndef OPENGLES return false; +#elif defined(OPENGLES_1) + return major_version == 1 && _gl_version_minor >= minor_version; #else if (_gl_version_major < major_version) { return false; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index ad15b7d210..f078ce0d8b 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -97,8 +97,8 @@ static void APIENTRY null_glPointParameterfv(GLenum, const GLfloat *) { } -#ifdef OPENGLES -// OpenGL ES doesn't support this, period. Might as well macro it. +#ifdef OPENGLES_1 +// OpenGL ES 1 doesn't support this, period. Might as well macro it. #define _glDrawRangeElements(mode, start, end, count, type, indices) \ glDrawElements(mode, count, type, indices) @@ -127,13 +127,25 @@ null_glActiveTexture(GLenum gl_texture_stage) { nassertv(gl_texture_stage == GL_TEXTURE0); } +#ifdef OPENGLES_2 +#define _glBlendEquation glBlendEquation +#define _glBlendEquationSeparate glBlendEquationSeparate +#define _glBlendFuncSeparate glBlendFuncSeparate +#define _glBlendColor glBlendColor +#else static void APIENTRY null_glBlendEquation(GLenum) { } +static void APIENTRY +null_glBlendFuncSeparate(GLenum src, GLenum dest, GLenum, GLenum) { + glBlendFunc(src, dest); +} + static void APIENTRY null_glBlendColor(GLclampf, GLclampf, GLclampf, GLclampf) { } +#endif #ifndef OPENGLES_1 // We have a default shader that will be applied when there isn't any shader @@ -186,7 +198,7 @@ static const string default_fshader = " p3d_FragColor += p3d_TexAlphaOnly;\n" // Hack for text rendering " p3d_FragColor *= color;\n" #else - " gl_FragColor = texture2D(p3d_Texture0, texcoord).bgra;\n" + " gl_FragColor = texture2D(p3d_Texture0, texcoord);\n" " gl_FragColor += p3d_TexAlphaOnly;\n" // Hack for text rendering " gl_FragColor *= color;\n" #endif @@ -404,7 +416,6 @@ CLP(GraphicsStateGuardian):: * This is called by the GL if an error occurs, if gl_debug has been enabled * (and the driver supports the GL_ARB_debug_output extension). */ -#ifndef OPENGLES_1 void CLP(GraphicsStateGuardian):: debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam) { // Determine how to map the severity level. @@ -445,7 +456,6 @@ debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei l } #endif } -#endif // OPENGLES_1 /** * Resets all internal state as if the gsg were newly created. @@ -498,9 +508,9 @@ reset() { // Save the extensions tokens. _extensions.clear(); - // In OpenGL 3.0 and later, glGetString(GL_EXTENSIONS) is deprecated. -#ifndef OPENGLES - if (is_at_least_gl_version(3, 0)) { + // In OpenGL (ES) 3.0 and later, glGetString(GL_EXTENSIONS) is deprecated. +#ifndef OPENGLES_1 + if (_gl_version_major >= 3) { PFNGLGETSTRINGIPROC _glGetStringi = (PFNGLGETSTRINGIPROC)get_extension_func("glGetStringi"); @@ -549,7 +559,6 @@ reset() { // Initialize OpenGL debugging output first, if enabled and supported. _supports_debug = false; _use_object_labels = false; -#ifndef OPENGLES_1 if (gl_debug) { PFNGLDEBUGMESSAGECALLBACKPROC_P _glDebugMessageCallback; PFNGLDEBUGMESSAGECONTROLPROC _glDebugMessageControl; @@ -617,7 +626,6 @@ reset() { GLCAT.debug() << "gl-debug disabled and unsupported.\n"; } } -#endif // OPENGLES_1 _supported_geom_rendering = Geom::GR_indexed_point | @@ -629,7 +637,11 @@ reset() { _supports_point_parameters = false; -#ifndef OPENGLES_2 +#ifdef OPENGLES_1 + _glPointParameterfv = glPointParameterfv; +#elif defined(OPENGLES) + // Other OpenGL ES versions don't support point parameters. +#else if (is_at_least_gl_version(1, 4)) { _supports_point_parameters = true; _glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) @@ -671,7 +683,16 @@ reset() { _supported_geom_rendering |= Geom::GR_point_sprite; } -#ifndef OPENGLES +#ifdef OPENGLES_1 + // OpenGL ES 1.0 does not support primitive restart indices. + +#elif defined(OPENGLES) + if (gl_support_primitive_restart_index && is_at_least_gles_version(3, 0)) { + glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); + _supported_geom_rendering |= Geom::GR_strip_cut_index; + } + +#else _explicit_primitive_restart = false; _glPrimitiveRestartIndex = NULL; @@ -682,7 +703,7 @@ reset() { // possible index for a numeric type as strip cut index, which coincides // with our convention. This saves us a call to glPrimitiveRestartIndex // ... of course, though, the Gallium driver bugs out here. See also: - // https:www.panda3d.orgforumsviewtopic.php?f=5&t=17512 + // https://www.panda3d.org/forums/viewtopic.php?f=5&t=17512 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); _supported_geom_rendering |= Geom::GR_strip_cut_index; @@ -709,9 +730,15 @@ reset() { } #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 _glDrawRangeElements = null_glDrawRangeElements; +#ifdef OPENGLES + if (is_at_least_gles_version(3, 0)) { + _glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) + get_extension_func("glDrawRangeElements"); + } +#else if (is_at_least_gl_version(1, 2)) { _glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) get_extension_func("glDrawRangeElements"); @@ -720,17 +747,18 @@ reset() { _glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) get_extension_func("glDrawRangeElementsEXT"); } +#endif if (_glDrawRangeElements == NULL) { GLCAT.warning() << "glDrawRangeElements advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n"; _glDrawRangeElements = null_glDrawRangeElements; } -#endif +#endif // !OPENGLES_1 _supports_3d_texture = false; #ifndef OPENGLES_1 - if (is_at_least_gl_version(1, 2)) { + if (is_at_least_gl_version(1, 2) || is_at_least_gles_version(3, 0)) { _supports_3d_texture = true; _glTexImage3D = (PFNGLTEXIMAGE3DPROC_P) @@ -740,6 +768,7 @@ reset() { _glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) get_extension_func("glCopyTexSubImage3D"); +#ifndef OPENGLES } else if (has_extension("GL_EXT_texture3D")) { _supports_3d_texture = true; @@ -753,7 +782,7 @@ reset() { _glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) get_extension_func("glCopyTexSubImage3DEXT"); } - +#else } else if (has_extension("GL_OES_texture_3D")) { _supports_3d_texture = true; @@ -763,8 +792,6 @@ reset() { get_extension_func("glTexSubImage3DOES"); _glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) get_extension_func("glCopyTexSubImage3DOES"); - -#ifdef OPENGLES_2 _glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DOES) get_extension_func("glFramebufferTexture3DOES"); #endif @@ -781,8 +808,11 @@ reset() { _supports_tex_storage = false; -#ifndef OPENGLES +#ifdef OPENGLES + if (is_at_least_gles_version(3, 0)) { +#else if (is_at_least_gl_version(4, 2) || has_extension("GL_ARB_texture_storage")) { +#endif _supports_tex_storage = true; _glTexStorage1D = (PFNGLTEXSTORAGE1DPROC) @@ -791,10 +821,9 @@ reset() { get_extension_func("glTexStorage2D"); _glTexStorage3D = (PFNGLTEXSTORAGE3DPROC) get_extension_func("glTexStorage3D"); - - } else -#endif - if (has_extension("GL_EXT_texture_storage")) { // GLES case + } +#ifdef OPENGLES + else if (has_extension("GL_EXT_texture_storage")) { _supports_tex_storage = true; _glTexStorage1D = (PFNGLTEXSTORAGE1DPROC) @@ -804,6 +833,7 @@ reset() { _glTexStorage3D = (PFNGLTEXSTORAGE3DPROC) get_extension_func("glTexStorage3DEXT"); } +#endif if (_supports_tex_storage) { if (_glTexStorage1D == NULL || _glTexStorage2D == NULL || _glTexStorage3D == NULL) { @@ -844,25 +874,27 @@ reset() { #endif _supports_2d_texture_array = false; -#ifndef OPENGLES - if (is_at_least_gl_version(3, 0)) { +#ifndef OPENGLES_1 + if (_gl_version_major >= 3) { _supports_2d_texture_array = true; _glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) get_extension_func("glFramebufferTextureLayer"); +#ifndef OPENGLES } else if (has_extension("GL_EXT_texture_array")) { _supports_2d_texture_array = true; _glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) get_extension_func("glFramebufferTextureLayerEXT"); +#endif } if (_supports_2d_texture_array && _glFramebufferTextureLayer == NULL) { GLCAT.warning() << "Texture arrays advertised as supported by OpenGL runtime, but could not get pointer to glFramebufferTextureLayer function.\n"; } -#endif +#endif // !OPENGLES_1 #ifdef OPENGLES_2 _supports_cube_map = true; @@ -897,13 +929,13 @@ reset() { } #endif - _supports_texture_srgb = false; - if (is_at_least_gl_version(2, 1) || has_extension("GL_EXT_texture_sRGB")) { - _supports_texture_srgb = true; - - } else if (has_extension("GL_EXT_sRGB")) { // GLES case. - _supports_texture_srgb = true; - } +#ifdef OPENGLES + _supports_texture_srgb = + is_at_least_gles_version(3, 0) || has_extension("GL_EXT_sRGB"); +#else + _supports_texture_srgb = + is_at_least_gl_version(2, 1) || has_extension("GL_EXT_texture_sRGB"); +#endif #ifdef OPENGLES _supports_compressed_texture = true; @@ -1037,23 +1069,30 @@ reset() { #endif } -#ifdef OPENGLES_2 - _supports_bgr = false; +#ifdef OPENGLES + // Note that these extensions only offer support for GL_BGRA, not GL_BGR. + _supports_bgr = has_extension("GL_EXT_texture_format_BGRA8888") || + has_extension("GL_APPLE_texture_format_BGRA8888"); #else + // In regular OpenGL, we have both GL_BGRA and GL_BGR. _supports_bgr = is_at_least_gl_version(1, 2) || has_extension("GL_EXT_bgra"); #endif #ifdef SUPPORT_FIXED_FUNCTION +#ifdef OPENGLES_1 + _supports_rescale_normal = true; +#else _supports_rescale_normal = !core_profile && gl_support_rescale_normal && (is_at_least_gl_version(1, 2) || has_extension("GL_EXT_rescale_normal")); +#endif #ifndef OPENGLES _use_separate_specular_color = gl_separate_specular_color && (is_at_least_gl_version(1, 2) || has_extension("GL_EXT_separate_specular_color")); #endif -#endif +#endif // SUPPORT_FIXED_FUNCTION #ifdef OPENGLES _supports_packed_dabc = false; @@ -1066,8 +1105,13 @@ reset() { has_extension("GL_ARB_vertex_type_10f_11f_11f_rev"); #endif +#ifdef OPENGLES + //TODO + _supports_multisample = false; +#else _supports_multisample = has_extension("GL_ARB_multisample") || is_at_least_gl_version(1, 3); +#endif #ifdef OPENGLES_1 _supports_generate_mipmap = is_at_least_gles_version(1, 1); @@ -1078,8 +1122,10 @@ reset() { has_extension("GL_SGIS_generate_mipmap"); #endif -#ifdef OPENGLES - _supports_tex_non_pow2 = +#ifdef OPENGLES_1 + _supports_tex_non_pow2 = false; +#elif defined(OPENGLES) + _supports_tex_non_pow2 = is_at_least_gles_version(3, 0) || has_extension("GL_OES_texture_npot"); #else _supports_tex_non_pow2 = is_at_least_gl_version(2, 0) || @@ -1179,19 +1225,31 @@ reset() { #endif #endif // OPENGLES_2 -#ifdef OPENGLES - if (has_extension("GL_ANGLE_depth_texture")) { - // This extension provides both depth textures and depth-stencil support. - _supports_depth_texture = true; - _supports_depth_stencil = true; - - } else if (has_extension("GL_OES_depth_texture")) { - _supports_depth_texture = true; - _supports_depth_stencil = has_extension("GL_OES_packed_depth_stencil"); - } +#ifdef OPENGLES_1 + _supports_depth_texture = false; + _supports_depth_stencil = has_extension("GL_OES_packed_depth_stencil"); _supports_depth24 = has_extension("GL_OES_depth24"); _supports_depth32 = has_extension("GL_OES_depth32"); +#elif defined(OPENGLES) + if (is_at_least_gles_version(3, 0)) { + _supports_depth_texture = true; + _supports_depth_stencil = true; + _supports_depth24 = true; + _supports_depth32 = true; + } else { + if (has_extension("GL_ANGLE_depth_texture")) { + // This extension provides both depth textures and depth-stencil support. + _supports_depth_texture = true; + _supports_depth_stencil = true; + + } else if (has_extension("GL_OES_depth_texture")) { + _supports_depth_texture = true; + _supports_depth_stencil = has_extension("GL_OES_packed_depth_stencil"); + } + _supports_depth24 = has_extension("GL_OES_depth24"); + _supports_depth32 = has_extension("GL_OES_depth32"); + } #else _supports_depth_texture = (is_at_least_gl_version(1, 4) || has_extension("GL_ARB_depth_texture")); @@ -1202,7 +1260,7 @@ reset() { #ifdef OPENGLES_2 if (gl_support_shadow_filter && _supports_depth_texture && - has_extension("GL_EXT_shadow_samplers")) { + (is_at_least_gles_version(3, 0) || has_extension("GL_EXT_shadow_samplers"))) { _supports_shadow_filter = true; } #else @@ -1232,17 +1290,21 @@ reset() { is_at_least_gles_version(1, 1) || has_extension("GL_ARB_texture_env_combine"); +#ifdef OPENGLES_1 + _supports_texture_saved_result = + has_extension("GL_OES_texture_env_crossbar"); +#else _supports_texture_saved_result = is_at_least_gl_version(1, 4) || - has_extension("GL_ARB_texture_env_crossbar") || - has_extension("GL_OES_texture_env_crossbar"); + has_extension("GL_ARB_texture_env_crossbar"); +#endif _supports_texture_dot3 = is_at_least_gl_version(1, 3) || is_at_least_gles_version(1, 1) || has_extension("GL_ARB_texture_env_dot3"); } -#endif +#endif // SUPPORT_FIXED_FUNCTION #ifdef OPENGLES_2 _supports_buffers = true; @@ -1307,7 +1369,19 @@ reset() { } #endif -#ifndef OPENGLES +#ifdef OPENGLES + if (is_at_least_gles_version(3, 0)) { + _glMapBufferRange = (PFNGLMAPBUFFERRANGEEXTPROC) + get_extension_func("glMapBufferRange"); + + } else if (has_extension("GL_EXT_map_buffer_range")) { + _glMapBufferRange = (PFNGLMAPBUFFERRANGEEXTPROC) + get_extension_func("glMapBufferRangeEXT"); + + } else { + _glMapBufferRange = NULL; + } +#else // Check for various advanced buffer management features. if (is_at_least_gl_version(3, 0) || has_extension("GL_ARB_map_buffer_range")) { _glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) @@ -1334,7 +1408,11 @@ reset() { _supports_vao = false; +#ifdef OPENGLES + if (is_at_least_gles_version(3, 0)) { +#else if (is_at_least_gl_version(3, 0) || has_extension("GL_ARB_vertex_array_object")) { +#endif _supports_vao = true; _glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) @@ -1344,6 +1422,7 @@ reset() { _glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) get_extension_func("glGenVertexArrays"); +#ifdef OPENGLES } else if (has_extension("GL_OES_vertex_array_object")) { _supports_vao = true; @@ -1353,6 +1432,7 @@ reset() { get_extension_func("glDeleteVertexArraysOES"); _glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) get_extension_func("glGenVertexArraysOES"); +#endif } if (_supports_vao) { @@ -1476,8 +1556,12 @@ reset() { #endif // HAVE_CG _supports_compute_shaders = false; -#ifndef OPENGLES +#ifndef OPENGLES_1 +#ifdef OPENGLES + if (is_at_least_gles_version(3, 1)) { +#else if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_compute_shader")) { +#endif _glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC) get_extension_func("glDispatchCompute"); @@ -1485,7 +1569,7 @@ reset() { _supports_compute_shaders = true; } } -#endif +#endif // !OPENGLES_1 #ifndef OPENGLES if (_supports_glsl) { @@ -1635,26 +1719,39 @@ reset() { _glVertexAttrib4fv = glVertexAttrib4fv; _glVertexAttrib4dv = null_glVertexAttrib4dv; _glVertexAttribPointer = glVertexAttribPointer; - _glVertexAttribIPointer = NULL; _glVertexAttribLPointer = NULL; + + if (is_at_least_gles_version(3, 0)) { + _glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) + get_extension_func("glVertexAttribIPointer"); + } else { + _glVertexAttribIPointer = NULL; + } #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 _use_vertex_attrib_binding = false; +#ifdef OPENGLES + if (is_at_least_gles_version(3, 1)) { +#else if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_vertex_attrib_binding")) { +#endif _glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC) get_extension_func("glBindVertexBuffer"); _glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC) get_extension_func("glVertexAttribFormat"); _glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC) get_extension_func("glVertexAttribIFormat"); - _glVertexAttribLFormat = (PFNGLVERTEXATTRIBLFORMATPROC) - get_extension_func("glVertexAttribLFormat"); _glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC) get_extension_func("glVertexAttribBinding"); _glVertexBindingDivisor = (PFNGLVERTEXBINDINGDIVISORPROC) get_extension_func("glVertexBindingDivisor"); +#ifndef OPENGLES + _glVertexAttribLFormat = (PFNGLVERTEXATTRIBLFORMATPROC) + get_extension_func("glVertexAttribLFormat"); +#endif + if (gl_fixed_vertex_attrib_locations) { _use_vertex_attrib_binding = true; } @@ -1676,7 +1773,11 @@ reset() { #ifndef OPENGLES // Check for uniform buffers. +#ifdef OPENGLES if (is_at_least_gl_version(3, 1) || has_extension("GL_ARB_uniform_buffer_object")) { +#else + if (is_at_least_gles_version(3, 0)) { +#endif _supports_uniform_buffers = true; _glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) get_extension_func("glGetActiveUniformsiv"); @@ -1698,8 +1799,20 @@ reset() { _supports_vertex_attrib_divisor = false; _supports_geometry_instancing = false; -#elif defined(OPENGLES_2) - if (has_extension("GL_ANGLE_instanced_arrays")) { +#elif defined(OPENGLES) + if (is_at_least_gles_version(3, 0)) { + // OpenGL ES 3 has all of this in the core. + _glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) + get_extension_func("glVertexAttribDivisor"); + _glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) + get_extension_func("glDrawArraysInstanced"); + _glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) + get_extension_func("glDrawElementsInstanced"); + + _supports_vertex_attrib_divisor = true; + _supports_geometry_instancing = true; + + } else if (has_extension("GL_ANGLE_instanced_arrays")) { // This extension has both things in one. #ifdef __EMSCRIPTEN__ // Work around bug - it doesn't allow ANGLE suffix in getProcAddress. @@ -1821,8 +1934,12 @@ reset() { // Check if we support indirect draw. _supports_indirect_draw = false; -#ifndef OPENGLES +#ifndef OPENGLES_1 +#ifdef OPENGLES + if (is_at_least_gles_version(3, 1)) { +#else if (is_at_least_gl_version(4, 0) || has_extension("GL_ARB_draw_indirect")) { +#endif _glDrawArraysIndirect = (PFNGLDRAWARRAYSINDIRECTPROC) get_extension_func("glDrawArraysIndirect"); _glDrawElementsIndirect = (PFNGLDRAWELEMENTSINDIRECTPROC) @@ -1837,7 +1954,48 @@ reset() { } #endif -#ifdef OPENGLES_2 +#ifdef OPENGLES_1 + _supports_framebuffer_multisample = false; + _supports_framebuffer_blit = false; + + if (has_extension("GL_OES_framebuffer_object")) { + _supports_framebuffer_object = true; + _glIsRenderbuffer = (PFNGLISRENDERBUFFEROESPROC) + get_extension_func("glIsRenderbufferOES"); + _glBindRenderbuffer = (PFNGLBINDRENDERBUFFEROESPROC) + get_extension_func("glBindRenderbufferOES"); + _glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSOESPROC) + get_extension_func("glDeleteRenderbuffersOES"); + _glGenRenderbuffers = (PFNGLGENRENDERBUFFERSOESPROC) + get_extension_func("glGenRenderbuffersOES"); + _glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEOESPROC) + get_extension_func("glRenderbufferStorageOES"); + _glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVOESPROC) + get_extension_func("glGetRenderbufferParameterivOES"); + _glIsFramebuffer = (PFNGLISFRAMEBUFFEROESPROC) + get_extension_func("glIsFramebufferOES"); + _glBindFramebuffer = (PFNGLBINDFRAMEBUFFEROESPROC) + get_extension_func("glBindFramebufferOES"); + _glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSOESPROC) + get_extension_func("glDeleteFramebuffersOES"); + _glGenFramebuffers = (PFNGLGENFRAMEBUFFERSOESPROC) + get_extension_func("glGenFramebuffersOES"); + _glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSOESPROC) + get_extension_func("glCheckFramebufferStatusOES"); + _glFramebufferTexture1D = NULL; + _glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DOESPROC) + get_extension_func("glFramebufferTexture2DOES"); + _glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEROESPROC) + get_extension_func("glFramebufferRenderbufferOES"); + _glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC) + get_extension_func("glGetFramebufferAttachmentParameterivOES"); + _glGenerateMipmap = (PFNGLGENERATEMIPMAPOESPROC) + get_extension_func("glGenerateMipmapOES"); + } else { + _supports_framebuffer_object = false; + _glGenerateMipmap = NULL; + } +#elif defined(OPENGLES) // In OpenGL ES 2.x, FBO's are supported in the core. _supports_framebuffer_object = true; _glIsRenderbuffer = glIsRenderbuffer; @@ -1856,14 +2014,77 @@ reset() { _glFramebufferRenderbuffer = glFramebufferRenderbuffer; _glGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv; _glGenerateMipmap = glGenerateMipmap; -#else - // Make sure this is properly initialized. - _glGenerateMipmap = NULL; - // TODO: add ARB3.0 version + if (is_at_least_gles_version(3, 0)) { + _supports_framebuffer_multisample = true; + _supports_framebuffer_blit = true; - _supports_framebuffer_object = false; - if (has_extension("GL_EXT_framebuffer_object")) { + _glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) + get_extension_func("glRenderbufferStorageMultisample"); + _glBlitFramebuffer = (PFNGLBLITFRAMEBUFFEREXTPROC) + get_extension_func("glBlitFramebuffer"); + } else { + if (has_extension("GL_ANGLE_framebuffer_multisample")) { + _supports_framebuffer_multisample = true; + _glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) + get_extension_func("glRenderbufferStorageMultisampleANGLE"); + } else { + _supports_framebuffer_multisample = false; + } + if (has_extension("GL_ANGLE_framebuffer_blit")) { + _supports_framebuffer_blit = true; + _glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERANGLEPROC) + get_extension_func("glBlitFramebufferANGLE"); + } else { + _supports_framebuffer_blit = false; + } + } +#else // Desktop OpenGL case. + if (is_at_least_gl_version(3, 0) || has_extension("GL_ARB_framebuffer_object")) { + _supports_framebuffer_object = true; + _supports_framebuffer_multisample = true; + _supports_framebuffer_blit = true; + + _glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) + get_extension_func("glIsRenderbuffer"); + _glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) + get_extension_func("glBindRenderbuffer"); + _glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) + get_extension_func("glDeleteRenderbuffers"); + _glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) + get_extension_func("glGenRenderbuffers"); + _glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) + get_extension_func("glRenderbufferStorage"); + _glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) + get_extension_func("glGetRenderbufferParameteriv"); + _glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) + get_extension_func("glIsFramebuffer"); + _glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) + get_extension_func("glBindFramebuffer"); + _glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) + get_extension_func("glDeleteFramebuffers"); + _glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) + get_extension_func("glGenFramebuffers"); + _glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) + get_extension_func("glCheckFramebufferStatus"); + _glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) + get_extension_func("glFramebufferTexture1D"); + _glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) + get_extension_func("glFramebufferTexture2D"); + _glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) + get_extension_func("glFramebufferTexture3D"); + _glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) + get_extension_func("glFramebufferRenderbuffer"); + _glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) + get_extension_func("glGetFramebufferAttachmentParameteriv"); + _glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) + get_extension_func("glGenerateMipmap"); + _glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) + get_extension_func("glRenderbufferStorageMultisampleEXT"); + _glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) + get_extension_func("glBlitFramebuffer"); + + } else if (has_extension("GL_EXT_framebuffer_object")) { _supports_framebuffer_object = true; _glIsRenderbuffer = (PFNGLISRENDERBUFFEREXTPROC) get_extension_func("glIsRenderbufferEXT"); @@ -1899,43 +2120,28 @@ reset() { get_extension_func("glGetFramebufferAttachmentParameterivEXT"); _glGenerateMipmap = (PFNGLGENERATEMIPMAPEXTPROC) get_extension_func("glGenerateMipmapEXT"); + + if (has_extension("GL_EXT_framebuffer_multisample")) { + _supports_framebuffer_multisample = true; + _glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) + get_extension_func("glRenderbufferStorageMultisampleEXT"); + } else { + _supports_framebuffer_multisample = false; + } + if (has_extension("GL_EXT_framebuffer_blit")) { + _supports_framebuffer_blit = true; + _glBlitFramebuffer = (PFNGLBLITFRAMEBUFFEREXTPROC) + get_extension_func("glBlitFramebufferEXT"); + } else { + _supports_framebuffer_blit = false; + } + + } else { + _supports_framebuffer_object = false; + _supports_framebuffer_multisample = false; + _supports_framebuffer_blit = false; + _glGenerateMipmap = NULL; } -#ifdef OPENGLES - else if (has_extension("GL_OES_framebuffer_object")) { - _supports_framebuffer_object = true; - _glIsRenderbuffer = (PFNGLISRENDERBUFFEROESPROC) - get_extension_func("glIsRenderbufferOES"); - _glBindRenderbuffer = (PFNGLBINDRENDERBUFFEROESPROC) - get_extension_func("glBindRenderbufferOES"); - _glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSOESPROC) - get_extension_func("glDeleteRenderbuffersOES"); - _glGenRenderbuffers = (PFNGLGENRENDERBUFFERSOESPROC) - get_extension_func("glGenRenderbuffersOES"); - _glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEOESPROC) - get_extension_func("glRenderbufferStorageOES"); - _glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVOESPROC) - get_extension_func("glGetRenderbufferParameterivOES"); - _glIsFramebuffer = (PFNGLISFRAMEBUFFEROESPROC) - get_extension_func("glIsFramebufferOES"); - _glBindFramebuffer = (PFNGLBINDFRAMEBUFFEROESPROC) - get_extension_func("glBindFramebufferOES"); - _glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSOESPROC) - get_extension_func("glDeleteFramebuffersOES"); - _glGenFramebuffers = (PFNGLGENFRAMEBUFFERSOESPROC) - get_extension_func("glGenFramebuffersOES"); - _glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSOESPROC) - get_extension_func("glCheckFramebufferStatusOES"); - _glFramebufferTexture1D = NULL; - _glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DOESPROC) - get_extension_func("glFramebufferTexture2DOES"); - _glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEROESPROC) - get_extension_func("glFramebufferRenderbufferOES"); - _glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC) - get_extension_func("glGetFramebufferAttachmentParameterivOES"); - _glGenerateMipmap = (PFNGLGENERATEMIPMAPOESPROC) - get_extension_func("glGenerateMipmapOES"); - } -#endif // OPENGLES #endif #ifndef OPENGLES @@ -1947,47 +2153,41 @@ reset() { } #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 + // Do we support empty framebuffer objects? +#ifdef OPENGLES + if (is_at_least_gles_version(3, 1)) { +#else if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_framebuffer_no_attachments")) { +#endif _glFramebufferParameteri = (PFNGLFRAMEBUFFERPARAMETERIPROC) get_extension_func("glFramebufferParameteri"); _supports_empty_framebuffer = true; } else { _supports_empty_framebuffer = false; } -#endif - - _supports_framebuffer_multisample = false; - if (has_extension("GL_EXT_framebuffer_multisample")) { - _supports_framebuffer_multisample = true; - _glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) - get_extension_func("glRenderbufferStorageMultisampleEXT"); - } +#endif // !OPENGLES_1 #ifndef OPENGLES _supports_framebuffer_multisample_coverage_nv = false; - if (has_extension("GL_NV_framebuffer_multisample_coverage")) { + if (_supports_framebuffer_multisample && + has_extension("GL_NV_framebuffer_multisample_coverage")) { _supports_framebuffer_multisample_coverage_nv = true; _glRenderbufferStorageMultisampleCoverage = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) get_extension_func("glRenderbufferStorageMultisampleCoverageNV"); } #endif -#ifndef OPENGLES_1 - _supports_framebuffer_blit = false; - if (has_extension("GL_EXT_framebuffer_blit")) { - _supports_framebuffer_blit = true; - _glBlitFramebuffer = (PFNGLBLITFRAMEBUFFEREXTPROC) - get_extension_func("glBlitFramebufferEXT"); - } -#endif - #if defined(OPENGLES_1) _glDrawBuffers = NULL; _max_color_targets = 1; #elif defined(OPENGLES_2) - if (has_extension("GL_EXT_draw_buffers")) { + if (is_at_least_gles_version(3, 0)) { + _glDrawBuffers = (PFNGLDRAWBUFFERSPROC) + get_extension_func("glDrawBuffers"); + + } else if (has_extension("GL_EXT_draw_buffers")) { _glDrawBuffers = (PFNGLDRAWBUFFERSPROC) get_extension_func("glDrawBuffersEXT"); @@ -2022,8 +2222,8 @@ reset() { } #endif // !OPENGLES_1 -#ifndef OPENGLES - if (is_at_least_gl_version(3, 0)) { +#ifndef OPENGLES_1 + if (_gl_version_major >= 3) { _glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) get_extension_func("glClearBufferfv"); _glClearBufferiv = (PFNGLCLEARBUFFERIVPROC) @@ -2139,38 +2339,120 @@ reset() { } #endif -#ifdef OPENGLES_2 - // In OpenGL ES 2.x, this is supported in the core. - _glBlendEquation = glBlendEquation; -#else - _glBlendEquation = NULL; - bool supports_blend_equation = false; - if (is_at_least_gl_version(1, 2)) { - supports_blend_equation = true; - _glBlendEquation = (PFNGLBLENDEQUATIONPROC) - get_extension_func("glBlendEquation"); - } else if (has_extension("GL_OES_blend_subtract")) { - supports_blend_equation = true; +#ifdef OPENGLES_1 + // In OpenGL ES 1, blending is supported via extensions. + if (has_extension("GL_OES_blend_subtract")) { _glBlendEquation = (PFNGLBLENDEQUATIONPROC) get_extension_func("glBlendEquationOES"); + + if (_glBlendEquation == NULL) { + _glBlendEquation = null_glBlendEquation; + GLCAT.warning() + << "BlendEquationOES advertised as supported by OpenGL ES runtime, but " + "could not get pointer to extension function.\n"; + } + } else { + _glBlendEquation = null_glBlendEquation; + } + + if (has_extension("GL_OES_blend_equation_separate")) { + _glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEOESPROC) + get_extension_func("glBlendEquationSeparateOES"); + + if (_glBlendEquation == NULL) { + _supports_blend_equation_separate = false; + GLCAT.warning() + << "BlendEquationSeparateOES advertised as supported by OpenGL ES " + "runtime, but could not get pointer to extension function.\n"; + } else { + _supports_blend_equation_separate = true; + } + } else { + _supports_blend_equation_separate = false; + _glBlendEquationSeparate = NULL; + } + + if (has_extension("GL_OES_blend_func_separate")) { + _glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEOESPROC) + get_extension_func("glBlendFuncSeparateOES"); + + if (_glBlendFuncSeparate == NULL) { + _glBlendFuncSeparate = null_glBlendFuncSeparate; + GLCAT.warning() + << "BlendFuncSeparateOES advertised as supported by OpenGL ES runtime, but " + "could not get pointer to extension function.\n"; + } + } else { + _glBlendFuncSeparate = null_glBlendFuncSeparate; + } + +#elif defined(OPENGLES) + // In OpenGL ES 2.x and above, this is supported in the core. + _supports_blend_equation_separate = false; + +#else + if (is_at_least_gl_version(1, 2)) { + _glBlendEquation = (PFNGLBLENDEQUATIONPROC) + get_extension_func("glBlendEquation"); + } else if (has_extension("GL_EXT_blend_minmax")) { - supports_blend_equation = true; _glBlendEquation = (PFNGLBLENDEQUATIONPROC) get_extension_func("glBlendEquationEXT"); + + } else { + _glBlendEquation = null_glBlendEquation; } - if (supports_blend_equation && _glBlendEquation == NULL) { - GLCAT.warning() - << "BlendEquation advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n"; - } + if (_glBlendEquation == NULL) { _glBlendEquation = null_glBlendEquation; + GLCAT.warning() + << "BlendEquation advertised as supported by OpenGL runtime, but could " + "not get pointer to extension function.\n"; + } + + if (is_at_least_gl_version(2, 0)) { + _supports_blend_equation_separate = true; + _glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) + get_extension_func("glBlendEquationSeparate"); + + } else if (has_extension("GL_EXT_blend_equation_separate")) { + _supports_blend_equation_separate = true; + _glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEEXTPROC) + get_extension_func("glBlendEquationSeparateEXT"); + + } else { + _supports_blend_equation_separate = false; + _glBlendEquationSeparate = NULL; + } + + if (_supports_blend_equation_separate && _glBlendEquationSeparate == NULL) { + _supports_blend_equation_separate = false; + GLCAT.warning() + << "BlendEquationSeparate advertised as supported by OpenGL runtime, " + "but could not get pointer to extension function.\n"; + } + + if (is_at_least_gl_version(1, 4)) { + _glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) + get_extension_func("glBlendFuncSeparate"); + + } else if (has_extension("GL_EXT_blend_func_separate")) { + _glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEEXTPROC) + get_extension_func("glBlendFuncSeparateEXT"); + + } else { + _glBlendFuncSeparate = null_glBlendFuncSeparate; + } + + if (_glBlendFuncSeparate == NULL) { + _glBlendFuncSeparate = null_glBlendFuncSeparate; + GLCAT.warning() + << "BlendFuncSeparate advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n"; } #endif -#ifdef OPENGLES_2 - // In OpenGL ES 2.x, this is supported in the core. - _glBlendColor = glBlendColor; -#else + // In OpenGL ES 2.x, this is supported in the core. In 1.x, not at all. +#ifndef OPENGLES _glBlendColor = NULL; bool supports_blend_color = false; if (is_at_least_gl_version(1, 2)) { @@ -2191,6 +2473,15 @@ reset() { } #endif +#ifdef OPENGLES_1 + // OpenGL ES 1 doesn't support dual-source blending. +#elif defined(OPENGLES) + _supports_dual_source_blending = has_extension("GL_EXT_blend_func_extended"); +#else + _supports_dual_source_blending = + is_at_least_gl_version(3, 3) || has_extension("GL_ARB_blend_func_extended"); +#endif + #ifdef OPENGLES _edge_clamp = GL_CLAMP_TO_EDGE; #else @@ -2210,13 +2501,18 @@ reset() { } #endif -#ifdef OPENGLES_2 +#ifdef OPENGLES_1 + _mirror_repeat = GL_REPEAT; + if (has_extension("GL_OES_texture_mirrored_repeat")) { + _mirror_repeat = GL_MIRRORED_REPEAT; + } +#elif defined(OPENGLES) + // OpenGL 2.x and above support this in the core. _mirror_repeat = GL_MIRRORED_REPEAT; #else _mirror_repeat = GL_REPEAT; - if (has_extension("GL_ARB_texture_mirrored_repeat") || - is_at_least_gl_version(1, 4) || - has_extension("GL_OES_texture_mirrored_repeat")) { + if (is_at_least_gl_version(1, 4) || + has_extension("GL_ARB_texture_mirrored_repeat")) { _mirror_repeat = GL_MIRRORED_REPEAT; } #endif @@ -2232,7 +2528,10 @@ reset() { } #endif -#ifndef OPENGLES +#ifdef OPENGLES + _supports_texture_lod = is_at_least_gles_version(3, 0); + _supports_texture_lod_bias = false; +#else _supports_texture_lod = false; _supports_texture_lod_bias = false; @@ -2246,6 +2545,13 @@ reset() { } #endif +#ifdef OPENGLES + _supports_texture_max_level = is_at_least_gles_version(3, 0) || + has_extension("GL_APPLE_texture_max_level"); +#else + _supports_texture_max_level = is_at_least_gl_version(1, 2); +#endif + if (_supports_multisample) { GLint sample_buffers = 0; glGetIntegerv(GL_SAMPLE_BUFFERS, &sample_buffers); @@ -2276,9 +2582,9 @@ reset() { } else { _max_3d_texture_dimension = 0; } -#ifndef OPENGLES - if(_supports_2d_texture_array) { - glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, &max_2d_texture_array_layers); +#ifndef OPENGLES_1 + if (_supports_2d_texture_array) { + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &max_2d_texture_array_layers); _max_2d_texture_array_layers = max_2d_texture_array_layers; } #endif @@ -2319,9 +2625,11 @@ reset() { << ", max 3d texture = " << _max_3d_texture_dimension << ", max 2d texture array = " << max_2d_texture_array_layers << ", max cube map = " << _max_cube_map_dimension << "\n"; +#ifndef OPENGLES GLCAT.debug() << "max_elements_vertices = " << max_elements_vertices << ", max_elements_indices = " << max_elements_indices << "\n"; +#endif if (_supports_buffers) { if (vertex_buffers) { GLCAT.debug() @@ -2386,10 +2694,14 @@ reset() { _supports_anisotropy = true; } - // Check availability of image readwrite functionality in shaders. + // Check availability of image read/write functionality in shaders. _max_image_units = 0; -#ifndef OPENGLES +#ifndef OPENGLES_1 +#ifdef OPENGLES + if (is_at_least_gl_version(3, 1)) { +#else if (is_at_least_gl_version(4, 2) || has_extension("GL_ARB_shader_image_load_store")) { +#endif _glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC) get_extension_func("glBindImageTexture"); _glMemoryBarrier = (PFNGLMEMORYBARRIERPROC) @@ -2397,6 +2709,7 @@ reset() { glGetIntegerv(GL_MAX_IMAGE_UNITS, &_max_image_units); +#ifndef OPENGLES } else if (has_extension("GL_EXT_shader_image_load_store")) { _glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC) get_extension_func("glBindImageTextureEXT"); @@ -2404,17 +2717,23 @@ reset() { get_extension_func("glMemoryBarrierEXT"); glGetIntegerv(GL_MAX_IMAGE_UNITS_EXT, &_max_image_units); +#endif } else { _glBindImageTexture = NULL; _glMemoryBarrier = NULL; } +#endif // !OPENGLES_1 _supports_sampler_objects = false; -#ifndef OPENGLES +#ifndef OPENGLES_1 if (gl_support_sampler_objects && - ((is_at_least_gl_version(3, 3) || has_extension("GL_ARB_sampler_objects")))) { +#ifdef OPENGLES + is_at_least_gles_version(3, 0)) { +#else + (is_at_least_gl_version(3, 3) || has_extension("GL_ARB_sampler_objects"))) { +#endif _glGenSamplers = (PFNGLGENSAMPLERSPROC) get_extension_func("glGenSamplers"); _glDeleteSamplers = (PFNGLDELETESAMPLERSPROC) get_extension_func("glDeleteSamplers"); _glBindSampler = (PFNGLBINDSAMPLERPROC) get_extension_func("glBindSampler"); @@ -2433,7 +2752,7 @@ reset() { _supports_sampler_objects = true; } } -#endif // OPENGLES +#endif // !OPENGLES_1 // Check availability of multi-bind functions. _supports_multi_bind = false; @@ -2461,9 +2780,14 @@ reset() { << "ARB_multi_bind advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n"; } } -#endif // OPENGLES +#endif // !OPENGLES +#ifndef OPENGLES_1 +#ifdef OPENGLES + if (is_at_least_gl_version(3, 0)) { +#else if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_internalformat_query2")) { +#endif _glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC) get_extension_func("glGetInternalformativ"); @@ -2472,8 +2796,10 @@ reset() { << "ARB_internalformat_query2 advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n"; } } +#endif // !OPENGLES_1 _supports_bindless_texture = false; +#ifndef OPENGLES if (has_extension("GL_ARB_bindless_texture")) { _glGetTextureHandle = (PFNGLGETTEXTUREHANDLEPROC) get_extension_func("glGetTextureHandleARB"); @@ -2492,13 +2818,17 @@ reset() { _supports_bindless_texture = true; } } -#endif +#endif // !OPENGLES -#ifndef OPENGLES +#ifndef OPENGLES_1 _supports_get_program_binary = false; _program_binary_formats.clear(); +#ifdef OPENGLES + if (is_at_least_gles_version(3, 0)) { +#else if (is_at_least_gl_version(4, 1) || has_extension("GL_ARB_get_program_binary")) { +#endif _glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC) get_extension_func("glGetProgramBinary"); _glProgramBinary = (PFNGLPROGRAMBINARYPROC) @@ -2524,7 +2854,7 @@ reset() { } } } -#endif +#endif // !OPENGLES_1 report_my_gl_errors(); @@ -2540,12 +2870,18 @@ reset() { } #endif - _supports_stencil_wrap = - has_extension("GL_EXT_stencil_wrap") || has_extension("GL_OES_stencil_wrap"); - +#ifdef OPENGLES_1 + _supports_stencil_wrap = has_extension("GL_OES_stencil_wrap"); +#elif defined(OPENGLES) + _supports_stencil_wrap = true; +#else + _supports_stencil_wrap = is_at_least_gl_version(1, 4) || + has_extension("GL_EXT_stencil_wrap"); +#endif _supports_two_sided_stencil = false; #ifndef OPENGLES + //TODO: support the two-sided stencil functions that ended up in core. if (has_extension("GL_EXT_stencil_two_side")) { _glActiveStencilFaceEXT = (PFNGLACTIVESTENCILFACEEXTPROC) get_extension_func("glActiveStencilFaceEXT"); @@ -2600,10 +2936,8 @@ reset() { memset(_vertex_attrib_divisors, 0, sizeof(GLint) * 32); #endif -#ifndef OPENGLES // Dither is on by default in GL; let's turn it off glDisable(GL_DITHER); -#endif // OPENGLES _dithering_enabled = false; #ifndef OPENGLES_1 @@ -2709,20 +3043,24 @@ reset() { report_my_gl_errors(); -#ifndef OPENGLES +#ifndef OPENGLES_1 if (GLCAT.is_debug()) { - GLCAT.debug() - << "Supported shader binary formats:\n"; - GLCAT.debug() << " "; + if (_supports_get_program_binary) { + GLCAT.debug() + << "Supported shader binary formats:\n"; + GLCAT.debug() << " "; - pset::const_iterator it; - for (it = _program_binary_formats.begin(); - it != _program_binary_formats.end(); ++it) { - char number[16]; - sprintf(number, "0x%04X", *it); - GLCAT.debug(false) << " " << number << ""; + pset::const_iterator it; + for (it = _program_binary_formats.begin(); + it != _program_binary_formats.end(); ++it) { + char number[16]; + sprintf(number, "0x%04X", *it); + GLCAT.debug(false) << " " << number << ""; + } + GLCAT.debug(false) << "\n"; + } else { + GLCAT.debug() << "No shader binary formats supported.\n"; } - GLCAT.debug(false) << "\n"; } #endif @@ -2882,7 +3220,7 @@ clear(DrawableRegion *clearable) { int mask = 0; -#ifndef OPENGLES +#ifndef OPENGLES_1 if (_current_fbo != 0 && _glClearBufferfv != NULL) { // We can use glClearBuffer to clear all the color attachments, which // protects us from the overhead of having to call set_draw_buffer for @@ -3174,7 +3512,7 @@ clear_before_callback() { // Clear the bound sampler object, so that we do not inadvertently override // the callback's desired sampler settings. -#ifndef OPENGLES +#ifndef OPENGLES_1 if (_supports_sampler_objects) { _glBindSampler(0, 0); @@ -3666,7 +4004,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, _use_sender = !vertex_arrays; #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 if (_use_vertex_attrib_binding) { const GeomVertexFormat *format = data_reader->get_format(); if (format != _current_vertex_format) { @@ -3982,7 +4320,7 @@ disable_standard_vertex_arrays() { } #endif // SUPPORT_FIXED_FUNCTION -#ifndef OPENGLES +#ifndef OPENGLES_1 /** * Updates the vertex format used by the shader. This is still an * experimental feature. @@ -4689,7 +5027,7 @@ end_draw_primitives() { report_my_gl_errors(); } -#ifndef OPENGLES +#ifndef OPENGLES_1 /** * Issues the given memory barriers, and clears the list of textures marked as * incoherent for the given bits. @@ -4734,7 +5072,7 @@ issue_memory_barrier(GLbitfield barriers) { report_my_gl_errors(); } -#endif // OPENGLES +#endif // OPENGLES_1 /** * Creates whatever structures the GSG requires to represent the texture @@ -4876,7 +5214,7 @@ void CLP(GraphicsStateGuardian):: release_texture(TextureContext *tc) { CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); -#ifndef OPENGLES +#ifndef OPENGLES_1 _textures_needing_fetch_barrier.erase(gtc); _textures_needing_image_access_barrier.erase(gtc); _textures_needing_update_barrier.erase(gtc); @@ -4920,7 +5258,7 @@ extract_texture_data(Texture *tex) { return success; } -#ifndef OPENGLES +#ifndef OPENGLES_1 /** * Creates whatever structures the GSG requires to represent the sampler state * internally, and returns a newly-allocated SamplerContext object with this @@ -4948,6 +5286,7 @@ prepare_sampler(const SamplerState &sampler) { _glSamplerParameteri(index, GL_TEXTURE_WRAP_R, get_texture_wrap_mode(sampler.get_wrap_w())); +#ifndef OPENGLES #ifdef STDFLOAT_DOUBLE LVecBase4f fvalue = LCAST(float, sampler.get_border_color()); _glSamplerParameterfv(index, GL_TEXTURE_BORDER_COLOR, fvalue.get_data()); @@ -4955,6 +5294,7 @@ prepare_sampler(const SamplerState &sampler) { _glSamplerParameterfv(index, GL_TEXTURE_BORDER_COLOR, sampler.get_border_color().get_data()); #endif +#endif // OPENGLES SamplerState::FilterType minfilter = sampler.get_effective_minfilter(); SamplerState::FilterType magfilter = sampler.get_effective_magfilter(); @@ -4997,18 +5337,20 @@ prepare_sampler(const SamplerState &sampler) { _glSamplerParameterf(index, GL_TEXTURE_MAX_LOD, sampler.get_max_lod()); } +#ifndef OPENGLES if (_supports_texture_lod_bias) { _glSamplerParameterf(index, GL_TEXTURE_LOD_BIAS, sampler.get_lod_bias()); } +#endif gsc->enqueue_lru(&_prepared_objects->_sampler_object_lru); report_my_gl_errors(); return gsc; } -#endif // !OPENGLES +#endif // !OPENGLES_1 -#ifndef OPENGLES +#ifndef OPENGLES_1 /** * Frees the GL resources previously allocated for the sampler. This function * should never be called directly; instead, call SamplerState::release(). @@ -5023,7 +5365,7 @@ release_sampler(SamplerContext *sc) { delete gsc; } -#endif // !OPENGLES +#endif // !OPENGLES_1 /** * Creates a new retained-mode representation of the given geom, and returns a @@ -5629,7 +5971,7 @@ issue_timer_query(int pstats_index) { #endif } -#ifndef OPENGLES +#ifndef OPENGLES_1 /** * Dispatches a currently bound compute shader using the given work group * counts. @@ -5645,7 +5987,7 @@ dispatch_compute(int num_groups_x, int num_groups_y, int num_groups_z) { maybe_gl_finish(); } -#endif // !OPENGLES +#endif // !OPENGLES_1 /** * Creates a new GeomMunger object to munge vertices appropriate to this GSG @@ -5825,7 +6167,7 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z, } } -#ifndef OPENGLES +#ifndef OPENGLES_1 if (gtc->needs_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT)) { // Make sure that any incoherent writes to this texture have been synced. issue_memory_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT); @@ -5905,7 +6247,6 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, dr->get_region_pixels(xo, yo, w, h); Texture::ComponentType component_type = tex->get_component_type(); - bool color_mode = false; Texture::Format format = tex->get_format(); switch (format) { @@ -5930,7 +6271,6 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, break; default: - color_mode = true; if (_current_properties->get_srgb_color()) { if (_current_properties->get_alpha_bits()) { format = Texture::F_srgb_alpha; @@ -5990,6 +6330,11 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, case GL_DEPTH_STENCIL: GLCAT.spam(false) << "GL_DEPTH_STENCIL, "; break; +#ifndef OPENGLES_1 + case GL_RG: + GLCAT.spam(false) << "GL_RG, "; + break; +#endif case GL_RGB: GLCAT.spam(false) << "GL_RGB, "; break; @@ -6048,7 +6393,7 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, // We may have to reverse the byte ordering of the image if GL didn't do it // for us. - if (color_mode && !_supports_bgr) { + if (external_format == GL_RGBA || external_format == GL_RGB) { PTA_uchar new_image; const unsigned char *result = fix_component_ordering(new_image, image_ptr, image_size, @@ -6707,6 +7052,7 @@ do_issue_blending() { _target_rs->get_attrib_def(target_color_blend); CPT(ColorBlendAttrib) color_blend = target_color_blend; ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode(); + ColorBlendAttrib::Mode alpha_blend_mode = target_color_blend->get_alpha_mode(); const TransparencyAttrib *target_transparency; _target_rs->get_attrib_def(target_transparency); @@ -6719,10 +7065,19 @@ do_issue_blending() { enable_multisample_alpha_one(false); enable_multisample_alpha_mask(false); enable_blend(true); - _glBlendEquation(get_blend_equation_type(color_blend_mode)); - glBlendFunc(get_blend_func(color_blend->get_operand_a()), - get_blend_func(color_blend->get_operand_b())); + if (_supports_blend_equation_separate) { + _glBlendEquationSeparate(get_blend_equation_type(color_blend_mode), + get_blend_equation_type(alpha_blend_mode)); + } else { + _glBlendEquation(get_blend_equation_type(color_blend_mode)); + } + _glBlendFuncSeparate(get_blend_func(color_blend->get_operand_a()), + get_blend_func(color_blend->get_operand_b()), + get_blend_func(color_blend->get_alpha_operand_a()), + get_blend_func(color_blend->get_alpha_operand_b())); + +#ifndef OPENGLES_1 LColor c; if (_color_blend_involves_color_scale) { // Apply the current color scale to the blend mode. @@ -6732,12 +7087,23 @@ do_issue_blending() { } _glBlendColor(c[0], c[1], c[2], c[3]); +#endif if (GLCAT.is_spam()) { - GLCAT.spam() << "glBlendEquation(" << color_blend_mode << ")\n"; - GLCAT.spam() << "glBlendFunc(" << color_blend->get_operand_a() - << color_blend->get_operand_b() << ")\n"; + if (_supports_blend_equation_separate) { + GLCAT.spam() << "glBlendEquationSeparate(" << color_blend_mode << ", " + << alpha_blend_mode << ")\n"; + } else { + GLCAT.spam() << "glBlendEquation(" << color_blend_mode << ")\n"; + } + GLCAT.spam() << "glBlendFuncSeparate(" + << color_blend->get_operand_a() << ", " + << color_blend->get_operand_b() << ", " + << color_blend->get_alpha_operand_a() << ", " + << color_blend->get_alpha_operand_b() << ")\n"; +#ifndef OPENGLES_1 GLCAT.spam() << "glBlendColor(" << c << ")\n"; +#endif } return; } @@ -7445,7 +7811,7 @@ do_get_extension_func(const char *) { */ void CLP(GraphicsStateGuardian):: set_draw_buffer(int rbtype) { -#ifndef OPENGLES // Draw buffers not supported by OpenGL ES. +#ifndef OPENGLES // Draw buffers not supported by OpenGL ES. (TODO!) if (_current_fbo) { GLuint buffers[16]; int nbuffers = 0; @@ -7539,7 +7905,7 @@ set_draw_buffer(int rbtype) { */ void CLP(GraphicsStateGuardian):: set_read_buffer(int rbtype) { -#ifndef OPENGLES // Draw buffers not supported by OpenGL ES. +#ifndef OPENGLES // Draw buffers not supported by OpenGL ES. (TODO!) if (rbtype & (RenderBuffer::T_depth | RenderBuffer::T_stencil)) { // Special case: don't have to call ReadBuffer for these. return; @@ -7667,7 +8033,7 @@ get_numeric_type(Geom::NumericType numeric_type) { #endif case Geom::NT_packed_ufloat: -#ifndef OPENGLES +#ifndef OPENGLES_1 return GL_UNSIGNED_INT_10F_11F_11F_REV; #else break; @@ -7703,7 +8069,7 @@ get_texture_target(Texture::TextureType texture_type) const { return GL_NONE; case Texture::TT_2d_texture_array: -#ifndef OPENGLES +#ifndef OPENGLES_1 if (_supports_2d_texture_array) { return GL_TEXTURE_2D_ARRAY; } @@ -7902,7 +8268,7 @@ get_component_type(Texture::ComponentType component_type) { case Texture::T_short: return GL_SHORT; -#ifndef OPENGLES +#ifndef OPENGLES_1 case Texture::T_half_float: return GL_HALF_FLOAT; #endif @@ -7968,6 +8334,7 @@ get_external_image_format(Texture *tex) const { case Texture::F_blue: case Texture::F_r8i: case Texture::F_r16: + case Texture::F_r16i: case Texture::F_r32: case Texture::F_r32i: return GL_COMPRESSED_RED; @@ -8137,10 +8504,12 @@ get_external_image_format(Texture *tex) const { case Texture::F_r11_g11_b10: case Texture::F_rgb9_e5: #ifdef OPENGLES + // OpenGL ES never supports BGR, even if _supports_bgr is true. return GL_RGB; #else return _supports_bgr ? GL_BGR : GL_RGB; #endif + case Texture::F_rgba: case Texture::F_rgbm: case Texture::F_rgba4: @@ -8151,11 +8520,7 @@ get_external_image_format(Texture *tex) const { case Texture::F_rgba32: case Texture::F_srgb_alpha: case Texture::F_rgb10_a2: -#ifdef OPENGLES_2 - return GL_RGBA; -#else return _supports_bgr ? GL_BGRA : GL_RGBA; -#endif case Texture::F_luminance: case Texture::F_sluminance: @@ -8173,8 +8538,9 @@ get_external_image_format(Texture *tex) const { return GL_RG; #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 case Texture::F_r8i: + case Texture::F_r16i: case Texture::F_r32i: return GL_RED_INTEGER; case Texture::F_rg8i: @@ -8232,6 +8598,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_rg8i: case Texture::F_rgb8i: case Texture::F_rgba8i: + case Texture::F_r16i: case Texture::F_r32i: case Texture::F_r11_g11_b10: case Texture::F_rgb9_e5: @@ -8708,6 +9075,12 @@ get_internal_image_format(Texture *tex, bool force_sized) const { } else { return GL_R16_SNORM; } + case Texture::F_r16i: + if (Texture::is_unsigned(tex->get_component_type())) { + return GL_R16UI; + } else { + return GL_R16I; + } case Texture::F_rg16: if (tex->get_component_type() == Texture::T_float) { return GL_RG16F; @@ -8776,7 +9149,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return force_sized ? GL_RG8 : GL_RG; #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 case Texture::F_rg: return force_sized ? GL_RG8 : GL_RG; #endif @@ -8801,7 +9174,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return GL_R32I; #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 case Texture::F_r11_g11_b10: return GL_R11F_G11F_B10F; @@ -9107,6 +9480,13 @@ get_blend_func(ColorBlendAttrib::Operand operand) { case ColorBlendAttrib::O_one_minus_constant_alpha: case ColorBlendAttrib::O_one_minus_alpha_scale: break; + + // No dual-source blending, either. + case ColorBlendAttrib::O_incoming1_color: + case ColorBlendAttrib::O_one_minus_incoming1_color: + case ColorBlendAttrib::O_incoming1_alpha: + case ColorBlendAttrib::O_one_minus_incoming1_alpha: + break; #else case ColorBlendAttrib::O_constant_color: case ColorBlendAttrib::O_color_scale: @@ -9123,6 +9503,18 @@ get_blend_func(ColorBlendAttrib::Operand operand) { case ColorBlendAttrib::O_one_minus_constant_alpha: case ColorBlendAttrib::O_one_minus_alpha_scale: return GL_ONE_MINUS_CONSTANT_ALPHA; + + case ColorBlendAttrib::O_incoming1_color: + return GL_SRC1_COLOR; + + case ColorBlendAttrib::O_one_minus_incoming1_color: + return GL_ONE_MINUS_SRC1_COLOR; + + case ColorBlendAttrib::O_incoming1_alpha: + return GL_SRC1_ALPHA; + + case ColorBlendAttrib::O_one_minus_incoming1_alpha: + return GL_ONE_MINUS_SRC1_ALPHA; #endif case ColorBlendAttrib::O_incoming_color_saturate: @@ -9141,7 +9533,7 @@ GLenum CLP(GraphicsStateGuardian):: get_usage(Geom::UsageHint usage_hint) { switch (usage_hint) { case Geom::UH_stream: -#ifdef OPENGLES +#ifdef OPENGLES_1 return GL_DYNAMIC_DRAW; #else return GL_STREAM_DRAW; @@ -9176,6 +9568,7 @@ get_compressed_format_string(GLenum format) { case 0x83F3: return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"; case 0x86B0: return "GL_COMPRESSED_RGB_FXT1_3DFX"; case 0x86B1: return "GL_COMPRESSED_RGBA_FXT1_3DFX"; + case 0x88EE: return "GL_ETC1_SRGB8_NV"; case 0x8A54: return "GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT"; case 0x8A55: return "GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT"; case 0x8A56: return "GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT"; @@ -9206,6 +9599,7 @@ get_compressed_format_string(GLenum format) { case 0x8C71: return "GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT"; case 0x8C72: return "GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT"; case 0x8C73: return "GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT"; + case 0x8D64: return "GL_ETC1_RGB8_OES"; case 0x8DBB: return "GL_COMPRESSED_RED_RGTC1"; case 0x8DBC: return "GL_COMPRESSED_SIGNED_RED_RGTC1"; case 0x8DBD: return "GL_COMPRESSED_RG_RGTC2"; @@ -9319,7 +9713,7 @@ reissue_transforms() { _active_texture_stage = -1; -#ifndef OPENGLES +#ifndef OPENGLES_1 // Might also want to reissue the vertex format, for good measure. _current_vertex_format.clear(); memset(_vertex_attrib_columns, 0, sizeof(const GeomVertexColumn *) * 32); @@ -9963,7 +10357,7 @@ update_standard_texture_bindings() { // Unsupported texture mode. continue; } -#ifndef OPENGLES +#ifndef OPENGLES_1 if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY) { // Cannot be applied via the FFP. continue; @@ -10289,7 +10683,7 @@ upload_usage_texture(int width, int height) { // Allocate a temporary array large enough to contain the toplevel mipmap. - PN_uint32 *buffer = (PN_uint32 *)PANDA_MALLOC_ARRAY(width * height * 4); + uint32_t *buffer = (uint32_t *)PANDA_MALLOC_ARRAY(width * height * 4); int n = 0; while (true) { @@ -10302,7 +10696,7 @@ upload_usage_texture(int width, int height) { struct { unsigned char r, g, b, a; } b; - PN_uint32 w; + uint32_t w; } store; store.b.r = (unsigned char)(c[0] * 255.0f); @@ -10681,7 +11075,9 @@ do_issue_tex_gen() { */ bool CLP(GraphicsStateGuardian):: specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) { +#ifndef OPENGLES nassertr(gtc->_handle == 0 /* can't modify tex with active handle */, false); +#endif Texture *tex = gtc->get_texture(); @@ -10703,23 +11099,20 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) { glTexParameteri(target, GL_TEXTURE_WRAP_S, get_texture_wrap_mode(sampler.get_wrap_u())); #ifndef OPENGLES - if (target != GL_TEXTURE_1D) { + if (target != GL_TEXTURE_1D) +#endif + { glTexParameteri(target, GL_TEXTURE_WRAP_T, get_texture_wrap_mode(sampler.get_wrap_v())); } -#endif -#ifdef OPENGLES_2 - if (target == GL_TEXTURE_3D_OES) { - glTexParameteri(target, GL_TEXTURE_WRAP_R_OES, - get_texture_wrap_mode(sampler.get_wrap_w())); - } -#endif -#ifndef OPENGLES +#ifndef OPENGLES_1 if (target == GL_TEXTURE_3D) { glTexParameteri(target, GL_TEXTURE_WRAP_R, get_texture_wrap_mode(sampler.get_wrap_w())); } +#endif +#ifndef OPENGLES LColor border_color = sampler.get_border_color(); call_glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, border_color); #endif // OPENGLES @@ -10782,12 +11175,14 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) { } #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 if (_supports_texture_lod) { glTexParameterf(target, GL_TEXTURE_MIN_LOD, sampler.get_min_lod()); glTexParameterf(target, GL_TEXTURE_MAX_LOD, sampler.get_max_lod()); } +#endif +#ifndef OPENGLES if (_supports_texture_lod_bias) { glTexParameterf(target, GL_TEXTURE_LOD_BIAS, sampler.get_lod_bias()); } @@ -10843,7 +11238,7 @@ apply_texture(CLP(TextureContext) *gtc) { */ bool CLP(GraphicsStateGuardian):: apply_sampler(GLuint unit, const SamplerState &sampler, CLP(TextureContext) *gtc) { -#ifndef OPENGLES +#ifndef OPENGLES_1 if (_supports_sampler_objects) { // We support sampler objects. Prepare the sampler object and bind it to // the indicated texture unit. @@ -10861,7 +11256,7 @@ apply_sampler(GLuint unit, const SamplerState &sampler, CLP(TextureContext) *gtc } } else -#endif // OPENGLES +#endif // !OPENGLES_1 { // We don't support sampler objects. We'll have to bind the texture and // change the texture parameters if they don't match. @@ -11118,7 +11513,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { } if (needs_reload && gtc->_immutable) { - GLCAT.warning() << "Attempt to modify texture with immutable storage, recreating texture.\n"; + GLCAT.info() << "Attempt to modify texture with immutable storage, recreating texture.\n"; gtc->reset_data(); glBindTexture(target, gtc->_index); @@ -11199,14 +11594,12 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { } } -#ifndef OPENGLES // OpenGL ES doesn't have GL_TEXTURE_MAX_LEVEL. - if (is_at_least_gl_version(1, 2)) { + if (_supports_texture_max_level) { // By the time we get here, we have a pretty good prediction for the // number of mipmaps we're going to have, so tell the GL that's all it's // going to get. glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, num_levels - 1); } -#endif #ifndef OPENGLES_2 if (gtc->_generate_mipmaps && _glGenerateMipmap == NULL) { @@ -11465,7 +11858,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, } } -#ifndef OPENGLES +#ifndef OPENGLES_1 if (needs_reload || num_ram_mipmap_levels > 0) { // Make sure that any incoherent writes to this texture have been synced. if (gtc->needs_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT)) { @@ -11568,7 +11961,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, } nassertr(image_ptr >= orig_image_ptr && image_ptr + view_size <= orig_image_ptr + tex->get_ram_mipmap_image_size(n), false); - if (!_supports_bgr && image_compression == Texture::CM_off) { + if (image_compression == Texture::CM_off) { // If the GL doesn't claim to support BGR, we may have to reverse // the component ordering of the image. image_ptr = fix_component_ordering(bgr_image, image_ptr, view_size, @@ -11613,7 +12006,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, break; #endif // OPENGLES -#ifndef OPENGLES +#ifndef OPENGLES_1 case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY: if (_supports_2d_texture_array) { @@ -11629,7 +12022,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, return false; } break; -#endif // OPENGLES +#endif // OPENGLES_1 #ifndef OPENGLES case GL_TEXTURE_BUFFER: @@ -11712,12 +12105,10 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, GLCAT.warning() << "No mipmap level " << n << " defined for " << tex->get_name() << "\n"; -#ifndef OPENGLES - if (is_at_least_gl_version(1, 2)) { + if (_supports_texture_max_level) { // Tell the GL we have no more mipmaps for it to use. glTexParameteri(texture_target, GL_TEXTURE_MAX_LEVEL, n - mipmap_bias); } -#endif break; } @@ -11742,7 +12133,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, } nassertr(image_ptr >= orig_image_ptr && image_ptr + view_size <= orig_image_ptr + tex->get_ram_mipmap_image_size(n), false); - if (!_supports_bgr && image_compression == Texture::CM_off) { + if (image_compression == Texture::CM_off) { // If the GL doesn't claim to support BGR, we may have to reverse // the component ordering of the image. image_ptr = fix_component_ordering(bgr_image, image_ptr, view_size, @@ -11771,13 +12162,8 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, break; #endif // OPENGLES // OpenGL ES will fall through. -#ifdef OPENGLES_2 - case GL_TEXTURE_3D_OES: -#endif -#ifndef OPENGLES - case GL_TEXTURE_3D: -#endif #ifndef OPENGLES_1 + case GL_TEXTURE_3D: if (_supports_3d_texture) { if (image_compression == Texture::CM_off) { _glTexImage3D(page_target, n - mipmap_bias, internal_format, @@ -11793,9 +12179,9 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, return false; } break; -#endif +#endif // OPENGLES_1 -#ifndef OPENGLES +#ifndef OPENGLES_1 case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY: if (_supports_2d_texture_array) { @@ -11813,7 +12199,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, return false; } break; -#endif // OPENGLES +#endif // OPENGLES_1 #ifndef OPENGLES case GL_TEXTURE_BUFFER: @@ -11892,12 +12278,8 @@ upload_simple_texture(CLP(TextureContext) *gtc) { Texture *tex = gtc->get_texture(); nassertr(tex != (Texture *)NULL, false); - int internal_format = GL_RGBA; -#ifdef OPENGLES_2 - int external_format = GL_RGBA; -#else - int external_format = GL_BGRA; -#endif + GLenum internal_format = GL_RGBA; + GLenum external_format = GL_BGRA; const unsigned char *image_ptr = tex->get_simple_ram_image(); if (image_ptr == (const unsigned char *)NULL) { @@ -11916,19 +12298,17 @@ upload_simple_texture(CLP(TextureContext) *gtc) { int width = tex->get_simple_x_size(); int height = tex->get_simple_y_size(); - int component_type = GL_UNSIGNED_BYTE; + GLenum component_type = GL_UNSIGNED_BYTE; if (GLCAT.is_debug()) { GLCAT.debug() << "loading simple image for " << tex->get_name() << "\n"; } -#ifndef OPENGLES // Turn off mipmaps for the simple texture. - if (tex->uses_mipmaps() && is_at_least_gl_version(1, 2)) { + if (tex->uses_mipmaps() && _supports_texture_max_level) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); } -#endif #ifdef DO_PSTATS _data_transferred_pcollector.add_level(image_size); @@ -12096,7 +12476,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { return false; } -#ifndef OPENGLES +#ifndef OPENGLES_1 // Make sure any incoherent writes to the texture have been synced. if (gtc->needs_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT)) { issue_memory_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT); @@ -12118,19 +12498,11 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { glGetTexParameteriv(target, GL_TEXTURE_WRAP_S, &wrap_u); glGetTexParameteriv(target, GL_TEXTURE_WRAP_T, &wrap_v); wrap_w = GL_REPEAT; +#ifndef OPENGLES_1 if (_supports_3d_texture) { -#ifdef OPENGLES_2 - glGetTexParameteriv(target, GL_TEXTURE_WRAP_R_OES, &wrap_w); -#endif -#ifndef OPENGLES glGetTexParameteriv(target, GL_TEXTURE_WRAP_R, &wrap_w); -#endif } - if (_supports_2d_texture_array) { -#ifndef OPENGLES - glGetTexParameteriv(target, GL_TEXTURE_WRAP_R, &wrap_w); #endif - } glGetTexParameteriv(target, GL_TEXTURE_MIN_FILTER, &minfilter); glGetTexParameteriv(target, GL_TEXTURE_MAG_FILTER, &magfilter); @@ -12153,13 +12525,9 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { if (_supports_3d_texture && target == GL_TEXTURE_3D) { glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_DEPTH, &depth); - } -#ifndef OPENGLES - else if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY) { + } else if (target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY) { glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_DEPTH, &depth); - } -#endif - else if (target == GL_TEXTURE_CUBE_MAP) { + } else if (target == GL_TEXTURE_CUBE_MAP) { depth = 6; } #endif @@ -12303,6 +12671,16 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { type = Texture::T_unsigned_byte; format = Texture::F_rgba8i; break; + + case GL_R16I: + type = Texture::T_short; + format = Texture::F_r16i; + break; + case GL_R16UI: + type = Texture::T_unsigned_short; + format = Texture::F_r16i; + break; + #endif #ifndef OPENGLES_1 @@ -12368,7 +12746,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { break; #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 case GL_R11F_G11F_B10F: type = Texture::T_float; format = Texture::F_r11_g11_b10; @@ -12618,12 +12996,11 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { // Also get the mipmap levels. GLint num_expected_levels = tex->get_expected_num_mipmap_levels(); GLint highest_level = num_expected_levels; -#ifndef OPENGLES - if (is_at_least_gl_version(1, 2)) { + + if (_supports_texture_max_level) { glGetTexParameteriv(target, GL_TEXTURE_MAX_LEVEL, &highest_level); highest_level = min(highest_level, num_expected_levels); } -#endif for (int n = 1; n <= highest_level; ++n) { if (!extract_texture_image(image, page_size, tex, target, page_target, type, compression, n)) { diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 5a1ded8644..3c93fcd174 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -68,8 +68,6 @@ typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target); typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids); typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params); -typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64 *params); -typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *params); typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); // There is some trivial disagreement between different gl.h headers about @@ -141,6 +139,8 @@ typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, G typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array); typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); #ifndef OPENGLES_1 // GLSL shader functions @@ -186,8 +186,26 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); -#endif // OPENGLES_1 -#ifndef OPENGLES +typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect); +typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex); +typedef void (APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor); +typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName); +typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers); typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers); typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); @@ -195,17 +213,22 @@ typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pnam typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param); typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param); -typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers); +typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +typedef void (APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); +typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); +typedef void (APIENTRYP PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); +typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +#endif // OPENGLES_1 +#ifndef OPENGLES typedef void (APIENTRYP PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data); typedef void (APIENTRYP PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data); typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures); typedef void (APIENTRYP PFNGLBINDSAMPLERSPROC) (GLuint first, GLsizei count, const GLuint *samplers); -typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); typedef void (APIENTRYP PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures); -typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); -typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers); -typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufsize, GLsizei *length, GLenum *binaryFormat, void *binary); -typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLEPROC) (GLuint texture); typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEPROC) (GLuint texture, GLuint sampler); typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTPROC) (GLuint64 handle); @@ -245,9 +268,7 @@ public: virtual int get_driver_shader_version_major(); virtual int get_driver_shader_version_minor(); -#ifndef OPENGLES_1 static void debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam); -#endif virtual void reset(); @@ -281,7 +302,7 @@ public: bool force); virtual void end_draw_primitives(); -#ifndef OPENGLES +#ifndef OPENGLES_1 void issue_memory_barrier(GLbitfield barrier); #endif @@ -290,7 +311,7 @@ public: virtual void release_texture(TextureContext *tc); virtual bool extract_texture_data(Texture *tex); -#ifndef OPENGLES +#ifndef OPENGLES_1 virtual SamplerContext *prepare_sampler(const SamplerState &sampler); virtual void release_sampler(SamplerContext *sc); #endif @@ -329,7 +350,7 @@ public: virtual PT(TimerQueryContext) issue_timer_query(int pstats_index); -#ifndef OPENGLES +#ifndef OPENGLES_1 virtual void dispatch_compute(int size_x, int size_y, int size_z); #endif @@ -536,7 +557,7 @@ protected: void disable_standard_texture_bindings(); void update_standard_texture_bindings(); #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 void update_shader_vertex_format(const GeomVertexFormat *format); #endif @@ -660,7 +681,7 @@ protected: GLuint _current_ibuffer_index; GLuint _current_fbo; -#ifndef OPENGLES +#ifndef OPENGLES_1 pvector _current_vertex_buffers; bool _use_vertex_attrib_binding; CPT(GeomVertexFormat) _current_vertex_format; @@ -704,7 +725,7 @@ public: PFNGLSECONDARYCOLORPOINTERPROC _glSecondaryColorPointer; #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 PFNGLDRAWRANGEELEMENTSPROC _glDrawRangeElements; #endif @@ -780,8 +801,15 @@ public: #ifndef OPENGLES PFNGLMAPBUFFERPROC _glMapBuffer; PFNGLUNMAPBUFFERPROC _glUnmapBuffer; - PFNGLMAPBUFFERRANGEPROC _glMapBufferRange; +#endif +#ifdef OPENGLES + PFNGLMAPBUFFERRANGEEXTPROC _glMapBufferRange; +#else + PFNGLMAPBUFFERRANGEPROC _glMapBufferRange; +#endif + +#ifndef OPENGLES_1 bool _supports_uniform_buffers; PFNGLBINDBUFFERBASEPROC _glBindBufferBase; @@ -789,8 +817,16 @@ public: PFNGLBUFFERSTORAGEPROC _glBufferStorage; #endif + bool _supports_blend_equation_separate; +#ifndef OPENGLES_2 + // OpenGL ES 2+ has these in the core. PFNGLBLENDEQUATIONPROC _glBlendEquation; + PFNGLBLENDEQUATIONSEPARATEPROC _glBlendEquationSeparate; + PFNGLBLENDFUNCSEPARATEPROC _glBlendFuncSeparate; +#endif +#ifndef OPENGLES PFNGLBLENDCOLORPROC _glBlendColor; +#endif bool _supports_vao; GLuint _current_vao_index; @@ -798,7 +834,7 @@ public: PFNGLDELETEVERTEXARRAYSPROC _glDeleteVertexArrays; PFNGLGENVERTEXARRAYSPROC _glGenVertexArrays; -#ifndef OPENGLES +#ifndef OPENGLES_1 PFNGLDRAWARRAYSINDIRECTPROC _glDrawArraysIndirect; PFNGLDRAWELEMENTSINDIRECTPROC _glDrawElementsIndirect; #endif @@ -833,7 +869,7 @@ public: PFNGLGENERATETEXTUREMIPMAPPROC _glGenerateTextureMipmap; #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 bool _supports_empty_framebuffer; PFNGLFRAMEBUFFERPARAMETERIPROC _glFramebufferParameteri; #endif @@ -849,7 +885,7 @@ public: PFNGLBLITFRAMEBUFFEREXTPROC _glBlitFramebuffer; PFNGLDRAWBUFFERSPROC _glDrawBuffers; -#ifndef OPENGLES +#ifndef OPENGLES_1 PFNGLCLEARBUFFERFVPROC _glClearBufferfv; PFNGLCLEARBUFFERIVPROC _glClearBufferiv; PFNGLCLEARBUFFERFIPROC _glClearBufferfi; @@ -920,10 +956,7 @@ public: PFNGLVERTEXATTRIBDIVISORPROC _glVertexAttribDivisor; PFNGLDRAWARRAYSINSTANCEDPROC _glDrawArraysInstanced; PFNGLDRAWELEMENTSINSTANCEDPROC _glDrawElementsInstanced; -#endif // !OPENGLES_1 -#ifndef OPENGLES PFNGLBINDVERTEXBUFFERPROC _glBindVertexBuffer; - PFNGLBINDVERTEXBUFFERSPROC _glBindVertexBuffers; PFNGLVERTEXATTRIBFORMATPROC _glVertexAttribFormat; PFNGLVERTEXATTRIBIFORMATPROC _glVertexAttribIFormat; PFNGLVERTEXATTRIBLFORMATPROC _glVertexAttribLFormat; @@ -940,16 +973,19 @@ public: PFNGLSAMPLERPARAMETERFPROC _glSamplerParameterf; PFNGLSAMPLERPARAMETERFVPROC _glSamplerParameterfv; PFNGLPROGRAMPARAMETERIPROC _glProgramParameteri; - PFNGLPATCHPARAMETERIPROC _glPatchParameteri; - PFNGLBINDTEXTURESPROC _glBindTextures; - PFNGLBINDSAMPLERSPROC _glBindSamplers; - PFNGLBINDIMAGETEXTUREPROC _glBindImageTexture; - PFNGLBINDIMAGETEXTURESPROC _glBindImageTextures; PFNGLDISPATCHCOMPUTEPROC _glDispatchCompute; PFNGLMEMORYBARRIERPROC _glMemoryBarrier; PFNGLGETPROGRAMBINARYPROC _glGetProgramBinary; PFNGLPROGRAMBINARYPROC _glProgramBinary; PFNGLGETINTERNALFORMATIVPROC _glGetInternalformativ; + PFNGLBINDIMAGETEXTUREPROC _glBindImageTexture; +#endif // !OPENGLES_1 +#ifndef OPENGLES + PFNGLBINDVERTEXBUFFERSPROC _glBindVertexBuffers; + PFNGLPATCHPARAMETERIPROC _glPatchParameteri; + PFNGLBINDTEXTURESPROC _glBindTextures; + PFNGLBINDSAMPLERSPROC _glBindSamplers; + PFNGLBINDIMAGETEXTURESPROC _glBindImageTextures; PFNGLVIEWPORTARRAYVPROC _glViewportArrayv; PFNGLSCISSORARRAYVPROC _glScissorArrayv; PFNGLDEPTHRANGEARRAYVPROC _glDepthRangeArrayv; @@ -968,10 +1004,9 @@ public: GLenum _mirror_edge_clamp; GLenum _mirror_border_clamp; -#ifndef OPENGLES bool _supports_texture_lod; bool _supports_texture_lod_bias; -#endif + bool _supports_texture_max_level; #ifndef OPENGLES_1 GLsizei _instance_count; @@ -982,7 +1017,7 @@ public: DeletedNames _deleted_display_lists; DeletedNames _deleted_queries; -#ifndef OPENGLES +#ifndef OPENGLES_1 // Stores textures for which memory bariers should be issued. typedef pset TextureSet; TextureSet _textures_needing_fetch_barrier; diff --git a/panda/src/glstuff/glSamplerContext_src.cxx b/panda/src/glstuff/glSamplerContext_src.cxx index fa5f4984ae..486ebb0cc5 100644 --- a/panda/src/glstuff/glSamplerContext_src.cxx +++ b/panda/src/glstuff/glSamplerContext_src.cxx @@ -13,7 +13,7 @@ #include "pnotify.h" -#ifndef OPENGLES +#ifndef OPENGLES_1 TypeHandle CLP(SamplerContext)::_type_handle; @@ -68,4 +68,4 @@ reset_data() { // the sampler later. glGenSamplers(1, &_index); } -#endif // OPENGLES +#endif // OPENGLES_1 diff --git a/panda/src/glstuff/glSamplerContext_src.h b/panda/src/glstuff/glSamplerContext_src.h index 369ab49ab6..2a07bdd4a1 100644 --- a/panda/src/glstuff/glSamplerContext_src.h +++ b/panda/src/glstuff/glSamplerContext_src.h @@ -11,7 +11,7 @@ * @date 2014-12-11 */ -#ifndef OPENGLES +#ifndef OPENGLES_1 #include "pandabase.h" #include "samplerContext.h" @@ -56,4 +56,4 @@ private: static TypeHandle _type_handle; }; -#endif // OPENGLES +#endif // OPENGLES_1 diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index c2f7edaa48..0324fbb4a1 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -300,7 +300,6 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext name_buflen = max(64, name_buflen); name_buffer = (char *)alloca(name_buflen); -#ifndef OPENGLES // Get the used uniform blocks. if (_glgsg->_supports_uniform_buffers) { GLint block_count = 0, block_maxlength = 0; @@ -324,7 +323,6 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext reflect_uniform_block(i, block_name_cstr, name_buffer, name_buflen); } } -#endif // !OPENGLES // Bind the program, so that we can call glUniform1i for the textures. _glgsg->_glUseProgram(_glsl_program); @@ -402,11 +400,9 @@ reflect_attribute(int i, char *name_buffer, GLsizei name_buflen) { param_type == GL_INT_VEC2 || param_type == GL_INT_VEC3 || param_type == GL_INT_VEC4 || -#ifndef OPENGLES param_type == GL_UNSIGNED_INT_VEC2 || param_type == GL_UNSIGNED_INT_VEC3 || param_type == GL_UNSIGNED_INT_VEC4 || -#endif param_type == GL_UNSIGNED_INT); // Check if it has a p3d_ prefix - if so, assign special meaning. @@ -505,7 +501,6 @@ reflect_attribute(int i, char *name_buffer, GLsizei name_buflen) { _shader->_var_spec.push_back(bind); } -#ifndef OPENGLES /** * Analyzes the uniform block and stores its format. */ @@ -515,7 +510,6 @@ reflect_uniform_block(int i, const char *name, char *name_buffer, GLsizei name_b GLint data_size = 0; GLint param_count = 0; - GLsizei param_size; _glgsg->_glGetActiveUniformBlockiv(_glsl_program, i, GL_UNIFORM_BLOCK_DATA_SIZE, &data_size); _glgsg->_glGetActiveUniformBlockiv(_glsl_program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, ¶m_count); @@ -583,6 +577,7 @@ reflect_uniform_block(int i, const char *name, char *name_buffer, GLsizei name_b numeric_type = GeomEnums::NT_float32; break; +#ifndef OPENGLES case GL_DOUBLE: case GL_DOUBLE_VEC2: case GL_DOUBLE_VEC3: @@ -592,6 +587,7 @@ reflect_uniform_block(int i, const char *name, char *name_buffer, GLsizei name_b case GL_DOUBLE_MAT4: numeric_type = GeomEnums::NT_float64; break; +#endif default: GLCAT.info() << "Ignoring uniform '" << name_buffer @@ -604,7 +600,9 @@ reflect_uniform_block(int i, const char *name, char *name_buffer, GLsizei name_b case GL_BOOL_VEC2: case GL_UNSIGNED_INT_VEC2: case GL_FLOAT_VEC2: +#ifndef OPENGLES case GL_DOUBLE_VEC2: +#endif num_components = 2; break; @@ -612,7 +610,9 @@ reflect_uniform_block(int i, const char *name, char *name_buffer, GLsizei name_b case GL_BOOL_VEC3: case GL_UNSIGNED_INT_VEC3: case GL_FLOAT_VEC3: +#ifndef OPENGLES case GL_DOUBLE_VEC3: +#endif num_components = 3; break; @@ -620,12 +620,16 @@ reflect_uniform_block(int i, const char *name, char *name_buffer, GLsizei name_b case GL_BOOL_VEC4: case GL_UNSIGNED_INT_VEC4: case GL_FLOAT_VEC4: +#ifndef OPENGLES case GL_DOUBLE_VEC4: +#endif num_components = 4; break; case GL_FLOAT_MAT3: +#ifndef OPENGLES case GL_DOUBLE_MAT3: +#endif num_components = 3; contents = GeomEnums::C_matrix; nassertd(param_size <= 1 || astrides[ui] == mstrides[ui] * 3) continue; @@ -633,7 +637,9 @@ reflect_uniform_block(int i, const char *name, char *name_buffer, GLsizei name_b break; case GL_FLOAT_MAT4: +#ifndef OPENGLES case GL_DOUBLE_MAT4: +#endif num_components = 4; contents = GeomEnums::C_matrix; nassertd(param_size <= 1 || astrides[ui] == mstrides[ui] * 4) continue; @@ -655,7 +661,6 @@ reflect_uniform_block(int i, const char *name, char *name_buffer, GLsizei name_b // _uniform_blocks.push_back(block); } -#endif // !OPENGLES /** * Analyzes a single uniform variable and considers how it should be handled @@ -671,23 +676,24 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { _glgsg->_glGetActiveUniform(_glsl_program, i, name_buflen, NULL, ¶m_size, ¶m_type, name_buffer); GLint p = _glgsg->_glGetUniformLocation(_glsl_program, name_buffer); + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Active uniform " << name_buffer << " with size " << param_size + << " and type 0x" << hex << param_type << dec + << " is bound to location " << p << "\n"; + } // Some NVidia drivers (361.43 for example) (incorrectly) include "internal" // uniforms in the list starting with "_main_" (for example, // "_main_0_gp5fp[0]") we need to skip those, because we don't know anything // about them if (strncmp(name_buffer, "_main_", 6) == 0) { - GLCAT.warning() << "Ignoring uniform " << name_buffer << " which may be generated by buggy Nvidia driver.\n"; + if (GLCAT.is_debug()) { + GLCAT.debug() << "Ignoring uniform " << name_buffer << " which may be generated by buggy Nvidia driver.\n"; + } return; } - if (GLCAT.is_debug()) { - GLCAT.debug() - << "Active uniform " << name_buffer << " with size " << param_size - << " and type 0x" << hex << param_type << dec - << " is bound to location " << p << "\n"; - } - if (p < 0) { // Special meaning, or it's in a uniform block. Let it go. return; @@ -1099,9 +1105,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { string member_name(name_buffer); if (member_name == "shadowMap") { switch (param_type) { -#ifndef OPENGLES case GL_SAMPLER_CUBE_SHADOW: -#endif // !OPENGLES case GL_SAMPLER_2D: case GL_SAMPLER_2D_SHADOW: case GL_SAMPLER_CUBE: @@ -1279,26 +1283,26 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { if (param_size == 1) { // A single uniform (not an array, or an array of size 1). switch (param_type) { -#ifndef OPENGLES - case GL_INT_SAMPLER_1D: case GL_INT_SAMPLER_2D: case GL_INT_SAMPLER_3D: case GL_INT_SAMPLER_2D_ARRAY: case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_BUFFER: - case GL_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_1D: case GL_UNSIGNED_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_3D: case GL_UNSIGNED_INT_SAMPLER_CUBE: case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_SAMPLER_1D_SHADOW: - case GL_SAMPLER_1D: case GL_SAMPLER_CUBE_SHADOW: case GL_SAMPLER_2D_ARRAY: case GL_SAMPLER_2D_ARRAY_SHADOW: +#ifndef OPENGLES + case GL_INT_SAMPLER_1D: + case GL_INT_SAMPLER_BUFFER: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_1D: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_1D: + case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_BUFFER: case GL_SAMPLER_CUBE_MAP_ARRAY: case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: @@ -1320,14 +1324,12 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { return; } case GL_FLOAT_MAT2: -#ifndef OPENGLES case GL_FLOAT_MAT2x3: case GL_FLOAT_MAT2x4: case GL_FLOAT_MAT3x2: case GL_FLOAT_MAT3x4: case GL_FLOAT_MAT4x2: case GL_FLOAT_MAT4x3: -#endif GLCAT.warning() << "GLSL shader requested an unsupported matrix type\n"; return; case GL_FLOAT_MAT3: { @@ -1461,28 +1463,29 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { _shader->_ptr_spec.push_back(bind); return; } -#ifndef OPENGLES - case GL_IMAGE_1D: case GL_IMAGE_2D: case GL_IMAGE_3D: case GL_IMAGE_CUBE: case GL_IMAGE_2D_ARRAY: - case GL_IMAGE_CUBE_MAP_ARRAY: - case GL_IMAGE_BUFFER: - case GL_INT_IMAGE_1D: case GL_INT_IMAGE_2D: case GL_INT_IMAGE_3D: case GL_INT_IMAGE_CUBE: case GL_INT_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_IMAGE_1D: case GL_UNSIGNED_INT_IMAGE_2D: case GL_UNSIGNED_INT_IMAGE_3D: case GL_UNSIGNED_INT_IMAGE_CUBE: case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: +#ifndef OPENGLES + case GL_IMAGE_1D: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_IMAGE_BUFFER: + case GL_INT_IMAGE_1D: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_1D: case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: case GL_UNSIGNED_INT_IMAGE_BUFFER: +#endif // This won't really change at runtime, so we might as well bind once // and then forget about it. _glgsg->_glUniform1i(p, _glsl_img_inputs.size()); @@ -1494,7 +1497,6 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { _glsl_img_inputs.push_back(input); } return; -#endif default: GLCAT.warning() << "Ignoring unrecognized GLSL parameter type!\n"; } @@ -1502,14 +1504,12 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { // A uniform array. switch (param_type) { case GL_FLOAT_MAT2: -#ifndef OPENGLES case GL_FLOAT_MAT2x3: case GL_FLOAT_MAT2x4: case GL_FLOAT_MAT3x2: case GL_FLOAT_MAT3x4: case GL_FLOAT_MAT4x2: case GL_FLOAT_MAT4x3: -#endif GLCAT.warning() << "GLSL shader requested an unrecognized matrix array type\n"; return; case GL_BOOL: @@ -1597,10 +1597,10 @@ get_sampler_texture_type(int &out, GLenum param_type) { case GL_SAMPLER_1D: out = Texture::TT_1d_texture; return true; +#endif case GL_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_2D: -#endif case GL_SAMPLER_2D: out = Texture::TT_2d_texture; return true; @@ -1614,10 +1614,8 @@ get_sampler_texture_type(int &out, GLenum param_type) { } return true; -#ifndef OPENGLES case GL_INT_SAMPLER_3D: case GL_UNSIGNED_INT_SAMPLER_3D: -#endif case GL_SAMPLER_3D: out = Texture::TT_3d_texture; if (_glgsg->_supports_3d_texture) { @@ -1628,7 +1626,6 @@ get_sampler_texture_type(int &out, GLenum param_type) { return false; } -#ifndef OPENGLES case GL_SAMPLER_CUBE_SHADOW: if (!_glgsg->_supports_shadow_filter) { GLCAT.error() @@ -1638,7 +1635,6 @@ get_sampler_texture_type(int &out, GLenum param_type) { // Fall through case GL_INT_SAMPLER_CUBE: case GL_UNSIGNED_INT_SAMPLER_CUBE: -#endif case GL_SAMPLER_CUBE: out = Texture::TT_cube_map; if (!_glgsg->_supports_cube_map) { @@ -1648,7 +1644,6 @@ get_sampler_texture_type(int &out, GLenum param_type) { } return true; -#ifndef OPENGLES case GL_SAMPLER_2D_ARRAY_SHADOW: if (!_glgsg->_supports_shadow_filter) { GLCAT.error() @@ -1668,6 +1663,7 @@ get_sampler_texture_type(int &out, GLenum param_type) { return false; } +#ifndef OPENGLES case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: if (!_glgsg->_supports_shadow_filter) { GLCAT.error() @@ -1699,7 +1695,7 @@ get_sampler_texture_type(int &out, GLenum param_type) { << "GLSL shader uses buffer texture, which is unsupported by the driver.\n"; return false; } -#endif +#endif // !OPENGLES default: GLCAT.error() @@ -2129,7 +2125,6 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { const GeomVertexArrayDataHandle *array_reader; -#ifndef OPENGLES if (_glgsg->_use_vertex_attrib_binding) { // Use experimental new separated formatbinding state. const GeomVertexDataPipelineReader *data_reader = _glgsg->_data_reader; @@ -2185,9 +2180,7 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { } _glgsg->_enabled_vertex_attrib_arrays = enabled_attribs; - } else -#endif - { + } else { Geom::NumericType numeric_type; int start, stride, num_values; size_t nvarying = _shader->_var_spec.size(); @@ -2230,13 +2223,10 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { for (int i = 0; i < num_elements; ++i) { _glgsg->enable_vertex_attrib_array(p); -#ifndef OPENGLES if (bind._integer) { _glgsg->_glVertexAttribIPointer(p, num_values, _glgsg->get_numeric_type(numeric_type), stride, client_pointer); - } else -#endif - if (numeric_type == GeomEnums::NT_packed_dabc) { + } else if (numeric_type == GeomEnums::NT_packed_dabc) { // GL_BGRA is a special accepted value available since OpenGL 3.2. // It requires us to pass GL_TRUE for normalized. _glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE, @@ -2340,9 +2330,7 @@ disable_shader_texture_bindings() { break; case Texture::TT_2d_texture_array: -#ifndef OPENGLES - glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 0); -#endif + glBindTexture(GL_TEXTURE_2D_ARRAY, 0); break; case Texture::TT_cube_map: @@ -2357,15 +2345,16 @@ disable_shader_texture_bindings() { } } -#ifndef OPENGLES // Now unbind all the image units. Not sure if we *have* to do this. int num_image_units = min(_glsl_img_inputs.size(), (size_t)_glgsg->_max_image_units); if (num_image_units > 0) { +#ifndef OPENGLES if (_glgsg->_supports_multi_bind) { _glgsg->_glBindImageTextures(0, num_image_units, NULL); - - } else { + } else +#endif + { for (int i = 0; i < num_image_units; ++i) { _glgsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); } @@ -2382,7 +2371,6 @@ disable_shader_texture_bindings() { } } } -#endif _glgsg->report_my_gl_errors(); } @@ -2402,7 +2390,6 @@ update_shader_texture_bindings(ShaderContext *prev) { return; } -#ifndef OPENGLES GLbitfield barriers = 0; // First bind all the 'image units'; a bit of an esoteric OpenGL feature @@ -2500,7 +2487,6 @@ update_shader_texture_bindings(ShaderContext *prev) { } } } -#endif size_t num_textures = _shader->_tex_spec.size(); GLuint *textures; @@ -2679,10 +2665,10 @@ glsl_report_shader_errors(GLuint shader, Shader::ShaderType type, bool fatal) { istringstream log(info_log); string line; while (getline(log, line)) { - int fileno, lineno; + int fileno, lineno, colno; int prefixlen = 0; - // First is AMDIntel driver syntax, second is NVIDIA syntax. + // This first format is used by the majority of compilers. if (sscanf(line.c_str(), "ERROR: %d:%d: %n", &fileno, &lineno, &prefixlen) == 2 && prefixlen > 0) { @@ -2697,14 +2683,22 @@ glsl_report_shader_errors(GLuint shader, Shader::ShaderType type, bool fatal) { GLCAT.warning(false) << "WARNING: " << fn << ":" << lineno << ": " << (line.c_str() + prefixlen) << "\n"; - } else if (sscanf(line.c_str(), "%d(%d) : %n", &fileno, &lineno, &prefixlen) == 2 && prefixlen > 0) { + // This is the format NVIDIA uses. Filename fn = _shader->get_filename_from_index(fileno, type); GLCAT.error(false) << fn << "(" << lineno << ") : " << (line.c_str() + prefixlen) << "\n"; + } else if (sscanf(line.c_str(), "%d:%d(%d): %n", &fileno, &lineno, &colno, &prefixlen) == 3 + && prefixlen > 0) { + + // This is the format for Mesa's OpenGL ES 2 implementation. + Filename fn = _shader->get_filename_from_index(fileno, type); + GLCAT.error(false) + << fn << ":" << lineno << "(" << colno << "): " << (line.c_str() + prefixlen) << "\n"; + } else if (!fatal) { GLCAT.warning(false) << line << "\n"; @@ -2781,12 +2775,12 @@ glsl_compile_shader(Shader::ShaderType type) { handle = _glgsg->_glCreateShader(GL_TESS_EVALUATION_SHADER); } break; +#endif case Shader::ST_compute: if (_glgsg->get_supports_compute_shaders()) { handle = _glgsg->_glCreateShader(GL_COMPUTE_SHADER); } break; -#endif default: break; } @@ -2844,7 +2838,6 @@ glsl_compile_and_link() { _glgsg->_glObjectLabel(GL_PROGRAM, _glsl_program, name.size(), name.data()); } -#ifndef OPENGLES // Do we have a compiled program? Try to load that. unsigned int format; string binary; @@ -2868,7 +2861,6 @@ glsl_compile_and_link() { << _shader->get_filename() << "\n"; } } -#endif bool valid = true; @@ -2933,7 +2925,6 @@ glsl_compile_and_link() { // If we requested to retrieve the shader, we should indicate that before // linking. -#ifndef OPENGLES bool retrieve_binary = false; if (_glgsg->_supports_get_program_binary) { retrieve_binary = _shader->get_cache_compiled_shader(); @@ -2946,7 +2937,6 @@ glsl_compile_and_link() { _glgsg->_glProgramParameteri(_glsl_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); } -#endif if (GLCAT.is_debug()) { GLCAT.debug() @@ -2967,7 +2957,6 @@ glsl_compile_and_link() { // Report any warnings. glsl_report_program_errors(_glsl_program, false); -#ifndef OPENGLES if (retrieve_binary) { GLint length = 0; _glgsg->_glGetProgramiv(_glsl_program, GL_PROGRAM_BINARY_LENGTH, &length); @@ -2998,7 +2987,6 @@ glsl_compile_and_link() { } #endif // NDEBUG } -#endif // OPENGLES _glgsg->report_my_gl_errors(); return true; diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index 4209ec66fb..183f068277 100644 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -35,10 +35,8 @@ public: ALLOC_DELETED_CHAIN(CLP(ShaderContext)); void reflect_attribute(int i, char *name_buf, GLsizei name_buflen); -#ifndef OPENGLES void reflect_uniform_block(int i, const char *block_name, char *name_buffer, GLsizei name_buflen); -#endif void reflect_uniform(int i, char *name_buffer, GLsizei name_buflen); bool get_sampler_texture_type(int &out, GLenum param_type); @@ -85,7 +83,9 @@ private: GLsizei _slider_table_size; GLint _frame_number_loc; GLint _frame_number; +#ifndef OPENGLES pmap _glsl_uniform_handles; +#endif struct ImageInput { CPT(InternalName) _name; diff --git a/panda/src/glstuff/glTextureContext_src.I b/panda/src/glstuff/glTextureContext_src.I index d4b4232513..33bda9a58f 100644 --- a/panda/src/glstuff/glTextureContext_src.I +++ b/panda/src/glstuff/glTextureContext_src.I @@ -24,7 +24,10 @@ CLP(TextureContext)(CLP(GraphicsStateGuardian) *glgsg, glGenTextures(1, &_index); _buffer = 0; +#ifndef OPENGLES _handle = 0; + _handle_resident = false; +#endif _has_storage = false; _immutable = false; _uses_mipmaps = false; diff --git a/panda/src/glstuff/glTextureContext_src.cxx b/panda/src/glstuff/glTextureContext_src.cxx index 8639b898a2..a56d6a20a4 100644 --- a/panda/src/glstuff/glTextureContext_src.cxx +++ b/panda/src/glstuff/glTextureContext_src.cxx @@ -77,12 +77,14 @@ reset_data() { // the texture later. glGenTextures(1, &_index); +#ifndef OPENGLES _handle = 0; _handle_resident = false; +#endif _has_storage = false; _immutable = false; -#ifndef OPENGLES +#ifndef OPENGLES_1 // Mark the texture as coherent. if (gl_enable_memory_barriers) { _glgsg->_textures_needing_fetch_barrier.erase(this); @@ -96,9 +98,9 @@ reset_data() { /** * */ +#ifndef OPENGLES void CLP(TextureContext):: make_handle_resident() { -#ifndef OPENGLES if (_handle != 0) { if (!_handle_resident) { _glgsg->_glMakeTextureHandleResident(_handle); @@ -106,18 +108,17 @@ make_handle_resident() { } set_resident(true); } -#endif } +#endif /** * Returns a handle for this texture. Once this has been created, the texture * data may still be updated, but its properties may not. */ +#ifndef OPENGLES INLINE GLuint64 CLP(TextureContext):: get_handle() { -#ifdef OPENGLES return 0; -#else if (!_glgsg->_supports_bindless_texture) { return false; } @@ -128,10 +129,10 @@ get_handle() { _immutable = true; return _handle; -#endif } +#endif -#ifndef OPENGLES +#ifndef OPENGLES_1 /** * */ @@ -176,4 +177,4 @@ mark_incoherent(bool wrote) { _glgsg->_textures_needing_framebuffer_barrier.insert(this); } -#endif // OPENGLES +#endif // !OPENGLES_1 diff --git a/panda/src/glstuff/glTextureContext_src.h b/panda/src/glstuff/glTextureContext_src.h index 8a36882f26..309550eced 100644 --- a/panda/src/glstuff/glTextureContext_src.h +++ b/panda/src/glstuff/glTextureContext_src.h @@ -33,10 +33,12 @@ public: virtual void evict_lru(); void reset_data(); +#ifndef OPENGLES void make_handle_resident(); GLuint64 get_handle(); +#endif -#ifdef OPENGLES +#ifdef OPENGLES_1 static CONSTEXPR bool needs_barrier(GLbitfield barrier) { return false; }; #else bool needs_barrier(GLbitfield barrier); @@ -49,9 +51,11 @@ public: // This is only used for buffer textures. GLuint _buffer; +#ifndef OPENGLES // This is the bindless "handle" to the texture object. GLuint64 _handle; bool _handle_resident; +#endif // These are the parameters that we specified with the last glTexImage2D() // or glTexStorage2D() call. If none of these have changed, we can reload diff --git a/panda/src/gobj/geom.h b/panda/src/gobj/geom.h index 3d6715b473..6a12e8ee98 100644 --- a/panda/src/gobj/geom.h +++ b/panda/src/gobj/geom.h @@ -95,6 +95,7 @@ PUBLISHED: void add_primitive(const GeomPrimitive *primitive); void remove_primitive(int i); void clear_primitives(); + MAKE_SEQ_PROPERTY(primitives, get_num_primitives, get_primitive, set_primitive, remove_primitive); INLINE PT(Geom) decompose() const; INLINE PT(Geom) doubleside() const; diff --git a/panda/src/gobj/geomPrimitive.cxx b/panda/src/gobj/geomPrimitive.cxx index 67b65689e1..6f918eefdb 100644 --- a/panda/src/gobj/geomPrimitive.cxx +++ b/panda/src/gobj/geomPrimitive.cxx @@ -2231,7 +2231,8 @@ get_num_primitives() const { */ bool GeomPrimitivePipelineReader:: check_valid(const GeomVertexDataPipelineReader *data_reader) const { - if (get_num_vertices() != 0 && + if (get_num_vertices() != 0 && + data_reader->get_num_arrays() > 0 && get_max_vertex() >= data_reader->get_num_rows()) { #ifndef NDEBUG diff --git a/panda/src/gobj/geomVertexArrayFormat.cxx b/panda/src/gobj/geomVertexArrayFormat.cxx index 30c961c33b..20568fa1a3 100644 --- a/panda/src/gobj/geomVertexArrayFormat.cxx +++ b/panda/src/gobj/geomVertexArrayFormat.cxx @@ -363,7 +363,8 @@ align_columns_for_animation() { add_column(column->get_name(), 4, column->get_numeric_type(), column->get_contents(), -1, 16); } else { add_column(column->get_name(), column->get_num_components(), - column->get_numeric_type(), column->get_contents()); + column->get_numeric_type(), column->get_contents(), + -1, column->get_column_alignment()); } } } @@ -708,7 +709,10 @@ write_datagram(BamWriter *manager, Datagram &dg) { dg.add_uint16(_stride); dg.add_uint16(_total_bytes); dg.add_uint8(_pad_to); - dg.add_uint16(_divisor); + + if (manager->get_file_minor_ver() > 36) { + dg.add_uint16(_divisor); + } consider_sort_columns(); diff --git a/panda/src/gobj/geomVertexArrayFormat.h b/panda/src/gobj/geomVertexArrayFormat.h index 6d252087f3..3b8ca3a221 100644 --- a/panda/src/gobj/geomVertexArrayFormat.h +++ b/panda/src/gobj/geomVertexArrayFormat.h @@ -104,6 +104,7 @@ PUBLISHED: INLINE int get_num_columns() const; INLINE const GeomVertexColumn *get_column(int i) const; MAKE_SEQ(get_columns, get_num_columns, get_column); + MAKE_SEQ_PROPERTY(columns, get_num_columns, get_column); const GeomVertexColumn *get_column(const InternalName *name) const; const GeomVertexColumn *get_column(int start_byte, int num_bytes) const; diff --git a/panda/src/gobj/geomVertexColumn.cxx b/panda/src/gobj/geomVertexColumn.cxx index a49dda6274..3227eb7b42 100644 --- a/panda/src/gobj/geomVertexColumn.cxx +++ b/panda/src/gobj/geomVertexColumn.cxx @@ -165,12 +165,12 @@ setup() { switch (_numeric_type) { case NT_uint16: case NT_int16: - _component_bytes = 2; // sizeof(PN_uint16) + _component_bytes = 2; // sizeof(uint16_t) break; case NT_uint32: case NT_int32: - _component_bytes = 4; // sizeof(PN_uint32) + _component_bytes = 4; // sizeof(uint32_t) break; case NT_uint8: @@ -180,7 +180,7 @@ setup() { case NT_packed_dcba: case NT_packed_dabc: - _component_bytes = 4; // sizeof(PN_uint32) + _component_bytes = 4; // sizeof(uint32_t) _num_values *= 4; break; @@ -197,7 +197,7 @@ setup() { break; case NT_packed_ufloat: - _component_bytes = 4; // sizeof(PN_uint32) + _component_bytes = 4; // sizeof(uint32_t) _num_values *= 3; break; } @@ -378,9 +378,19 @@ write_datagram(BamWriter *manager, Datagram &dg) { manager->write_pointer(dg, _name); dg.add_uint8(_num_components); dg.add_uint8(_numeric_type); - dg.add_uint8(_contents); + + if (_contents == C_normal && manager->get_file_minor_ver() < 38) { + // Panda 1.9 did not have C_normal. + dg.add_uint8(C_vector); + } else { + dg.add_uint8(_contents); + } + dg.add_uint16(_start); - dg.add_uint8(_column_alignment); + + if (manager->get_file_minor_ver() >= 29) { + dg.add_uint8(_column_alignment); + } } /** @@ -441,23 +451,23 @@ float GeomVertexColumn::Packer:: get_data1f(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: - return *(const PN_uint8 *)pointer; + return *(const uint8_t *)pointer; case NT_uint16: - return *(const PN_uint16 *)pointer; + return *(const uint16_t *)pointer; case NT_uint32: - return *(const PN_uint32 *)pointer; + return *(const uint32_t *)pointer; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_abcd_d(dword); } case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_abcd_b(dword); } @@ -468,17 +478,17 @@ get_data1f(const unsigned char *pointer) { return *(const PN_float64 *)pointer; case NT_int8: - return *(const PN_int8 *)pointer; + return *(const int8_t *)pointer; case NT_int16: - return *(const PN_int16 *)pointer; + return *(const int16_t *)pointer; case NT_int32: - return *(const PN_int32 *)pointer; + return *(const int32_t *)pointer; case NT_packed_ufloat: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_ufloat_a(dword); } @@ -502,28 +512,28 @@ get_data2f(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v2.set(pi[0], pi[1]); } return _v2; case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v2.set(pi[0], pi[1]); } return _v2; case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v2.set(pi[0], pi[1]); } return _v2; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v2.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword)); } @@ -531,7 +541,7 @@ get_data2f(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v2.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword)); } @@ -557,21 +567,21 @@ get_data2f(const unsigned char *pointer) { case NT_int8: { - const PN_int8 *pi = (const PN_int8 *)pointer; + const int8_t *pi = (const int8_t *)pointer; _v2.set(pi[0], pi[1]); } return _v2; case NT_int16: { - const PN_int16 *pi = (const PN_int16 *)pointer; + const int16_t *pi = (const int16_t *)pointer; _v2.set(pi[0], pi[1]); } return _v2; case NT_int32: { - const PN_int32 *pi = (const PN_int32 *)pointer; + const int32_t *pi = (const int32_t *)pointer; _v2.set(pi[0], pi[1]); } return _v2; @@ -606,28 +616,28 @@ get_data3f(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v3.set(pi[0], pi[1], pi[2]); } return _v3; case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v3.set(pi[0], pi[1], pi[2]); } return _v3; case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v3.set(pi[0], pi[1], pi[2]); } return _v3; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v3.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_b(dword)); @@ -636,7 +646,7 @@ get_data3f(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v3.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_d(dword)); @@ -663,28 +673,28 @@ get_data3f(const unsigned char *pointer) { case NT_int8: { - const PN_int8 *pi = (const PN_int8 *)pointer; + const int8_t *pi = (const int8_t *)pointer; _v3.set(pi[0], pi[1], pi[2]); } return _v3; case NT_int16: { - const PN_int16 *pi = (const PN_int16 *)pointer; + const int16_t *pi = (const int16_t *)pointer; _v3.set(pi[0], pi[1], pi[2]); } return _v3; case NT_int32: { - const PN_int32 *pi = (const PN_int32 *)pointer; + const int32_t *pi = (const int32_t *)pointer; _v3.set(pi[0], pi[1], pi[2]); } return _v3; case NT_packed_ufloat: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v3.set(GeomVertexData::unpack_ufloat_a(dword), GeomVertexData::unpack_ufloat_b(dword), GeomVertexData::unpack_ufloat_c(dword)); @@ -724,28 +734,28 @@ get_data4f(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_b(dword), @@ -755,7 +765,7 @@ get_data4f(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_d(dword), @@ -783,21 +793,21 @@ get_data4f(const unsigned char *pointer) { case NT_int8: { - const PN_int8 *pi = (const PN_int8 *)pointer; + const int8_t *pi = (const int8_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; case NT_int16: { - const PN_int16 *pi = (const PN_int16 *)pointer; + const int16_t *pi = (const int16_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; case NT_int32: { - const PN_int32 *pi = (const PN_int32 *)pointer; + const int32_t *pi = (const int32_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; @@ -818,23 +828,23 @@ double GeomVertexColumn::Packer:: get_data1d(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: - return *(const PN_uint8 *)pointer; + return *(const uint8_t *)pointer; case NT_uint16: - return *(const PN_uint16 *)pointer; + return *(const uint16_t *)pointer; case NT_uint32: - return *(const PN_uint32 *)pointer; + return *(const uint32_t *)pointer; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_abcd_d(dword); } case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_abcd_b(dword); } @@ -849,17 +859,17 @@ get_data1d(const unsigned char *pointer) { return 0.0; case NT_int8: - return *(const PN_int8 *)pointer; + return *(const int8_t *)pointer; case NT_int16: - return *(const PN_int16 *)pointer; + return *(const int16_t *)pointer; case NT_int32: - return *(const PN_int32 *)pointer; + return *(const int32_t *)pointer; case NT_packed_ufloat: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_ufloat_a(dword); } } @@ -880,28 +890,28 @@ get_data2d(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v2d.set(pi[0], pi[1]); } return _v2d; case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v2d.set(pi[0], pi[1]); } return _v2d; case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v2d.set(pi[0], pi[1]); } return _v2d; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v2d.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword)); } @@ -909,7 +919,7 @@ get_data2d(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v2d.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword)); } @@ -935,21 +945,21 @@ get_data2d(const unsigned char *pointer) { case NT_int8: { - const PN_int8 *pi = (const PN_int8 *)pointer; + const int8_t *pi = (const int8_t *)pointer; _v2d.set(pi[0], pi[1]); } return _v2d; case NT_int16: { - const PN_int16 *pi = (const PN_int16 *)pointer; + const int16_t *pi = (const int16_t *)pointer; _v2d.set(pi[0], pi[1]); } return _v2d; case NT_int32: { - const PN_int32 *pi = (const PN_int32 *)pointer; + const int32_t *pi = (const int32_t *)pointer; _v2d.set(pi[0], pi[1]); } return _v2d; @@ -984,28 +994,28 @@ get_data3d(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v3d.set(pi[0], pi[1], pi[2]); } return _v3d; case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v3d.set(pi[0], pi[1], pi[2]); } return _v3d; case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v3d.set(pi[0], pi[1], pi[2]); } return _v3d; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v3d.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_b(dword)); @@ -1014,7 +1024,7 @@ get_data3d(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v3d.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_d(dword)); @@ -1041,28 +1051,28 @@ get_data3d(const unsigned char *pointer) { case NT_int8: { - const PN_int8 *pi = (const PN_int8 *)pointer; + const int8_t *pi = (const int8_t *)pointer; _v3d.set(pi[0], pi[1], pi[2]); } return _v3d; case NT_int16: { - const PN_int16 *pi = (const PN_int16 *)pointer; + const int16_t *pi = (const int16_t *)pointer; _v3d.set(pi[0], pi[1], pi[2]); } return _v3d; case NT_int32: { - const PN_int32 *pi = (const PN_int32 *)pointer; + const int32_t *pi = (const int32_t *)pointer; _v3d.set(pi[0], pi[1], pi[2]); } return _v3d; case NT_packed_ufloat: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v3d.set(GeomVertexData::unpack_ufloat_a(dword), GeomVertexData::unpack_ufloat_b(dword), GeomVertexData::unpack_ufloat_c(dword)); @@ -1102,28 +1112,28 @@ get_data4d(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4d.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_b(dword), @@ -1133,7 +1143,7 @@ get_data4d(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4d.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_d(dword), @@ -1161,21 +1171,21 @@ get_data4d(const unsigned char *pointer) { case NT_int8: { - const PN_int8 *pi = (const PN_int8 *)pointer; + const int8_t *pi = (const int8_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; case NT_int16: { - const PN_int16 *pi = (const PN_int16 *)pointer; + const int16_t *pi = (const int16_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; case NT_int32: { - const PN_int32 *pi = (const PN_int32 *)pointer; + const int32_t *pi = (const int32_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; @@ -1199,20 +1209,20 @@ get_data1i(const unsigned char *pointer) { return *pointer; case NT_uint16: - return *(const PN_uint16 *)pointer; + return *(const uint16_t *)pointer; case NT_uint32: - return *(const PN_uint32 *)pointer; + return *(const uint32_t *)pointer; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_abcd_d(dword); } case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_abcd_b(dword); } @@ -1227,17 +1237,17 @@ get_data1i(const unsigned char *pointer) { break; case NT_int8: - return *(const PN_int8 *)pointer; + return *(const int8_t *)pointer; case NT_int16: - return *(const PN_int16 *)pointer; + return *(const int16_t *)pointer; case NT_int32: - return *(const PN_int32 *)pointer; + return *(const int32_t *)pointer; case NT_packed_ufloat: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return (int)GeomVertexData::unpack_ufloat_a(dword); } } @@ -1263,21 +1273,21 @@ get_data2i(const unsigned char *pointer) { case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v2i.set(pi[0], pi[1]); } return _v2i; case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v2i.set(pi[0], pi[1]); } return _v2i; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v2i.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword)); } @@ -1285,7 +1295,7 @@ get_data2i(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v2i.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword)); } @@ -1311,21 +1321,21 @@ get_data2i(const unsigned char *pointer) { case NT_int8: { - const PN_int8 *pi = (const PN_int8 *)pointer; + const int8_t *pi = (const int8_t *)pointer; _v2i.set(pi[0], pi[1]); } return _v2i; case NT_int16: { - const PN_int16 *pi = (const PN_int16 *)pointer; + const int16_t *pi = (const int16_t *)pointer; _v2i.set(pi[0], pi[1]); } return _v2i; case NT_int32: { - const PN_int32 *pi = (const PN_int32 *)pointer; + const int32_t *pi = (const int32_t *)pointer; _v2i.set(pi[0], pi[1]); } return _v2i; @@ -1364,21 +1374,21 @@ get_data3i(const unsigned char *pointer) { case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v3i.set(pi[0], pi[1], pi[2]); } return _v3i; case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v3i.set(pi[0], pi[1], pi[2]); } return _v3i; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v3i.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_b(dword)); @@ -1387,7 +1397,7 @@ get_data3i(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v3i.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_d(dword)); @@ -1414,28 +1424,28 @@ get_data3i(const unsigned char *pointer) { case NT_int8: { - const PN_int8 *pi = (const PN_int8 *)pointer; + const int8_t *pi = (const int8_t *)pointer; _v3i.set(pi[0], pi[1], pi[2]); } return _v3i; case NT_int16: { - const PN_int16 *pi = (const PN_int16 *)pointer; + const int16_t *pi = (const int16_t *)pointer; _v3i.set(pi[0], pi[1], pi[2]); } return _v3i; case NT_int32: { - const PN_int32 *pi = (const PN_int32 *)pointer; + const int32_t *pi = (const int32_t *)pointer; _v3i.set(pi[0], pi[1], pi[2]); } return _v3i; case NT_packed_ufloat: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v3i.set((int)GeomVertexData::unpack_ufloat_a(dword), (int)GeomVertexData::unpack_ufloat_b(dword), (int)GeomVertexData::unpack_ufloat_c(dword)); @@ -1479,21 +1489,21 @@ get_data4i(const unsigned char *pointer) { case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v4i.set(pi[0], pi[1], pi[2], pi[3]); } return _v4i; case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v4i.set(pi[0], pi[1], pi[2], pi[3]); } return _v4i; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4i.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_b(dword), @@ -1503,7 +1513,7 @@ get_data4i(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4i.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_d(dword), @@ -1531,21 +1541,21 @@ get_data4i(const unsigned char *pointer) { case NT_int8: { - const PN_int8 *pi = (const PN_int8 *)pointer; + const int8_t *pi = (const int8_t *)pointer; _v4i.set(pi[0], pi[1], pi[2], pi[3]); } return _v4i; case NT_int16: { - const PN_int16 *pi = (const PN_int16 *)pointer; + const int16_t *pi = (const int16_t *)pointer; _v4i.set(pi[0], pi[1], pi[2], pi[3]); } return _v4i; case NT_int32: { - const PN_int32 *pi = (const PN_int32 *)pointer; + const int32_t *pi = (const int32_t *)pointer; _v4i.set(pi[0], pi[1], pi[2], pi[3]); } return _v4i; @@ -1568,15 +1578,15 @@ set_data1f(unsigned char *pointer, float data) { case 1: switch (_column->get_numeric_type()) { case NT_uint8: - *(PN_uint8 *)pointer = (unsigned int)data; + *(uint8_t *)pointer = (unsigned int)data; break; case NT_uint16: - *(PN_uint16 *)pointer = (unsigned int)data; + *(uint16_t *)pointer = (unsigned int)data; break; case NT_uint32: - *(PN_uint32 *)pointer = (unsigned int)data; + *(uint32_t *)pointer = (unsigned int)data; break; case NT_packed_dcba: @@ -1597,15 +1607,15 @@ set_data1f(unsigned char *pointer, float data) { break; case NT_int8: - *(PN_int8 *)pointer = (int)data; + *(int8_t *)pointer = (int)data; break; case NT_int16: - *(PN_int16 *)pointer = (int)data; + *(int16_t *)pointer = (int)data; break; case NT_int32: - *(PN_int32 *)pointer = (int)data; + *(int32_t *)pointer = (int)data; break; case NT_packed_ufloat: @@ -1642,7 +1652,7 @@ set_data2f(unsigned char *pointer, const LVecBase2f &data) { switch (_column->get_numeric_type()) { case NT_uint8: { - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; } @@ -1650,7 +1660,7 @@ set_data2f(unsigned char *pointer, const LVecBase2f &data) { case NT_uint16: { - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; } @@ -1658,7 +1668,7 @@ set_data2f(unsigned char *pointer, const LVecBase2f &data) { case NT_uint32: { - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; } @@ -1691,7 +1701,7 @@ set_data2f(unsigned char *pointer, const LVecBase2f &data) { case NT_int8: { - PN_int8 *pi = (PN_int8 *)pointer; + int8_t *pi = (int8_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; } @@ -1699,7 +1709,7 @@ set_data2f(unsigned char *pointer, const LVecBase2f &data) { case NT_int16: { - PN_int16 *pi = (PN_int16 *)pointer; + int16_t *pi = (int16_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; } @@ -1707,7 +1717,7 @@ set_data2f(unsigned char *pointer, const LVecBase2f &data) { case NT_int32: { - PN_int32 *pi = (PN_int32 *)pointer; + int32_t *pi = (int32_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; } @@ -1747,7 +1757,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { switch (_column->get_numeric_type()) { case NT_uint8: { - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -1756,7 +1766,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { case NT_uint16: { - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -1765,7 +1775,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { case NT_uint32: { - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -1801,7 +1811,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { case NT_int8: { - PN_int8 *pi = (PN_int8 *)pointer; + int8_t *pi = (int8_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -1810,7 +1820,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { case NT_int16: { - PN_int16 *pi = (PN_int16 *)pointer; + int16_t *pi = (int16_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -1819,7 +1829,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { case NT_int32: { - PN_int32 *pi = (PN_int32 *)pointer; + int32_t *pi = (int32_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -1827,7 +1837,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { break; case NT_packed_ufloat: - *(PN_uint32 *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]); + *(uint32_t *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]); break; } break; @@ -1860,7 +1870,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { switch (_column->get_numeric_type()) { case NT_uint8: { - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -1870,7 +1880,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_uint16: { - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -1880,7 +1890,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_uint32: { - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -1889,11 +1899,11 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { break; case NT_packed_dcba: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]); + *(uint32_t *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]); break; case NT_packed_dabc: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]); + *(uint32_t *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]); break; case NT_float32: @@ -1922,7 +1932,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_int8: { - PN_int8 *pi = (PN_int8 *)pointer; + int8_t *pi = (int8_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -1932,7 +1942,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_int16: { - PN_int16 *pi = (PN_int16 *)pointer; + int16_t *pi = (int16_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -1942,7 +1952,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_int32: { - PN_int32 *pi = (PN_int32 *)pointer; + int32_t *pi = (int32_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -1967,15 +1977,15 @@ set_data1d(unsigned char *pointer, double data) { case 1: switch (_column->get_numeric_type()) { case NT_uint8: - *(PN_uint8 *)pointer = (unsigned int)data; + *(uint8_t *)pointer = (unsigned int)data; break; case NT_uint16: - *(PN_uint16 *)pointer = (unsigned int)data; + *(uint16_t *)pointer = (unsigned int)data; break; case NT_uint32: - *(PN_uint32 *)pointer = (unsigned int)data; + *(uint32_t *)pointer = (unsigned int)data; break; case NT_packed_dcba: @@ -1996,15 +2006,15 @@ set_data1d(unsigned char *pointer, double data) { break; case NT_int8: - *(PN_int8 *)pointer = (int)data; + *(int8_t *)pointer = (int)data; break; case NT_int16: - *(PN_int16 *)pointer = (int)data; + *(int16_t *)pointer = (int)data; break; case NT_int32: - *(PN_int32 *)pointer = (int)data; + *(int32_t *)pointer = (int)data; break; case NT_packed_ufloat: @@ -2040,7 +2050,7 @@ set_data2d(unsigned char *pointer, const LVecBase2d &data) { switch (_column->get_numeric_type()) { case NT_uint8: { - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; } @@ -2048,7 +2058,7 @@ set_data2d(unsigned char *pointer, const LVecBase2d &data) { case NT_uint16: { - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; } @@ -2056,7 +2066,7 @@ set_data2d(unsigned char *pointer, const LVecBase2d &data) { case NT_uint32: { - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; } @@ -2089,7 +2099,7 @@ set_data2d(unsigned char *pointer, const LVecBase2d &data) { case NT_int8: { - PN_int8 *pi = (PN_int8 *)pointer; + int8_t *pi = (int8_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; } @@ -2097,7 +2107,7 @@ set_data2d(unsigned char *pointer, const LVecBase2d &data) { case NT_int16: { - PN_int16 *pi = (PN_int16 *)pointer; + int16_t *pi = (int16_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; } @@ -2105,7 +2115,7 @@ set_data2d(unsigned char *pointer, const LVecBase2d &data) { case NT_int32: { - PN_int32 *pi = (PN_int32 *)pointer; + int32_t *pi = (int32_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; } @@ -2145,7 +2155,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { switch (_column->get_numeric_type()) { case NT_uint8: { - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -2154,7 +2164,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { case NT_uint16: { - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -2163,7 +2173,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { case NT_uint32: { - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -2199,7 +2209,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { case NT_int8: { - PN_int8 *pi = (PN_int8 *)pointer; + int8_t *pi = (int8_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -2208,7 +2218,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { case NT_int16: { - PN_int16 *pi = (PN_int16 *)pointer; + int16_t *pi = (int16_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -2217,7 +2227,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { case NT_int32: { - PN_int32 *pi = (PN_int32 *)pointer; + int32_t *pi = (int32_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -2225,7 +2235,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { break; case NT_packed_ufloat: - *(PN_uint32 *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]); + *(uint32_t *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]); break; } break; @@ -2258,7 +2268,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { switch (_column->get_numeric_type()) { case NT_uint8: { - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -2268,7 +2278,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_uint16: { - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -2278,7 +2288,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_uint32: { - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -2287,11 +2297,11 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { break; case NT_packed_dcba: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]); + *(uint32_t *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]); break; case NT_packed_dabc: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]); + *(uint32_t *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]); break; case NT_float32: @@ -2320,7 +2330,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_int8: { - PN_int8 *pi = (PN_int8 *)pointer; + int8_t *pi = (int8_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -2330,7 +2340,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_int16: { - PN_int16 *pi = (PN_int16 *)pointer; + int16_t *pi = (int16_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -2340,7 +2350,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_int32: { - PN_int32 *pi = (PN_int32 *)pointer; + int32_t *pi = (int32_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -2370,12 +2380,12 @@ set_data1i(unsigned char *pointer, int data) { break; case NT_uint16: - *(PN_uint16 *)pointer = data; - nassertv(*(PN_uint16 *)pointer == data); + *(uint16_t *)pointer = data; + nassertv(*(uint16_t *)pointer == data); break; case NT_uint32: - *(PN_uint32 *)pointer = data; + *(uint32_t *)pointer = data; break; case NT_packed_dcba: @@ -2396,17 +2406,17 @@ set_data1i(unsigned char *pointer, int data) { break; case NT_int8: - *(PN_int8 *)pointer = data; - nassertv(*(PN_int8 *)pointer == data); + *(int8_t *)pointer = data; + nassertv(*(int8_t *)pointer == data); break; case NT_int16: - *(PN_int16 *)pointer = data; - nassertv(*(PN_int16 *)pointer == data); + *(int16_t *)pointer = data; + nassertv(*(int16_t *)pointer == data); break; case NT_int32: - *(PN_int32 *)pointer = data; + *(int32_t *)pointer = data; break; case NT_packed_ufloat: @@ -2448,7 +2458,7 @@ set_data2i(unsigned char *pointer, const LVecBase2i &data) { case NT_uint16: { - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; } @@ -2456,7 +2466,7 @@ set_data2i(unsigned char *pointer, const LVecBase2i &data) { case NT_uint32: { - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; } @@ -2489,7 +2499,7 @@ set_data2i(unsigned char *pointer, const LVecBase2i &data) { case NT_int8: { - PN_int8 *pi = (PN_int8 *)pointer; + int8_t *pi = (int8_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; } @@ -2497,7 +2507,7 @@ set_data2i(unsigned char *pointer, const LVecBase2i &data) { case NT_int16: { - PN_int16 *pi = (PN_int16 *)pointer; + int16_t *pi = (int16_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; } @@ -2505,7 +2515,7 @@ set_data2i(unsigned char *pointer, const LVecBase2i &data) { case NT_int32: { - PN_int32 *pi = (PN_int32 *)pointer; + int32_t *pi = (int32_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; } @@ -2551,7 +2561,7 @@ set_data3i(unsigned char *pointer, const LVecBase3i &data) { case NT_uint16: { - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; pi[2] = data[2]; @@ -2560,7 +2570,7 @@ set_data3i(unsigned char *pointer, const LVecBase3i &data) { case NT_uint32: { - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; pi[2] = data[2]; @@ -2596,7 +2606,7 @@ set_data3i(unsigned char *pointer, const LVecBase3i &data) { case NT_int8: { - PN_int8 *pi = (PN_int8 *)pointer; + int8_t *pi = (int8_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; pi[2] = data[2]; @@ -2605,7 +2615,7 @@ set_data3i(unsigned char *pointer, const LVecBase3i &data) { case NT_int16: { - PN_int16 *pi = (PN_int16 *)pointer; + int16_t *pi = (int16_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; pi[2] = data[2]; @@ -2614,7 +2624,7 @@ set_data3i(unsigned char *pointer, const LVecBase3i &data) { case NT_int32: { - PN_int32 *pi = (PN_int32 *)pointer; + int32_t *pi = (int32_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; pi[2] = data[2]; @@ -2622,7 +2632,7 @@ set_data3i(unsigned char *pointer, const LVecBase3i &data) { break; case NT_packed_ufloat: - *(PN_uint32 *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]); + *(uint32_t *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]); break; } break; @@ -2662,7 +2672,7 @@ set_data4i(unsigned char *pointer, const LVecBase4i &data) { case NT_uint16: { - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; pi[2] = data[2]; @@ -2672,7 +2682,7 @@ set_data4i(unsigned char *pointer, const LVecBase4i &data) { case NT_uint32: { - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; pi[2] = data[2]; @@ -2681,11 +2691,11 @@ set_data4i(unsigned char *pointer, const LVecBase4i &data) { break; case NT_packed_dcba: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]); + *(uint32_t *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]); break; case NT_packed_dabc: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]); + *(uint32_t *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]); break; case NT_float32: @@ -2714,7 +2724,7 @@ set_data4i(unsigned char *pointer, const LVecBase4i &data) { case NT_int8: { - PN_int8 *pi = (PN_int8 *)pointer; + int8_t *pi = (int8_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; pi[2] = data[2]; @@ -2724,7 +2734,7 @@ set_data4i(unsigned char *pointer, const LVecBase4i &data) { case NT_int16: { - PN_int16 *pi = (PN_int16 *)pointer; + int16_t *pi = (int16_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; pi[2] = data[2]; @@ -2734,7 +2744,7 @@ set_data4i(unsigned char *pointer, const LVecBase4i &data) { case NT_int32: { - PN_int32 *pi = (PN_int32 *)pointer; + int32_t *pi = (int32_t *)pointer; pi[0] = data[0]; pi[1] = data[1]; pi[2] = data[2]; @@ -2819,28 +2829,28 @@ get_data4f(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_b(dword), @@ -2850,7 +2860,7 @@ get_data4f(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_d(dword), @@ -2878,21 +2888,21 @@ get_data4f(const unsigned char *pointer) { case NT_int8: { - const PN_int8 *pi = (const PN_int8 *)pointer; + const int8_t *pi = (const int8_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; case NT_int16: { - const PN_int16 *pi = (const PN_int16 *)pointer; + const int16_t *pi = (const int16_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; case NT_int32: { - const PN_int32 *pi = (const PN_int32 *)pointer; + const int32_t *pi = (const int32_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); } return _v4; @@ -2975,28 +2985,28 @@ get_data4d(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4d.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_b(dword), @@ -3006,7 +3016,7 @@ get_data4d(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4d.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_d(dword), @@ -3034,21 +3044,21 @@ get_data4d(const unsigned char *pointer) { case NT_int8: { - const PN_int8 *pi = (const PN_int8 *)pointer; + const int8_t *pi = (const int8_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; case NT_int16: { - const PN_int16 *pi = (const PN_int16 *)pointer; + const int16_t *pi = (const int16_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; case NT_int32: { - const PN_int32 *pi = (const PN_int32 *)pointer; + const int32_t *pi = (const int32_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); } return _v4d; @@ -3120,7 +3130,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { switch (_column->get_numeric_type()) { case NT_uint8: { - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -3130,7 +3140,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_uint16: { - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -3140,7 +3150,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_uint32: { - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -3149,11 +3159,11 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { break; case NT_packed_dcba: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]); + *(uint32_t *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]); break; case NT_packed_dabc: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]); + *(uint32_t *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]); break; case NT_float32: @@ -3182,7 +3192,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_int8: { - PN_int8 *pi = (PN_int8 *)pointer; + int8_t *pi = (int8_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -3192,7 +3202,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_int16: { - PN_int16 *pi = (PN_int16 *)pointer; + int16_t *pi = (int16_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -3202,7 +3212,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_int32: { - PN_int32 *pi = (PN_int32 *)pointer; + int32_t *pi = (int32_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -3276,7 +3286,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { switch (_column->get_numeric_type()) { case NT_uint8: { - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -3286,7 +3296,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_uint16: { - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -3296,7 +3306,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_uint32: { - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -3305,11 +3315,11 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { break; case NT_packed_dcba: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]); + *(uint32_t *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]); break; case NT_packed_dabc: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]); + *(uint32_t *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]); break; case NT_float32: @@ -3338,7 +3348,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_int8: { - PN_int8 *pi = (PN_int8 *)pointer; + int8_t *pi = (int8_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -3348,7 +3358,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_int16: { - PN_int16 *pi = (PN_int16 *)pointer; + int16_t *pi = (int16_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -3358,7 +3368,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_int32: { - PN_int32 *pi = (PN_int32 *)pointer; + int32_t *pi = (int32_t *)pointer; pi[0] = (int)data[0]; pi[1] = (int)data[1]; pi[2] = (int)data[2]; @@ -3381,23 +3391,23 @@ float GeomVertexColumn::Packer_color:: get_data1f(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: - return (*(const PN_uint8 *)pointer) / 255.0f; + return (*(const uint8_t *)pointer) / 255.0f; case NT_uint16: - return (*(const PN_uint16 *)pointer) / 65535.0f; + return (*(const uint16_t *)pointer) / 65535.0f; case NT_uint32: - return (*(const PN_uint32 *)pointer) / 4294967295.0f; + return (*(const uint32_t *)pointer) / 4294967295.0f; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_abcd_d(dword) / 255.0f; } case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_abcd_b(dword) / 255.0f; } @@ -3439,7 +3449,7 @@ get_data3f(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v3.set(pi[0], pi[1], pi[2]); _v3 /= 255.0f; } @@ -3447,7 +3457,7 @@ get_data3f(const unsigned char *pointer) { case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v3.set(pi[0], pi[1], pi[2]); _v3 /= 65535.0f; } @@ -3455,7 +3465,7 @@ get_data3f(const unsigned char *pointer) { case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v3.set(pi[0], pi[1], pi[2]); _v3 /= 4294967295.0f; } @@ -3489,7 +3499,7 @@ get_data3f(const unsigned char *pointer) { case NT_packed_ufloat: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v3.set(GeomVertexData::unpack_ufloat_a(dword), GeomVertexData::unpack_ufloat_b(dword), GeomVertexData::unpack_ufloat_c(dword)); @@ -3518,7 +3528,7 @@ get_data4f(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); _v4 /= 255.0f; } @@ -3526,7 +3536,7 @@ get_data4f(const unsigned char *pointer) { case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); _v4 /= 65535.0f; } @@ -3534,7 +3544,7 @@ get_data4f(const unsigned char *pointer) { case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v4.set(pi[0], pi[1], pi[2], pi[3]); _v4 /= 4294967295.0f; } @@ -3542,7 +3552,7 @@ get_data4f(const unsigned char *pointer) { case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_b(dword), @@ -3553,7 +3563,7 @@ get_data4f(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_d(dword), @@ -3596,23 +3606,23 @@ double GeomVertexColumn::Packer_color:: get_data1d(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: - return (*(const PN_uint8 *)pointer) / 255.0; + return (*(const uint8_t *)pointer) / 255.0; case NT_uint16: - return (*(const PN_uint16 *)pointer) / 65535.0; + return (*(const uint16_t *)pointer) / 65535.0; case NT_uint32: - return (*(const PN_uint32 *)pointer) / 4294967295.0; + return (*(const uint32_t *)pointer) / 4294967295.0; case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_abcd_d(dword) / 255.0; } case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; return GeomVertexData::unpack_abcd_b(dword) / 255.0; } @@ -3654,7 +3664,7 @@ get_data3d(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v3d.set(pi[0], pi[1], pi[2]); _v3d /= 255.0; } @@ -3662,7 +3672,7 @@ get_data3d(const unsigned char *pointer) { case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v3d.set(pi[0], pi[1], pi[2]); _v3d /= 65535.0; } @@ -3670,7 +3680,7 @@ get_data3d(const unsigned char *pointer) { case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v3d.set(pi[0], pi[1], pi[2]); _v3d /= 4294967295.0; } @@ -3704,7 +3714,7 @@ get_data3d(const unsigned char *pointer) { case NT_packed_ufloat: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v3d.set(GeomVertexData::unpack_ufloat_a(dword), GeomVertexData::unpack_ufloat_b(dword), GeomVertexData::unpack_ufloat_c(dword)); @@ -3733,7 +3743,7 @@ get_data4d(const unsigned char *pointer) { switch (_column->get_numeric_type()) { case NT_uint8: { - const PN_uint8 *pi = (const PN_uint8 *)pointer; + const uint8_t *pi = (const uint8_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); _v4d /= 255.0; } @@ -3741,7 +3751,7 @@ get_data4d(const unsigned char *pointer) { case NT_uint16: { - const PN_uint16 *pi = (const PN_uint16 *)pointer; + const uint16_t *pi = (const uint16_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); _v4d /= 65535.0; } @@ -3749,7 +3759,7 @@ get_data4d(const unsigned char *pointer) { case NT_uint32: { - const PN_uint32 *pi = (const PN_uint32 *)pointer; + const uint32_t *pi = (const uint32_t *)pointer; _v4d.set(pi[0], pi[1], pi[2], pi[3]); _v4d /= 4294967295.0; } @@ -3757,7 +3767,7 @@ get_data4d(const unsigned char *pointer) { case NT_packed_dcba: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4d.set(GeomVertexData::unpack_abcd_d(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_b(dword), @@ -3768,7 +3778,7 @@ get_data4d(const unsigned char *pointer) { case NT_packed_dabc: { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4d.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_d(dword), @@ -3838,7 +3848,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { case NT_uint8: { LVecBase3f scaled = data * 255.0f; - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)scaled[0]; pi[1] = (unsigned int)scaled[1]; pi[2] = (unsigned int)scaled[2]; @@ -3848,7 +3858,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { case NT_uint16: { LVecBase3f scaled = data * 65535.0f; - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)scaled[0]; pi[1] = (unsigned int)scaled[1]; pi[2] = (unsigned int)scaled[2]; @@ -3858,7 +3868,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { case NT_uint32: { LVecBase3f scaled = data * 4294967295.0f; - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -3868,7 +3878,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { case NT_packed_dcba: { LVecBase3f scaled = data * 255.0f; - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd( + *(uint32_t *)pointer = GeomVertexData::pack_abcd( 1.0f, scaled[2], scaled[1], scaled[0]); } break; @@ -3876,7 +3886,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { case NT_packed_dabc: { LVecBase3f scaled = data * 255.0f; - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd( + *(uint32_t *)pointer = GeomVertexData::pack_abcd( 1.0f, scaled[0], scaled[1], scaled[2]); } break; @@ -3907,7 +3917,7 @@ set_data3f(unsigned char *pointer, const LVecBase3f &data) { break; case NT_packed_ufloat: - *(PN_uint32 *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]); + *(uint32_t *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]); break; } } else { @@ -3927,7 +3937,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_uint8: { LVecBase4f scaled = data * 255.0f; - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)scaled[0]; pi[1] = (unsigned int)scaled[1]; pi[2] = (unsigned int)scaled[2]; @@ -3938,7 +3948,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_uint16: { LVecBase4f scaled = data * 65535.0f; - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)scaled[0]; pi[1] = (unsigned int)scaled[1]; pi[2] = (unsigned int)scaled[2]; @@ -3949,7 +3959,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_uint32: { LVecBase4f scaled = data * 4294967295.0f; - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -3960,7 +3970,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_packed_dcba: { LVecBase4f scaled = data * 255.0f; - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd( + *(uint32_t *)pointer = GeomVertexData::pack_abcd( scaled[3], scaled[2], scaled[1], scaled[0]); } break; @@ -3968,7 +3978,7 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) { case NT_packed_dabc: { LVecBase4f scaled = data * 255.0f; - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd( + *(uint32_t *)pointer = GeomVertexData::pack_abcd( scaled[3], scaled[0], scaled[1], scaled[2]); } break; @@ -4041,7 +4051,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { case NT_uint8: { LVecBase3d scaled = data * 255.0; - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)scaled[0]; pi[1] = (unsigned int)scaled[1]; pi[2] = (unsigned int)scaled[2]; @@ -4051,7 +4061,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { case NT_uint16: { LVecBase3d scaled = data * 65535.0; - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)scaled[0]; pi[1] = (unsigned int)scaled[1]; pi[2] = (unsigned int)scaled[2]; @@ -4061,7 +4071,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { case NT_uint32: { LVecBase3d scaled = data * 4294967295.0; - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -4071,7 +4081,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { case NT_packed_dcba: { LVecBase3d scaled = data * 255.0; - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd( + *(uint32_t *)pointer = GeomVertexData::pack_abcd( 1.0, scaled[2], scaled[1], scaled[0]); } break; @@ -4079,7 +4089,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { case NT_packed_dabc: { LVecBase3d scaled = data * 255.0; - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd( + *(uint32_t *)pointer = GeomVertexData::pack_abcd( 1.0, scaled[0], scaled[1], scaled[2]); } break; @@ -4110,7 +4120,7 @@ set_data3d(unsigned char *pointer, const LVecBase3d &data) { break; case NT_packed_ufloat: - *(PN_uint32 *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]); + *(uint32_t *)pointer = GeomVertexData::pack_ufloat(data[0], data[1], data[2]); break; } } else { @@ -4130,7 +4140,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_uint8: { LVecBase4d scaled = data * 255.0; - PN_uint8 *pi = (PN_uint8 *)pointer; + uint8_t *pi = (uint8_t *)pointer; pi[0] = (unsigned int)scaled[0]; pi[1] = (unsigned int)scaled[1]; pi[2] = (unsigned int)scaled[2]; @@ -4141,7 +4151,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_uint16: { LVecBase4d scaled = data * 65535.0; - PN_uint16 *pi = (PN_uint16 *)pointer; + uint16_t *pi = (uint16_t *)pointer; pi[0] = (unsigned int)scaled[0]; pi[1] = (unsigned int)scaled[1]; pi[2] = (unsigned int)scaled[2]; @@ -4152,7 +4162,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_uint32: { LVecBase4d scaled = data * 4294967295.0; - PN_uint32 *pi = (PN_uint32 *)pointer; + uint32_t *pi = (uint32_t *)pointer; pi[0] = (unsigned int)data[0]; pi[1] = (unsigned int)data[1]; pi[2] = (unsigned int)data[2]; @@ -4163,7 +4173,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_packed_dcba: { LVecBase4d scaled = data * 255.0; - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd( + *(uint32_t *)pointer = GeomVertexData::pack_abcd( scaled[3], scaled[2], scaled[1], scaled[0]); } break; @@ -4171,7 +4181,7 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { case NT_packed_dabc: { LVecBase4d scaled = data * 255.0; - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd( + *(uint32_t *)pointer = GeomVertexData::pack_abcd( scaled[3], scaled[0], scaled[1], scaled[2]); } break; @@ -4447,7 +4457,7 @@ get_data4d(const unsigned char *pointer) { */ const LVecBase4f &GeomVertexColumn::Packer_argb_packed:: get_data4f(const unsigned char *pointer) { - PN_uint32 dword = *(const PN_uint32 *)pointer; + uint32_t dword = *(const uint32_t *)pointer; _v4.set(GeomVertexData::unpack_abcd_b(dword), GeomVertexData::unpack_abcd_c(dword), GeomVertexData::unpack_abcd_d(dword), @@ -4463,7 +4473,7 @@ void GeomVertexColumn::Packer_argb_packed:: set_data4f(unsigned char *pointer, const LVecBase4f &data) { // when packing an argb, we want to make sure we cap the input values at 1 // since going above one will cause the value to be truncated. - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd + *(uint32_t *)pointer = GeomVertexData::pack_abcd ((unsigned int)(min(max(data[3], 0.0f), 1.0f) * 255.0f), (unsigned int)(min(max(data[0], 0.0f), 1.0f) * 255.0f), (unsigned int)(min(max(data[1], 0.0f), 1.0f) * 255.0f), @@ -4527,7 +4537,7 @@ get_data4f(const unsigned char *pointer) { */ int GeomVertexColumn::Packer_uint16_1:: get_data1i(const unsigned char *pointer) { - return *(const PN_uint16 *)pointer; + return *(const uint16_t *)pointer; } /** @@ -4535,6 +4545,6 @@ get_data1i(const unsigned char *pointer) { */ void GeomVertexColumn::Packer_uint16_1:: set_data1i(unsigned char *pointer, int data) { - *(PN_uint16 *)pointer = data; - nassertv(*(PN_uint16 *)pointer == data); + *(uint16_t *)pointer = data; + nassertv(*(uint16_t *)pointer == data); } diff --git a/panda/src/gobj/geomVertexData.I b/panda/src/gobj/geomVertexData.I index 0d32813912..dfb2138c1a 100644 --- a/panda/src/gobj/geomVertexData.I +++ b/panda/src/gobj/geomVertexData.I @@ -273,7 +273,7 @@ get_modified(Thread *current_thread) const { /** * Packs four values in a DirectX-style NT_packed_abcd value. */ -INLINE PN_uint32 GeomVertexData:: +INLINE uint32_t GeomVertexData:: pack_abcd(unsigned int a, unsigned int b, unsigned int c, unsigned int d) { return (((a & 0xff) << 24) | @@ -286,7 +286,7 @@ pack_abcd(unsigned int a, unsigned int b, * Returns the first packed value from a DirectX-style NT_packed_abcd. */ INLINE unsigned int GeomVertexData:: -unpack_abcd_a(PN_uint32 data) { +unpack_abcd_a(uint32_t data) { return (data >> 24) & 0xff; } @@ -294,7 +294,7 @@ unpack_abcd_a(PN_uint32 data) { * Returns the second packed value from a DirectX-style NT_packed_abcd. */ INLINE unsigned int GeomVertexData:: -unpack_abcd_b(PN_uint32 data) { +unpack_abcd_b(uint32_t data) { return (data >> 16) & 0xff; } @@ -302,7 +302,7 @@ unpack_abcd_b(PN_uint32 data) { * Returns the third packed value from a DirectX-style NT_packed_abcd. */ INLINE unsigned int GeomVertexData:: -unpack_abcd_c(PN_uint32 data) { +unpack_abcd_c(uint32_t data) { return (data >> 8) & 0xff; } @@ -310,19 +310,19 @@ unpack_abcd_c(PN_uint32 data) { * Returns the fourth packed value from a DirectX-style NT_packed_abcd. */ INLINE unsigned int GeomVertexData:: -unpack_abcd_d(PN_uint32 data) { +unpack_abcd_d(uint32_t data) { return data & 0xff; } /** * Packs three float values in an unsigned 32-bit int. */ -INLINE PN_uint32 GeomVertexData:: +INLINE uint32_t GeomVertexData:: pack_ufloat(float a, float b, float c) { // Since we have to clamp both low exponents and negative numbers to 0, it's // easier to see a float as having a 9-bit signed exponent. union { - PN_int32 _packed; + int32_t _packed; float _float; } f0, f1, f2; @@ -335,7 +335,7 @@ pack_ufloat(float a, float b, float c) { // normalized float 4. exponent 0: denormal float 5. zero or anything // negative, clamped to 0 - PN_uint32 packed = 0; + uint32_t packed = 0; if ((f0._packed & 0x7f800000) == 0x7f800000 && (unsigned)f0._packed != 0xff800000u) { packed |= (f0._packed >> 17) & 0x7ffu; @@ -374,14 +374,14 @@ pack_ufloat(float a, float b, float c) { * Unpacks an unsigned float11 value from an uint32. */ INLINE float GeomVertexData:: -unpack_ufloat_a(PN_uint32 data) { +unpack_ufloat_a(uint32_t data) { if ((data & 0x7c0) == 0) { // Denormal float (includes zero). return ldexpf((data & 63) / 64.0f, -14); } union { - PN_uint32 _packed; + uint32_t _packed; float _float; } value; value._packed = ((data & 0x7ff) << 17); @@ -400,14 +400,14 @@ unpack_ufloat_a(PN_uint32 data) { * Unpacks an unsigned float11 value from an uint32. */ INLINE float GeomVertexData:: -unpack_ufloat_b(PN_uint32 data) { +unpack_ufloat_b(uint32_t data) { if ((data & 0x3e0000) == 0) { // Denormal float (includes zero). return ldexpf(((data >> 11) & 63) / 64.0f, -14); } union { - PN_uint32 _packed; + uint32_t _packed; float _float; } value; value._packed = ((data & 0x3ff800) << 6); @@ -426,14 +426,14 @@ unpack_ufloat_b(PN_uint32 data) { * Unpacks an unsigned float10 value from an uint32. */ INLINE float GeomVertexData:: -unpack_ufloat_c(PN_uint32 data) { +unpack_ufloat_c(uint32_t data) { if ((data & 0xf8000000u) == 0) { // Denormal float (includes zero). return ldexpf(((data >> 22) & 31) / 32.0f, -14); } union { - PN_uint32 _packed; + uint32_t _packed; float _float; } value; value._packed = ((data & 0xffc00000u) >> 4); diff --git a/panda/src/gobj/geomVertexData.cxx b/panda/src/gobj/geomVertexData.cxx index 9b1aa50d84..6b73e4fe0f 100644 --- a/panda/src/gobj/geomVertexData.cxx +++ b/panda/src/gobj/geomVertexData.cxx @@ -1434,7 +1434,7 @@ packed_argb_to_uint8_rgba(unsigned char *to, int to_stride, } while (num_records > 0) { - PN_uint32 dword = *(const PN_uint32 *)from; + uint32_t dword = *(const uint32_t *)from; to[0] = unpack_abcd_b(dword); to[1] = unpack_abcd_c(dword); to[2] = unpack_abcd_d(dword); @@ -1461,7 +1461,7 @@ uint8_rgba_to_packed_argb(unsigned char *to, int to_stride, } while (num_records > 0) { - *(PN_uint32 *)to = pack_abcd(from[3], from[0], from[1], from[2]); + *(uint32_t *)to = pack_abcd(from[3], from[0], from[1], from[2]); to += to_stride; from += from_stride; @@ -2515,7 +2515,7 @@ set_num_rows(int n) { case NT_packed_ufloat: while (pointer < stop) { - *(PN_int32 *)pointer = 0x781e03c0; + *(int32_t *)pointer = 0x781e03c0; pointer += stride; } break; diff --git a/panda/src/gobj/geomVertexData.h b/panda/src/gobj/geomVertexData.h index d2bf71d957..cfb592529d 100644 --- a/panda/src/gobj/geomVertexData.h +++ b/panda/src/gobj/geomVertexData.h @@ -110,6 +110,7 @@ PUBLISHED: MAKE_SEQ(get_arrays, get_num_arrays, get_array); INLINE PT(GeomVertexArrayData) modify_array(int i); INLINE void set_array(int i, const GeomVertexArrayData *array); + MAKE_SEQ_PROPERTY(arrays, get_num_arrays, get_array, set_array); INLINE const TransformTable *get_transform_table() const; void set_transform_table(const TransformTable *table); @@ -169,17 +170,17 @@ PUBLISHED: void clear_cache_stage(); public: - static INLINE PN_uint32 pack_abcd(unsigned int a, unsigned int b, + static INLINE uint32_t pack_abcd(unsigned int a, unsigned int b, unsigned int c, unsigned int d); - static INLINE unsigned int unpack_abcd_a(PN_uint32 data); - static INLINE unsigned int unpack_abcd_b(PN_uint32 data); - static INLINE unsigned int unpack_abcd_c(PN_uint32 data); - static INLINE unsigned int unpack_abcd_d(PN_uint32 data); + static INLINE unsigned int unpack_abcd_a(uint32_t data); + static INLINE unsigned int unpack_abcd_b(uint32_t data); + static INLINE unsigned int unpack_abcd_c(uint32_t data); + static INLINE unsigned int unpack_abcd_d(uint32_t data); - static INLINE PN_uint32 pack_ufloat(float a, float b, float c); - static INLINE float unpack_ufloat_a(PN_uint32 data); - static INLINE float unpack_ufloat_b(PN_uint32 data); - static INLINE float unpack_ufloat_c(PN_uint32 data); + static INLINE uint32_t pack_ufloat(float a, float b, float c); + static INLINE float unpack_ufloat_a(uint32_t data); + static INLINE float unpack_ufloat_b(uint32_t data); + static INLINE float unpack_ufloat_c(uint32_t data); private: static void do_set_color(GeomVertexData *vdata, const LColor &color); diff --git a/panda/src/gobj/geomVertexFormat.I b/panda/src/gobj/geomVertexFormat.I index e9d4110820..2879599cc5 100644 --- a/panda/src/gobj/geomVertexFormat.I +++ b/panda/src/gobj/geomVertexFormat.I @@ -235,6 +235,15 @@ get_morph_delta(size_t n) const { return _morphs[n]._delta; } +/** + * Returns a standard vertex format containing no arrays at all, useful for + * pull-style vertex rendering. + */ +INLINE const GeomVertexFormat *GeomVertexFormat:: +get_empty() { + return get_registry()->_empty; +} + /** * Returns a standard vertex format with just a 3-component vertex position. */ diff --git a/panda/src/gobj/geomVertexFormat.cxx b/panda/src/gobj/geomVertexFormat.cxx index 99b0ecfcc7..0b1795c093 100644 --- a/panda/src/gobj/geomVertexFormat.cxx +++ b/panda/src/gobj/geomVertexFormat.cxx @@ -890,6 +890,8 @@ Registry() { */ void GeomVertexFormat::Registry:: make_standard_formats() { + _empty = register_format(new GeomVertexFormat); + _v3 = register_format(new GeomVertexArrayFormat (InternalName::get_vertex(), 3, NT_stdfloat, C_point)); @@ -1011,10 +1013,6 @@ register_format(GeomVertexFormat *format) { new_format = (*fi); if (!new_format->is_registered()) { new_format->do_register(); - if (new_format->get_num_arrays() == 0) { - gobj_cat.warning() - << "Empty GeomVertexFormat registered.\n"; - } } } diff --git a/panda/src/gobj/geomVertexFormat.h b/panda/src/gobj/geomVertexFormat.h index 68ce5dda8b..c7451225e2 100644 --- a/panda/src/gobj/geomVertexFormat.h +++ b/panda/src/gobj/geomVertexFormat.h @@ -120,11 +120,18 @@ PUBLISHED: MAKE_SEQ(get_morph_bases, get_num_morphs, get_morph_base); MAKE_SEQ(get_morph_deltas, get_num_morphs, get_morph_delta); + MAKE_SEQ_PROPERTY(arrays, get_num_arrays, get_array, set_array, remove_array); + MAKE_SEQ_PROPERTY(columns, get_num_columns, get_column); + MAKE_SEQ_PROPERTY(points, get_num_points, get_point); + MAKE_SEQ_PROPERTY(vectors, get_num_vectors, get_vector); + void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; void write_with_data(ostream &out, int indent_level, const GeomVertexData *data) const; + INLINE static const GeomVertexFormat *get_empty(); + // Some standard vertex formats. No particular requirement to use one of // these, but the DirectX renderers can use these formats directly, whereas // any other format will have to be converted first. @@ -227,6 +234,8 @@ private: Formats _formats; LightReMutex _lock; + CPT(GeomVertexFormat) _empty; + CPT(GeomVertexFormat) _v3; CPT(GeomVertexFormat) _v3n3; CPT(GeomVertexFormat) _v3t2; diff --git a/panda/src/gobj/material.cxx b/panda/src/gobj/material.cxx index 2d7b25bf6c..12d4f15365 100644 --- a/panda/src/gobj/material.cxx +++ b/panda/src/gobj/material.cxx @@ -257,7 +257,7 @@ set_roughness(PN_stdfloat roughness) { // Calculate the specular exponent from the roughness as it is used in // Blinn-Phong shading model. We use the popular Disney method of squaring // the roughness to get a more perceptually linear scale. From: - // http:graphicrants.blogspot.de201308specular-brdf-reference.html + // http://graphicrants.blogspot.de/2013/08/specular-brdf-reference.html if (roughness <= 0 || IS_NEARLY_ZERO(roughness)) { _shininess = make_inf((PN_stdfloat)0); } else { @@ -481,26 +481,35 @@ void Material:: write_datagram(BamWriter *manager, Datagram &me) { me.add_string(get_name()); - me.add_int32(_flags); + if (manager->get_file_minor_ver() >= 39) { + me.add_int32(_flags); - if (_flags & F_metallic) { - // Metalness workflow. - _base_color.write_datagram(me); - me.add_stdfloat(_metallic); + if (_flags & F_metallic) { + // Metalness workflow. + _base_color.write_datagram(me); + me.add_stdfloat(_metallic); + } else { + _ambient.write_datagram(me); + _diffuse.write_datagram(me); + _specular.write_datagram(me); + } + _emission.write_datagram(me); + + if (_flags & F_roughness) { + me.add_stdfloat(_roughness); + } else { + me.add_stdfloat(_shininess); + } + + me.add_stdfloat(_refractive_index); } else { _ambient.write_datagram(me); _diffuse.write_datagram(me); _specular.write_datagram(me); - } - _emission.write_datagram(me); - - if (_flags & F_roughness) { - me.add_stdfloat(_roughness); - } else { + _emission.write_datagram(me); me.add_stdfloat(_shininess); + me.add_int32(_flags & 0x7f); } - - me.add_stdfloat(_refractive_index); } /** diff --git a/panda/src/gobj/matrixLens.cxx b/panda/src/gobj/matrixLens.cxx index 169de788b1..f501e7c6d4 100644 --- a/panda/src/gobj/matrixLens.cxx +++ b/panda/src/gobj/matrixLens.cxx @@ -83,14 +83,18 @@ register_with_read_factory() { */ void MatrixLens:: write_datagram(BamWriter *manager, Datagram &dg) { - dg.add_uint8(_ml_flags); - _user_mat.write_datagram(dg); + Lens::write_datagram(manager, dg); - if (_ml_flags & MF_has_left_eye) { - _left_eye_mat.write_datagram(dg); - } - if (_ml_flags & MF_has_right_eye) { - _left_eye_mat.write_datagram(dg); + if (manager->get_file_minor_ver() >= 41) { + dg.add_uint8(_ml_flags); + _user_mat.write_datagram(dg); + + if (_ml_flags & MF_has_left_eye) { + _left_eye_mat.write_datagram(dg); + } + if (_ml_flags & MF_has_right_eye) { + _left_eye_mat.write_datagram(dg); + } } } diff --git a/panda/src/gobj/shader.I b/panda/src/gobj/shader.I index f1fb1dabf2..fe74b2bda6 100644 --- a/panda/src/gobj/shader.I +++ b/panda/src/gobj/shader.I @@ -50,6 +50,38 @@ get_filename(ShaderType type) const { } } +/** + * Sets the Shader's filename for the given shader type. Useful for + * associating a shader created with Shader.make with a name for diagnostics. + */ +INLINE void Shader:: +set_filename(ShaderType type, const Filename &filename) { + _filename._separate = true; + switch (type) { + case ST_vertex: + _filename._vertex = filename; + break; + case ST_fragment: + _filename._fragment = filename; + break; + case ST_geometry: + _filename._geometry = filename; + break; + case ST_tess_control: + _filename._tess_control = filename; + break; + case ST_tess_evaluation: + _filename._tess_evaluation = filename; + break; + case ST_compute: + _filename._compute = filename; + break; + default: + _filename._shared = filename; + _filename._separate = false; + } +} + /** * Return the Shader's text for the given shader type. */ @@ -603,7 +635,7 @@ ShaderPtrData(const LVecBase2i &vec) : INLINE void Shader::ShaderPtrData:: write_datagram(Datagram &dg) const { dg.add_uint8(_type); - dg.add_uint32((PN_uint32)_size); + dg.add_uint32((uint32_t)_size); if (_type == SPT_double) { const double *data = (const double *) _ptr; @@ -760,25 +792,3 @@ operator < (const Shader::ShaderFile &other) const { } return false; } - -/** - * Returns the filename of the included shader with the given source file - * index (as recorded in the #line statement in r_preprocess_source). We use - * this to associate error messages with included files. - */ -INLINE Filename Shader:: -get_filename_from_index(int index, ShaderType type) const { - if (index == 0) { - Filename fn = get_filename(type); - if (!fn.empty()) { - return fn; - } - } else if (glsl_preprocess && index >= 2048 && - (index - 2048) < (int)_included_files.size()) { - return _included_files[(size_t)index - 2048]; - } - // Must be a mistake. Quietly put back the integer. - char str[32]; - sprintf(str, "%d", index); - return Filename(str); -} diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 2905d54d7d..d668af1882 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -21,6 +21,7 @@ #include "virtualFileSystem.h" #include "config_util.h" #include "bamCache.h" +#include "string_utils.h" #ifdef HAVE_CG #include @@ -1625,11 +1626,11 @@ cg_compile_entry_point(const char *entry, const ShaderCaps &caps, compiler_args[nargs++] = "ATI_draw_buffers"; } - char version_arg[16]; + string version_arg; if (!cg_glsl_version.empty() && active != CG_PROFILE_UNKNOWN && cgGetProfileProperty((CGprofile) active, CG_IS_GLSL_PROFILE)) { - string version_arg("version="); + version_arg = "version="; version_arg += cg_glsl_version; compiler_args[nargs++] = "-po"; @@ -2362,15 +2363,14 @@ r_preprocess_source(ostream &out, const Filename &fn, bool had_include = false; int lineno = 0; while (getline(*source, line)) { - // We always forward the actual line - the GLSL compiler will silently - // ignore #pragma lines anyway. ++lineno; - out << line << "\n"; // Check if this line contains a #pragma. char pragma[64]; if (line.size() < 8 || sscanf(line.c_str(), " # pragma %63s", pragma) != 1) { + // Just pass the line through unmodified. + out << line << "\n"; // One exception: check for an #endif after an include. We have to // restore the line number in case the include happened under an #if @@ -2435,8 +2435,11 @@ r_preprocess_source(ostream &out, const Filename &fn, } else if (strcmp(pragma, "optionNV") == 0) { // This is processed by NVIDIA drivers. Don't touch it. + out << line << "\n"; } else { + // Forward it, the driver will ignore it if it doesn't know it. + out << line << "\n"; shader_cat.warning() << "Ignoring unknown pragma directive \"" << pragma << "\" at line " << lineno << " of file " << fn << ":\n " << line << "\n"; @@ -2613,6 +2616,27 @@ Shader:: }*/ } +/** + * Returns the filename of the included shader with the given source file + * index (as recorded in the #line statement in r_preprocess_source). We use + * this to associate error messages with included files. + */ +Filename Shader:: +get_filename_from_index(int index, ShaderType type) const { + if (index == 0) { + Filename fn = get_filename(type); + if (!fn.empty()) { + return fn; + } + } else if (glsl_preprocess && index >= 2048 && + (index - 2048) < (int)_included_files.size()) { + return _included_files[(size_t)index - 2048]; + } + // Must be a mistake. Quietly put back the integer. + string str = format_string(index); + return Filename(str); +} + /** * Loads the shader with the given filename. */ diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index dbdde6f5ba..e7e843b9c6 100644 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -98,6 +98,7 @@ PUBLISHED: static PT(Shader) make_compute(ShaderLanguage lang, const string &body); INLINE Filename get_filename(ShaderType type = ST_none) const; + INLINE void set_filename(ShaderType type, const Filename &filename); INLINE const string &get_text(ShaderType type = ST_none) const; INLINE bool get_error_flag() const; INLINE ShaderLanguage get_language() const; @@ -555,10 +556,10 @@ public: #endif public: - pvector _ptr_spec; - epvector _mat_spec; - pvector _tex_spec; - pvector _var_spec; + pvector _ptr_spec; + epvector _mat_spec; + pvector _tex_spec; + pvector _var_spec; int _mat_deps; bool _error_flag; @@ -615,7 +616,7 @@ private: public: ~Shader(); - INLINE Filename get_filename_from_index(int index, ShaderType type) const; + Filename get_filename_from_index(int index, ShaderType type) const; public: static void register_with_read_factory(); diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 25244367a8..b608a39c00 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -2325,7 +2325,7 @@ INLINE bool Texture:: is_txo_filename(const Filename &fullpath) { string extension = fullpath.get_extension(); #ifdef HAVE_ZLIB - if (extension == "pz") { + if (extension == "pz" || extension == "gz") { extension = Filename(fullpath.get_basename_wo_extension()).get_extension(); } #endif // HAVE_ZLIB @@ -2340,7 +2340,7 @@ INLINE bool Texture:: is_dds_filename(const Filename &fullpath) { string extension = fullpath.get_extension(); #ifdef HAVE_ZLIB - if (extension == "pz") { + if (extension == "pz" || extension == "gz") { extension = Filename(fullpath.get_basename_wo_extension()).get_extension(); } #endif // HAVE_ZLIB diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 0d0054fed7..8368dcf926 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -514,6 +514,7 @@ estimate_texture_memory() const { break; case Texture::F_r16: + case Texture::F_r16i: case Texture::F_rg8i: bpp = 2; break; @@ -830,8 +831,11 @@ set_ram_image_as(CPTA_uchar image, const string &supplied_format) { } else if (format.at(s) == 'R') { component = 2; } else if (format.at(s) == 'A') { - nassertv(cdata->_num_components != 3); - component = cdata->_num_components - 1; + if (cdata->_num_components != 3) { + component = cdata->_num_components - 1; + } else { + // Ignore. + } } else if (format.at(s) == '0') { // Ignore. } else if (format.at(s) == '1') { @@ -859,8 +863,11 @@ set_ram_image_as(CPTA_uchar image, const string &supplied_format) { } else if (format.at(s) == 'R') { component = 2; } else if (format.at(s) == 'A') { - nassertv(cdata->_num_components != 3); - component = cdata->_num_components - 1; + if (cdata->_num_components != 3) { + component = cdata->_num_components - 1; + } else { + // Ignore. + } } else if (format.at(s) == '0') { // Ignore. } else if (format.at(s) == '1') { @@ -1028,7 +1035,7 @@ clear_ram_mipmap_image(int n) { PTA_uchar Texture:: modify_simple_ram_image() { CDWriter cdata(_cycler, true); - cdata->_simple_image_date_generated = (PN_int32)time(NULL); + cdata->_simple_image_date_generated = (int32_t)time(NULL); return cdata->_simple_ram_image._image; } @@ -1046,7 +1053,7 @@ new_simple_ram_image(int x_size, int y_size) { cdata->_simple_y_size = y_size; cdata->_simple_ram_image._image = PTA_uchar::empty_array(expected_page_size); cdata->_simple_ram_image._page_size = expected_page_size; - cdata->_simple_image_date_generated = (PN_int32)time(NULL); + cdata->_simple_image_date_generated = (int32_t)time(NULL); cdata->inc_simple_image_modified(); return cdata->_simple_ram_image._image; @@ -1132,7 +1139,7 @@ generate_simple_ram_image() { convert_from_pnmimage(image, expected_page_size, x_size, 0, 0, 0, scaled, 4, 1); do_set_simple_ram_image(cdata, image, x_size, y_size); - cdata->_simple_image_date_generated = (PN_int32)time(NULL); + cdata->_simple_image_date_generated = (int32_t)time(NULL); } /** @@ -1526,6 +1533,10 @@ write(ostream &out, int indent_level) const { case F_r16: out << "r16"; break; + case F_r16i: + out << "r16i"; + break; + case F_rg16: out << "rg16"; break; @@ -1944,6 +1955,8 @@ format_format(Format format) { return "rgba32"; case F_r16: return "r16"; + case F_r16i: + return "r16i"; case F_rg16: return "rg16"; case F_rgb16: @@ -2043,6 +2056,8 @@ string_format(const string &str) { return F_rgba32; } else if (cmp_nocase(str, "r16") == 0 || cmp_nocase(str, "red16") == 0) { return F_r16; + } else if (cmp_nocase(str, "r16i") == 0) { + return F_r16i; } else if (cmp_nocase(str, "rg16") == 0 || cmp_nocase(str, "r16g16") == 0) { return F_rg16; } else if (cmp_nocase(str, "rgb16") == 0 || cmp_nocase(str, "r16g16b16") == 0) { @@ -5191,7 +5206,7 @@ do_uncompress_ram_image_bc4(const RamImage &compressed_image, unsigned const char *src = compressed_image._image.p() + z * compressed_image._page_size; // Unconvert one 4 x 4 block at a time. - PN_uint8 tbl[8]; + uint8_t tbl[8]; for (int y = 0; y < y_blocks; ++y) { for (int x = 0; x < x_blocks; ++x) { unsigned char *blk = dest; @@ -5258,8 +5273,8 @@ do_uncompress_ram_image_bc5(const RamImage &compressed_image, unsigned const char *src = compressed_image._image.p() + z * compressed_image._page_size; // Unconvert one 4 x 4 block at a time. - PN_uint8 red[8]; - PN_uint8 grn[8]; + uint8_t red[8]; + uint8_t grn[8]; for (int y = 0; y < y_blocks; ++y) { for (int x = 0; x < x_blocks; ++x) { unsigned char *blk = dest; @@ -5739,6 +5754,7 @@ do_set_format(CData *cdata, Texture::Format format) { case F_alpha: case F_luminance: case F_r16: + case F_r16i: case F_sluminance: case F_r32i: case F_r32: @@ -6088,18 +6104,23 @@ do_get_uncompressed_ram_image(CData *cdata) { * Rather than just returning a pointer to the data, like * get_uncompressed_ram_image, this function first processes the data and * reorders the components using the specified format string, and places these - * into a new char array. The 'format' argument should specify in which order - * the components of the texture must be. For example, valid format strings - * are "RGBA", "GA", "ABRG" or "AAA". A component can also be written as "0" - * or "1", which means an empty/black or a full/white channel, respectively. + * into a new char array. + * + * The 'format' argument should specify in which order the components of the + * texture must be. For example, valid format strings are "RGBA", "GA", + * "ABRG" or "AAA". A component can also be written as "0" or "1", which + * means an empty/black or a full/white channel, respectively. + * * This function is particularly useful to copy an image in-memory to a * different library (for example, PIL or wxWidgets) that require a different * component order than Panda's internal format, BGRA. Note, however, that * this conversion can still be too slow if you want to do it every frame, and - * should thus be avoided for that purpose. The only requirement for the - * reordering is that an uncompressed image must be available. If the RAM - * image is compressed, it will attempt to re-load the texture from disk, if - * it doesn't find an uncompressed image there, it will return NULL. + * should thus be avoided for that purpose. + * + * The only requirement for the reordering is that an uncompressed image must + * be available. If the RAM image is compressed, it will attempt to re-load + * the texture from disk, if it doesn't find an uncompressed image there, it + * will return NULL. */ CPTA_uchar Texture:: get_ram_image_as(const string &requested_format) { @@ -6125,92 +6146,177 @@ get_ram_image_as(const string &requested_format) { return CPTA_uchar(data); } + // Check if we have an alpha channel, and remember which channel we use. + int alpha = -1; + if (Texture::has_alpha(cdata->_format)) { + alpha = cdata->_num_components - 1; + } + + // Validate the format beforehand. + for (size_t i = 0; i < format.size(); ++i) { + if (format[i] != 'B' && format[i] != 'G' && format[i] != 'R' && + format[i] != 'A' && format[i] != '0' && format[i] != '1') { + gobj_cat.error() << "Unexpected component character '" + << format[i] << "', expected one of RGBA01!\n"; + return CPTA_uchar(get_class_type()); + } + } + // Create a new empty array that can hold our image. PTA_uchar newdata = PTA_uchar::empty_array(imgsize * format.size() * cdata->_component_width, get_class_type()); // These ifs are for optimization of commonly used image types. - if (format == "RGBA" && cdata->_num_components == 4 && cdata->_component_width == 1) { - imgsize *= 4; - for (int p = 0; p < imgsize; p += 4) { - newdata[p ] = data[p + 2]; - newdata[p + 1] = data[p + 1]; - newdata[p + 2] = data[p ]; - newdata[p + 3] = data[p + 3]; - } - return newdata; - } - if (format == "RGB" && cdata->_num_components == 3 && cdata->_component_width == 1) { - imgsize *= 3; - for (int p = 0; p < imgsize; p += 3) { - newdata[p ] = data[p + 2]; - newdata[p + 1] = data[p + 1]; - newdata[p + 2] = data[p ]; - } - return newdata; - } - if (format == "A" && cdata->_component_width == 1 && cdata->_num_components != 3) { - // We can generally rely on alpha to be the last component. - int component = cdata->_num_components - 1; - for (int p = 0; p < imgsize; ++p) { - newdata[p] = data[component]; - } - return newdata; - } if (cdata->_component_width == 1) { + if (format == "RGBA" && cdata->_num_components == 4) { + const uint32_t *src = (const uint32_t *)data.p(); + uint32_t *dst = (uint32_t *)newdata.p(); + + for (int p = 0; p < imgsize; ++p) { + uint32_t v = *src++; + *dst++ = ((v & 0xff00ff00u)) | + ((v & 0x00ff0000u) >> 16) | + ((v & 0x000000ffu) << 16); + } + return newdata; + } + if (format == "RGB" && cdata->_num_components == 4) { + const uint32_t *src = (const uint32_t *)data.p(); + uint32_t *dst = (uint32_t *)newdata.p(); + + // Convert blocks of 4 pixels at a time, so that we can treat both the + // source and destination as 32-bit integers. + int blocks = imgsize >> 2; + for (int i = 0; i < blocks; ++i) { + uint32_t v0 = *src++; + uint32_t v1 = *src++; + uint32_t v2 = *src++; + uint32_t v3 = *src++; + *dst++ = ((v0 & 0x00ff0000u) >> 16) | + ((v0 & 0x0000ff00u)) | + ((v0 & 0x000000ffu) << 16) | + ((v1 & 0x00ff0000u) << 8); + *dst++ = ((v1 & 0x0000ff00u) >> 8) | + ((v1 & 0x000000ffu) << 8) | + ((v2 & 0x00ff0000u)) | + ((v2 & 0x0000ff00u) << 16); + *dst++ = ((v2 & 0x000000ffu)) | + ((v3 & 0x00ff0000u) >> 8) | + ((v3 & 0x0000ff00u) << 8) | + ((v3 & 0x000000ffu) << 24); + } + + // If the image size wasn't a multiple of 4, we may have a handful of + // pixels left over. Convert those the slower way. + uint8_t *tail = (uint8_t *)dst; + for (int i = (imgsize & ~0x3); i < imgsize; ++i) { + uint32_t v = *src++; + *tail++ = (v & 0x00ff0000u) >> 16; + *tail++ = (v & 0x0000ff00u) >> 8; + *tail++ = (v & 0x000000ffu); + } + return newdata; + } + if (format == "BGR" && cdata->_num_components == 4) { + const uint32_t *src = (const uint32_t *)data.p(); + uint32_t *dst = (uint32_t *)newdata.p(); + + // Convert blocks of 4 pixels at a time, so that we can treat both the + // source and destination as 32-bit integers. + int blocks = imgsize >> 2; + for (int i = 0; i < blocks; ++i) { + uint32_t v0 = *src++; + uint32_t v1 = *src++; + uint32_t v2 = *src++; + uint32_t v3 = *src++; + *dst++ = (v0 & 0x00ffffffu) | ((v1 & 0x000000ffu) << 24); + *dst++ = ((v1 & 0x00ffff00u) >> 8) | ((v2 & 0x0000ffffu) << 16); + *dst++ = ((v2 & 0x00ff0000u) >> 16) | ((v3 & 0x00ffffffu) << 8); + } + + // If the image size wasn't a multiple of 4, we may have a handful of + // pixels left over. Convert those the slower way. + uint8_t *tail = (uint8_t *)dst; + for (int i = (imgsize & ~0x3); i < imgsize; ++i) { + uint32_t v = *src++; + *tail++ = (v & 0x000000ffu); + *tail++ = (v & 0x0000ff00u) >> 8; + *tail++ = (v & 0x00ff0000u) >> 16; + } + return newdata; + } + const uint8_t *src = (const uint8_t *)data.p(); + uint8_t *dst = (uint8_t *)newdata.p(); + + if (format == "RGB" && cdata->_num_components == 3) { + for (int i = 0; i < imgsize; ++i) { + *dst++ = src[2]; + *dst++ = src[1]; + *dst++ = src[0]; + src += 3; + } + return newdata; + } + if (format == "A" && cdata->_num_components != 3) { + // We can generally rely on alpha to be the last component. + for (int p = 0; p < imgsize; ++p) { + dst[p] = src[alpha]; + src += cdata->_num_components; + } + return newdata; + } + // Fallback case for other 8-bit-per-channel formats. for (int p = 0; p < imgsize; ++p) { - for (uchar s = 0; s < format.size(); ++s) { - signed char component = -1; - if (format.at(s) == 'B' || (cdata->_num_components <= 2 && format.at(s) != 'A')) { - component = 0; - } else if (format.at(s) == 'G') { - component = 1; - } else if (format.at(s) == 'R') { - component = 2; - } else if (format.at(s) == 'A') { - nassertr(cdata->_num_components != 3, CPTA_uchar(get_class_type())); - component = cdata->_num_components - 1; - } else if (format.at(s) == '0') { - newdata[p * format.size() + s] = 0x00; - } else if (format.at(s) == '1') { - newdata[p * format.size() + s] = 0xff; + for (size_t i = 0; i < format.size(); ++i) { + if (format[i] == 'B' || (cdata->_num_components <= 2 && format[i] != 'A')) { + *dst++ = src[0]; + } else if (format[i] == 'G') { + *dst++ = src[1]; + } else if (format[i] == 'R') { + *dst++ = src[2]; + } else if (format[i] == 'A') { + if (alpha >= 0) { + *dst++ = src[alpha]; + } else { + *dst++ = 0xff; + } + } else if (format[i] == '1') { + *dst++ = 0xff; } else { - gobj_cat.error() << "Unexpected component character '" - << format.at(s) << "', expected one of RGBA!\n"; - return CPTA_uchar(get_class_type()); - } - if (component >= 0) { - newdata[p * format.size() + s] = data[p * cdata->_num_components + component]; + *dst++ = 0x00; } } + src += cdata->_num_components; } return newdata; } + + // The slow and general case. for (int p = 0; p < imgsize; ++p) { - for (uchar s = 0; s < format.size(); ++s) { - signed char component = -1; - if (format.at(s) == 'B' || (cdata->_num_components <= 2 && format.at(s) != 'A')) { + for (size_t i = 0; i < format.size(); ++i) { + int component = 0; + if (format[i] == 'B' || (cdata->_num_components <= 2 && format[i] != 'A')) { component = 0; - } else if (format.at(s) == 'G') { + } else if (format[i] == 'G') { component = 1; - } else if (format.at(s) == 'R') { + } else if (format[i] == 'R') { component = 2; - } else if (format.at(s) == 'A') { - nassertr(cdata->_num_components != 3, CPTA_uchar(get_class_type())); - component = cdata->_num_components - 1; - } else if (format.at(s) == '0') { - memset((void*)(newdata + (p * format.size() + s) * cdata->_component_width), 0, cdata->_component_width); - } else if (format.at(s) == '1') { - memset((void*)(newdata + (p * format.size() + s) * cdata->_component_width), -1, cdata->_component_width); + } else if (format[i] == 'A') { + if (alpha >= 0) { + component = alpha; + } else { + memset((void*)(newdata + (p * format.size() + i) * cdata->_component_width), -1, cdata->_component_width); + continue; + } + } else if (format[i] == '1') { + memset((void*)(newdata + (p * format.size() + i) * cdata->_component_width), -1, cdata->_component_width); + continue; } else { - gobj_cat.error() << "Unexpected component character '" - << format.at(s) << "', expected one of RGBA!\n"; - return CPTA_uchar(get_class_type()); - } - if (component >= 0) { - memcpy((void*)(newdata + (p * format.size() + s) * cdata->_component_width), - (void*)(data + (p * cdata->_num_components + component) * cdata->_component_width), - cdata->_component_width); + memset((void*)(newdata + (p * format.size() + i) * cdata->_component_width), 0, cdata->_component_width); + continue; } + memcpy((void*)(newdata + (p * format.size() + i) * cdata->_component_width), + (void*)(data + (p * cdata->_num_components + component) * cdata->_component_width), + cdata->_component_width); } } return newdata; @@ -6229,7 +6335,7 @@ do_set_simple_ram_image(CData *cdata, CPTA_uchar image, int x_size, int y_size) cdata->_simple_y_size = y_size; cdata->_simple_ram_image._image = image.cast_non_const(); cdata->_simple_ram_image._page_size = image.size(); - cdata->_simple_image_date_generated = (PN_int32)time(NULL); + cdata->_simple_image_date_generated = (int32_t)time(NULL); cdata->inc_simple_image_modified(); } @@ -6546,25 +6652,84 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, if (maxval == 255 && component_width == 1) { // Most common case: one byte per pixel, and the source image shows a - // maxval of 255. No scaling is necessary. - for (int j = y_size-1; j >= 0; j--) { - for (int i = 0; i < x_size; i++) { - if (is_grayscale) { - store_unscaled_byte(p, pnmimage.get_gray_val(i, j)); - } else { - store_unscaled_byte(p, pnmimage.get_blue_val(i, j)); - store_unscaled_byte(p, pnmimage.get_green_val(i, j)); - store_unscaled_byte(p, pnmimage.get_red_val(i, j)); + // maxval of 255. No scaling is necessary. Because this is such a common + // case, we break it out per component for best performance. + switch (num_components) { + case 1: + for (int j = y_size-1; j >= 0; j--) { + xel *row = pnmimage.row(j); + for (int i = 0; i < x_size; i++) { + *p++ = (uchar)PPM_GETB(row[i]); } - if (has_alpha) { - if (img_has_alpha) { - store_unscaled_byte(p, pnmimage.get_alpha_val(i, j)); - } else { - store_unscaled_byte(p, 255); + p += row_skip; + } + break; + + case 2: + if (img_has_alpha) { + for (int j = y_size-1; j >= 0; j--) { + xel *row = pnmimage.row(j); + xelval *alpha_row = pnmimage.alpha_row(j); + for (int i = 0; i < x_size; i++) { + *p++ = (uchar)PPM_GETB(row[i]); + *p++ = (uchar)alpha_row[i]; } + p += row_skip; + } + } else { + for (int j = y_size-1; j >= 0; j--) { + xel *row = pnmimage.row(j); + for (int i = 0; i < x_size; i++) { + *p++ = (uchar)PPM_GETB(row[i]); + *p++ = (uchar)255; + } + p += row_skip; } } - p += row_skip; + break; + + case 3: + for (int j = y_size-1; j >= 0; j--) { + xel *row = pnmimage.row(j); + for (int i = 0; i < x_size; i++) { + *p++ = (uchar)PPM_GETB(row[i]); + *p++ = (uchar)PPM_GETG(row[i]); + *p++ = (uchar)PPM_GETR(row[i]); + } + p += row_skip; + } + break; + + case 4: + if (img_has_alpha) { + for (int j = y_size-1; j >= 0; j--) { + xel *row = pnmimage.row(j); + xelval *alpha_row = pnmimage.alpha_row(j); + for (int i = 0; i < x_size; i++) { + *p++ = (uchar)PPM_GETB(row[i]); + *p++ = (uchar)PPM_GETG(row[i]); + *p++ = (uchar)PPM_GETR(row[i]); + *p++ = (uchar)alpha_row[i]; + } + p += row_skip; + } + } else { + for (int j = y_size-1; j >= 0; j--) { + xel *row = pnmimage.row(j); + for (int i = 0; i < x_size; i++) { + *p++ = (uchar)PPM_GETB(row[i]); + *p++ = (uchar)PPM_GETG(row[i]); + *p++ = (uchar)PPM_GETR(row[i]); + *p++ = (uchar)255; + } + p += row_skip; + } + } + break; + + default: + nassertv(num_components >= 1 && num_components <= 4); + break; } } else if (maxval == 65535 && component_width == 2) { @@ -6739,17 +6904,44 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size, const unsigned char *p = &image[idx]; if (component_width == 1) { - for (int j = y_size-1; j >= 0; j--) { - for (int i = 0; i < x_size; i++) { - if (is_grayscale) { - pnmimage.set_gray(i, j, get_unsigned_byte(p)); - } else { - pnmimage.set_blue(i, j, get_unsigned_byte(p)); - pnmimage.set_green(i, j, get_unsigned_byte(p)); - pnmimage.set_red(i, j, get_unsigned_byte(p)); + if (is_grayscale) { + if (has_alpha) { + for (int j = y_size-1; j >= 0; j--) { + xel *row = pnmimage.row(j); + xelval *alpha_row = pnmimage.alpha_row(j); + for (int i = 0; i < x_size; i++) { + PPM_PUTB(row[i], *p++); + alpha_row[i] = *p++; + } } - if (has_alpha) { - pnmimage.set_alpha(i, j, get_unsigned_byte(p)); + } else { + for (int j = y_size-1; j >= 0; j--) { + xel *row = pnmimage.row(j); + for (int i = 0; i < x_size; i++) { + PPM_PUTB(row[i], *p++); + } + } + } + } else { + if (has_alpha) { + for (int j = y_size-1; j >= 0; j--) { + xel *row = pnmimage.row(j); + xelval *alpha_row = pnmimage.alpha_row(j); + for (int i = 0; i < x_size; i++) { + PPM_PUTB(row[i], *p++); + PPM_PUTG(row[i], *p++); + PPM_PUTR(row[i], *p++); + alpha_row[i] = *p++; + } + } + } else { + for (int j = y_size-1; j >= 0; j--) { + xel *row = pnmimage.row(j); + for (int i = 0; i < x_size; i++) { + PPM_PUTB(row[i], *p++); + PPM_PUTG(row[i], *p++); + PPM_PUTR(row[i], *p++); + } } } } @@ -6913,9 +7105,9 @@ read_dds_level_abgr8(Texture *tex, CData *cdata, const DDSHeader &header, int n, unsigned char *p = image.p() + y * row_bytes; in.read((char *)p, row_bytes); - PN_uint32 *pw = (PN_uint32 *)p; + uint32_t *pw = (uint32_t *)p; for (int x = 0; x < x_size; ++x) { - PN_uint32 w = *pw; + uint32_t w = *pw; #ifdef WORDS_BIGENDIAN // bigendian: convert R, G, B, A to B, G, R, A. w = ((w & 0xff00) << 16) | ((w & 0xff000000U) >> 16) | (w & 0xff00ff); @@ -6969,7 +7161,7 @@ read_dds_level_abgr16(Texture *tex, CData *cdata, const DDSHeader &header, int n unsigned char *p = image.p() + y * row_bytes; in.read((char *)p, row_bytes); - PN_uint16 *pw = (PN_uint16 *)p; + uint16_t *pw = (uint16_t *)p; for (int x = 0; x < x_size; ++x) { swap(pw[0], pw[2]); pw += 4; @@ -6996,7 +7188,7 @@ read_dds_level_abgr32(Texture *tex, CData *cdata, const DDSHeader &header, int n unsigned char *p = image.p() + y * row_bytes; in.read((char *)p, row_bytes); - PN_uint32 *pw = (PN_uint32 *)p; + uint32_t *pw = (uint32_t *)p; for (int x = 0; x < x_size; ++x) { swap(pw[0], pw[2]); pw += 4; @@ -7225,8 +7417,8 @@ read_dds_level_bc1(Texture *tex, CData *cdata, const DDSHeader &header, int n, i for (int ci = 0; ci < num_cols; ++ci) { // . . . and (b) within each block, we reverse the 4 individual rows // of 4 pixels. - PN_uint32 *cells = (PN_uint32 *)p; - PN_uint32 w = cells[1]; + uint32_t *cells = (uint32_t *)p; + uint32_t w = cells[1]; w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24); cells[1] = w; @@ -7240,8 +7432,8 @@ read_dds_level_bc1(Texture *tex, CData *cdata, const DDSHeader &header, int n, i in.read((char *)p, row_length); for (int ci = 0; ci < num_cols; ++ci) { - PN_uint32 *cells = (PN_uint32 *)p; - PN_uint32 w = cells[1]; + uint32_t *cells = (uint32_t *)p; + uint32_t w = cells[1]; w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8); cells[1] = w; @@ -7295,11 +7487,11 @@ read_dds_level_bc2(Texture *tex, CData *cdata, const DDSHeader &header, int n, i for (int ci = 0; ci < num_cols; ++ci) { // . . . and (b) within each block, we reverse the 4 individual rows // of 4 pixels. - PN_uint32 *cells = (PN_uint32 *)p; + uint32_t *cells = (uint32_t *)p; // Alpha. The block is four 16-bit words of pixel data. - PN_uint32 w0 = cells[0]; - PN_uint32 w1 = cells[1]; + uint32_t w0 = cells[0]; + uint32_t w1 = cells[1]; w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16); w1 = ((w1 & 0xffff) << 16) | ((w1 & 0xffff0000U) >> 16); cells[0] = w1; @@ -7307,7 +7499,7 @@ read_dds_level_bc2(Texture *tex, CData *cdata, const DDSHeader &header, int n, i // Color. Only the second 32-bit dword of the color block represents // the pixel data. - PN_uint32 w = cells[3]; + uint32_t w = cells[3]; w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24); cells[3] = w; @@ -7321,13 +7513,13 @@ read_dds_level_bc2(Texture *tex, CData *cdata, const DDSHeader &header, int n, i in.read((char *)p, row_length); for (int ci = 0; ci < num_cols; ++ci) { - PN_uint32 *cells = (PN_uint32 *)p; + uint32_t *cells = (uint32_t *)p; - PN_uint32 w0 = cells[0]; + uint32_t w0 = cells[0]; w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16); cells[0] = w0; - PN_uint32 w = cells[3]; + uint32_t w = cells[3]; w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8); cells[3] = w; @@ -7381,7 +7573,7 @@ read_dds_level_bc3(Texture *tex, CData *cdata, const DDSHeader &header, int n, i for (int ci = 0; ci < num_cols; ++ci) { // . . . and (b) within each block, we reverse the 4 individual rows // of 4 pixels. - PN_uint32 *cells = (PN_uint32 *)p; + uint32_t *cells = (uint32_t *)p; // Alpha. The block is one 16-bit word of reference values, followed // by six words of pixel values, in 12-bit rows. Tricky to invert. @@ -7401,7 +7593,7 @@ read_dds_level_bc3(Texture *tex, CData *cdata, const DDSHeader &header, int n, i // Color. Only the second 32-bit dword of the color block represents // the pixel data. - PN_uint32 w = cells[3]; + uint32_t w = cells[3]; w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24); cells[3] = w; @@ -7415,7 +7607,7 @@ read_dds_level_bc3(Texture *tex, CData *cdata, const DDSHeader &header, int n, i in.read((char *)p, row_length); for (int ci = 0; ci < num_cols; ++ci) { - PN_uint32 *cells = (PN_uint32 *)p; + uint32_t *cells = (uint32_t *)p; unsigned char p2 = p[2]; unsigned char p3 = p[3]; @@ -7425,11 +7617,11 @@ read_dds_level_bc3(Texture *tex, CData *cdata, const DDSHeader &header, int n, i p[3] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4); p[4] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4); - PN_uint32 w0 = cells[0]; + uint32_t w0 = cells[0]; w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16); cells[0] = w0; - PN_uint32 w = cells[3]; + uint32_t w = cells[3]; w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8); cells[3] = w; @@ -7667,11 +7859,15 @@ compare_images(const PNMImage &a, const PNMImage &b) { int delta = 0; for (int yi = 0; yi < a.get_y_size(); ++yi) { + xel *a_row = a.row(yi); + xel *b_row = b.row(yi); + xelval *a_alpha_row = a.alpha_row(yi); + xelval *b_alpha_row = b.alpha_row(yi); for (int xi = 0; xi < a.get_x_size(); ++xi) { - delta += abs(a.get_red_val(xi, yi) - b.get_red_val(xi, yi)); - delta += abs(a.get_green_val(xi, yi) - b.get_green_val(xi, yi)); - delta += abs(a.get_blue_val(xi, yi) - b.get_blue_val(xi, yi)); - delta += abs(a.get_alpha_val(xi, yi) - b.get_alpha_val(xi, yi)); + delta += abs(PPM_GETR(a_row[xi]) - PPM_GETR(b_row[xi])); + delta += abs(PPM_GETG(a_row[xi]) - PPM_GETG(b_row[xi])); + delta += abs(PPM_GETB(a_row[xi]) - PPM_GETB(b_row[xi])); + delta += abs(a_alpha_row[xi] - b_alpha_row[xi]); } } @@ -8567,8 +8763,19 @@ do_write_datagram_header(CData *cdata, BamWriter *manager, Datagram &me, bool &h me.add_uint8(cdata->_primary_file_num_channels); me.add_uint8(cdata->_alpha_file_channel); me.add_bool(has_rawdata); - me.add_uint8(cdata->_texture_type); - me.add_bool(cdata->_has_read_mipmaps); + + if (manager->get_file_minor_ver() < 25 && + cdata->_texture_type == TT_cube_map) { + // Between Panda3D releases 1.7.2 and 1.8.0 (bam versions 6.24 and 6.25), + // we added TT_2d_texture_array, shifting the definition for TT_cube_map. + me.add_uint8(TT_2d_texture_array); + } else { + me.add_uint8(cdata->_texture_type); + } + + if (manager->get_file_minor_ver() >= 32) { + me.add_bool(cdata->_has_read_mipmaps); + } } /** @@ -8577,7 +8784,18 @@ do_write_datagram_header(CData *cdata, BamWriter *manager, Datagram &me, bool &h */ void Texture:: do_write_datagram_body(CData *cdata, BamWriter *manager, Datagram &me) { - cdata->_default_sampler.write_datagram(me); + if (manager->get_file_minor_ver() >= 36) { + cdata->_default_sampler.write_datagram(me); + } else { + const SamplerState &s = cdata->_default_sampler; + me.add_uint8(s.get_wrap_u()); + me.add_uint8(s.get_wrap_v()); + me.add_uint8(s.get_wrap_w()); + me.add_uint8(s.get_minfilter()); + me.add_uint8(s.get_magfilter()); + me.add_int16(s.get_anisotropic_degree()); + s.get_border_color().write_datagram(me); + } me.add_uint8(cdata->_compression); me.add_uint8(cdata->_quality_level); @@ -8589,7 +8807,9 @@ do_write_datagram_body(CData *cdata, BamWriter *manager, Datagram &me) { me.add_uint8(cdata->_usage_hint); } - me.add_uint8(cdata->_auto_texture_scale); + if (manager->get_file_minor_ver() >= 28) { + me.add_uint8(cdata->_auto_texture_scale); + } me.add_uint32(cdata->_orig_file_x_size); me.add_uint32(cdata->_orig_file_y_size); @@ -8615,11 +8835,15 @@ do_write_datagram_rawdata(CData *cdata, BamWriter *manager, Datagram &me) { me.add_uint32(cdata->_y_size); me.add_uint32(cdata->_z_size); - me.add_uint32(cdata->_pad_x_size); - me.add_uint32(cdata->_pad_y_size); - me.add_uint32(cdata->_pad_z_size); + if (manager->get_file_minor_ver() >= 30) { + me.add_uint32(cdata->_pad_x_size); + me.add_uint32(cdata->_pad_y_size); + me.add_uint32(cdata->_pad_z_size); + } - me.add_uint32(cdata->_num_views); + if (manager->get_file_minor_ver() >= 26) { + me.add_uint32(cdata->_num_views); + } me.add_uint8(cdata->_component_type); me.add_uint8(cdata->_component_width); me.add_uint8(cdata->_ram_image_compression); diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index e1226579b2..010f847b6a 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -40,7 +40,6 @@ #include "cycleDataStageWriter.h" #include "pipelineCycler.h" #include "samplerState.h" -#include "pnmImage.h" #include "colorSpace.h" #include "geomEnums.h" #include "bamCacheRecord.h" @@ -159,6 +158,7 @@ PUBLISHED: F_rgb10_a2, F_rg, + F_r16i }; // Deprecated. See SamplerState.FilterType. @@ -976,7 +976,7 @@ protected: RamImage _simple_ram_image; int _simple_x_size; int _simple_y_size; - PN_int32 _simple_image_date_generated; + int32_t _simple_image_date_generated; // This is the color that should be used when no image was given. bool _has_clear_color; diff --git a/panda/src/gobj/textureStage.cxx b/panda/src/gobj/textureStage.cxx index 96edb74e6d..708b6d140d 100644 --- a/panda/src/gobj/textureStage.cxx +++ b/panda/src/gobj/textureStage.cxx @@ -438,7 +438,10 @@ write_datagram(BamWriter *manager, Datagram &me) { me.add_uint8(_rgb_scale); me.add_uint8(_alpha_scale); me.add_bool(_saved_result); - me.add_int32(_tex_view_offset); + + if (manager->get_file_minor_ver() >= 26) { + me.add_int32(_tex_view_offset); + } me.add_uint8(_combine_rgb_mode); me.add_uint8(_num_combine_rgb_operands); diff --git a/panda/src/gobj/transformBlendTable.h b/panda/src/gobj/transformBlendTable.h index 3981278b04..55d628d349 100644 --- a/panda/src/gobj/transformBlendTable.h +++ b/panda/src/gobj/transformBlendTable.h @@ -55,7 +55,7 @@ PUBLISHED: INLINE size_t get_num_blends() const; INLINE const TransformBlend &get_blend(size_t n) const; MAKE_SEQ(get_blends, get_num_blends, get_blend); - INLINE UpdateSeq get_modified(Thread *current_thread) const; + INLINE UpdateSeq get_modified(Thread *current_thread = Thread::get_current_thread()) const; void set_blend(size_t n, const TransformBlend &blend); void remove_blend(size_t n); @@ -70,6 +70,12 @@ PUBLISHED: void write(ostream &out, int indent_level) const; + MAKE_SEQ_PROPERTY(blends, get_num_blends, get_blend, set_blend, remove_blend); + MAKE_PROPERTY(modified, get_modified); + MAKE_PROPERTY(num_transforms, get_num_transforms); + MAKE_PROPERTY(max_simultaneous_transforms, get_max_simultaneous_transforms); + MAKE_PROPERTY(rows, get_rows, set_rows); + private: class CData; diff --git a/panda/src/gobj/transformTable.h b/panda/src/gobj/transformTable.h index 48fa0abb7e..0483fced99 100644 --- a/panda/src/gobj/transformTable.h +++ b/panda/src/gobj/transformTable.h @@ -48,7 +48,7 @@ PUBLISHED: INLINE size_t get_num_transforms() const; INLINE const VertexTransform *get_transform(size_t n) const; MAKE_SEQ(get_transforms, get_num_transforms, get_transform); - INLINE UpdateSeq get_modified(Thread *current_thread) const; + INLINE UpdateSeq get_modified(Thread *current_thread = Thread::get_current_thread()) const; void set_transform(size_t n, const VertexTransform *transform); void remove_transform(size_t n); @@ -56,6 +56,10 @@ PUBLISHED: void write(ostream &out) const; + MAKE_PROPERTY(registered, is_registered); + MAKE_PROPERTY(modified, get_modified); + MAKE_SEQ_PROPERTY(transforms, get_num_transforms, get_transform, set_transform, remove_transform); + private: void do_register(); void do_unregister(); diff --git a/panda/src/grutil/config_grutil.cxx b/panda/src/grutil/config_grutil.cxx index ea8aa7174d..5564a3719d 100644 --- a/panda/src/grutil/config_grutil.cxx +++ b/panda/src/grutil/config_grutil.cxx @@ -23,6 +23,7 @@ #include "nodeVertexTransform.h" #include "rigidBodyCombiner.h" #include "pipeOcclusionCullTraverser.h" +#include "shaderTerrainMesh.h" #include "dconfig.h" @@ -123,6 +124,7 @@ init_libgrutil() { RigidBodyCombiner::init_type(); PipeOcclusionCullTraverser::init_type(); SceneGraphAnalyzerMeter::init_type(); + ShaderTerrainMesh::init_type(); #ifdef HAVE_AUDIO MovieTexture::init_type(); diff --git a/panda/src/grutil/movieTexture.cxx b/panda/src/grutil/movieTexture.cxx index aac04d4b0b..a2d8d3bc3a 100644 --- a/panda/src/grutil/movieTexture.cxx +++ b/panda/src/grutil/movieTexture.cxx @@ -816,7 +816,10 @@ do_write_datagram_rawdata(Texture::CData *cdata_tex, BamWriter *manager, Datagra CDReader cdata(_cycler); dg.add_uint16(cdata_tex->_z_size); - dg.add_uint16(cdata_tex->_num_views); + if (manager->get_file_minor_ver() >= 26) { + dg.add_uint16(cdata_tex->_num_views); + } + nassertv(cdata->_pages.size() == (size_t)(cdata_tex->_z_size * cdata_tex->_num_views)); for (size_t n = 0; n < cdata->_pages.size(); ++n) { const VideoPage &page = cdata->_pages[n]; diff --git a/panda/src/grutil/p3grutil_composite1.cxx b/panda/src/grutil/p3grutil_composite1.cxx index c02bb0c421..85d1c61e50 100644 --- a/panda/src/grutil/p3grutil_composite1.cxx +++ b/panda/src/grutil/p3grutil_composite1.cxx @@ -1,6 +1,7 @@ #include "cardMaker.cxx" #include "heightfieldTesselator.cxx" #include "geoMipTerrain.cxx" +#include "shaderTerrainMesh.cxx" #include "config_grutil.cxx" #include "lineSegs.cxx" #include "fisheyeMaker.cxx" diff --git a/panda/src/grutil/rigidBodyCombiner.cxx b/panda/src/grutil/rigidBodyCombiner.cxx index 696e81a13f..7e3ccefd65 100644 --- a/panda/src/grutil/rigidBodyCombiner.cxx +++ b/panda/src/grutil/rigidBodyCombiner.cxx @@ -210,9 +210,9 @@ convert_vd(const VertexTransform *transform, const GeomVertexData *orig) { PT(GeomVertexFormat) format = new GeomVertexFormat(*orig->get_format()); if (!orig->get_format()->has_column(InternalName::get_transform_blend())) { - PT(GeomVertexArrayFormat) af = - new GeomVertexArrayFormat(InternalName::get_transform_blend(), 1, - Geom::NT_uint16, Geom::C_index); + PT(GeomVertexArrayFormat) af = new GeomVertexArrayFormat(); + af->add_column(InternalName::get_transform_blend(), 1, + Geom::NT_uint16, Geom::C_index, 0, 2); format->add_array(af); } diff --git a/panda/src/grutil/shaderTerrainMesh.I b/panda/src/grutil/shaderTerrainMesh.I new file mode 100644 index 0000000000..91ac1035d3 --- /dev/null +++ b/panda/src/grutil/shaderTerrainMesh.I @@ -0,0 +1,182 @@ +/** + * 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 shaderTerrainMesh.I + * @author tobspr + * @date 2016-02-16 + */ + +/** + * @brief Sets the heightfield texture + * @details This sets the heightfield texture. It should be 16bit + * single channel, and have a power-of-two resolution greater than 32. + * Common sizes are 2048x2048 or 4096x4096. + * + * You should call generate() after setting the heightfield. + * + * @param filename Heightfield texture + */ +INLINE void ShaderTerrainMesh::set_heightfield(Texture* heightfield) { + _heightfield_tex = heightfield; +} + +/** + * @brief Returns the heightfield + * @details This returns the terrain heightfield, previously set with + * set_heightfield() + * + * @return Path to the heightfield + */ +INLINE Texture* ShaderTerrainMesh::get_heightfield() const { + return _heightfield_tex; +} + +/** + * @brief Sets the chunk size + * @details This sets the chunk size of the terrain. A chunk is basically the + * smallest unit in LOD. If the chunk size is too small, the terrain will + * perform bad, since there will be way too many chunks. If the chunk size + * is too big, you will not get proper LOD, and might also get bad performance. + * + * For terrains of the size 4096x4096 or 8192x8192, a chunk size of 32 seems + * to produce good results. For smaller resolutions, you should try out a + * size of 16 or even 8 for very small terrains. + * + * The amount of chunks generated for the last level equals to + * (heightfield_size / chunk_size) ** 2. The chunk size has to be a power + * of two. + * + * @param chunk_size Size of the chunks, has to be a power of two + */ +INLINE void ShaderTerrainMesh::set_chunk_size(size_t chunk_size) { + _chunk_size = chunk_size; +} + +/** + * @brief Returns the chunk size + * @details This returns the chunk size, previously set with set_chunk_size() + * @return Chunk size + */ +INLINE size_t ShaderTerrainMesh::get_chunk_size() const { + return _chunk_size; +} + +/** + * @brief Sets whether to generate patches + * @details If this option is set to true, GeomPatches will be used instead of + * GeomTriangles. This is required when the terrain is used with tesselation + * shaders, since patches are required for tesselation, whereas triangles + * are required for regular rendering. + * + * If this option is set to true while not using a tesselation shader, the + * terrain will not get rendered, or even produce errors. The same applies + * when this is option is not set, but the terrain is used with tesselation + * shaders. + * + * @param generate_patches [description] + */ +INLINE void ShaderTerrainMesh::set_generate_patches(bool generate_patches) { + _generate_patches = generate_patches; +} + +/** + * @brief Returns whether to generate patches + * @details This returns whether patches are generated, previously set with + * set_generate_patches() + * + * @return Whether to generate patches + */ +INLINE bool ShaderTerrainMesh::get_generate_patches() const { + return _generate_patches; +} + + +/** + * @brief Sets the desired triangle width + * @details This sets the desired width a triangle should have in pixels. + * A value of 10.0 for example will make the terrain tesselate everything + * in a way that each triangle edge roughly is 10 pixels wide. + * Of course this will not always accurately match, however you can use this + * setting to control the LOD algorithm of the terrain. + * + * @param target_triangle_width Desired triangle width in pixels + */ +INLINE void ShaderTerrainMesh::set_target_triangle_width(PN_stdfloat target_triangle_width) { + _target_triangle_width = target_triangle_width; +} + +/** + * @brief Returns the target triangle width + * @details This returns the target triangle width, previously set with + * ShaderTerrainMesh::set_target_triangle_width() + * + * @return Target triangle width + */ +INLINE PN_stdfloat ShaderTerrainMesh::get_target_triangle_width() const { + return _target_triangle_width; +} + + +/** + * @brief Sets whether to enable terrain updates + * @details This flag controls whether the terrain should be updated. If this value + * is set to false, no updating of the terrain will happen. This can be useful + * to debug the culling algorithm used by the terrain. + * + * @param update_enabled Whether to update the terrain + */ +INLINE void ShaderTerrainMesh::set_update_enabled(bool update_enabled) { + _update_enabled = update_enabled; +} + +/** + * @brief Returns whether the terrain is getting updated + * @details This returns whether the terrain is getting updates, previously set with + * set_update_enabled() + * + * @return Whether to update the terrain + */ +INLINE bool ShaderTerrainMesh::get_update_enabled() const { + return _update_enabled; +} + +/** + * @brief Clears all children + * @details This clears all children on the chunk and sets them to NULL. This will + * effectively free all memory consumed by this chunk and its children. + */ +INLINE void ShaderTerrainMesh::Chunk::clear_children() { + for (size_t i = 0; i < 4; ++i) { + delete children[i]; + children[i] = NULL; + } +} + +/** + * @brief Chunk constructor + * @details This constructs a new chunk, and sets all children to NULL. + */ +INLINE ShaderTerrainMesh::Chunk::Chunk() { + for (size_t i = 0; i < 4; ++i) + children[i] = NULL; +} + +/** + * @brief Chunk destructor + * @details This destructs the chunk, freeing all used resources + */ +INLINE ShaderTerrainMesh::Chunk::~Chunk() { + clear_children(); +} + +/** + * @see ShaderTerrainMesh::uv_to_world(LTexCoord) + */ +INLINE LPoint3 ShaderTerrainMesh::uv_to_world(PN_stdfloat u, PN_stdfloat v) const { + return uv_to_world(LTexCoord(u, v)); +} diff --git a/panda/src/grutil/shaderTerrainMesh.cxx b/panda/src/grutil/shaderTerrainMesh.cxx new file mode 100644 index 0000000000..8e655de000 --- /dev/null +++ b/panda/src/grutil/shaderTerrainMesh.cxx @@ -0,0 +1,709 @@ +/** + * 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 shaderTerrainMesh.cxx + * @author tobspr + * @date 2016-02-16 + */ + + +#include "shaderTerrainMesh.h" +#include "geom.h" +#include "geomVertexFormat.h" +#include "geomVertexData.h" +#include "geomVertexWriter.h" +#include "geomNode.h" +#include "geomTriangles.h" +#include "geomPatches.h" +#include "omniBoundingVolume.h" +#include "cullableObject.h" +#include "cullTraverser.h" +#include "cullHandler.h" +#include "cullTraverserData.h" +#include "clockObject.h" +#include "shaderAttrib.h" +#include "renderAttrib.h" +#include "shaderInput.h" +#include "boundingBox.h" +#include "samplerState.h" +#include "config_grutil.h" +#include "typeHandle.h" + +ConfigVariableBool stm_use_hexagonal_layout +("stm-use-hexagonal-layout", false, + PRC_DESC("Set this to true to use a hexagonal vertex layout. This approximates " + "the heightfield in a better way, however the CLOD transitions might be " + "visible due to the vertices not matching exactly.")); + +ConfigVariableInt stm_max_chunk_count +("stm-max-chunk-count", 2048, + PRC_DESC("Controls the maximum amount of chunks the Terrain can display. If you use " + "a high LOD, you might have to increment this value. The lower this value is " + "the less data has to be transferred to the GPU.")); + +ConfigVariableInt stm_max_views +("stm-max-views", 8, + PRC_DESC("Controls the maximum amount of different views the Terrain can be rendered " + "with. Each camera rendering the terrain corresponds to a view. Lowering this " + "value will reduce the data that has to be transferred to the GPU.")); + +PStatCollector ShaderTerrainMesh::_basic_collector("Cull:ShaderTerrainMesh:Setup"); +PStatCollector ShaderTerrainMesh::_lod_collector("Cull:ShaderTerrainMesh:CollectLOD"); + +NotifyCategoryDef(shader_terrain, ""); + +TypeHandle ShaderTerrainMesh::_type_handle; + +/** + * @brief Helper function to check for a power of two + * @details This method checks for a power of two by using bitmasks + * + * @param x Number to check + * @return true if x is a power of two, false otherwise + */ +int check_power_of_two(size_t x) +{ + return ((x != 0) && ((x & (~x + 1)) == x)); +} + +/** + * @brief Constructs a new Terrain Mesh + * @details This constructs a new terrain mesh. By default, no transform is set + * on the mesh, causing it to range over the unit box from (0, 0, 0) to + * (1, 1, 1). Usually you want to set a custom transform with NodePath::set_scale() + */ +ShaderTerrainMesh::ShaderTerrainMesh() : + PandaNode("ShaderTerrainMesh"), + _size(0), + _chunk_size(32), + _generate_patches(false), + _data_texture(NULL), + _chunk_geom(NULL), + _current_view_index(0), + _last_frame_count(-1), + _target_triangle_width(10.0f), + _update_enabled(true), + _heightfield_tex(NULL) +{ + set_final(true); + set_bounds(new OmniBoundingVolume()); +} + +/** + * @brief Generates the terrain mesh + * @details This generates the terrain mesh, initializing all chunks of the + * internal used quadtree. At this point, a heightfield and a chunk size should + * have been set, otherwise an error is thrown. + * + * If anything goes wrong, like a missing heightfield, then an error is printed + * and false is returned. + * + * @return true if the terrain was initialized, false if an error occured + */ +bool ShaderTerrainMesh::generate() { + if (!do_check_heightfield()) + return false; + + if (_chunk_size < 8 || !check_power_of_two(_chunk_size)) { + shader_terrain_cat.error() << "Invalid chunk size! Has to be >= 8 and a power of two!" << endl; + return false; + } + + if (_chunk_size > _size / 4) { + shader_terrain_cat.error() << "Chunk size too close or greater than the actual terrain size!" << endl; + return false; + } + + do_extract_heightfield(); + do_create_chunks(); + do_compute_bounds(&_base_chunk); + do_create_chunk_geom(); + do_init_data_texture(); + + // Clear image after using it, otherwise we have two copies of the heightfield + // in memory. + _heightfield.clear(); + + return true; +} + +/** + * @brief Converts the internal used Texture to a PNMImage + * @details This converts the texture passed with set_heightfield to a PNMImage, + * so we can read the pixels in a fast way. This is only used while generating + * the chunks, and the PNMImage is destroyed afterwards. + */ +void ShaderTerrainMesh::do_extract_heightfield() { + nassertv(_heightfield_tex->has_ram_image()); // Heightfield not in RAM, extract ram image first + + _heightfield_tex->store(_heightfield); + + if (_heightfield.get_maxval() != 65535) { + shader_terrain_cat.warning() << "Using non 16-bit heightfield!" << endl; + } else { + _heightfield_tex->set_format(Texture::F_r16); + } + _heightfield_tex->set_minfilter(SamplerState::FT_linear); + _heightfield_tex->set_magfilter(SamplerState::FT_linear); +} + +/** + * @brief Intermal method to check the heightfield + * @details This method cecks the heightfield generated from the heightfield texture, + * and performs some basic checks, including a check for a power of two, + * and same width and height. + * + * @return true if the heightfield meets the requirements + */ +bool ShaderTerrainMesh::do_check_heightfield() { + if (_heightfield_tex->get_x_size() != _heightfield_tex->get_y_size()) { + shader_terrain_cat.error() << "Only square heightfields are supported!"; + return false; + } + + _size = _heightfield_tex->get_x_size(); + if (_size < 32 || !check_power_of_two(_size)) { + shader_terrain_cat.error() << "Invalid heightfield! Needs to be >= 32 and a power of two (was: " + << _size << ")!" << endl; + return false; + } + + return true; +} + +/** + * @brief Internal method to init the terrain data texture + * @details This method creates the data texture, used to store all chunk data. + * The data texture is set as a shader input later on, and stores the position + * and scale of each chunk. Every row in the data texture denotes a view on + * the terrain. + */ +void ShaderTerrainMesh::do_init_data_texture() { + _data_texture = new Texture("TerrainDataTexture"); + _data_texture->setup_2d_texture(stm_max_chunk_count, stm_max_views, Texture::T_float, Texture::F_rgba32); + _data_texture->set_clear_color(LVector4(0)); + _data_texture->clear_image(); +} + +/** + * @brief Internal method to init the quadtree + * @details This method creates the base chunk and then inits all chunks recursively + * by using ShaderTerrainMesh::do_init_chunk(). + */ +void ShaderTerrainMesh::do_create_chunks() { + + // Release any previously stored children + _base_chunk.clear_children(); + + // Create the base chunk + _base_chunk.depth = 0; + _base_chunk.x = 0; + _base_chunk.y = 0; + _base_chunk.size = _size; + _base_chunk.edges.set(0, 0, 0, 0); + _base_chunk.avg_height = 0.5; + _base_chunk.min_height = 0.0; + _base_chunk.max_height = 1.0; + _base_chunk.last_clod = 0.0; + do_init_chunk(&_base_chunk); +} + +/** + * @brief Internal method to recursively init the quadtree + * @details This method inits the quadtree. Starting from a given node, it + * first examines if that node should be subdivided. + * + * If the node should be subdivided, four children are created and this method + * is called on the children again. If the node is a leaf, all children are + * set to NULL and nothing else happens. + * + * The chunk parameter may not be zero or undefined behaviour occurs. + * + * @param chunk The parent chunk + */ +void ShaderTerrainMesh::do_init_chunk(Chunk* chunk) { + if (chunk->size > _chunk_size) { + + // Compute children chunk size + size_t child_chunk_size = chunk->size / 2; + + // Subdivide chunk into 4 children + for (size_t y = 0; y < 2; ++y) { + for (size_t x = 0; x < 2; ++x) { + Chunk* child = new Chunk(); + child->size = child_chunk_size; + child->depth = chunk->depth + 1; + child->x = chunk->x + x * child_chunk_size; + child->y = chunk->y + y * child_chunk_size; + do_init_chunk(child); + chunk->children[x + 2*y] = child; + } + } + } else { + // Final chunk, initialize all children to zero + for (size_t i = 0; i < 4; ++i) { + chunk->children[i] = NULL; + } + } +} + +/** + * @brief Recursively computes the bounds for a given chunk + * @details This method takes a parent chunk, and computes the bounds recursively, + * depending on whether the chunk is a leaf or a node. + * + * If the chunk is a leaf, then the average, min and max values for that chunk + * are computed by iterating over the heightfield region of that chunk. + * + * If the chunk is a node, this method is called recursively on all children + * first, and after that, the average, min and max values for that chunk + * are computed by merging those values of the children. + * + * If chunk is NULL, undefined behaviour occurs. + * + * @param chunk The parent chunk + */ +void ShaderTerrainMesh::do_compute_bounds(Chunk* chunk) { + + // Final chunk (Leaf) + if (chunk->size == _chunk_size) { + + // Get a pointer to the PNMImage data, this is faster than using get_xel() + // for all pixels, since get_xel() also includes bounds checks and so on. + xel* data = _heightfield.get_array(); + + // Pixel getter function. Note that we have to flip the Y-component, since + // panda itself also flips it + // auto get_xel = [&](size_t x, size_t y){ return data[x + (_size - 1 - y) * _size].b / (PN_stdfloat)PGM_MAXMAXVAL; }; + #define get_xel(x, y) (data[(x) + (_size - 1 - (y)) * _size].b / (PN_stdfloat)PGM_MAXMAXVAL) + + // Iterate over all pixels + PN_stdfloat avg_height = 0.0, min_height = 1.0, max_height = 0.0; + for (size_t x = 0; x < _chunk_size; ++x) { + for (size_t y = 0; y < _chunk_size; ++y) { + + // Access data directly, to improve performance + PN_stdfloat height = get_xel(chunk->x + x, chunk->y + y); + avg_height += height; + min_height = min(min_height, height); + max_height = max(max_height, height); + } + } + + // Normalize average height + avg_height /= _chunk_size * _chunk_size; + + // Store values + chunk->min_height = min_height; + chunk->max_height = max_height; + chunk->avg_height = avg_height; + + // Get edges in the order (0, 0) (1, 0) (0, 1) (1, 1) + for (size_t y = 0; y < 2; ++y) { + for (size_t x = 0; x < 2; ++x) { + chunk->edges.set_cell(x + 2 * y, get_xel( + chunk->x + x * (_chunk_size - 1), + chunk->y + y * (_chunk_size - 1) + )); + } + } + + #undef get_xel + + } else { + + // Reset heights + chunk->avg_height = 0.0; + chunk->min_height = 1.0; + chunk->max_height = 0.0; + + // Perform bounds computation for every children and merge the children values + for (size_t i = 0; i < 4; ++i) { + do_compute_bounds(chunk->children[i]); + chunk->avg_height += chunk->children[i]->avg_height / 4.0; + chunk->min_height = min(chunk->min_height, chunk->children[i]->min_height); + chunk->max_height = max(chunk->max_height, chunk->children[i]->max_height); + } + + // Also take the edge points from the children + chunk->edges.set_x(chunk->children[0]->edges.get_x()); + chunk->edges.set_y(chunk->children[1]->edges.get_y()); + chunk->edges.set_z(chunk->children[2]->edges.get_z()); + chunk->edges.set_w(chunk->children[3]->edges.get_w()); + } +} + +/** + * @brief Internal method to create the chunk geom + * @details This method generates the internal used base chunk. The base chunk geom + * is used to render the actual terrain, and will get instanced for every chunk. + * + * The chunk has a size of (size+3) * (size+3), since additional triangles are + * inserted at the borders to prevent holes between chunks of a different LOD. + * + * If the generate patches option is set, patches will be generated instead + * of triangles, which allows the terrain to use a tesselation shader. + */ +void ShaderTerrainMesh::do_create_chunk_geom() { + + // Convert chunk size to an integer, because we operate on integers and get + // signed/unsigned mismatches otherwise + int size = (int)_chunk_size; + + // Create vertex data + PT(GeomVertexData) gvd = new GeomVertexData("vertices", GeomVertexFormat::get_v3(), Geom::UH_static); + gvd->reserve_num_rows( (size + 3) * (size + 3) ); + GeomVertexWriter vertex_writer(gvd, "vertex"); + + // Create primitive + PT(GeomPrimitive) triangles = NULL; + if (_generate_patches) { + triangles = new GeomPatches(3, Geom::UH_static); + } else { + triangles = new GeomTriangles(Geom::UH_static); + } + + // Insert chunk vertices + for (int y = -1; y <= size + 1; ++y) { + for (int x = -1; x <= size + 1; ++x) { + LVector3 vtx_pos(x / (PN_stdfloat)size, y / (PN_stdfloat)size, 0.0f); + // Stitched vertices at the cornders + if (x == -1 || y == -1 || x == size + 1 || y == size + 1) { + vtx_pos.set_z(-1.0f / (PN_stdfloat)size); + vtx_pos.set_x(max((PN_stdfloat)0, min((PN_stdfloat)1, vtx_pos.get_x()))); + vtx_pos.set_y(max((PN_stdfloat)0, min((PN_stdfloat)1, vtx_pos.get_y()))); + } + vertex_writer.add_data3(vtx_pos); + } + } + + // Its important to use int and not size_t here, since we do store negative values + // auto get_point_index = [&size](int x, int y){ return (x + 1) + (size + 3) * (y + 1); }; + #define get_point_index(x, y) (((x) + 1) + (size + 3) * ((y) + 1)) + + // Create triangles + for (int y = -1; y <= size; ++y) { + for (int x = -1; x <= size; ++x) { + // Get point indices of the quad vertices + int tl = get_point_index(x, y); + int tr = get_point_index(x + 1, y); + int bl = get_point_index(x, y + 1); + int br = get_point_index(x + 1, y + 1); + + // Vary triangle scheme on each uneven quad + if (stm_use_hexagonal_layout && (x + y) % 2 == 0 ) { + triangles->add_vertices(tl, tr, br); + triangles->add_vertices(tl, br, bl); + } else { + triangles->add_vertices(tl, tr, bl); + triangles->add_vertices(bl, tr, br); + } + } + } + + #undef get_point_index + + // Construct geom + PT(Geom) geom = new Geom(gvd); + geom->add_primitive(triangles); + + // Do not set any bounds, we do culling ourself + geom->clear_bounds(); + geom->set_bounds(new OmniBoundingVolume()); + _chunk_geom = geom; +} + +/** + * @copydoc PandaNode::is_renderable() + */ +bool ShaderTerrainMesh::is_renderable() const { + return true; +} + +/** + * @copydoc PandaNode::is_renderable() + */ +bool ShaderTerrainMesh::safe_to_flatten() const { + return false; +} + +/** + * @copydoc PandaNode::safe_to_combine() + */ +bool ShaderTerrainMesh::safe_to_combine() const { + return false; +} + +/** + * @copydoc PandaNode::add_for_draw() + */ +void ShaderTerrainMesh::add_for_draw(CullTraverser *trav, CullTraverserData &data) { + + // Make sure the terrain was properly initialized, and the geom was created + // successfully + nassertv(_data_texture != NULL); + nassertv(_chunk_geom != NULL); + + _basic_collector.start(); + + // Get current frame count + int frame_count = ClockObject::get_global_clock()->get_frame_count(); + + if (_last_frame_count != frame_count) { + // Frame count changed, this means we are at the beginning of a new frame. + // In this case, update the frame count and reset the view index. + _last_frame_count = frame_count; + _current_view_index = 0; + } + + // Get transform and render state for this render pass + CPT(TransformState) modelview_transform = data.get_internal_transform(trav); + CPT(RenderState) state = data._state->compose(get_state()); + + // Store a handle to the scene setup + const SceneSetup* scene = trav->get_scene(); + + // Get the MVP matrix, this is required for the LOD + const Lens* current_lens = scene->get_lens(); + const LMatrix4& projection_mat = current_lens->get_projection_mat(); + + // Get the current lens bounds + PT(BoundingVolume) cam_bounds = scene->get_cull_bounds(); + + // Transform the camera bounds with the main camera transform + DCAST(GeometricBoundingVolume, cam_bounds)->xform(scene->get_camera_transform()->get_mat()); + + TraversalData traversal_data; + traversal_data.cam_bounds = cam_bounds; + traversal_data.model_mat = get_transform()->get_mat(); + traversal_data.mvp_mat = modelview_transform->get_mat() * projection_mat; + traversal_data.emitted_chunks = 0; + traversal_data.storage_ptr = (ChunkDataEntry*)_data_texture->modify_ram_image().p(); + traversal_data.screen_size.set(scene->get_viewport_width(), scene->get_viewport_height()); + + // Move write pointer so it points to the beginning of the current view + traversal_data.storage_ptr += _data_texture->get_x_size() * _current_view_index; + + if (_update_enabled) { + // Traverse recursively + _lod_collector.start(); + do_traverse(&_base_chunk, &traversal_data); + _lod_collector.stop(); + } else { + // Do a rough guess of the emitted chunks, we don't know the actual count + // (we would have to store it). This is only for debugging anyways, so + // its not important we get an accurate count here. + traversal_data.emitted_chunks = _data_texture->get_x_size(); + } + + // Set shader inputs + CPT(RenderAttrib) current_shader_attrib = state->get_attrib_def(ShaderAttrib::get_class_slot()); + + // Make sure the user didn't forget to set a shader + if (!DCAST(ShaderAttrib, current_shader_attrib)->has_shader()) { + shader_terrain_cat.warning() << "No shader set on the terrain! You need to set the appropriate shader!" << endl; + } + + // Should never happen + nassertv(current_shader_attrib != NULL); + + current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input( + new ShaderInput("ShaderTerrainMesh.terrain_size", LVecBase2i(_size)) ); + current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input( + new ShaderInput("ShaderTerrainMesh.chunk_size", LVecBase2i(_chunk_size))); + current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input( + new ShaderInput("ShaderTerrainMesh.view_index", LVecBase2i(_current_view_index))); + current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input( + new ShaderInput("ShaderTerrainMesh.data_texture", _data_texture)); + current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_shader_input( + new ShaderInput("ShaderTerrainMesh.heightfield", _heightfield_tex)); + current_shader_attrib = DCAST(ShaderAttrib, current_shader_attrib)->set_instance_count( + traversal_data.emitted_chunks); + + state = state->set_attrib(current_shader_attrib, 10000); + + // Emit chunk + CullableObject *object = new CullableObject(_chunk_geom, state, modelview_transform); + trav->get_cull_handler()->record_object(object, trav); + + // After rendering, increment the view index + ++_current_view_index; + + if (_current_view_index > stm_max_views) { + shader_terrain_cat.error() << "More views than supported! Increase the stm-max-views config variable!" << endl; + } + + _basic_collector.stop(); +} + +/** + * @brief Traverses the quadtree + * @details This method traverses the given chunk, deciding whether it should + * be rendered or subdivided. + * + * In case the chunk is decided to be subdivided, this method is called on + * all children. + * + * In case the chunk is decided to be rendered, ShaderTerrainMesh::do_emit_chunk() is + * called. Otherwise nothing happens, and the chunk does not get rendered. + * + * @param chunk Chunk to traverse + * @param data Traversal data + */ +void ShaderTerrainMesh::do_traverse(Chunk* chunk, TraversalData* data, bool fully_visible) { + + // Don't check bounds if we are fully visible + if (!fully_visible) { + + // Construct chunk bounding volume + PN_stdfloat scale = 1.0 / (PN_stdfloat)_size; + LPoint3 bb_min(chunk->x * scale, chunk->y * scale, chunk->min_height); + LPoint3 bb_max((chunk->x + chunk->size) * scale, (chunk->y + chunk->size) * scale, chunk->max_height); + + BoundingBox bbox = BoundingBox(bb_min, bb_max); + DCAST(GeometricBoundingVolume, &bbox)->xform(data->model_mat); + int intersection = data->cam_bounds->contains(&bbox); + + if (intersection == BoundingVolume::IF_no_intersection) { + // No intersection with frustum + return; + } + + // If the bounds are fully visible, there is no reason to perform culling + // on the children, so we set this flag to prevent any bounding computation + // on the child nodes. + fully_visible = (intersection & BoundingVolume::IF_all) != 0; + } + + // Check if the chunk should be subdivided. In case the chunk is a leaf node, + // the chunk will never get subdivided. + // NOTE: We still always perform the LOD check. This is for the reason that + // the lod check also computes the CLOD factor, which is useful. + if (do_check_lod_matches(chunk, data) || chunk->size == _chunk_size) { + do_emit_chunk(chunk, data); + } else { + // Traverse children + for (size_t i = 0; i < 4; ++i) { + do_traverse(chunk->children[i], data, fully_visible); + } + } +} + +/** + * @brief Checks whether a chunk should get subdivided + * @details This method checks whether a chunk fits on screen, or should be + * subdivided in order to provide bigger detail. + * + * In case this method returns true, the chunk lod is fine, and the chunk + * can be rendered. If the method returns false, the chunk should be subdivided. + * + * @param chunk Chunk to check + * @param data Traversal data + * + * @return true if the chunk is sufficient, false if the chunk should be subdivided + */ +bool ShaderTerrainMesh::do_check_lod_matches(Chunk* chunk, TraversalData* data) { + + // Project all points to world space + LVector2 projected_points[4]; + for (size_t y = 0; y < 2; ++y) { + for (size_t x = 0; x < 2; ++x) { + + // Compute point in model space (0,0,0 to 1,1,1) + LVector3 edge_pos = LVector3( + (PN_stdfloat)(chunk->x + x * (chunk->size - 1)) / (PN_stdfloat)_size, + (PN_stdfloat)(chunk->y + y * (chunk->size - 1)) / (PN_stdfloat)_size, + chunk->edges.get_cell(x + 2 * y) + ); + LVector4 projected = data->mvp_mat.xform(LVector4(edge_pos, 1.0)); + if (projected.get_w() == 0.0) { + projected.set(0.0, 0.0, -1.0, 1.0f); + } + projected *= 1.0 / projected.get_w(); + projected_points[x + 2 * y].set( + projected.get_x() * data->screen_size.get_x(), + projected.get_y() * data->screen_size.get_y()); + } + } + + // Compute the length of the edges in screen space + PN_stdfloat edge_top = (projected_points[1] - projected_points[3]).length_squared(); + PN_stdfloat edge_right = (projected_points[0] - projected_points[2]).length_squared(); + PN_stdfloat edge_bottom = (projected_points[2] - projected_points[3]).length_squared(); + PN_stdfloat edge_left = (projected_points[0] - projected_points[1]).length_squared(); + + // CLOD factor + PN_stdfloat max_edge = max(edge_top, max(edge_right, max(edge_bottom, edge_left))); + + // Micro-Optimization: We use length_squared() instead of length() to compute the + // maximum edge length. This reduces it to one csqrt instead of four. + max_edge = csqrt(max_edge); + + PN_stdfloat tesselation_factor = (max_edge / _target_triangle_width) / (PN_stdfloat)_chunk_size; + PN_stdfloat clod_factor = max(0.0, min(1.0, 2.0 - tesselation_factor)); + + // Store the clod factor + chunk->last_clod = clod_factor; + + return tesselation_factor <= 2.0; +} + +/** + * @brief Internal method to spawn a chunk + * @details This method is used to spawn a chunk in case the traversal decided + * that the chunk gets rendered. It writes the chunks data to the texture, and + * increments the write pointer + * + * @param chunk Chunk to spawn + * @param data Traversal data + */ +void ShaderTerrainMesh::do_emit_chunk(Chunk* chunk, TraversalData* data) { + if (data->emitted_chunks >= _data_texture->get_x_size()) { + + // Only print warning once + if (data->emitted_chunks == _data_texture->get_x_size()) { + shader_terrain_cat.error() << "Too many chunks in the terrain! Consider lowering the desired LOD, or increase the stm-max-chunk-count variable." << endl; + data->emitted_chunks++; + } + return; + } + + ChunkDataEntry& data_entry = *data->storage_ptr; + data_entry.x = chunk->x; + data_entry.y = chunk->y; + data_entry.size = chunk->size / _chunk_size; + data_entry.clod = chunk->last_clod; + + data->emitted_chunks++; + data->storage_ptr++; +} + +/** + * @brief Transforms a texture coordinate to world space + * @details This transforms a texture coordinatefrom uv-space (0 to 1) to world + * space. This takes the terrains transform into account, and also samples the + * heightmap. This method should be called after generate(). + * + * @param coord Coordinate in uv-space from 0, 0 to 1, 1 + * @return World-Space point + */ +LPoint3 ShaderTerrainMesh::uv_to_world(const LTexCoord& coord) const { + nassertr(_heightfield_tex != NULL, LPoint3(0)); // Heightfield not set yet + nassertr(_heightfield_tex->has_ram_image(), LPoint3(0)); // Heightfield not in memory + + PT(TexturePeeker) peeker = _heightfield_tex->peek(); + nassertr(peeker != NULL, LPoint3(0)); + + LColor result; + if (!peeker->lookup_bilinear(result, coord.get_x(), coord.get_y())) { + shader_terrain_cat.error() << "UV out of range, cant transform to world!" << endl; + return LPoint3(0); + } + LPoint3 unit_point(coord.get_x(), coord.get_y(), result.get_x()); + return get_transform()->get_mat().xform_point_general(unit_point); +} diff --git a/panda/src/grutil/shaderTerrainMesh.h b/panda/src/grutil/shaderTerrainMesh.h new file mode 100644 index 0000000000..c57a5d4e74 --- /dev/null +++ b/panda/src/grutil/shaderTerrainMesh.h @@ -0,0 +1,201 @@ +/** + * 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 shaderTerrainMesh.h + * @author tobspr + * @date 2016-02-16 + */ + +#ifndef SHADER_TERRAIN_MESH_H +#define SHADER_TERRAIN_MESH_H + +#include "pandabase.h" +#include "luse.h" +#include "pnmImage.h" +#include "geom.h" +#include "pandaNode.h" +#include "texture.h" +#include "texturePeeker.h" +#include "configVariableBool.h" +#include "configVariableInt.h" +#include "pStatCollector.h" +#include "filename.h" +#include + +extern ConfigVariableBool stm_use_hexagonal_layout; +extern ConfigVariableInt stm_max_chunk_count; +extern ConfigVariableInt stm_max_views; + + +NotifyCategoryDecl(shader_terrain, EXPCL_PANDA_GRUTIL, EXPTP_PANDA_GRUTIL); + + +/** + * @brief Terrain Renderer class utilizing the GPU + * @details This class provides functionality to render heightfields of large + * sizes utilizing the GPU. Internally a quadtree is used to generate the LODs. + * The final terrain is then rendered using instancing on the GPU. This makes + * it possible to use very large heightfields (8192+) with very reasonable + * performance. The terrain provides options to control the LOD using a + * target triangle width, see ShaderTerrainMesh::set_target_triangle_width(). + * + * Because the Terrain is rendered entirely on the GPU, it needs a special + * vertex shader. There is a default vertex shader available, which you can + * use in your own shaders. IMPORTANT: If you don't set an appropriate shader + * on the terrain, nothing will be visible. + */ +class EXPCL_PANDA_GRUTIL ShaderTerrainMesh : public PandaNode { + +PUBLISHED: + + ShaderTerrainMesh(); + + INLINE void set_heightfield(Texture* heightfield); + INLINE Texture* get_heightfield() const; + MAKE_PROPERTY(heightfield, get_heightfield, set_heightfield); + + INLINE void set_chunk_size(size_t chunk_size); + INLINE size_t get_chunk_size() const; + MAKE_PROPERTY(chunk_size, get_chunk_size, set_chunk_size); + + INLINE void set_generate_patches(bool generate_patches); + INLINE bool get_generate_patches() const; + MAKE_PROPERTY(generate_patches, get_generate_patches, set_generate_patches); + + INLINE void set_update_enabled(bool update_enabled); + INLINE bool get_update_enabled() const; + MAKE_PROPERTY(update_enabled, get_update_enabled, set_update_enabled); + + INLINE void set_target_triangle_width(PN_stdfloat target_triangle_width); + INLINE PN_stdfloat get_target_triangle_width() const; + MAKE_PROPERTY(target_triangle_width, get_target_triangle_width, set_target_triangle_width); + + LPoint3 uv_to_world(const LTexCoord& coord) const; + INLINE LPoint3 uv_to_world(PN_stdfloat u, PN_stdfloat v) const; + + bool generate(); + +public: + + // Methods derived from PandaNode + virtual bool is_renderable() const; + virtual bool safe_to_flatten() const; + virtual bool safe_to_combine() const; + virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data); + +private: + + // Chunk data + struct Chunk { + // Depth, starting at 0 + size_t depth; + + // Chunk position in heightfield space + size_t x, y; + + // Chunk size in heightfield space + size_t size; + + // Children, in the order (0, 0) (1, 0) (0, 1) (1, 1) + Chunk* children[4]; + + // Chunk heights, used for culling + PN_stdfloat avg_height, min_height, max_height; + + // Edge heights, used for lod computation, in the same order as the children + LVector4 edges; + + // Last CLOD factor, stored while computing LOD, used for seamless transitions between lods + PN_stdfloat last_clod; + + INLINE void clear_children(); + INLINE Chunk(); + INLINE ~Chunk(); + }; + + + // Single entry in the data block + struct ChunkDataEntry { + // float x, y, size, clod; + + // Panda uses BGRA, the above layout shows how its actually in texture memory, + // the layout below makes it work with BGRA. + PN_float32 size, y, x, clod; + }; + + // Data used while traversing all chunks + struct TraversalData { + // Global MVP used for LOD + LMatrix4 mvp_mat; + + // Local model matrix used for culling + LMatrix4 model_mat; + + // Camera bounds in world space + BoundingVolume* cam_bounds; + + // Amount of emitted chunks so far + int emitted_chunks; + + // Screen resolution, used for LOD + LVector2i screen_size; + + // Pointer to the texture memory, where each chunk is written to + ChunkDataEntry* storage_ptr; + }; + + bool do_check_heightfield(); + void do_extract_heightfield(); + void do_init_data_texture(); + void do_create_chunks(); + void do_init_chunk(Chunk* chunk); + void do_compute_bounds(Chunk* chunk); + void do_create_chunk_geom(); + void do_traverse(Chunk* chunk, TraversalData* data, bool fully_visible = false); + void do_emit_chunk(Chunk* chunk, TraversalData* data); + bool do_check_lod_matches(Chunk* chunk, TraversalData* data); + + Chunk _base_chunk; + size_t _size; + size_t _chunk_size; + bool _generate_patches; + PNMImage _heightfield; + PT(Texture) _heightfield_tex; + PT(Geom) _chunk_geom; + PT(Texture) _data_texture; + size_t _current_view_index; + int _last_frame_count; + PN_stdfloat _target_triangle_width; + bool _update_enabled; + + // PStats stuff + static PStatCollector _lod_collector; + static PStatCollector _basic_collector; + + +// Type handle stuff +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + PandaNode::init_type(); + register_type(_type_handle, "ShaderTerrainMesh", PandaNode::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "shaderTerrainMesh.I" + +#endif // SHADER_TERRAIN_MESH_H diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.cxx b/panda/src/gsgbase/graphicsStateGuardianBase.cxx index 30d5d20871..aa23375418 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.cxx +++ b/panda/src/gsgbase/graphicsStateGuardianBase.cxx @@ -15,9 +15,7 @@ #include "lightMutexHolder.h" #include -GraphicsStateGuardianBase::GSGs GraphicsStateGuardianBase::_gsgs; -GraphicsStateGuardianBase *GraphicsStateGuardianBase::_default_gsg; -LightMutex GraphicsStateGuardianBase::_lock; +AtomicAdjust::Pointer GraphicsStateGuardianBase::_gsg_list; TypeHandle GraphicsStateGuardianBase::_type_handle; /** @@ -30,8 +28,13 @@ TypeHandle GraphicsStateGuardianBase::_type_handle; */ GraphicsStateGuardianBase *GraphicsStateGuardianBase:: get_default_gsg() { - LightMutexHolder holder(_lock); - return _default_gsg; + GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list); + if (gsg_list == NULL) { + // Nobody created a GSG list, so we won't have any GSGs either. + return NULL; + } + LightMutexHolder holder(gsg_list->_lock); + return gsg_list->_default_gsg; } /** @@ -40,22 +43,35 @@ get_default_gsg() { */ void GraphicsStateGuardianBase:: set_default_gsg(GraphicsStateGuardianBase *default_gsg) { - LightMutexHolder holder(_lock); - if (find(_gsgs.begin(), _gsgs.end(), default_gsg) == _gsgs.end()) { + GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list); + if (gsg_list == NULL) { + // Nobody ever created a GSG list. How could we have a GSG? + nassertv(false); + return; + } + + LightMutexHolder holder(gsg_list->_lock); + if (find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), default_gsg) == gsg_list->_gsgs.end()) { // The specified GSG doesn't exist or it has already destructed. nassertv(false); return; } - _default_gsg = default_gsg; + gsg_list->_default_gsg = default_gsg; } /** * Returns the total number of GSG's in the universe. */ -int GraphicsStateGuardianBase:: +size_t GraphicsStateGuardianBase:: get_num_gsgs() { - return _gsgs.size(); + GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list); + if (gsg_list == NULL) { + // Nobody created a GSG list, so we won't have any GSGs either. + return 0; + } + LightMutexHolder holder(gsg_list->_lock); + return gsg_list->_gsgs.size(); } /** @@ -63,9 +79,13 @@ get_num_gsgs() { * and remove themselves from this list as they are created and destroyed. */ GraphicsStateGuardianBase *GraphicsStateGuardianBase:: -get_gsg(int n) { - nassertr(n >= 0 && n < (int)_gsgs.size(), NULL); - return _gsgs[n]; +get_gsg(size_t n) { + GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list); + nassertr(gsg_list != NULL, NULL); + + LightMutexHolder holder(gsg_list->_lock); + nassertr(n < gsg_list->_gsgs.size(), NULL); + return gsg_list->_gsgs[n]; } /** @@ -74,17 +94,32 @@ get_gsg(int n) { */ void GraphicsStateGuardianBase:: add_gsg(GraphicsStateGuardianBase *gsg) { - LightMutexHolder holder(_lock); + GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list); + if (gsg_list == NULL) { + gsg_list = new GSGList; + gsg_list->_default_gsg = NULL; - if (find(_gsgs.begin(), _gsgs.end(), gsg) != _gsgs.end()) { + GSGList *orig_gsg_list = (GSGList *) + AtomicAdjust::compare_and_exchange_ptr(_gsg_list, NULL, gsg_list); + + if (orig_gsg_list != NULL) { + // Another thread beat us to it. No problem, we'll use that. + delete gsg_list; + gsg_list = orig_gsg_list; + } + } + + LightMutexHolder holder(gsg_list->_lock); + + if (find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), gsg) != gsg_list->_gsgs.end()) { // Already on the list. return; } - _gsgs.push_back(gsg); + gsg_list->_gsgs.push_back(gsg); - if (_default_gsg == (GraphicsStateGuardianBase *)NULL) { - _default_gsg = gsg; + if (gsg_list->_default_gsg == (GraphicsStateGuardianBase *)NULL) { + gsg_list->_default_gsg = gsg; } } @@ -93,21 +128,28 @@ add_gsg(GraphicsStateGuardianBase *gsg) { */ void GraphicsStateGuardianBase:: remove_gsg(GraphicsStateGuardianBase *gsg) { - LightMutexHolder holder(_lock); + GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list); + if (gsg_list == NULL) { + // No GSGs were added yet, or the program is destructing anyway. + return; + } - GSGs::iterator gi = find(_gsgs.begin(), _gsgs.end(), gsg); - if (gi == _gsgs.end()) { + LightMutexHolder holder(gsg_list->_lock); + + GSGList::GSGs::iterator gi; + gi = find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), gsg); + if (gi == gsg_list->_gsgs.end()) { // Already removed, or never added. return; } - _gsgs.erase(gi); + gsg_list->_gsgs.erase(gi); - if (_default_gsg == gsg) { - if (!_gsgs.empty()) { - _default_gsg = *_gsgs.begin(); + if (gsg_list->_default_gsg == gsg) { + if (!gsg_list->_gsgs.empty()) { + gsg_list->_default_gsg = *gsg_list->_gsgs.begin(); } else { - _default_gsg = NULL; + gsg_list->_default_gsg = NULL; } } } diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 2fecf301a8..90455869ac 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -223,8 +223,8 @@ PUBLISHED: static GraphicsStateGuardianBase *get_default_gsg(); static void set_default_gsg(GraphicsStateGuardianBase *default_gsg); - static int get_num_gsgs(); - static GraphicsStateGuardianBase *get_gsg(int n); + static size_t get_num_gsgs(); + static GraphicsStateGuardianBase *get_gsg(size_t n); MAKE_SEQ(get_gsgs, get_num_gsgs, get_gsg); public: @@ -232,10 +232,14 @@ public: static void remove_gsg(GraphicsStateGuardianBase *gsg); private: - typedef pvector GSGs; - static GSGs _gsgs; - static GraphicsStateGuardianBase *_default_gsg; - static LightMutex _lock; + struct GSGList { + LightMutex _lock; + + typedef pvector GSGs; + GSGs _gsgs; + GraphicsStateGuardianBase *_default_gsg; + }; + static AtomicAdjust::Pointer _gsg_list; public: static TypeHandle get_class_type() { diff --git a/panda/src/linmath/lmatrix3_src.h b/panda/src/linmath/lmatrix3_src.h index 1960e586e7..fa01ef2c27 100644 --- a/panda/src/linmath/lmatrix3_src.h +++ b/panda/src/linmath/lmatrix3_src.h @@ -86,6 +86,8 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVecBase3) get_col(int col) const; MAKE_SEQ(get_rows, size, get_row); MAKE_SEQ(get_cols, size, get_col); + MAKE_SEQ_PROPERTY(rows, size, get_row); + MAKE_SEQ_PROPERTY(cols, size, get_col); INLINE_LINMATH FLOATNAME(LVecBase2) get_row2(int row) const; INLINE_LINMATH FLOATNAME(LVecBase2) get_col2(int col) const; diff --git a/panda/src/linmath/lmatrix4_src.h b/panda/src/linmath/lmatrix4_src.h index eac09f85e9..0b9f1557e5 100644 --- a/panda/src/linmath/lmatrix4_src.h +++ b/panda/src/linmath/lmatrix4_src.h @@ -99,6 +99,8 @@ PUBLISHED: MAKE_SEQ(get_rows, size, get_row); MAKE_SEQ(get_cols, size, get_col); MAKE_SEQ(get_row3s, size, get_row3); + MAKE_SEQ_PROPERTY(rows, size, get_row); + MAKE_SEQ_PROPERTY(cols, size, get_col); // these versions inline better INLINE_LINMATH void get_row(FLOATNAME(LVecBase4) &result_vec, int row) const; diff --git a/panda/src/linmath/lpoint2_ext_src.I b/panda/src/linmath/lpoint2_ext_src.I index 88e146e462..371017955d 100644 --- a/panda/src/linmath/lpoint2_ext_src.I +++ b/panda/src/linmath/lpoint2_ext_src.I @@ -11,16 +11,6 @@ * @date 2011-01-02 */ -#ifdef FLOATTYPE_IS_INT -#if PY_MAJOR_VERSION >= 3 -#define PY_FROM_FLOATTYPE PyLong_FromLong -#else -#define PY_FROM_FLOATTYPE PyInt_FromLong -#endif -#else -#define PY_FROM_FLOATTYPE PyFloat_FromDouble -#endif - /** * */ @@ -53,7 +43,7 @@ __getattr__(PyObject *self, const string &attr_name) const { switch (attr_name.size()) { case 1: - return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); + return Dtool_WrapValue(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2); @@ -89,5 +79,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase2. return invoke_extension(_this).__setattr__(self, attr_name, assign); } - -#undef PY_FROM_FLOATTYPE diff --git a/panda/src/linmath/lpoint3_ext_src.I b/panda/src/linmath/lpoint3_ext_src.I index dc0d68240d..e695988177 100644 --- a/panda/src/linmath/lpoint3_ext_src.I +++ b/panda/src/linmath/lpoint3_ext_src.I @@ -11,16 +11,6 @@ * @date 2011-01-02 */ -#ifdef FLOATTYPE_IS_INT -#if PY_MAJOR_VERSION >= 3 -#define PY_FROM_FLOATTYPE PyLong_FromLong -#else -#define PY_FROM_FLOATTYPE PyInt_FromLong -#endif -#else -#define PY_FROM_FLOATTYPE PyFloat_FromDouble -#endif - /** * */ @@ -54,7 +44,7 @@ __getattr__(PyObject *self, const string &attr_name) const { switch (attr_name.size()) { case 1: - return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); + return Dtool_WrapValue(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2); @@ -90,5 +80,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase2. return invoke_extension(_this).__setattr__(self, attr_name, assign); } - -#undef PY_FROM_FLOATTYPE diff --git a/panda/src/linmath/lpoint4_ext_src.I b/panda/src/linmath/lpoint4_ext_src.I index 4a17134496..bef1b1d012 100644 --- a/panda/src/linmath/lpoint4_ext_src.I +++ b/panda/src/linmath/lpoint4_ext_src.I @@ -11,16 +11,6 @@ * @date 2011-01-02 */ -#ifdef FLOATTYPE_IS_INT -#if PY_MAJOR_VERSION >= 3 -#define PY_FROM_FLOATTYPE PyLong_FromLong -#else -#define PY_FROM_FLOATTYPE PyInt_FromLong -#endif -#else -#define PY_FROM_FLOATTYPE PyFloat_FromDouble -#endif - /** * */ @@ -56,9 +46,9 @@ __getattr__(PyObject *self, const string &attr_name) const { switch (attr_name.size()) { case 1: if (attr_name[0] == 'w') { - return PY_FROM_FLOATTYPE(_this->_v(3)); + return Dtool_WrapValue(_this->_v(3)); } else { - return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); + return Dtool_WrapValue(_this->_v(attr_name[0] - 'x')); } case 2: { @@ -95,5 +85,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase4. return invoke_extension(_this).__setattr__(self, attr_name, assign); } - -#undef PY_FROM_FLOATTYPE diff --git a/panda/src/linmath/lvecBase2_ext_src.I b/panda/src/linmath/lvecBase2_ext_src.I index 7355fd5e61..40399dc327 100644 --- a/panda/src/linmath/lvecBase2_ext_src.I +++ b/panda/src/linmath/lvecBase2_ext_src.I @@ -14,16 +14,13 @@ #ifdef FLOATTYPE_IS_INT #if PY_MAJOR_VERSION >= 3 #define PYNUMBER_FLOATTYPE PyNumber_Long -#define PY_FROM_FLOATTYPE PyLong_FromLong #define PY_AS_FLOATTYPE PyLong_AS_LONG #else #define PYNUMBER_FLOATTYPE PyNumber_Int -#define PY_FROM_FLOATTYPE PyInt_FromLong #define PY_AS_FLOATTYPE PyInt_AS_LONG #endif #else #define PYNUMBER_FLOATTYPE PyNumber_Float -#define PY_FROM_FLOATTYPE PyFloat_FromDouble #define PY_AS_FLOATTYPE (FLOATTYPE)PyFloat_AsDouble #endif @@ -88,7 +85,7 @@ __getattr__(PyObject *self, const string &attr_name) const { switch (attr_name.size()) { case 1: - return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); + return Dtool_WrapValue(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2); @@ -222,5 +219,4 @@ __ipow__(PyObject *self, FLOATTYPE exponent) { } #undef PYNUMBER_FLOATTYPE -#undef PY_FROM_FLOATTYPE #undef PY_AS_FLOATTYPE diff --git a/panda/src/linmath/lvecBase2_src.I b/panda/src/linmath/lvecBase2_src.I index 7a8cddc5a0..9ddce8966c 100644 --- a/panda/src/linmath/lvecBase2_src.I +++ b/panda/src/linmath/lvecBase2_src.I @@ -393,9 +393,8 @@ INLINE_LINMATH size_t FLOATNAME(LVecBase2):: add_hash(size_t hash) const { TAU_PROFILE("size_t LVecBase2::add_hash(size_t)", " ", TAU_USER); #ifdef FLOATTYPE_IS_INT - int_hash ihasher; - hash = ihasher.add_hash(hash, _v(0)); - hash = ihasher.add_hash(hash, _v(1)); + hash = int_hash::add_hash(hash, _v(0)); + hash = int_hash::add_hash(hash, _v(1)); return hash; #else return add_hash(hash, NEARLY_ZERO(FLOATTYPE)); diff --git a/panda/src/linmath/lvecBase3_ext_src.I b/panda/src/linmath/lvecBase3_ext_src.I index 4450a3ac30..a2705edbb6 100644 --- a/panda/src/linmath/lvecBase3_ext_src.I +++ b/panda/src/linmath/lvecBase3_ext_src.I @@ -14,16 +14,13 @@ #ifdef FLOATTYPE_IS_INT #if PY_MAJOR_VERSION >= 3 #define PYNUMBER_FLOATTYPE PyNumber_Long -#define PY_FROM_FLOATTYPE PyLong_FromLong #define PY_AS_FLOATTYPE PyLong_AS_LONG #else #define PYNUMBER_FLOATTYPE PyNumber_Int -#define PY_FROM_FLOATTYPE PyInt_FromLong #define PY_AS_FLOATTYPE PyInt_AS_LONG #endif #else #define PYNUMBER_FLOATTYPE PyNumber_Float -#define PY_FROM_FLOATTYPE PyFloat_FromDouble #define PY_AS_FLOATTYPE (FLOATTYPE)PyFloat_AsDouble #endif @@ -89,7 +86,7 @@ __getattr__(PyObject *self, const string &attr_name) const { switch (attr_name.size()) { case 1: - return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); + return Dtool_WrapValue(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2); @@ -225,5 +222,4 @@ __ipow__(PyObject *self, FLOATTYPE exponent) { } #undef PYNUMBER_FLOATTYPE -#undef PY_FROM_FLOATTYPE #undef PY_AS_FLOATTYPE diff --git a/panda/src/linmath/lvecBase3_src.I b/panda/src/linmath/lvecBase3_src.I index ec9cc7be39..b7011da0ca 100644 --- a/panda/src/linmath/lvecBase3_src.I +++ b/panda/src/linmath/lvecBase3_src.I @@ -528,10 +528,9 @@ INLINE_LINMATH size_t FLOATNAME(LVecBase3):: add_hash(size_t hash) const { TAU_PROFILE("size_t LVecBase3::add_hash(size_t)", " ", TAU_USER); #ifdef FLOATTYPE_IS_INT - int_hash ihasher; - hash = ihasher.add_hash(hash, _v(0)); - hash = ihasher.add_hash(hash, _v(1)); - hash = ihasher.add_hash(hash, _v(2)); + hash = int_hash::add_hash(hash, _v(0)); + hash = int_hash::add_hash(hash, _v(1)); + hash = int_hash::add_hash(hash, _v(2)); return hash; #else return add_hash(hash, NEARLY_ZERO(FLOATTYPE)); diff --git a/panda/src/linmath/lvecBase4_ext_src.I b/panda/src/linmath/lvecBase4_ext_src.I index a802815db0..76eee6b7bf 100644 --- a/panda/src/linmath/lvecBase4_ext_src.I +++ b/panda/src/linmath/lvecBase4_ext_src.I @@ -14,16 +14,13 @@ #ifdef FLOATTYPE_IS_INT #if PY_MAJOR_VERSION >= 3 #define PYNUMBER_FLOATTYPE PyNumber_Long -#define PY_FROM_FLOATTYPE PyLong_FromLong #define PY_AS_FLOATTYPE PyLong_AS_LONG #else #define PYNUMBER_FLOATTYPE PyNumber_Int -#define PY_FROM_FLOATTYPE PyInt_FromLong #define PY_AS_FLOATTYPE PyInt_AS_LONG #endif #else #define PYNUMBER_FLOATTYPE PyNumber_Float -#define PY_FROM_FLOATTYPE PyFloat_FromDouble #define PY_AS_FLOATTYPE (FLOATTYPE)PyFloat_AsDouble #endif @@ -91,9 +88,9 @@ __getattr__(PyObject *self, const string &attr_name) const { switch (attr_name.size()) { case 1: if (attr_name[0] == 'w') { - return PY_FROM_FLOATTYPE(_this->_v(3)); + return Dtool_WrapValue(_this->_v(3)); } else { - return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); + return Dtool_WrapValue(_this->_v(attr_name[0] - 'x')); } case 2: { @@ -233,5 +230,4 @@ __ipow__(PyObject *self, FLOATTYPE exponent) { } #undef PYNUMBER_FLOATTYPE -#undef PY_FROM_FLOATTYPE #undef PY_AS_FLOATTYPE diff --git a/panda/src/linmath/lvecBase4_src.I b/panda/src/linmath/lvecBase4_src.I index 6771e563ff..7890a6f8f0 100644 --- a/panda/src/linmath/lvecBase4_src.I +++ b/panda/src/linmath/lvecBase4_src.I @@ -521,11 +521,10 @@ INLINE_LINMATH size_t FLOATNAME(LVecBase4):: add_hash(size_t hash) const { TAU_PROFILE("size_t LVecBase4::add_hash(size_t)", " ", TAU_USER); #ifdef FLOATTYPE_IS_INT - int_hash ihasher; - hash = ihasher.add_hash(hash, _v(0)); - hash = ihasher.add_hash(hash, _v(1)); - hash = ihasher.add_hash(hash, _v(2)); - hash = ihasher.add_hash(hash, _v(3)); + hash = int_hash::add_hash(hash, _v(0)); + hash = int_hash::add_hash(hash, _v(1)); + hash = int_hash::add_hash(hash, _v(2)); + hash = int_hash::add_hash(hash, _v(3)); return hash; #else return add_hash(hash, NEARLY_ZERO(FLOATTYPE)); diff --git a/panda/src/linmath/lvector2_ext_src.I b/panda/src/linmath/lvector2_ext_src.I index b08f96f217..dd4dc5e95e 100644 --- a/panda/src/linmath/lvector2_ext_src.I +++ b/panda/src/linmath/lvector2_ext_src.I @@ -11,16 +11,6 @@ * @date 2011-01-02 */ -#ifdef FLOATTYPE_IS_INT -#if PY_MAJOR_VERSION >= 3 -#define PY_FROM_FLOATTYPE PyLong_FromLong -#else -#define PY_FROM_FLOATTYPE PyInt_FromLong -#endif -#else -#define PY_FROM_FLOATTYPE PyFloat_FromDouble -#endif - /** * */ @@ -53,7 +43,7 @@ __getattr__(PyObject *self, const string &attr_name) const { switch (attr_name.size()) { case 1: - return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); + return Dtool_WrapValue(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2); @@ -89,5 +79,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase2. return invoke_extension(_this).__setattr__(self, attr_name, assign); } - -#undef PY_FROM_FLOATTYPE diff --git a/panda/src/linmath/lvector3_ext_src.I b/panda/src/linmath/lvector3_ext_src.I index 36012e7917..155c2a013a 100644 --- a/panda/src/linmath/lvector3_ext_src.I +++ b/panda/src/linmath/lvector3_ext_src.I @@ -11,16 +11,6 @@ * @date 2011-01-02 */ -#ifdef FLOATTYPE_IS_INT -#if PY_MAJOR_VERSION >= 3 -#define PY_FROM_FLOATTYPE PyLong_FromLong -#else -#define PY_FROM_FLOATTYPE PyInt_FromLong -#endif -#else -#define PY_FROM_FLOATTYPE PyFloat_FromDouble -#endif - /** * */ @@ -54,7 +44,7 @@ __getattr__(PyObject *self, const string &attr_name) const { switch (attr_name.size()) { case 1: - return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); + return Dtool_WrapValue(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2); @@ -90,5 +80,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase3. return invoke_extension(_this).__setattr__(self, attr_name, assign); } - -#undef PY_FROM_FLOATTYPE diff --git a/panda/src/linmath/lvector4_ext_src.I b/panda/src/linmath/lvector4_ext_src.I index 4964a1fc68..a188d6c4a2 100644 --- a/panda/src/linmath/lvector4_ext_src.I +++ b/panda/src/linmath/lvector4_ext_src.I @@ -11,16 +11,6 @@ * @date 2011-01-02 */ -#ifdef FLOATTYPE_IS_INT -#if PY_MAJOR_VERSION >= 3 -#define PY_FROM_FLOATTYPE PyLong_FromLong -#else -#define PY_FROM_FLOATTYPE PyInt_FromLong -#endif -#else -#define PY_FROM_FLOATTYPE PyFloat_FromDouble -#endif - /** * */ @@ -56,9 +46,9 @@ __getattr__(PyObject *self, const string &attr_name) const { switch (attr_name.size()) { case 1: if (attr_name[0] == 'w') { - return PY_FROM_FLOATTYPE(_this->_v(3)); + return Dtool_WrapValue(_this->_v(3)); } else { - return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); + return Dtool_WrapValue(_this->_v(attr_name[0] - 'x')); } case 2: { @@ -95,5 +85,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase4. return invoke_extension(_this).__setattr__(self, attr_name, assign); } - -#undef PY_FROM_FLOATTYPE diff --git a/panda/src/mathutil/boundingBox.h b/panda/src/mathutil/boundingBox.h index d65aa80dc4..53c24c521d 100644 --- a/panda/src/mathutil/boundingBox.h +++ b/panda/src/mathutil/boundingBox.h @@ -53,6 +53,9 @@ PUBLISHED: INLINE_MATHUTIL LPlane get_plane(int n) const; MAKE_SEQ(get_planes, get_num_planes, get_plane); + MAKE_SEQ_PROPERTY(points, get_num_points, get_point); + MAKE_SEQ_PROPERTY(planes, get_num_planes, get_plane); + INLINE_MATHUTIL void set_min_max(const LPoint3 &min, const LPoint3 &max); public: diff --git a/panda/src/mathutil/boundingHexahedron.h b/panda/src/mathutil/boundingHexahedron.h index a7d55b8643..40851a219f 100644 --- a/panda/src/mathutil/boundingHexahedron.h +++ b/panda/src/mathutil/boundingHexahedron.h @@ -62,6 +62,9 @@ PUBLISHED: INLINE_MATHUTIL LPlane get_plane(int n) const; MAKE_SEQ(get_planes, get_num_planes, get_plane); + MAKE_SEQ_PROPERTY(points, get_num_points, get_point); + MAKE_SEQ_PROPERTY(planes, get_num_planes, get_plane); + public: virtual const BoundingHexahedron *as_bounding_hexahedron() const; diff --git a/panda/src/mathutil/fftCompressor.cxx b/panda/src/mathutil/fftCompressor.cxx index 47193445b9..f96c6f5f7c 100644 --- a/panda/src/mathutil/fftCompressor.cxx +++ b/panda/src/mathutil/fftCompressor.cxx @@ -849,7 +849,7 @@ write_run(Datagram &datagram, FFTCompressor::RunWidth run_width, // In the case of RW_double, we only write the numbers one at a time, // each time preceded by the RW_double flag. Hopefully this will happen // only rarely. - datagram.add_int8((PN_int8)RW_double); + datagram.add_int8((int8_t)RW_double); datagram.add_float64(*ri); } break; @@ -869,7 +869,7 @@ write_run(Datagram &datagram, FFTCompressor::RunWidth run_width, */ int FFTCompressor:: read_run(DatagramIterator &di, vector_double &run) { - PN_uint8 start = di.get_uint8(); + uint8_t start = di.get_uint8(); RunWidth run_width; int length; diff --git a/panda/src/mathutil/intersectionBoundingVolume.h b/panda/src/mathutil/intersectionBoundingVolume.h index 38759e0d29..74e750acb9 100644 --- a/panda/src/mathutil/intersectionBoundingVolume.h +++ b/panda/src/mathutil/intersectionBoundingVolume.h @@ -47,6 +47,7 @@ PUBLISHED: INLINE_MATHUTIL int get_num_components() const; INLINE_MATHUTIL const GeometricBoundingVolume *get_component(int n) const; MAKE_SEQ(get_components, get_num_components, get_component); + MAKE_SEQ_PROPERTY(components, get_num_components, get_component); void clear_components(); void add_component(const GeometricBoundingVolume *component); diff --git a/panda/src/mathutil/triangulator.h b/panda/src/mathutil/triangulator.h index 8008cef8eb..0514917cfd 100644 --- a/panda/src/mathutil/triangulator.h +++ b/panda/src/mathutil/triangulator.h @@ -40,6 +40,7 @@ PUBLISHED: INLINE int get_num_vertices() const; INLINE const LPoint2d &get_vertex(int n) const; MAKE_SEQ(get_vertices, get_num_vertices, get_vertex); + MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex); void clear_polygon(); void add_polygon_vertex(int index); diff --git a/panda/src/mathutil/triangulator3.h b/panda/src/mathutil/triangulator3.h index 786b2f581a..d4657668e4 100644 --- a/panda/src/mathutil/triangulator3.h +++ b/panda/src/mathutil/triangulator3.h @@ -40,6 +40,9 @@ PUBLISHED: void triangulate(); INLINE const LPlaned &get_plane() const; + MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex); + MAKE_PROPERTY(plane, get_plane); + private: typedef pvector Vertices3; Vertices3 _vertices3; diff --git a/panda/src/mathutil/unionBoundingVolume.h b/panda/src/mathutil/unionBoundingVolume.h index dd4366abfb..4af835eae7 100644 --- a/panda/src/mathutil/unionBoundingVolume.h +++ b/panda/src/mathutil/unionBoundingVolume.h @@ -46,6 +46,7 @@ PUBLISHED: INLINE_MATHUTIL int get_num_components() const; INLINE_MATHUTIL const GeometricBoundingVolume *get_component(int n) const; MAKE_SEQ(get_components, get_num_components, get_component); + MAKE_SEQ_PROPERTY(components, get_num_components, get_component); void clear_components(); void add_component(const GeometricBoundingVolume *component); diff --git a/panda/src/movies/config_movies.cxx b/panda/src/movies/config_movies.cxx index db5d6be074..fbd80e275d 100644 --- a/panda/src/movies/config_movies.cxx +++ b/panda/src/movies/config_movies.cxx @@ -13,6 +13,8 @@ #include "config_movies.h" #include "dconfig.h" +#include "flacAudio.h" +#include "flacAudioCursor.h" #include "inkblotVideo.h" #include "inkblotVideoCursor.h" #include "microphoneAudio.h" @@ -75,6 +77,8 @@ init_libmovies() { } initialized = true; + FlacAudio::init_type(); + FlacAudioCursor::init_type(); InkblotVideo::init_type(); InkblotVideoCursor::init_type(); MicrophoneAudio::init_type(); @@ -93,6 +97,7 @@ init_libmovies() { #endif MovieTypeRegistry *reg = MovieTypeRegistry::get_global_ptr(); + reg->register_audio_type(&FlacAudio::make, "flac"); reg->register_audio_type(&WavAudio::make, "wav wave"); #ifdef HAVE_VORBIS diff --git a/panda/src/movies/dr_flac.h b/panda/src/movies/dr_flac.h new file mode 100644 index 0000000000..c6da7b9004 --- /dev/null +++ b/panda/src/movies/dr_flac.h @@ -0,0 +1,2972 @@ +// Public domain. See "unlicense" statement at the end of this file. +//NB: modified by rdb to use 16-bit instead of 32-bit samples. + +// ABOUT +// +// This is a simple library for decoding FLAC files. +// +// +// +// USAGE +// +// This is a single-file library. To use it, do something like the following in one .c file. +// #define DR_FLAC_IMPLEMENTATION +// #include "dr_flac.h" +// +// You can then #include this file in other parts of the program as you would with any other header file. To decode audio data, +// do something like the following: +// +// drflac* pFlac = drflac_open_file("MySong.flac"); +// if (pFlac == NULL) { +// ... Failed to open FLAC file ... +// } +// +// int16_t* pSamples = malloc(pFlac->totalSampleCount * sizeof(int16_t)); +// uint64_t numberOfSamplesActuallyRead = drflac_read_s16(pFlac, pFlac->totalSampleCount, pSamples); +// +// ... pSamples now contains the decoded samples as interleaved signed 16-bit PCM ... +// +// The drflac object represents the decoder. It is a transparent type so all the information you need, such as the number of +// channels and the bits per sample, should be directly accessible - just make sure you don't change their values. +// +// You do not need to decode the entire stream in one go - you just specify how many samples you'd like at any given time and +// the decoder will give you as many samples as it can, up to the amount requested. Later on when you need the next batch of +// samples, just call it again. Example: +// +// while (drflac_read_s16(pFlac, chunkSize, pChunkSamples) > 0) { +// do_something(); +// } +// +// You can seek to a specific sample with drflac_seek_to_sample(). The given sample is based on interleaving. So for example, +// if you were to seek to the sample at index 0 in a stereo stream, you'll be seeking to the first sample of the left channel. +// The sample at index 1 will be the first sample of the right channel. The sample at index 2 will be the second sample of the +// left channel, etc. +// +// +// +// OPTIONS +// #define these options before including this file. +// +// #define DR_FLAC_NO_STDIO +// Disable drflac_open_file(). +// +// #define DR_FLAC_NO_WIN32_IO +// Don't use the Win32 API internally for drflac_open_file(). Setting this will force stdio FILE APIs instead. This is +// mainly for testing, but it's left here in case somebody might find use for it. dr_flac will use the Win32 API by +// default. Ignored when DR_FLAC_NO_STDIO is #defined. +// +// #define DR_FLAC_BUFFER_SIZE +// Defines the size of the internal buffer to store data from onRead(). This buffer is used to reduce the number of calls +// back to the client for more data. Larger values means more memory, but better performance. My tests show diminishing +// returns after about 4KB (which is the default). Consider reducing this if you have a very efficient implementation of +// onRead(), or increase it if it's very inefficient. +// +// +// +// QUICK NOTES +// +// - Based on my own tests, the 32-bit build is about about 1.1x-1.25x slower than the reference implementation. The 64-bit +// build is at about parity. +// - This should work fine with valid native FLAC files, but it won't work very well when the STREAMINFO block is unavailable +// and when a stream starts in the middle of a frame. This is something I plan on addressing. +// - Audio data is retrieved as signed 16-bit PCM, regardless of the bits per sample the FLAC stream is encoded as. +// - This has not been tested on big-endian architectures. +// - Rice codes in unencoded binary form (see https://xiph.org/flac/format.html#rice_partition) has not been tested. If anybody +// knows where I can find some test files for this, let me know. +// - Perverse and erroneous files have not been tested. Again, if you know where I can get some test files let me know. +// - dr_flac is not thread-safe, but it's APIs can be called from any thread so long as you do your own synchronization. +// - dr_flac does not currently do any CRC checks. +// - Ogg encapsulation is not supported, but I want to add it at some point. +// +// +// +// TODO +// - Implement a proper test suite. +// - Add support for initializing the decoder without a STREAMINFO block. Build a synthethic test to get support working at at least +// a basic level. +// - Add support for retrieving metadata blocks so applications can retrieve the album art or whatnot. +// - Add support for Ogg encapsulation. + +#ifndef dr_flac_h +#define dr_flac_h + +#include +#include +//#include + +// As data is read from the client it is placed into an internal buffer for fast access. This controls the +// size of that buffer. Larger values means more speed, but also more memory. In my testing there is diminishing +// returns after about 4KB, but you can fiddle with this to suit your own needs. Must be a multiple of 8. +#ifndef DR_FLAC_BUFFER_SIZE +#define DR_FLAC_BUFFER_SIZE 4096 +#endif + +// Check if we can enable 64-bit optimizations. +#if defined(_WIN64) +#define DRFLAC_64BIT +#endif + +#if defined(__GNUC__) +#if defined(__x86_64__) || defined(__ppc64__) +#define DRFLAC_64BIT +#endif +#endif + +#ifdef DRFLAC_64BIT +typedef uint64_t drflac_cache_t; +#else +typedef uint32_t drflac_cache_t; +#endif + + + +// Callback for when data is read. Return value is the number of bytes actually read. +typedef size_t (* drflac_read_proc)(void* userData, void* bufferOut, size_t bytesToRead); + +// Callback for when data needs to be seeked. Offset is always relative to the current position. Return value is false on failure, true success. +typedef bool (* drflac_seek_proc)(void* userData, int offset); + + +typedef struct +{ + // The absolute position of the first byte of the data of the block. This is just past the block's header. + long long pos; + + // The size in bytes of the block's data. + unsigned int sizeInBytes; + +} drflac_block; + +typedef struct +{ + // The type of the subframe: SUBFRAME_CONSTANT, SUBFRAME_VERBATIM, SUBFRAME_FIXED or SUBFRAME_LPC. + unsigned char subframeType; + + // The number of wasted bits per sample as specified by the sub-frame header. + unsigned char wastedBitsPerSample; + + // The order to use for the prediction stage for SUBFRAME_FIXED and SUBFRAME_LPC. + unsigned char lpcOrder; + + // The number of bits per sample for this subframe. This is not always equal to the current frame's bit per sample because + // an extra bit is required for side channels when interchannel decorrelation is being used. + int bitsPerSample; + + // A pointer to the buffer containing the decoded samples in the subframe. This pointer is an offset from drflac::pHeap, or + // NULL if the heap is not being used. Note that it's a signed 32-bit integer for each value. + int32_t* pDecodedSamples; + +} drflac_subframe; + +typedef struct +{ + // If the stream uses variable block sizes, this will be set to the index of the first sample. If fixed block sizes are used, this will + // always be set to 0. + unsigned long long sampleNumber; + + // If the stream uses fixed block sizes, this will be set to the frame number. If variable block sizes are used, this will always be 0. + unsigned int frameNumber; + + // The sample rate of this frame. + unsigned int sampleRate; + + // The number of samples in each sub-frame within this frame. + unsigned short blockSize; + + // The channel assignment of this frame. This is not always set to the channel count. If interchannel decorrelation is being used this + // will be set to DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE, DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE or DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE. + unsigned char channelAssignment; + + // The number of bits per sample within this frame. + unsigned char bitsPerSample; + + // The frame's CRC. This is set, but unused at the moment. + unsigned char crc8; + + // The number of samples left to be read in this frame. This is initially set to the block size multiplied by the channel count. As samples + // are read, this will be decremented. When it reaches 0, the decoder will see this frame as fully consumed and load the next frame. + unsigned int samplesRemaining; + + // The list of sub-frames within the frame. There is one sub-frame for each channel, and there's a maximum of 8 channels. + drflac_subframe subframes[8]; + +} drflac_frame; + +typedef struct +{ + // The function to call when more data needs to be read. This is set by drflac_open(). + drflac_read_proc onRead; + + // The function to call when the current read position needs to be moved. + drflac_seek_proc onSeek; + + // The user data to pass around to onRead and onSeek. + void* pUserData; + + + // The sample rate. Will be set to something like 44100. + unsigned int sampleRate; + + // The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc. Maximum 8. This is set based on the + // value specified in the STREAMINFO block. + unsigned char channels; + + // The bits per sample. Will be set to somthing like 16, 24, etc. + unsigned char bitsPerSample; + + // The maximum block size, in samples. This number represents the number of samples in each channel (not combined). + unsigned short maxBlockSize; + + // The total number of samples making up the stream. This includes every channel. For example, if the stream has 2 channels, + // with each channel having a total of 4096, this value will be set to 2*4096 = 8192. + uint64_t totalSampleCount; + + + // The location and size of the APPLICATION block. + drflac_block applicationBlock; + + // The location and size of the SEEKTABLE block. + drflac_block seektableBlock; + + // The location and size of the VORBIS_COMMENT block. + drflac_block vorbisCommentBlock; + + // The location and size of the CUESHEET block. + drflac_block cuesheetBlock; + + // The location and size of the PICTURE block. + drflac_block pictureBlock; + + + // Information about the frame the decoder is currently sitting on. + drflac_frame currentFrame; + + // The position of the first frame in the stream. This is only ever used for seeking. + unsigned long long firstFramePos; + + + + // The current byte position in the client's data stream. + uint64_t currentBytePos; + + // The index of the next valid cache line in the "L2" cache. + size_t nextL2Line; + + // The number of bits that have been consumed by the cache. This is used to determine how many valid bits are remaining. + size_t consumedBits; + + // Unused L2 lines. This will always be 0 until the end of the stream is hit. Used for correctly calculating the current byte + // position of the read pointer in the stream. + size_t unusedL2Lines; + + // The cached data which was most recently read from the client. When data is read from the client, it is placed within this + // variable. As data is read, it's bit-shifted such that the next valid bit is sitting on the most significant bit. + drflac_cache_t cache; + drflac_cache_t cacheL2[DR_FLAC_BUFFER_SIZE/sizeof(drflac_cache_t)]; + + + // A pointer to the decoded sample data. This is an offset of pExtraData. + int32_t* pDecodedSamples; + + // Variable length extra data. We attach this to the end of the object so we avoid unnecessary mallocs. + char pExtraData[1]; + +} drflac; + + + + +// Opens a FLAC decoder. +// +// This is the lowest level function for opening a FLAC stream. You can also use drflac_open_file() and drflac_open_memory() +// to open the stream from a file or from a block of memory respectively. +// +// At the moment the STREAMINFO block must be present for this to succeed. +// +// The onRead and onSeek callbacks are used to read and seek data provided by the client. +static drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData); + +// Closes the given FLAC decoder. +static void drflac_close(drflac* pFlac); + +// Reads sample data from the given FLAC decoder, output as interleaved signed 16-bit PCM. +// +// Returns the number of samples actually read. +static uint64_t drflac_read_s16(drflac* pFlac, uint64_t samplesToRead, int16_t* pBufferOut); + +// Seeks to the sample at the given index. +static bool drflac_seek_to_sample(drflac* pFlac, uint64_t sampleIndex); + + + +#ifndef DR_FLAC_NO_STDIO +// Opens a flac decoder from the file at the given path. +static drflac* drflac_open_file(const char* pFile); +#endif + +// Helper for opening a file from a pre-allocated memory buffer. +// +// This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for +// the lifetime of the decoder. +static drflac* drflac_open_memory(const void* data, size_t dataSize); + +#endif //dr_flac_h + + +/////////////////////////////////////////////////////////////////////////////// +// +// IMPLEMENTATION +// +/////////////////////////////////////////////////////////////////////////////// +#ifdef DR_FLAC_IMPLEMENTATION +#include +#include +#include + +#ifdef _MSC_VER +#include // For _byteswap_ulong and _byteswap_uint64 +#endif + +#ifdef __linux__ +#define _BSD_SOURCE +#include +#endif + +#define DRFLAC_INLINE ALWAYS_INLINE + +#define DRFLAC_BLOCK_TYPE_STREAMINFO 0 +#define DRFLAC_BLOCK_TYPE_PADDING 1 +#define DRFLAC_BLOCK_TYPE_APPLICATION 2 +#define DRFLAC_BLOCK_TYPE_SEEKTABLE 3 +#define DRFLAC_BLOCK_TYPE_VORBIS_COMMENT 4 +#define DRFLAC_BLOCK_TYPE_CUESHEET 5 +#define DRFLAC_BLOCK_TYPE_PICTURE 6 +#define DRFLAC_BLOCK_TYPE_INVALID 127 + +#define DRFLAC_SUBFRAME_CONSTANT 0 +#define DRFLAC_SUBFRAME_VERBATIM 1 +#define DRFLAC_SUBFRAME_FIXED 8 +#define DRFLAC_SUBFRAME_LPC 32 +#define DRFLAC_SUBFRAME_RESERVED 255 + +#define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE 0 +#define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2 1 + +#define DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT 0 +#define DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE 8 +#define DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE 9 +#define DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE 10 + +typedef struct +{ + uint64_t firstSample; + uint64_t frameOffset; // The offset from the first byte of the header of the first frame. + uint16_t sampleCount; +} drflac_seekpoint; + +#ifndef DR_FLAC_NO_STDIO +#if defined(DR_FLAC_NO_WIN32_IO) || !defined(_WIN32) +#include + +static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead) +{ + return fread(bufferOut, 1, bytesToRead, (FILE*)pUserData); +} + +static bool drflac__on_seek_stdio(void* pUserData, int offset) +{ + return fseek((FILE*)pUserData, offset, SEEK_CUR) == 0; +} + +drflac* drflac_open_file(const char* filename) +{ + FILE* pFile; +#ifdef _MSC_VER + if (fopen_s(&pFile, filename, "rb") != 0) { + return NULL; + } +#else + pFile = fopen(filename, "rb"); + if (pFile == NULL) { + return NULL; + } +#endif + + return drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, pFile); +} +#else +#include + +static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead) +{ + assert(bytesToRead < 0xFFFFFFFF); // dr_flac will never request huge amounts of data at a time. This is a safe assertion. + + DWORD bytesRead; + ReadFile((HANDLE)pUserData, bufferOut, (DWORD)bytesToRead, &bytesRead, NULL); + + return (size_t)bytesRead; +} + +static bool drflac__on_seek_stdio(void* pUserData, int offset) +{ + return SetFilePointer((HANDLE)pUserData, offset, NULL, FILE_CURRENT) != INVALID_SET_FILE_POINTER; +} + +static drflac* drflac_open_file(const char* filename) +{ + HANDLE hFile = CreateFileA(filename, FILE_GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + return NULL; + } + + return drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)hFile); +} +#endif +#endif //DR_FLAC_NO_STDIO + + +typedef struct +{ + /// A pointer to the beginning of the data. We use a char as the type here for easy offsetting. + const unsigned char* data; + + /// The size of the data. + size_t dataSize; + + /// The position we're currently sitting at. + size_t currentReadPos; + +} drflac_memory; + +static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t bytesToRead) +{ + drflac_memory* memory = (drflac_memory*)pUserData; + assert(memory != NULL); + assert(memory->dataSize >= memory->currentReadPos); + + size_t bytesRemaining = memory->dataSize - memory->currentReadPos; + if (bytesToRead > bytesRemaining) { + bytesToRead = bytesRemaining; + } + + if (bytesToRead > 0) { + memcpy(bufferOut, memory->data + memory->currentReadPos, bytesToRead); + memory->currentReadPos += bytesToRead; + } + + return bytesToRead; +} + +static bool drflac__on_seek_memory(void* pUserData, int offset) +{ + drflac_memory* memory = (drflac_memory*)pUserData; + assert(memory != NULL); + + if (offset > 0) { + if (memory->currentReadPos + offset > memory->dataSize) { + offset = (int)(memory->dataSize - memory->currentReadPos); // Trying to seek too far forward. + } + } else { + if (memory->currentReadPos < (size_t)-offset) { + offset = -(int)memory->currentReadPos; // Trying to seek too far backwards. + } + } + + // This will never underflow thanks to the clamps above. + memory->currentReadPos += offset; + + return 1; +} + +static drflac* drflac_open_memory(const void* data, size_t dataSize) +{ + drflac_memory* pUserData = (drflac_memory*)malloc(sizeof(*pUserData)); + if (pUserData == NULL) { + return NULL; + } + + pUserData->data = (const unsigned char*)data; + pUserData->dataSize = dataSize; + pUserData->currentReadPos = 0; + return drflac_open(drflac__on_read_memory, drflac__on_seek_memory, pUserData); +} + + +//// Endian Management //// +static DRFLAC_INLINE bool drflac__is_little_endian() +{ + int n = 1; + return (*(char*)&n) == 1; +} + +static DRFLAC_INLINE uint32_t drflac__swap_endian_uint32(uint32_t n) +{ +#ifdef _MSC_VER + return _byteswap_ulong(n); +#elif defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC__ >= 3)) + return __builtin_bswap32(n); +#else + return ((n & 0xFF000000) >> 24) | + ((n & 0x00FF0000) >> 8) | + ((n & 0x0000FF00) << 8) | + ((n & 0x000000FF) << 24); +#endif +} + +static DRFLAC_INLINE uint64_t drflac__swap_endian_uint64(uint64_t n) +{ +#ifdef _MSC_VER + return _byteswap_uint64(n); +#elif defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC__ >= 3)) + return __builtin_bswap64(n); +#else + return ((n & 0xFF00000000000000ULL) >> 56) | + ((n & 0x00FF000000000000ULL) >> 40) | + ((n & 0x0000FF0000000000ULL) >> 24) | + ((n & 0x000000FF00000000ULL) >> 8) | + ((n & 0x00000000FF000000ULL) << 8) | + ((n & 0x0000000000FF0000ULL) << 24) | + ((n & 0x000000000000FF00ULL) << 40) | + ((n & 0x00000000000000FFULL) << 56); +#endif +} + + +static DRFLAC_INLINE uint32_t drflac__be2host_32(uint32_t n) +{ +#ifdef __linux__ + return be32toh(n); +#else + if (drflac__is_little_endian()) { + return drflac__swap_endian_uint32(n); + } + + return n; +#endif +} + +static DRFLAC_INLINE uint64_t drflac__be2host_64(uint64_t n) +{ +#ifdef __linux__ + return be64toh(n); +#else + if (drflac__is_little_endian()) { + return drflac__swap_endian_uint64(n); + } + + return n; +#endif +} + +#ifdef DRFLAC_64BIT +#define drflac__be2host__cache_line drflac__be2host_64 +#else +#define drflac__be2host__cache_line drflac__be2host_32 +#endif + + +// BIT READING ATTEMPT #2 +// +// This uses a 32- or 64-bit bit-shifted cache - as bits are read, the cache is shifted such that the first valid bit is sitting +// on the most significant bit. It uses the notion of an L1 and L2 cache (borrowed from CPU architecture), where the L1 cache +// is a 32- or 64-bit unsigned integer (depending on whether or not a 32- or 64-bit build is being compiled) and the L2 is an +// array of "cache lines", with each cache line being the same size as the L1. The L2 is a buffer of about 4KB and is where data +// from onRead() is read into. +#define DRFLAC_CACHE_L1_SIZE_BYTES (sizeof(pFlac->cache)) +#define DRFLAC_CACHE_L1_SIZE_BITS (sizeof(pFlac->cache)*8) +#define DRFLAC_CACHE_L1_BITS_REMAINING (DRFLAC_CACHE_L1_SIZE_BITS - (pFlac->consumedBits)) +#ifdef DRFLAC_64BIT +#define DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount) (~(((uint64_t)-1LL) >> (_bitCount))) +#else +#define DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount) (~(((uint32_t)-1) >> (_bitCount))) +#endif +#define DRFLAC_CACHE_L1_SELECTION_SHIFT(_bitCount) (DRFLAC_CACHE_L1_SIZE_BITS - (_bitCount)) +#define DRFLAC_CACHE_L1_SELECT(_bitCount) ((pFlac->cache) & DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount)) +#define DRFLAC_CACHE_L1_SELECT_AND_SHIFT(_bitCount) (DRFLAC_CACHE_L1_SELECT(_bitCount) >> DRFLAC_CACHE_L1_SELECTION_SHIFT(_bitCount)) +#define DRFLAC_CACHE_L2_SIZE_BYTES (sizeof(pFlac->cacheL2)) +#define DRFLAC_CACHE_L2_LINE_COUNT (DRFLAC_CACHE_L2_SIZE_BYTES / sizeof(pFlac->cacheL2[0])) +#define DRFLAC_CACHE_L2_LINES_REMAINING (DRFLAC_CACHE_L2_LINE_COUNT - pFlac->nextL2Line) + +static DRFLAC_INLINE bool drflac__reload_l1_cache_from_l2(drflac* pFlac) +{ + // Fast path. Try loading straight from L2. + if (pFlac->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT) { + pFlac->cache = pFlac->cacheL2[pFlac->nextL2Line++]; + return true; + } + + // If we get here it means we've run out of data in the L2 cache. We'll need to fetch more from the client. + size_t bytesRead = pFlac->onRead(pFlac->pUserData, pFlac->cacheL2, DRFLAC_CACHE_L2_SIZE_BYTES); + pFlac->currentBytePos += bytesRead; + + pFlac->nextL2Line = 0; + if (bytesRead == DRFLAC_CACHE_L2_SIZE_BYTES) { + pFlac->cache = pFlac->cacheL2[pFlac->nextL2Line++]; + return true; + } + + + // If we get here it means we were unable to retrieve enough data to fill the entire L2 cache. It probably + // means we've just reached the end of the file. We need to move the valid data down to the end of the buffer + // and adjust the index of the next line accordingly. Also keep in mind that the L2 cache must be aligned to + // the size of the L1 so we'll need to seek backwards by any misaligned bytes. + size_t alignedL1LineCount = bytesRead / DRFLAC_CACHE_L1_SIZE_BYTES; + if (alignedL1LineCount > 0) + { + size_t offset = DRFLAC_CACHE_L2_LINE_COUNT - alignedL1LineCount; + for (size_t i = alignedL1LineCount; i > 0; --i) { + pFlac->cacheL2[i-1 + offset] = pFlac->cacheL2[i-1]; + } + + pFlac->nextL2Line = offset; + pFlac->unusedL2Lines = offset; + + // At this point there may be some leftover unaligned bytes. We need to seek backwards so we don't lose + // those bytes. + size_t unalignedBytes = bytesRead - (alignedL1LineCount * DRFLAC_CACHE_L1_SIZE_BYTES); + if (unalignedBytes > 0) { + pFlac->onSeek(pFlac->pUserData, -(int)unalignedBytes); + pFlac->currentBytePos -= unalignedBytes; + } + + pFlac->cache = pFlac->cacheL2[pFlac->nextL2Line++]; + return true; + } + else + { + // If we get into this branch it means we weren't able to load any L1-aligned data. We just need to seek + // backwards by the leftover bytes and return false. + if (bytesRead > 0) { + pFlac->onSeek(pFlac->pUserData, -(int)bytesRead); + pFlac->currentBytePos -= bytesRead; + } + + pFlac->nextL2Line = DRFLAC_CACHE_L2_LINE_COUNT; + return false; + } +} + +static bool drflac__reload_cache(drflac* pFlac) +{ + // Fast path. Try just moving the next value in the L2 cache to the L1 cache. + if (drflac__reload_l1_cache_from_l2(pFlac)) { + pFlac->cache = drflac__be2host__cache_line(pFlac->cache); + pFlac->consumedBits = 0; + return true; + } + + // Slow path. + + // If we get here it means we have failed to load the L1 cache from the L2. Likely we've just reached the end of the stream and the last + // few bytes did not meet the alignment requirements for the L2 cache. In this case we need to fall back to a slower path and read the + // data straight from the client into the L1 cache. This should only really happen once per stream so efficiency is not important. + size_t bytesRead = pFlac->onRead(pFlac->pUserData, &pFlac->cache, DRFLAC_CACHE_L1_SIZE_BYTES); + if (bytesRead == 0) { + return false; + } + + pFlac->currentBytePos += bytesRead; + + assert(bytesRead < DRFLAC_CACHE_L1_SIZE_BYTES); + pFlac->consumedBits = (DRFLAC_CACHE_L1_SIZE_BYTES - bytesRead) * 8; + + pFlac->cache = drflac__be2host__cache_line(pFlac->cache); + pFlac->cache &= DRFLAC_CACHE_L1_SELECTION_MASK(DRFLAC_CACHE_L1_SIZE_BITS - pFlac->consumedBits); // <-- Make sure the consumed bits are always set to zero. Other parts of the library depend on this property. + return true; +} + +static bool drflac__seek_bits(drflac* pFlac, size_t bitsToSeek) +{ + if (bitsToSeek <= DRFLAC_CACHE_L1_BITS_REMAINING) { + pFlac->consumedBits += bitsToSeek; + pFlac->cache <<= bitsToSeek; + return true; + } else { + // It straddles the cached data. This function isn't called too frequently so I'm favouring simplicity here. + bitsToSeek -= DRFLAC_CACHE_L1_BITS_REMAINING; + pFlac->consumedBits += DRFLAC_CACHE_L1_BITS_REMAINING; + pFlac->cache = 0; + + size_t wholeBytesRemaining = bitsToSeek/8; + if (wholeBytesRemaining > 0) + { + // The next bytes to seek will be located in the L2 cache. The problem is that the L2 cache is not byte aligned, + // but rather DRFLAC_CACHE_L1_SIZE_BYTES aligned (usually 4 or 8). If, for example, the number of bytes to seek is + // 3, we'll need to handle it in a special way. + size_t wholeCacheLinesRemaining = wholeBytesRemaining / DRFLAC_CACHE_L1_SIZE_BYTES; + if (wholeCacheLinesRemaining < DRFLAC_CACHE_L2_LINES_REMAINING) + { + wholeBytesRemaining -= wholeCacheLinesRemaining * DRFLAC_CACHE_L1_SIZE_BYTES; + bitsToSeek -= wholeCacheLinesRemaining * DRFLAC_CACHE_L1_SIZE_BITS; + pFlac->nextL2Line += wholeCacheLinesRemaining; + } + else + { + wholeBytesRemaining -= DRFLAC_CACHE_L2_LINES_REMAINING * DRFLAC_CACHE_L1_SIZE_BYTES; + bitsToSeek -= DRFLAC_CACHE_L2_LINES_REMAINING * DRFLAC_CACHE_L1_SIZE_BITS; + pFlac->nextL2Line += DRFLAC_CACHE_L2_LINES_REMAINING; + + pFlac->onSeek(pFlac->pUserData, (int)wholeBytesRemaining); + pFlac->currentBytePos += wholeBytesRemaining; + bitsToSeek -= wholeBytesRemaining*8; + } + } + + + if (bitsToSeek > 0) { + if (!drflac__reload_cache(pFlac)) { + return false; + } + + return drflac__seek_bits(pFlac, bitsToSeek); + } + + return true; + } +} + +static bool drflac__read_uint32(drflac* pFlac, unsigned int bitCount, uint32_t* pResultOut) +{ + assert(pFlac != NULL); + assert(pResultOut != NULL); + assert(bitCount > 0); + assert(bitCount <= 32); + + if (pFlac->consumedBits == DRFLAC_CACHE_L1_SIZE_BITS) { + if (!drflac__reload_cache(pFlac)) { + return false; + } + } + + if (bitCount <= DRFLAC_CACHE_L1_BITS_REMAINING) { + if (bitCount < DRFLAC_CACHE_L1_SIZE_BITS) { + *pResultOut = DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bitCount); + pFlac->consumedBits += bitCount; + pFlac->cache <<= bitCount; + } else { + *pResultOut = (uint32_t)pFlac->cache; + pFlac->consumedBits = DRFLAC_CACHE_L1_SIZE_BITS; + pFlac->cache = 0; + } + return true; + } else { + // It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them. + size_t bitCountHi = DRFLAC_CACHE_L1_BITS_REMAINING; + size_t bitCountLo = bitCount - bitCountHi; + uint32_t resultHi = DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bitCountHi); + + if (!drflac__reload_cache(pFlac)) { + return false; + } + + *pResultOut = (resultHi << bitCountLo) | DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bitCountLo); + pFlac->consumedBits += bitCountLo; + pFlac->cache <<= bitCountLo; + return true; + } +} + +static bool drflac__read_int32(drflac* pFlac, unsigned int bitCount, int32_t* pResult) +{ + assert(pFlac != NULL); + assert(pResult != NULL); + assert(bitCount > 0); + assert(bitCount <= 32); + + uint32_t result; + if (!drflac__read_uint32(pFlac, bitCount, &result)) { + return false; + } + + if ((result & (1 << (bitCount - 1)))) { // TODO: See if we can get rid of this branch. + result |= (-1 << bitCount); + } + + *pResult = (int32_t)result; + return true; +} + +static bool drflac__read_uint64(drflac* pFlac, unsigned int bitCount, uint64_t* pResultOut) +{ + assert(bitCount <= 64); + assert(bitCount > 32); + + uint32_t resultHi; + if (!drflac__read_uint32(pFlac, bitCount - 32, &resultHi)) { + return false; + } + + uint32_t resultLo; + if (!drflac__read_uint32(pFlac, 32, &resultLo)) { + return false; + } + + *pResultOut = (((uint64_t)resultHi) << 32) | ((uint64_t)resultLo); + return true; +} + +static bool drflac__read_int64(drflac* pFlac, unsigned int bitCount, int64_t* pResultOut) +{ + assert(bitCount <= 64); + + uint64_t result; + if (!drflac__read_uint64(pFlac, bitCount, &result)) { + return false; + } + + if ((result & (1ULL << (bitCount - 1)))) { // TODO: See if we can get rid of this branch. + result |= (-1LL << bitCount); + } + + *pResultOut = (int64_t)result; + return true; +} + +static bool drflac__read_uint16(drflac* pFlac, unsigned int bitCount, uint16_t* pResult) +{ + assert(pFlac != NULL); + assert(pResult != NULL); + assert(bitCount > 0); + assert(bitCount <= 16); + + uint32_t result; + if (!drflac__read_uint32(pFlac, bitCount, &result)) { + return false; + } + + *pResult = (uint16_t)result; + return true; +} + +static bool drflac__read_int16(drflac* pFlac, unsigned int bitCount, int16_t* pResult) +{ + assert(pFlac != NULL); + assert(pResult != NULL); + assert(bitCount > 0); + assert(bitCount <= 16); + + int32_t result; + if (!drflac__read_int32(pFlac, bitCount, &result)) { + return false; + } + + *pResult = (int16_t)result; + return true; +} + +static bool drflac__read_uint8(drflac* pFlac, unsigned int bitCount, uint8_t* pResult) +{ + assert(pFlac != NULL); + assert(pResult != NULL); + assert(bitCount > 0); + assert(bitCount <= 8); + + uint32_t result; + if (!drflac__read_uint32(pFlac, bitCount, &result)) { + return false; + } + + *pResult = (uint8_t)result; + return true; +} + +static bool drflac__read_int8(drflac* pFlac, unsigned int bitCount, int8_t* pResult) +{ + assert(pFlac != NULL); + assert(pResult != NULL); + assert(bitCount > 0); + assert(bitCount <= 8); + + int32_t result; + if (!drflac__read_int32(pFlac, bitCount, &result)) { + return false; + } + + *pResult = (int8_t)result; + return true; +} + + +static inline bool drflac__seek_past_next_set_bit(drflac* pFlac, unsigned int* pOffsetOut) +{ + unsigned int zeroCounter = 0; + while (pFlac->cache == 0) { + zeroCounter += (unsigned int)DRFLAC_CACHE_L1_BITS_REMAINING; + if (!drflac__reload_cache(pFlac)) { + return false; + } + } + + // At this point the cache should not be zero, in which case we know the first set bit should be somewhere in here. There is + // no need for us to perform any cache reloading logic here which should make things much faster. + assert(pFlac->cache != 0); + + unsigned int bitOffsetTable[] = { + 0, + 4, + 3, 3, + 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1 + }; + + unsigned int setBitOffsetPlus1 = bitOffsetTable[DRFLAC_CACHE_L1_SELECT_AND_SHIFT(4)]; + if (setBitOffsetPlus1 == 0) { + if (pFlac->cache == 1) { + setBitOffsetPlus1 = DRFLAC_CACHE_L1_SIZE_BITS; + } else { + setBitOffsetPlus1 = 5; + for (;;) + { + if ((pFlac->cache & DRFLAC_CACHE_L1_SELECT(setBitOffsetPlus1))) { + break; + } + + setBitOffsetPlus1 += 1; + } + } + } + + pFlac->consumedBits += setBitOffsetPlus1; + pFlac->cache <<= setBitOffsetPlus1; + + *pOffsetOut = zeroCounter + setBitOffsetPlus1 - 1; + return true; +} + + + +static bool drflac__seek_to_byte(drflac* pFlac, long long offsetFromStart) +{ + assert(pFlac != NULL); + + long long bytesToMove = offsetFromStart - pFlac->currentBytePos; + if (bytesToMove == 0) { + return 1; + } + + if (bytesToMove > 0x7FFFFFFF) { + while (bytesToMove > 0x7FFFFFFF) { + if (!pFlac->onSeek(pFlac->pUserData, 0x7FFFFFFF)) { + return 0; + } + + pFlac->currentBytePos += 0x7FFFFFFF; + bytesToMove -= 0x7FFFFFFF; + } + } else { + while (bytesToMove < (int)0x80000000) { + if (!pFlac->onSeek(pFlac->pUserData, (int)0x80000000)) { + return 0; + } + + pFlac->currentBytePos += (int)0x80000000; + bytesToMove -= (int)0x80000000; + } + } + + assert(bytesToMove <= 0x7FFFFFFF && bytesToMove >= (int)0x80000000); + + bool result = pFlac->onSeek(pFlac->pUserData, (int)bytesToMove); // <-- Safe cast as per the assert above. + pFlac->currentBytePos += (int)bytesToMove; + + pFlac->consumedBits = DRFLAC_CACHE_L1_SIZE_BITS; + pFlac->cache = 0; + pFlac->nextL2Line = DRFLAC_CACHE_L2_LINE_COUNT; // <-- This clears the L2 cache. + + return result; +} + +static long long drflac__tell(drflac* pFlac) +{ + assert(pFlac != NULL); + + size_t unreadBytesFromL1 = (DRFLAC_CACHE_L1_SIZE_BYTES - (pFlac->consumedBits/8)); + size_t unreadBytesFromL2 = (DRFLAC_CACHE_L2_SIZE_BYTES - ((pFlac->nextL2Line - pFlac->unusedL2Lines)*DRFLAC_CACHE_L1_SIZE_BYTES)); + + return pFlac->currentBytePos - unreadBytesFromL1 - unreadBytesFromL2; +} + + + +static bool drflac__read_utf8_coded_number(drflac* pFlac, unsigned long long* pNumberOut) +{ + assert(pFlac != NULL); + assert(pNumberOut != NULL); + + // We should never need to read UTF-8 data while not being aligned to a byte boundary. Therefore we can grab the data + // directly from the input stream rather than using drflac__read_uint8(). + assert((pFlac->consumedBits & 7) == 0); + + unsigned char utf8[7] = {0}; + if (!drflac__read_uint8(pFlac, 8, utf8)) { + *pNumberOut = 0; + return false; + } + + if ((utf8[0] & 0x80) == 0) { + *pNumberOut = utf8[0]; + return true; + } + + int byteCount = 1; + if ((utf8[0] & 0xE0) == 0xC0) { + byteCount = 2; + } else if ((utf8[0] & 0xF0) == 0xE0) { + byteCount = 3; + } else if ((utf8[0] & 0xF8) == 0xF0) { + byteCount = 4; + } else if ((utf8[0] & 0xFC) == 0xF8) { + byteCount = 5; + } else if ((utf8[0] & 0xFE) == 0xFC) { + byteCount = 6; + } else if ((utf8[0] & 0xFF) == 0xFE) { + byteCount = 7; + } else { + *pNumberOut = 0; + return false; // Bad UTF-8 encoding. + } + + // Read extra bytes. + assert(byteCount > 1); + + unsigned long long result = ((long long)(utf8[0] & (0xFF >> (byteCount + 1)))); + for (int i = 1; i < byteCount; ++i) { + if (!drflac__read_uint8(pFlac, 8, utf8 + i)) { + *pNumberOut = 0; + return false; + } + + result = (result << 6) | (utf8[i] & 0x3F); + } + + *pNumberOut = result; + return true; +} + + + +static DRFLAC_INLINE bool drflac__read_and_seek_rice(drflac* pFlac, unsigned char m) +{ + unsigned int unused; + if (!drflac__seek_past_next_set_bit(pFlac, &unused)) { + return false; + } + + if (m > 0) { + if (!drflac__seek_bits(pFlac, m)) { + return false; + } + } + + return true; +} + + +// The next two functions are responsible for calculating the prediction. +// +// When the bits per sample is >16 we need to use 64-bit integer arithmetic because otherwise we'll run out of precision. It's +// safe to assume this will be slower on 32-bit platforms so we use a more optimal solution when the bits per sample is <=16. +// +// +// Optimization Experiment #1 +// +// The first optimization experiment I'm trying here is a loop unroll for the most common LPC orders. I've done a little test +// and the results are as follows, in order of most common: +// 1) order = 8 : 93.1M +// 2) order = 7 : 36.6M +// 3) order = 3 : 33.2M +// 4) order = 6 : 20.9M +// 5) order = 5 : 18.1M +// 6) order = 4 : 15.8M +// 7) order = 12 : 10.8M +// 8) order = 2 : 9.8M +// 9) order = 1 : 1.6M +// 10) order = 10 : 1.0M +// 11) order = 9 : 0.8M +// 12) order = 11 : 0.8M +// +// We'll experiment with unrolling the top 8 most common ones. We'll ignore the least common ones since there seems to be a +// large drop off there. +// +// Result: There's a tiny improvement in some cases, but it could just be within margin of error so unsure if it's worthwhile +// just yet. +static DRFLAC_INLINE int32_t drflac__calculate_prediction_32(unsigned int order, int shift, const short* coefficients, int32_t* pDecodedSamples) +{ + assert(order <= 32); + + // 32-bit version. + + // This method is slower on both 32- and 64-bit builds with VC++. Leaving this here for now just in case we need it later + // for whatever reason. +#if 0 + int prediction; + if (order == 8) + { + prediction = coefficients[0] * pDecodedSamples[-1]; + prediction += coefficients[1] * pDecodedSamples[-2]; + prediction += coefficients[2] * pDecodedSamples[-3]; + prediction += coefficients[3] * pDecodedSamples[-4]; + prediction += coefficients[4] * pDecodedSamples[-5]; + prediction += coefficients[5] * pDecodedSamples[-6]; + prediction += coefficients[6] * pDecodedSamples[-7]; + prediction += coefficients[7] * pDecodedSamples[-8]; + } + else if (order == 7) + { + prediction = coefficients[0] * pDecodedSamples[-1]; + prediction += coefficients[1] * pDecodedSamples[-2]; + prediction += coefficients[2] * pDecodedSamples[-3]; + prediction += coefficients[3] * pDecodedSamples[-4]; + prediction += coefficients[4] * pDecodedSamples[-5]; + prediction += coefficients[5] * pDecodedSamples[-6]; + prediction += coefficients[6] * pDecodedSamples[-7]; + } + else if (order == 3) + { + prediction = coefficients[0] * pDecodedSamples[-1]; + prediction += coefficients[1] * pDecodedSamples[-2]; + prediction += coefficients[2] * pDecodedSamples[-3]; + } + else if (order == 6) + { + prediction = coefficients[0] * pDecodedSamples[-1]; + prediction += coefficients[1] * pDecodedSamples[-2]; + prediction += coefficients[2] * pDecodedSamples[-3]; + prediction += coefficients[3] * pDecodedSamples[-4]; + prediction += coefficients[4] * pDecodedSamples[-5]; + prediction += coefficients[5] * pDecodedSamples[-6]; + } + else if (order == 5) + { + prediction = coefficients[0] * pDecodedSamples[-1]; + prediction += coefficients[1] * pDecodedSamples[-2]; + prediction += coefficients[2] * pDecodedSamples[-3]; + prediction += coefficients[3] * pDecodedSamples[-4]; + prediction += coefficients[4] * pDecodedSamples[-5]; + } + else if (order == 4) + { + prediction = coefficients[0] * pDecodedSamples[-1]; + prediction += coefficients[1] * pDecodedSamples[-2]; + prediction += coefficients[2] * pDecodedSamples[-3]; + prediction += coefficients[3] * pDecodedSamples[-4]; + } + else if (order == 12) + { + prediction = coefficients[0] * pDecodedSamples[-1]; + prediction += coefficients[1] * pDecodedSamples[-2]; + prediction += coefficients[2] * pDecodedSamples[-3]; + prediction += coefficients[3] * pDecodedSamples[-4]; + prediction += coefficients[4] * pDecodedSamples[-5]; + prediction += coefficients[5] * pDecodedSamples[-6]; + prediction += coefficients[6] * pDecodedSamples[-7]; + prediction += coefficients[7] * pDecodedSamples[-8]; + prediction += coefficients[8] * pDecodedSamples[-9]; + prediction += coefficients[9] * pDecodedSamples[-10]; + prediction += coefficients[10] * pDecodedSamples[-11]; + prediction += coefficients[11] * pDecodedSamples[-12]; + } + else if (order == 2) + { + prediction = coefficients[0] * pDecodedSamples[-1]; + prediction += coefficients[1] * pDecodedSamples[-2]; + } + else if (order == 1) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + } + else if (order == 10) + { + prediction = coefficients[0] * pDecodedSamples[-1]; + prediction += coefficients[1] * pDecodedSamples[-2]; + prediction += coefficients[2] * pDecodedSamples[-3]; + prediction += coefficients[3] * pDecodedSamples[-4]; + prediction += coefficients[4] * pDecodedSamples[-5]; + prediction += coefficients[5] * pDecodedSamples[-6]; + prediction += coefficients[6] * pDecodedSamples[-7]; + prediction += coefficients[7] * pDecodedSamples[-8]; + prediction += coefficients[8] * pDecodedSamples[-9]; + prediction += coefficients[9] * pDecodedSamples[-10]; + } + else if (order == 9) + { + prediction = coefficients[0] * pDecodedSamples[-1]; + prediction += coefficients[1] * pDecodedSamples[-2]; + prediction += coefficients[2] * pDecodedSamples[-3]; + prediction += coefficients[3] * pDecodedSamples[-4]; + prediction += coefficients[4] * pDecodedSamples[-5]; + prediction += coefficients[5] * pDecodedSamples[-6]; + prediction += coefficients[6] * pDecodedSamples[-7]; + prediction += coefficients[7] * pDecodedSamples[-8]; + prediction += coefficients[8] * pDecodedSamples[-9]; + } + else if (order == 11) + { + prediction = coefficients[0] * pDecodedSamples[-1]; + prediction += coefficients[1] * pDecodedSamples[-2]; + prediction += coefficients[2] * pDecodedSamples[-3]; + prediction += coefficients[3] * pDecodedSamples[-4]; + prediction += coefficients[4] * pDecodedSamples[-5]; + prediction += coefficients[5] * pDecodedSamples[-6]; + prediction += coefficients[6] * pDecodedSamples[-7]; + prediction += coefficients[7] * pDecodedSamples[-8]; + prediction += coefficients[8] * pDecodedSamples[-9]; + prediction += coefficients[9] * pDecodedSamples[-10]; + prediction += coefficients[10] * pDecodedSamples[-11]; + } + else + { + prediction = 0; + for (int j = 0; j < (int)order; ++j) { + prediction += coefficients[j] * pDecodedSamples[-j-1]; + } + } +#endif + + // Experiment #2. See if we can use a switch and let the compiler optimize it to a jump table. + // Result: VC++ definitely optimizes this to a single jmp as expected. I expect other compilers should do the same, but I've + // not verified yet. +#if 1 + int prediction = 0; + + switch (order) + { + case 32: prediction += coefficients[31] * pDecodedSamples[-32]; + case 31: prediction += coefficients[30] * pDecodedSamples[-31]; + case 30: prediction += coefficients[29] * pDecodedSamples[-30]; + case 29: prediction += coefficients[28] * pDecodedSamples[-29]; + case 28: prediction += coefficients[27] * pDecodedSamples[-28]; + case 27: prediction += coefficients[26] * pDecodedSamples[-27]; + case 26: prediction += coefficients[25] * pDecodedSamples[-26]; + case 25: prediction += coefficients[24] * pDecodedSamples[-25]; + case 24: prediction += coefficients[23] * pDecodedSamples[-24]; + case 23: prediction += coefficients[22] * pDecodedSamples[-23]; + case 22: prediction += coefficients[21] * pDecodedSamples[-22]; + case 21: prediction += coefficients[20] * pDecodedSamples[-21]; + case 20: prediction += coefficients[19] * pDecodedSamples[-20]; + case 19: prediction += coefficients[18] * pDecodedSamples[-19]; + case 18: prediction += coefficients[17] * pDecodedSamples[-18]; + case 17: prediction += coefficients[16] * pDecodedSamples[-17]; + case 16: prediction += coefficients[15] * pDecodedSamples[-16]; + case 15: prediction += coefficients[14] * pDecodedSamples[-15]; + case 14: prediction += coefficients[13] * pDecodedSamples[-14]; + case 13: prediction += coefficients[12] * pDecodedSamples[-13]; + case 12: prediction += coefficients[11] * pDecodedSamples[-12]; + case 11: prediction += coefficients[10] * pDecodedSamples[-11]; + case 10: prediction += coefficients[ 9] * pDecodedSamples[-10]; + case 9: prediction += coefficients[ 8] * pDecodedSamples[- 9]; + case 8: prediction += coefficients[ 7] * pDecodedSamples[- 8]; + case 7: prediction += coefficients[ 6] * pDecodedSamples[- 7]; + case 6: prediction += coefficients[ 5] * pDecodedSamples[- 6]; + case 5: prediction += coefficients[ 4] * pDecodedSamples[- 5]; + case 4: prediction += coefficients[ 3] * pDecodedSamples[- 4]; + case 3: prediction += coefficients[ 2] * pDecodedSamples[- 3]; + case 2: prediction += coefficients[ 1] * pDecodedSamples[- 2]; + case 1: prediction += coefficients[ 0] * pDecodedSamples[- 1]; + } +#endif + + return (int32_t)(prediction >> shift); +} + +static DRFLAC_INLINE int32_t drflac__calculate_prediction(unsigned int order, int shift, const short* coefficients, int32_t* pDecodedSamples) +{ + assert(order <= 32); + + // 64-bit version. + + // This method is faster on the 32-bit build when compiling with VC++. See note below. +#ifndef DRFLAC_64BIT + long long prediction; + if (order == 8) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + prediction += (long long)coefficients[1] * (long long)pDecodedSamples[-2]; + prediction += (long long)coefficients[2] * (long long)pDecodedSamples[-3]; + prediction += (long long)coefficients[3] * (long long)pDecodedSamples[-4]; + prediction += (long long)coefficients[4] * (long long)pDecodedSamples[-5]; + prediction += (long long)coefficients[5] * (long long)pDecodedSamples[-6]; + prediction += (long long)coefficients[6] * (long long)pDecodedSamples[-7]; + prediction += (long long)coefficients[7] * (long long)pDecodedSamples[-8]; + } + else if (order == 7) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + prediction += (long long)coefficients[1] * (long long)pDecodedSamples[-2]; + prediction += (long long)coefficients[2] * (long long)pDecodedSamples[-3]; + prediction += (long long)coefficients[3] * (long long)pDecodedSamples[-4]; + prediction += (long long)coefficients[4] * (long long)pDecodedSamples[-5]; + prediction += (long long)coefficients[5] * (long long)pDecodedSamples[-6]; + prediction += (long long)coefficients[6] * (long long)pDecodedSamples[-7]; + } + else if (order == 3) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + prediction += (long long)coefficients[1] * (long long)pDecodedSamples[-2]; + prediction += (long long)coefficients[2] * (long long)pDecodedSamples[-3]; + } + else if (order == 6) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + prediction += (long long)coefficients[1] * (long long)pDecodedSamples[-2]; + prediction += (long long)coefficients[2] * (long long)pDecodedSamples[-3]; + prediction += (long long)coefficients[3] * (long long)pDecodedSamples[-4]; + prediction += (long long)coefficients[4] * (long long)pDecodedSamples[-5]; + prediction += (long long)coefficients[5] * (long long)pDecodedSamples[-6]; + } + else if (order == 5) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + prediction += (long long)coefficients[1] * (long long)pDecodedSamples[-2]; + prediction += (long long)coefficients[2] * (long long)pDecodedSamples[-3]; + prediction += (long long)coefficients[3] * (long long)pDecodedSamples[-4]; + prediction += (long long)coefficients[4] * (long long)pDecodedSamples[-5]; + } + else if (order == 4) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + prediction += (long long)coefficients[1] * (long long)pDecodedSamples[-2]; + prediction += (long long)coefficients[2] * (long long)pDecodedSamples[-3]; + prediction += (long long)coefficients[3] * (long long)pDecodedSamples[-4]; + } + else if (order == 12) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + prediction += (long long)coefficients[1] * (long long)pDecodedSamples[-2]; + prediction += (long long)coefficients[2] * (long long)pDecodedSamples[-3]; + prediction += (long long)coefficients[3] * (long long)pDecodedSamples[-4]; + prediction += (long long)coefficients[4] * (long long)pDecodedSamples[-5]; + prediction += (long long)coefficients[5] * (long long)pDecodedSamples[-6]; + prediction += (long long)coefficients[6] * (long long)pDecodedSamples[-7]; + prediction += (long long)coefficients[7] * (long long)pDecodedSamples[-8]; + prediction += (long long)coefficients[8] * (long long)pDecodedSamples[-9]; + prediction += (long long)coefficients[9] * (long long)pDecodedSamples[-10]; + prediction += (long long)coefficients[10] * (long long)pDecodedSamples[-11]; + prediction += (long long)coefficients[11] * (long long)pDecodedSamples[-12]; + } + else if (order == 2) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + prediction += (long long)coefficients[1] * (long long)pDecodedSamples[-2]; + } + else if (order == 1) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + } + else if (order == 10) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + prediction += (long long)coefficients[1] * (long long)pDecodedSamples[-2]; + prediction += (long long)coefficients[2] * (long long)pDecodedSamples[-3]; + prediction += (long long)coefficients[3] * (long long)pDecodedSamples[-4]; + prediction += (long long)coefficients[4] * (long long)pDecodedSamples[-5]; + prediction += (long long)coefficients[5] * (long long)pDecodedSamples[-6]; + prediction += (long long)coefficients[6] * (long long)pDecodedSamples[-7]; + prediction += (long long)coefficients[7] * (long long)pDecodedSamples[-8]; + prediction += (long long)coefficients[8] * (long long)pDecodedSamples[-9]; + prediction += (long long)coefficients[9] * (long long)pDecodedSamples[-10]; + } + else if (order == 9) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + prediction += (long long)coefficients[1] * (long long)pDecodedSamples[-2]; + prediction += (long long)coefficients[2] * (long long)pDecodedSamples[-3]; + prediction += (long long)coefficients[3] * (long long)pDecodedSamples[-4]; + prediction += (long long)coefficients[4] * (long long)pDecodedSamples[-5]; + prediction += (long long)coefficients[5] * (long long)pDecodedSamples[-6]; + prediction += (long long)coefficients[6] * (long long)pDecodedSamples[-7]; + prediction += (long long)coefficients[7] * (long long)pDecodedSamples[-8]; + prediction += (long long)coefficients[8] * (long long)pDecodedSamples[-9]; + } + else if (order == 11) + { + prediction = (long long)coefficients[0] * (long long)pDecodedSamples[-1]; + prediction += (long long)coefficients[1] * (long long)pDecodedSamples[-2]; + prediction += (long long)coefficients[2] * (long long)pDecodedSamples[-3]; + prediction += (long long)coefficients[3] * (long long)pDecodedSamples[-4]; + prediction += (long long)coefficients[4] * (long long)pDecodedSamples[-5]; + prediction += (long long)coefficients[5] * (long long)pDecodedSamples[-6]; + prediction += (long long)coefficients[6] * (long long)pDecodedSamples[-7]; + prediction += (long long)coefficients[7] * (long long)pDecodedSamples[-8]; + prediction += (long long)coefficients[8] * (long long)pDecodedSamples[-9]; + prediction += (long long)coefficients[9] * (long long)pDecodedSamples[-10]; + prediction += (long long)coefficients[10] * (long long)pDecodedSamples[-11]; + } + else + { + prediction = 0; + for (int j = 0; j < (int)order; ++j) { + prediction += (long long)coefficients[j] * (long long)pDecodedSamples[-j-1]; + } + } +#endif + + // Experiment #2. See if we can use a switch and let the compiler optimize it to a single jmp instruction. + // Result: VC++ optimizes this to a single jmp on the 64-bit build, but for some reason the 32-bit version compiles to less efficient + // code. Thus, we use this version on the 64-bit build and the uglier version above for the 32-bit build. If anyone has an idea on how + // I can get VC++ to generate an efficient jump table for the 32-bit build let me know. +#ifdef DRFLAC_64BIT + long long prediction = 0; + + switch (order) + { + case 32: prediction += (long long)coefficients[31] * (long long)pDecodedSamples[-32]; + case 31: prediction += (long long)coefficients[30] * (long long)pDecodedSamples[-31]; + case 30: prediction += (long long)coefficients[29] * (long long)pDecodedSamples[-30]; + case 29: prediction += (long long)coefficients[28] * (long long)pDecodedSamples[-29]; + case 28: prediction += (long long)coefficients[27] * (long long)pDecodedSamples[-28]; + case 27: prediction += (long long)coefficients[26] * (long long)pDecodedSamples[-27]; + case 26: prediction += (long long)coefficients[25] * (long long)pDecodedSamples[-26]; + case 25: prediction += (long long)coefficients[24] * (long long)pDecodedSamples[-25]; + case 24: prediction += (long long)coefficients[23] * (long long)pDecodedSamples[-24]; + case 23: prediction += (long long)coefficients[22] * (long long)pDecodedSamples[-23]; + case 22: prediction += (long long)coefficients[21] * (long long)pDecodedSamples[-22]; + case 21: prediction += (long long)coefficients[20] * (long long)pDecodedSamples[-21]; + case 20: prediction += (long long)coefficients[19] * (long long)pDecodedSamples[-20]; + case 19: prediction += (long long)coefficients[18] * (long long)pDecodedSamples[-19]; + case 18: prediction += (long long)coefficients[17] * (long long)pDecodedSamples[-18]; + case 17: prediction += (long long)coefficients[16] * (long long)pDecodedSamples[-17]; + case 16: prediction += (long long)coefficients[15] * (long long)pDecodedSamples[-16]; + case 15: prediction += (long long)coefficients[14] * (long long)pDecodedSamples[-15]; + case 14: prediction += (long long)coefficients[13] * (long long)pDecodedSamples[-14]; + case 13: prediction += (long long)coefficients[12] * (long long)pDecodedSamples[-13]; + case 12: prediction += (long long)coefficients[11] * (long long)pDecodedSamples[-12]; + case 11: prediction += (long long)coefficients[10] * (long long)pDecodedSamples[-11]; + case 10: prediction += (long long)coefficients[ 9] * (long long)pDecodedSamples[-10]; + case 9: prediction += (long long)coefficients[ 8] * (long long)pDecodedSamples[- 9]; + case 8: prediction += (long long)coefficients[ 7] * (long long)pDecodedSamples[- 8]; + case 7: prediction += (long long)coefficients[ 6] * (long long)pDecodedSamples[- 7]; + case 6: prediction += (long long)coefficients[ 5] * (long long)pDecodedSamples[- 6]; + case 5: prediction += (long long)coefficients[ 4] * (long long)pDecodedSamples[- 5]; + case 4: prediction += (long long)coefficients[ 3] * (long long)pDecodedSamples[- 4]; + case 3: prediction += (long long)coefficients[ 2] * (long long)pDecodedSamples[- 3]; + case 2: prediction += (long long)coefficients[ 1] * (long long)pDecodedSamples[- 2]; + case 1: prediction += (long long)coefficients[ 0] * (long long)pDecodedSamples[- 1]; + } +#endif + + return (int32_t)(prediction >> shift); +} + + +// Reads and decodes a string of residual values as Rice codes. The decoder should be sitting on the first bit of the Rice codes. +// +// This is the most frequently called function in the library. It does both the Rice decoding and the prediction in a single loop +// iteration. +static bool drflac__decode_samples_with_residual__rice(drflac* pFlac, unsigned int count, unsigned char riceParam, unsigned int order, int shift, const short* coefficients, int* pSamplesOut) +{ + assert(pFlac != NULL); + assert(count > 0); + assert(pSamplesOut != NULL); + + static unsigned int bitOffsetTable[] = { + 0, + 4, + 3, 3, + 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1 + }; + + drflac_cache_t riceParamMask = DRFLAC_CACHE_L1_SELECTION_MASK(riceParam); + drflac_cache_t resultHiShift = DRFLAC_CACHE_L1_SIZE_BITS - riceParam; + + for (int i = 0; i < (int)count; ++i) + { + unsigned int zeroCounter = 0; + while (pFlac->cache == 0) { + zeroCounter += (unsigned int)DRFLAC_CACHE_L1_BITS_REMAINING; + if (!drflac__reload_cache(pFlac)) { + return false; + } + } + + // At this point the cache should not be zero, in which case we know the first set bit should be somewhere in here. There is + // no need for us to perform any cache reloading logic here which should make things much faster. + assert(pFlac->cache != 0); + unsigned int decodedRice; + + unsigned int setBitOffsetPlus1 = bitOffsetTable[DRFLAC_CACHE_L1_SELECT_AND_SHIFT(4)]; + if (setBitOffsetPlus1 > 0) { + decodedRice = (zeroCounter + (setBitOffsetPlus1-1)) << riceParam; + } else { + if (pFlac->cache == 1) { + setBitOffsetPlus1 = DRFLAC_CACHE_L1_SIZE_BITS; + decodedRice = (zeroCounter + (DRFLAC_CACHE_L1_SIZE_BITS-1)) << riceParam; + } else { + setBitOffsetPlus1 = 5; + for (;;) + { + if ((pFlac->cache & DRFLAC_CACHE_L1_SELECT(setBitOffsetPlus1))) { + decodedRice = (zeroCounter + (setBitOffsetPlus1-1)) << riceParam; + break; + } + + setBitOffsetPlus1 += 1; + } + } + } + + + unsigned int bitsLo = 0; + unsigned int riceLength = setBitOffsetPlus1 + riceParam; + if (riceLength < DRFLAC_CACHE_L1_BITS_REMAINING) + { + bitsLo = (unsigned int)((pFlac->cache & (riceParamMask >> setBitOffsetPlus1)) >> (DRFLAC_CACHE_L1_SIZE_BITS - riceLength)); + + pFlac->consumedBits += riceLength; + pFlac->cache <<= riceLength; + } + else + { + pFlac->consumedBits += riceLength; + pFlac->cache <<= setBitOffsetPlus1; + + // It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them. + size_t bitCountLo = pFlac->consumedBits - DRFLAC_CACHE_L1_SIZE_BITS; + drflac_cache_t resultHi = pFlac->cache & riceParamMask; // <-- This mask is OK because all bits after the first bits are always zero. + + + if (pFlac->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT) { + pFlac->cache = drflac__be2host__cache_line(pFlac->cacheL2[pFlac->nextL2Line++]); + } else { + // Slow path. We need to fetch more data from the client. + if (!drflac__reload_cache(pFlac)) { + return false; + } + } + + bitsLo = (unsigned int)((resultHi >> resultHiShift) | DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bitCountLo)); + pFlac->consumedBits = bitCountLo; + pFlac->cache <<= bitCountLo; + } + + + decodedRice |= bitsLo; + if ((decodedRice & 0x01)) { + decodedRice = ~(decodedRice >> 1); + } else { + decodedRice = (decodedRice >> 1); + } + + + // In order to properly calculate the prediction when the bits per sample is >16 we need to do it using 64-bit arithmetic. We can assume this + // is probably going to be slower on 32-bit systems so we'll do a more optimized 32-bit version when the bits per sample is low enough. + if (pFlac->currentFrame.bitsPerSample > 16) { + pSamplesOut[i] = ((int)decodedRice + drflac__calculate_prediction(order, shift, coefficients, pSamplesOut + i)); + } else { + pSamplesOut[i] = ((int)decodedRice + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + i)); + } + } + + return true; +} + + +// Reads and seeks past a string of residual values as Rice codes. The decoder should be sitting on the first bit of the Rice codes. +static bool drflac__read_and_seek_residual__rice(drflac* pFlac, unsigned int count, unsigned char riceParam) +{ + assert(pFlac != NULL); + assert(count > 0); + + for (unsigned int i = 0; i < count; ++i) { + if (!drflac__read_and_seek_rice(pFlac, riceParam)) { + return false; + } + } + + return true; +} + +static bool drflac__decode_samples_with_residual__unencoded(drflac* pFlac, unsigned int count, unsigned char unencodedBitsPerSample, unsigned int order, int shift, const short* coefficients, int* pSamplesOut) +{ + assert(pFlac != NULL); + assert(count > 0); + assert(unencodedBitsPerSample > 0 && unencodedBitsPerSample <= 32); + assert(pSamplesOut != NULL); + + for (unsigned int i = 0; i < count; ++i) + { + if (!drflac__read_int32(pFlac, unencodedBitsPerSample, pSamplesOut + i)) { + return false; + } + + pSamplesOut[i] += drflac__calculate_prediction(order, shift, coefficients, pSamplesOut + i); + } + + return true; +} + + +// Reads and decodes the residual for the sub-frame the decoder is currently sitting on. This function should be called +// when the decoder is sitting at the very start of the RESIDUAL block. The first residuals will be ignored. The +// and parameters are used to determine how many residual values need to be decoded. +static bool drflac__decode_samples_with_residual(drflac* pFlac, unsigned int blockSize, unsigned int order, int shift, const short* coefficients, int* pDecodedSamples) +{ + assert(pFlac != NULL); + assert(blockSize != 0); + assert(pDecodedSamples != NULL); // <-- Should we allow NULL, in which case we just seek past the residual rather than do a full decode? + + unsigned char residualMethod; + if (!drflac__read_uint8(pFlac, 2, &residualMethod)) { + return false; + } + + if (residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE && residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) { + return false; // Unknown or unsupported residual coding method. + } + + // Ignore the first values. + pDecodedSamples += order; + + + unsigned char partitionOrder; + if (!drflac__read_uint8(pFlac, 4, &partitionOrder)) { + return false; + } + + + unsigned int samplesInPartition = (blockSize / (1 << partitionOrder)) - order; + unsigned int partitionsRemaining = (1 << partitionOrder); + for (;;) + { + unsigned char riceParam = 0; + if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE) { + if (!drflac__read_uint8(pFlac, 4, &riceParam)) { + return false; + } + if (riceParam == 16) { + riceParam = 0xFF; + } + } else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) { + if (!drflac__read_uint8(pFlac, 5, &riceParam)) { + return false; + } + if (riceParam == 32) { + riceParam = 0xFF; + } + } + + if (riceParam != 0xFF) { + if (!drflac__decode_samples_with_residual__rice(pFlac, samplesInPartition, riceParam, order, shift, coefficients, pDecodedSamples)) { + return false; + } + } else { + unsigned char unencodedBitsPerSample = 0; + if (!drflac__read_uint8(pFlac, 5, &unencodedBitsPerSample)) { + return false; + } + + if (!drflac__decode_samples_with_residual__unencoded(pFlac, samplesInPartition, unencodedBitsPerSample, order, shift, coefficients, pDecodedSamples)) { + return false; + } + } + + pDecodedSamples += samplesInPartition; + + + if (partitionsRemaining == 1) { + break; + } + + partitionsRemaining -= 1; + samplesInPartition = blockSize / (1 << partitionOrder); + } + + return true; +} + +// Reads and seeks past the residual for the sub-frame the decoder is currently sitting on. This function should be called +// when the decoder is sitting at the very start of the RESIDUAL block. The first residuals will be set to 0. The +// and parameters are used to determine how many residual values need to be decoded. +static bool drflac__read_and_seek_residual(drflac* pFlac, unsigned int blockSize, unsigned int order) +{ + assert(pFlac != NULL); + assert(blockSize != 0); + + unsigned char residualMethod; + if (!drflac__read_uint8(pFlac, 2, &residualMethod)) { + return false; + } + + if (residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE && residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) { + return false; // Unknown or unsupported residual coding method. + } + + unsigned char partitionOrder; + if (!drflac__read_uint8(pFlac, 4, &partitionOrder)) { + return false; + } + + unsigned int samplesInPartition = (blockSize / (1 << partitionOrder)) - order; + unsigned int partitionsRemaining = (1 << partitionOrder); + for (;;) + { + unsigned char riceParam = 0; + if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE) { + if (!drflac__read_uint8(pFlac, 4, &riceParam)) { + return false; + } + if (riceParam == 16) { + riceParam = 0xFF; + } + } else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) { + if (!drflac__read_uint8(pFlac, 5, &riceParam)) { + return false; + } + if (riceParam == 32) { + riceParam = 0xFF; + } + } + + if (riceParam != 0xFF) { + if (!drflac__read_and_seek_residual__rice(pFlac, samplesInPartition, riceParam)) { + return false; + } + } else { + unsigned char unencodedBitsPerSample = 0; + if (!drflac__read_uint8(pFlac, 5, &unencodedBitsPerSample)) { + return false; + } + + if (!drflac__seek_bits(pFlac, unencodedBitsPerSample * samplesInPartition)) { + return false; + } + } + + + if (partitionsRemaining == 1) { + break; + } + + partitionsRemaining -= 1; + samplesInPartition = blockSize / (1 << partitionOrder); + } + + return true; +} + + +static bool drflac__decode_samples__constant(drflac* pFlac, drflac_subframe* pSubframe) +{ + // Only a single sample needs to be decoded here. + int sample; + if (!drflac__read_int32(pFlac, pSubframe->bitsPerSample, &sample)) { + return false; + } + + // We don't really need to expand this, but it does simplify the process of reading samples. If this becomes a performance issue (unlikely) + // we'll want to look at a more efficient way. + for (unsigned int i = 0; i < pFlac->currentFrame.blockSize; ++i) { + pSubframe->pDecodedSamples[i] = sample; + } + + return true; +} + +static bool drflac__decode_samples__verbatim(drflac* pFlac, drflac_subframe* pSubframe) +{ + for (unsigned int i = 0; i < pFlac->currentFrame.blockSize; ++i) { + int sample; + if (!drflac__read_int32(pFlac, pSubframe->bitsPerSample, &sample)) { + return false; + } + + pSubframe->pDecodedSamples[i] = sample; + } + + return true; +} + +static bool drflac__decode_samples__fixed(drflac* pFlac, drflac_subframe* pSubframe) +{ + short lpcCoefficientsTable[5][4] = { + {0, 0, 0, 0}, + {1, 0, 0, 0}, + {2, -1, 0, 0}, + {3, -3, 1, 0}, + {4, -6, 4, -1} + }; + + // Warm up samples and coefficients. + for (unsigned int i = 0; i < pSubframe->lpcOrder; ++i) { + int sample; + if (!drflac__read_int32(pFlac, pSubframe->bitsPerSample, &sample)) { + return false; + } + + pSubframe->pDecodedSamples[i] = sample; + } + + + if (!drflac__decode_samples_with_residual(pFlac, pFlac->currentFrame.blockSize, pSubframe->lpcOrder, 0, lpcCoefficientsTable[pSubframe->lpcOrder], pSubframe->pDecodedSamples)) { + return false; + } + + return true; +} + +static bool drflac__decode_samples__lpc(drflac* pFlac, drflac_subframe* pSubframe) +{ + // Warm up samples. + for (unsigned int i = 0; i < pSubframe->lpcOrder; ++i) { + int sample; + if (!drflac__read_int32(pFlac, pSubframe->bitsPerSample, &sample)) { + return false; + } + + pSubframe->pDecodedSamples[i] = sample; + } + + unsigned char lpcPrecision; + if (!drflac__read_uint8(pFlac, 4, &lpcPrecision)) { + return false; + } + if (lpcPrecision == 15) { + return false; // Invalid. + } + lpcPrecision += 1; + + + signed char lpcShift; + if (!drflac__read_int8(pFlac, 5, &lpcShift)) { + return false; + } + + + short coefficients[32]; + for (unsigned int i = 0; i < pSubframe->lpcOrder; ++i) { + if (!drflac__read_int16(pFlac, lpcPrecision, coefficients + i)) { + return false; + } + } + + if (!drflac__decode_samples_with_residual(pFlac, pFlac->currentFrame.blockSize, pSubframe->lpcOrder, lpcShift, coefficients, pSubframe->pDecodedSamples)) { + return false; + } + + return true; +} + + +static bool drflac__read_next_frame_header(drflac* pFlac) +{ + assert(pFlac != NULL); + assert(pFlac->onRead != NULL); + + // At the moment the sync code is as a form of basic validation. The CRC is stored, but is unused at the moment. This + // should probably be handled better in the future. + + const int sampleRateTable[12] = {0, 88200, 176400, 192000, 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000}; + const uint8_t bitsPerSampleTable[8] = {0, 8, 12, (uint8_t)-1, 16, 20, 24, (uint8_t)-1}; // -1 = reserved. + + unsigned short syncCode = 0; + if (!drflac__read_uint16(pFlac, 14, &syncCode)) { + return false; + } + + if (syncCode != 0x3FFE) { + // TODO: Try and recover by attempting to seek to and read the next frame? + return false; + } + + unsigned char reserved; + if (!drflac__read_uint8(pFlac, 1, &reserved)) { + return false; + } + + unsigned char blockingStrategy = 0; + if (!drflac__read_uint8(pFlac, 1, &blockingStrategy)) { + return false; + } + + + + unsigned char blockSize = 0; + if (!drflac__read_uint8(pFlac, 4, &blockSize)) { + return false; + } + + unsigned char sampleRate = 0; + if (!drflac__read_uint8(pFlac, 4, &sampleRate)) { + return false; + } + + unsigned char channelAssignment = 0; + if (!drflac__read_uint8(pFlac, 4, &channelAssignment)) { + return false; + } + + unsigned char bitsPerSample = 0; + if (!drflac__read_uint8(pFlac, 3, &bitsPerSample)) { + return false; + } + + if (!drflac__read_uint8(pFlac, 1, &reserved)) { + return false; + } + + + unsigned char isVariableBlockSize = blockingStrategy == 1; + if (isVariableBlockSize) { + pFlac->currentFrame.frameNumber = 0; + if (!drflac__read_utf8_coded_number(pFlac, &pFlac->currentFrame.sampleNumber)) { + return false; + } + } else { + unsigned long long frameNumber = 0; + if (!drflac__read_utf8_coded_number(pFlac, &frameNumber)) { + return false; + } + pFlac->currentFrame.frameNumber = (unsigned int)frameNumber; // <-- Safe cast. + pFlac->currentFrame.sampleNumber = 0; + } + + + if (blockSize == 1) { + pFlac->currentFrame.blockSize = 192; + } else if (blockSize >= 2 && blockSize <= 5) { + pFlac->currentFrame.blockSize = 576 * (1 << (blockSize - 2)); + } else if (blockSize == 6) { + if (!drflac__read_uint16(pFlac, 8, &pFlac->currentFrame.blockSize)) { + return false; + } + pFlac->currentFrame.blockSize += 1; + } else if (blockSize == 7) { + if (!drflac__read_uint16(pFlac, 16, &pFlac->currentFrame.blockSize)) { + return false; + } + pFlac->currentFrame.blockSize += 1; + } else { + pFlac->currentFrame.blockSize = 256 * (1 << (blockSize - 8)); + } + + + if (sampleRate <= 11) { + pFlac->currentFrame.sampleRate = sampleRateTable[sampleRate]; + } else if (sampleRate == 12) { + if (!drflac__read_uint32(pFlac, 8, &pFlac->currentFrame.sampleRate)) { + return false; + } + pFlac->currentFrame.sampleRate *= 1000; + } else if (sampleRate == 13) { + if (!drflac__read_uint32(pFlac, 16, &pFlac->currentFrame.sampleRate)) { + return false; + } + } else if (sampleRate == 14) { + if (!drflac__read_uint32(pFlac, 16, &pFlac->currentFrame.sampleRate)) { + return false; + } + pFlac->currentFrame.sampleRate *= 10; + } else { + return false; // Invalid. + } + + + pFlac->currentFrame.channelAssignment = channelAssignment; + + pFlac->currentFrame.bitsPerSample = bitsPerSampleTable[bitsPerSample]; + if (pFlac->currentFrame.bitsPerSample == 0) { + pFlac->currentFrame.bitsPerSample = pFlac->bitsPerSample; + } + + if (drflac__read_uint8(pFlac, 8, &pFlac->currentFrame.crc8) != 1) { + return false; + } + + memset(pFlac->currentFrame.subframes, 0, sizeof(pFlac->currentFrame.subframes)); + + return true; +} + +static bool drflac__read_subframe_header(drflac* pFlac, drflac_subframe* pSubframe) +{ + unsigned char header; + if (!drflac__read_uint8(pFlac, 8, &header)) { + return false; + } + + // First bit should always be 0. + if ((header & 0x80) != 0) { + return false; + } + + int type = (header & 0x7E) >> 1; + if (type == 0) { + pSubframe->subframeType = DRFLAC_SUBFRAME_CONSTANT; + } else if (type == 1) { + pSubframe->subframeType = DRFLAC_SUBFRAME_VERBATIM; + } else { + if ((type & 0x20) != 0) { + pSubframe->subframeType = DRFLAC_SUBFRAME_LPC; + pSubframe->lpcOrder = (type & 0x1F) + 1; + } else if ((type & 0x08) != 0) { + pSubframe->subframeType = DRFLAC_SUBFRAME_FIXED; + pSubframe->lpcOrder = (type & 0x07); + if (pSubframe->lpcOrder > 4) { + pSubframe->subframeType = DRFLAC_SUBFRAME_RESERVED; + pSubframe->lpcOrder = 0; + } + } else { + pSubframe->subframeType = DRFLAC_SUBFRAME_RESERVED; + } + } + + if (pSubframe->subframeType == DRFLAC_SUBFRAME_RESERVED) { + return false; + } + + // Wasted bits per sample. + pSubframe->wastedBitsPerSample = 0; + if ((header & 0x01) == 1) { + unsigned int wastedBitsPerSample; + if (!drflac__seek_past_next_set_bit(pFlac, &wastedBitsPerSample)) { + return false; + } + pSubframe->wastedBitsPerSample = (unsigned char)wastedBitsPerSample + 1; + } + + return true; +} + +static bool drflac__decode_subframe(drflac* pFlac, int subframeIndex) +{ + assert(pFlac != NULL); + + drflac_subframe* pSubframe = pFlac->currentFrame.subframes + subframeIndex; + if (!drflac__read_subframe_header(pFlac, pSubframe)) { + return false; + } + + // Side channels require an extra bit per sample. Took a while to figure that one out... + pSubframe->bitsPerSample = pFlac->currentFrame.bitsPerSample; + if ((pFlac->currentFrame.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE || pFlac->currentFrame.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE) && subframeIndex == 1) { + pSubframe->bitsPerSample += 1; + } else if (pFlac->currentFrame.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE && subframeIndex == 0) { + pSubframe->bitsPerSample += 1; + } + + // Need to handle wasted bits per sample. + pSubframe->bitsPerSample -= pSubframe->wastedBitsPerSample; + pSubframe->pDecodedSamples = pFlac->pDecodedSamples + (pFlac->currentFrame.blockSize * subframeIndex); + + switch (pSubframe->subframeType) + { + case DRFLAC_SUBFRAME_CONSTANT: + { + drflac__decode_samples__constant(pFlac, pSubframe); + } break; + + case DRFLAC_SUBFRAME_VERBATIM: + { + drflac__decode_samples__verbatim(pFlac, pSubframe); + } break; + + case DRFLAC_SUBFRAME_FIXED: + { + drflac__decode_samples__fixed(pFlac, pSubframe); + } break; + + case DRFLAC_SUBFRAME_LPC: + { + drflac__decode_samples__lpc(pFlac, pSubframe); + } break; + + default: return false; + } + + return true; +} + +static bool drflac__seek_subframe(drflac* pFlac, int subframeIndex) +{ + assert(pFlac != NULL); + + drflac_subframe* pSubframe = pFlac->currentFrame.subframes + subframeIndex; + if (!drflac__read_subframe_header(pFlac, pSubframe)) { + return false; + } + + // Side channels require an extra bit per sample. Took a while to figure that one out... + pSubframe->bitsPerSample = pFlac->currentFrame.bitsPerSample; + if ((pFlac->currentFrame.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE || pFlac->currentFrame.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE) && subframeIndex == 1) { + pSubframe->bitsPerSample += 1; + } else if (pFlac->currentFrame.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE && subframeIndex == 0) { + pSubframe->bitsPerSample += 1; + } + + // Need to handle wasted bits per sample. + pSubframe->bitsPerSample -= pSubframe->wastedBitsPerSample; + pSubframe->pDecodedSamples = pFlac->pDecodedSamples + (pFlac->currentFrame.blockSize * subframeIndex); + + switch (pSubframe->subframeType) + { + case DRFLAC_SUBFRAME_CONSTANT: + { + if (!drflac__seek_bits(pFlac, pSubframe->bitsPerSample)) { + return false; + } + } break; + + case DRFLAC_SUBFRAME_VERBATIM: + { + unsigned int bitsToSeek = pFlac->currentFrame.blockSize * pSubframe->bitsPerSample; + if (!drflac__seek_bits(pFlac, bitsToSeek)) { + return false; + } + } break; + + case DRFLAC_SUBFRAME_FIXED: + { + unsigned int bitsToSeek = pSubframe->lpcOrder * pSubframe->bitsPerSample; + if (!drflac__seek_bits(pFlac, bitsToSeek)) { + return false; + } + + if (!drflac__read_and_seek_residual(pFlac, pFlac->currentFrame.blockSize, pSubframe->lpcOrder)) { + return false; + } + } break; + + case DRFLAC_SUBFRAME_LPC: + { + unsigned int bitsToSeek = pSubframe->lpcOrder * pSubframe->bitsPerSample; + if (!drflac__seek_bits(pFlac, bitsToSeek)) { + return false; + } + + unsigned char lpcPrecision; + if (!drflac__read_uint8(pFlac, 4, &lpcPrecision)) { + return false; + } + if (lpcPrecision == 15) { + return false; // Invalid. + } + lpcPrecision += 1; + + + bitsToSeek = (pSubframe->lpcOrder * lpcPrecision) + 5; // +5 for shift. + if (!drflac__seek_bits(pFlac, bitsToSeek)) { + return false; + } + + if (!drflac__read_and_seek_residual(pFlac, pFlac->currentFrame.blockSize, pSubframe->lpcOrder)) { + return false; + } + } break; + + default: return false; + } + + return true; +} + + +static DRFLAC_INLINE int drflac__get_channel_count_from_channel_assignment(int channelAssignment) +{ + assert(channelAssignment <= 10); + + int lookup[] = {1, 2, 3, 4, 5, 6, 7, 8, 2, 2, 2}; + return lookup[channelAssignment]; +} + +static bool drflac__decode_frame(drflac* pFlac) +{ + // This function should be called while the stream is sitting on the first byte after the frame header. + + int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.channelAssignment); + for (int i = 0; i < channelCount; ++i) + { + if (!drflac__decode_subframe(pFlac, i)) { + return false; + } + } + + // At the end of the frame sits the padding and CRC. We don't use these so we can just seek past. + if (!drflac__seek_bits(pFlac, (DRFLAC_CACHE_L1_BITS_REMAINING & 7) + 16)) { + return false; + } + + + pFlac->currentFrame.samplesRemaining = pFlac->currentFrame.blockSize * channelCount; + + return true; +} + +static bool drflac__seek_frame(drflac* pFlac) +{ + int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.channelAssignment); + for (int i = 0; i < channelCount; ++i) + { + if (!drflac__seek_subframe(pFlac, i)) { + return false; + } + } + + // Padding and CRC. + return drflac__seek_bits(pFlac, (DRFLAC_CACHE_L1_BITS_REMAINING & 7) + 16); +} + +static bool drflac__read_and_decode_next_frame(drflac* pFlac) +{ + assert(pFlac != NULL); + + if (!drflac__read_next_frame_header(pFlac)) { + return false; + } + + return drflac__decode_frame(pFlac); +} + +static unsigned int drflac__read_block_header(drflac* pFlac, unsigned int* pBlockSizeOut, bool* pIsLastBlockOut) // Returns the block type. +{ + assert(pFlac != NULL); + + unsigned char isLastBlock = 1; + unsigned char blockType = DRFLAC_BLOCK_TYPE_INVALID; + unsigned int blockSize = 0; + + if (!drflac__read_uint8(pFlac, 1, &isLastBlock)) { + goto done_reading_block_header; + } + + if (!drflac__read_uint8(pFlac, 7, &blockType)) { + goto done_reading_block_header; + } + + if (!drflac__read_uint32(pFlac, 24, &blockSize)) { + goto done_reading_block_header; + } + + +done_reading_block_header: + if (pBlockSizeOut) { + *pBlockSizeOut = blockSize; + } + + if (pIsLastBlockOut) { + *pIsLastBlockOut = (isLastBlock != 0); + } + + return blockType; +} + + +static void drflac__get_current_frame_sample_range(drflac* pFlac, uint64_t* pFirstSampleInFrameOut, uint64_t* pLastSampleInFrameOut) +{ + assert(pFlac != NULL); + + unsigned int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.channelAssignment); + + uint64_t firstSampleInFrame = pFlac->currentFrame.sampleNumber; + if (firstSampleInFrame == 0) { + firstSampleInFrame = pFlac->currentFrame.frameNumber * pFlac->maxBlockSize*channelCount; + } + + uint64_t lastSampleInFrame = firstSampleInFrame + (pFlac->currentFrame.blockSize*channelCount); + if (lastSampleInFrame > 0) { + lastSampleInFrame -= 1; // Needs to be zero based. + } + + + if (pFirstSampleInFrameOut) { + *pFirstSampleInFrameOut = firstSampleInFrame; + } + if (pLastSampleInFrameOut) { + *pLastSampleInFrameOut = lastSampleInFrame; + } +} + +static bool drflac__seek_to_first_frame(drflac* pFlac) +{ + assert(pFlac != NULL); + + bool result = drflac__seek_to_byte(pFlac, (long long)pFlac->firstFramePos); + pFlac->consumedBits = DRFLAC_CACHE_L1_SIZE_BITS; + pFlac->cache = 0; + + memset(&pFlac->currentFrame, 0, sizeof(pFlac->currentFrame)); + + + return result; +} + +static DRFLAC_INLINE bool drflac__seek_to_next_frame(drflac* pFlac) +{ + // This function should only ever be called while the decoder is sitting on the first byte past the FRAME_HEADER section. + assert(pFlac != NULL); + return drflac__seek_frame(pFlac); +} + +static bool drflac__seek_to_frame_containing_sample(drflac* pFlac, uint64_t sampleIndex) +{ + assert(pFlac != NULL); + + if (!drflac__seek_to_first_frame(pFlac)) { + return false; + } + + uint64_t firstSampleInFrame = 0; + uint64_t lastSampleInFrame = 0; + for (;;) + { + // We need to read the frame's header in order to determine the range of samples it contains. + if (!drflac__read_next_frame_header(pFlac)) { + return false; + } + + drflac__get_current_frame_sample_range(pFlac, &firstSampleInFrame, &lastSampleInFrame); + if (sampleIndex >= firstSampleInFrame && sampleIndex <= lastSampleInFrame) { + break; // The sample is in this frame. + } + + if (!drflac__seek_to_next_frame(pFlac)) { + return false; + } + } + + // If we get here we should be right at the start of the frame containing the sample. + return true; +} + +static bool drflac__seek_to_sample__brute_force(drflac* pFlac, uint64_t sampleIndex) +{ + if (!drflac__seek_to_frame_containing_sample(pFlac, sampleIndex)) { + return false; + } + + // At this point we should be sitting on the first byte of the frame containing the sample. We need to decode every sample up to (but + // not including) the sample we're seeking to. + uint64_t firstSampleInFrame = 0; + drflac__get_current_frame_sample_range(pFlac, &firstSampleInFrame, NULL); + + assert(firstSampleInFrame <= sampleIndex); + size_t samplesToDecode = (size_t)(sampleIndex - firstSampleInFrame); // <-- Safe cast because the maximum number of samples in a frame is 65535. + if (samplesToDecode == 0) { + return true; + } + + // At this point we are just sitting on the byte after the frame header. We need to decode the frame before reading anything from it. + if (!drflac__decode_frame(pFlac)) { + return false; + } + + return (drflac_read_s16(pFlac, samplesToDecode, NULL) != 0); +} + +static bool drflac__seek_to_sample__seek_table(drflac* pFlac, uint64_t sampleIndex) +{ + assert(pFlac != NULL); + + if (pFlac->seektableBlock.pos == 0) { + return false; + } + + if (!drflac__seek_to_byte(pFlac, pFlac->seektableBlock.pos)) { + return false; + } + + // The number of seek points is derived from the size of the SEEKTABLE block. + unsigned int seekpointCount = pFlac->seektableBlock.sizeInBytes / 18; // 18 = the size of each seek point. + if (seekpointCount == 0) { + return false; // Would this ever happen? + } + + + drflac_seekpoint closestSeekpoint = {0}; + + unsigned int seekpointsRemaining = seekpointCount; + while (seekpointsRemaining > 0) + { + drflac_seekpoint seekpoint; + if (!drflac__read_uint64(pFlac, 64, &seekpoint.firstSample)) { + break; + } + if (!drflac__read_uint64(pFlac, 64, &seekpoint.frameOffset)) { + break; + } + if (!drflac__read_uint16(pFlac, 16, &seekpoint.sampleCount)) { + break; + } + + if (seekpoint.firstSample * pFlac->channels > sampleIndex) { + break; + } + + closestSeekpoint = seekpoint; + seekpointsRemaining -= 1; + } + + // At this point we should have found the seekpoint closest to our sample. We need to seek to it using basically the same + // technique as we use with the brute force method. + drflac__seek_to_byte(pFlac, pFlac->firstFramePos + closestSeekpoint.frameOffset); + + uint64_t firstSampleInFrame = 0; + uint64_t lastSampleInFrame = 0; + for (;;) + { + // We need to read the frame's header in order to determine the range of samples it contains. + if (!drflac__read_next_frame_header(pFlac)) { + return false; + } + + drflac__get_current_frame_sample_range(pFlac, &firstSampleInFrame, &lastSampleInFrame); + if (sampleIndex >= firstSampleInFrame && sampleIndex <= lastSampleInFrame) { + break; // The sample is in this frame. + } + + if (!drflac__seek_to_next_frame(pFlac)) { + return false; + } + } + + assert(firstSampleInFrame <= sampleIndex); + + // At this point we are just sitting on the byte after the frame header. We need to decode the frame before reading anything from it. + if (!drflac__decode_frame(pFlac)) { + return false; + } + + size_t samplesToDecode = (size_t)(sampleIndex - firstSampleInFrame); // <-- Safe cast because the maximum number of samples in a frame is 65535. + return drflac_read_s16(pFlac, samplesToDecode, NULL) == samplesToDecode; +} + + +static drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData) +{ + if (onRead == NULL || onSeek == NULL) { + return NULL; + } + + unsigned char id[4]; + if (onRead(pUserData, id, 4) != 4 || id[0] != 'f' || id[1] != 'L' || id[2] != 'a' || id[3] != 'C') { + return NULL; // Not a FLAC stream. + } + + drflac tempFlac; + memset(&tempFlac, 0, sizeof(tempFlac)); + tempFlac.onRead = onRead; + tempFlac.onSeek = onSeek; + tempFlac.pUserData = pUserData; + tempFlac.currentBytePos = 4; + tempFlac.nextL2Line = sizeof(tempFlac.cacheL2) / sizeof(tempFlac.cacheL2[0]); // <-- Initialize to this to force a client-side data retrieval right from the start. + tempFlac.consumedBits = sizeof(tempFlac.cache)*8; + + // The first metadata block should be the STREAMINFO block. We don't care about everything in here. + unsigned int blockSize; + bool isLastBlock; + int blockType = drflac__read_block_header(&tempFlac, &blockSize, &isLastBlock); + if (blockType != DRFLAC_BLOCK_TYPE_STREAMINFO && blockSize != 34) { + return NULL; + } + + if (!drflac__seek_bits(&tempFlac, 16)) { // minBlockSize + return NULL; + } + if (!drflac__read_uint16(&tempFlac, 16, &tempFlac.maxBlockSize)) { + return NULL; + } + if (!drflac__seek_bits(&tempFlac, 48)) { // minFrameSize + maxFrameSize + return NULL; + } + if (!drflac__read_uint32(&tempFlac, 20, &tempFlac.sampleRate)) { + return NULL; + } + if (!drflac__read_uint8(&tempFlac, 3, &tempFlac.channels)) { + return NULL; + } + if (!drflac__read_uint8(&tempFlac, 5, &tempFlac.bitsPerSample)) { + return NULL; + } + if (!drflac__read_uint64(&tempFlac, 36, &tempFlac.totalSampleCount)) { + return NULL; + } + if (!drflac__seek_bits(&tempFlac, 128)) { // MD5 + return NULL; + } + + tempFlac.channels += 1; + tempFlac.bitsPerSample += 1; + tempFlac.totalSampleCount *= tempFlac.channels; + + while (!isLastBlock) + { + blockType = drflac__read_block_header(&tempFlac, &blockSize, &isLastBlock); + + switch (blockType) + { + case DRFLAC_BLOCK_TYPE_APPLICATION: + { + tempFlac.applicationBlock.pos = drflac__tell(&tempFlac); + tempFlac.applicationBlock.sizeInBytes = blockSize; + } break; + + case DRFLAC_BLOCK_TYPE_SEEKTABLE: + { + tempFlac.seektableBlock.pos = drflac__tell(&tempFlac); + tempFlac.seektableBlock.sizeInBytes = blockSize; + } break; + + case DRFLAC_BLOCK_TYPE_VORBIS_COMMENT: + { + tempFlac.vorbisCommentBlock.pos = drflac__tell(&tempFlac); + tempFlac.vorbisCommentBlock.sizeInBytes = blockSize; + } break; + + case DRFLAC_BLOCK_TYPE_CUESHEET: + { + tempFlac.cuesheetBlock.pos = drflac__tell(&tempFlac); + tempFlac.cuesheetBlock.sizeInBytes = blockSize; + } break; + + case DRFLAC_BLOCK_TYPE_PICTURE: + { + tempFlac.pictureBlock.pos = drflac__tell(&tempFlac); + tempFlac.pictureBlock.sizeInBytes = blockSize; + } break; + + + // These blocks we either don't care about or aren't supporting. + case DRFLAC_BLOCK_TYPE_PADDING: + case DRFLAC_BLOCK_TYPE_INVALID: + default: break; + } + + if (!drflac__seek_bits(&tempFlac, blockSize*8)) { + return NULL; + } + } + + + // At this point we should be sitting right at the start of the very first frame. + tempFlac.firstFramePos = drflac__tell(&tempFlac); + + drflac* pFlac = (drflac*)malloc(sizeof(*pFlac) - sizeof(pFlac->pExtraData) + (tempFlac.maxBlockSize * tempFlac.channels * sizeof(int32_t))); + memcpy(pFlac, &tempFlac, sizeof(tempFlac) - sizeof(pFlac->pExtraData)); + pFlac->pDecodedSamples = (int32_t*)pFlac->pExtraData; + + return pFlac; +} + +static void drflac_close(drflac* pFlac) +{ + if (pFlac == NULL) { + return; + } + +#ifndef DR_FLAC_NO_STDIO + // If we opened the file with drflac_open_file() we will want to close the file handle. We can know whether or not drflac_open_file() + // was used by looking at the callbacks. + if (pFlac->onRead == drflac__on_read_stdio) { +#if defined(DR_OPUS_NO_WIN32_IO) || !defined(_WIN32) + fclose((FILE*)pFlac->pUserData); +#else + CloseHandle((HANDLE)pFlac->pUserData); +#endif + } +#endif + + // If we opened the file with drflac_open_memory() we will want to free() the user data. + if (pFlac->onRead == drflac__on_read_memory) { + free(pFlac->pUserData); + } + + free(pFlac); +} + +static uint64_t drflac__read_s16__misaligned(drflac* pFlac, uint64_t samplesToRead, int16_t* bufferOut) +{ + unsigned int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.channelAssignment); + + // We should never be calling this when the number of samples to read is >= the sample count. + assert(samplesToRead < channelCount); + assert(pFlac->currentFrame.samplesRemaining > 0 && samplesToRead <= pFlac->currentFrame.samplesRemaining); + + + uint64_t samplesRead = 0; + while (samplesToRead > 0) + { + uint64_t totalSamplesInFrame = pFlac->currentFrame.blockSize * channelCount; + uint64_t samplesReadFromFrameSoFar = totalSamplesInFrame - pFlac->currentFrame.samplesRemaining; + unsigned int channelIndex = samplesReadFromFrameSoFar % channelCount; + + unsigned long long nextSampleInFrame = samplesReadFromFrameSoFar / channelCount; + + int decodedSample = 0; + switch (pFlac->currentFrame.channelAssignment) + { + case DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE: + { + if (channelIndex == 0) { + decodedSample = pFlac->currentFrame.subframes[channelIndex].pDecodedSamples[nextSampleInFrame]; + } else { + int side = pFlac->currentFrame.subframes[channelIndex + 0].pDecodedSamples[nextSampleInFrame]; + int left = pFlac->currentFrame.subframes[channelIndex - 1].pDecodedSamples[nextSampleInFrame]; + decodedSample = left - side; + } + + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE: + { + if (channelIndex == 0) { + int side = pFlac->currentFrame.subframes[channelIndex + 0].pDecodedSamples[nextSampleInFrame]; + int right = pFlac->currentFrame.subframes[channelIndex + 1].pDecodedSamples[nextSampleInFrame]; + decodedSample = side + right; + } else { + decodedSample = pFlac->currentFrame.subframes[channelIndex].pDecodedSamples[nextSampleInFrame]; + } + + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE: + { + int mid; + int side; + if (channelIndex == 0) { + mid = pFlac->currentFrame.subframes[channelIndex + 0].pDecodedSamples[nextSampleInFrame]; + side = pFlac->currentFrame.subframes[channelIndex + 1].pDecodedSamples[nextSampleInFrame]; + + mid = (((unsigned int)mid) << 1) | (side & 0x01); + decodedSample = (mid + side) >> 1; + } else { + mid = pFlac->currentFrame.subframes[channelIndex - 1].pDecodedSamples[nextSampleInFrame]; + side = pFlac->currentFrame.subframes[channelIndex + 0].pDecodedSamples[nextSampleInFrame]; + + mid = (((unsigned int)mid) << 1) | (side & 0x01); + decodedSample = (mid - side) >> 1; + } + + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT: + default: + { + decodedSample = pFlac->currentFrame.subframes[channelIndex].pDecodedSamples[nextSampleInFrame]; + } break; + } + + int shift = (16 - pFlac->bitsPerSample) + pFlac->currentFrame.subframes[channelIndex].wastedBitsPerSample; + if (shift >= 0) { + decodedSample <<= shift; + } else { + decodedSample >>= -shift; + } + + if (bufferOut) { + *bufferOut++ = decodedSample; + } + + samplesRead += 1; + pFlac->currentFrame.samplesRemaining -= 1; + samplesToRead -= 1; + } + + return samplesRead; +} + +static uint64_t drflac__seek_forward_by_samples(drflac* pFlac, uint64_t samplesToRead) +{ + uint64_t samplesRead = 0; + while (samplesToRead > 0) + { + if (pFlac->currentFrame.samplesRemaining == 0) + { + if (!drflac__read_and_decode_next_frame(pFlac)) { + break; // Couldn't read the next frame, so just break from the loop and return. + } + } + else + { + samplesRead += 1; + pFlac->currentFrame.samplesRemaining -= 1; + samplesToRead -= 1; + } + } + + return samplesRead; +} + +static uint64_t drflac_read_s16(drflac* pFlac, uint64_t samplesToRead, int16_t* bufferOut) +{ + // Note that is allowed to be null, in which case this will be treated as something like a seek. + if (pFlac == NULL || samplesToRead == 0) { + return 0; + } + + if (bufferOut == NULL) { + return drflac__seek_forward_by_samples(pFlac, samplesToRead); + } + + + uint64_t samplesRead = 0; + while (samplesToRead > 0) + { + // If we've run out of samples in this frame, go to the next. + if (pFlac->currentFrame.samplesRemaining == 0) + { + if (!drflac__read_and_decode_next_frame(pFlac)) { + break; // Couldn't read the next frame, so just break from the loop and return. + } + } + else + { + // Here is where we grab the samples and interleave them. + + unsigned int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFrame.channelAssignment); + uint64_t totalSamplesInFrame = pFlac->currentFrame.blockSize * channelCount; + uint64_t samplesReadFromFrameSoFar = totalSamplesInFrame - pFlac->currentFrame.samplesRemaining; + + int misalignedSampleCount = samplesReadFromFrameSoFar % channelCount; + if (misalignedSampleCount > 0) { + uint64_t misalignedSamplesRead = drflac__read_s16__misaligned(pFlac, misalignedSampleCount, bufferOut); + samplesRead += misalignedSamplesRead; + samplesReadFromFrameSoFar += misalignedSamplesRead; + bufferOut += misalignedSamplesRead; + samplesToRead -= misalignedSamplesRead; + } + + + uint64_t alignedSampleCountPerChannel = samplesToRead / channelCount; + if (alignedSampleCountPerChannel > pFlac->currentFrame.samplesRemaining / channelCount) { + alignedSampleCountPerChannel = pFlac->currentFrame.samplesRemaining / channelCount; + } + + uint64_t firstAlignedSampleInFrame = samplesReadFromFrameSoFar / channelCount; + int unusedBitsPerSample = 16 - pFlac->bitsPerSample; + + if (unusedBitsPerSample >= 0) { + int lshift0 = unusedBitsPerSample + pFlac->currentFrame.subframes[0].wastedBitsPerSample; + int lshift1 = unusedBitsPerSample + pFlac->currentFrame.subframes[1].wastedBitsPerSample; + + switch (pFlac->currentFrame.channelAssignment) + { + case DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE: + { + const int* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const int* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (uint64_t i = 0; i < alignedSampleCountPerChannel; ++i) { + int left = pDecodedSamples0[i]; + int side = pDecodedSamples1[i]; + int right = left - side; + + bufferOut[i*2+0] = left << lshift0; + bufferOut[i*2+1] = right << lshift1; + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE: + { + const int* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const int* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (uint64_t i = 0; i < alignedSampleCountPerChannel; ++i) { + int side = pDecodedSamples0[i]; + int right = pDecodedSamples1[i]; + int left = right + side; + + bufferOut[i*2+0] = left << lshift0; + bufferOut[i*2+1] = right << lshift1; + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE: + { + const int* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const int* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (uint64_t i = 0; i < alignedSampleCountPerChannel; ++i) { + int side = pDecodedSamples1[i]; + int mid = (((uint32_t)pDecodedSamples0[i]) << 1) | (side & 0x01); + + bufferOut[i*2+0] = ((mid + side) >> 1) << lshift0; + bufferOut[i*2+1] = ((mid - side) >> 1) << lshift1; + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT: + default: + { + if (pFlac->currentFrame.channelAssignment == 1) // 1 = Stereo + { + // Stereo optimized inner loop unroll. + const int* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const int* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (uint64_t i = 0; i < alignedSampleCountPerChannel; ++i) { + bufferOut[i*2+0] = pDecodedSamples0[i] << lshift0; + bufferOut[i*2+1] = pDecodedSamples1[i] << lshift1; + } + } + else + { + // Generic interleaving. + for (uint64_t i = 0; i < alignedSampleCountPerChannel; ++i) { + for (unsigned int j = 0; j < channelCount; ++j) { + bufferOut[(i*channelCount)+j] = (pFlac->currentFrame.subframes[j].pDecodedSamples[firstAlignedSampleInFrame + i]) << (unusedBitsPerSample + pFlac->currentFrame.subframes[j].wastedBitsPerSample); + } + } + } + } break; + } + } else { + int rshift0 = -unusedBitsPerSample + pFlac->currentFrame.subframes[0].wastedBitsPerSample; + int rshift1 = -unusedBitsPerSample + pFlac->currentFrame.subframes[1].wastedBitsPerSample; + + switch (pFlac->currentFrame.channelAssignment) + { + case DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE: + { + const int* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const int* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (uint64_t i = 0; i < alignedSampleCountPerChannel; ++i) { + int left = pDecodedSamples0[i]; + int side = pDecodedSamples1[i]; + int right = left - side; + + bufferOut[i*2+0] = left >> rshift0; + bufferOut[i*2+1] = right >> rshift1; + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE: + { + const int* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const int* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (uint64_t i = 0; i < alignedSampleCountPerChannel; ++i) { + int side = pDecodedSamples0[i]; + int right = pDecodedSamples1[i]; + int left = right + side; + + bufferOut[i*2+0] = left >> rshift0; + bufferOut[i*2+1] = right >> rshift1; + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE: + { + const int* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const int* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (uint64_t i = 0; i < alignedSampleCountPerChannel; ++i) { + int side = pDecodedSamples1[i]; + int mid = (((uint32_t)pDecodedSamples0[i]) << 1) | (side & 0x01); + + bufferOut[i*2+0] = ((mid + side) >> 1) >> rshift0; + bufferOut[i*2+1] = ((mid - side) >> 1) >> rshift1; + } + } break; + + case DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT: + default: + { + if (pFlac->currentFrame.channelAssignment == 1) // 1 = Stereo + { + // Stereo optimized inner loop unroll. + const int* pDecodedSamples0 = pFlac->currentFrame.subframes[0].pDecodedSamples + firstAlignedSampleInFrame; + const int* pDecodedSamples1 = pFlac->currentFrame.subframes[1].pDecodedSamples + firstAlignedSampleInFrame; + + for (uint64_t i = 0; i < alignedSampleCountPerChannel; ++i) { + bufferOut[i*2+0] = pDecodedSamples0[i] >> rshift0; + bufferOut[i*2+1] = pDecodedSamples1[i] >> rshift1; + } + } + else + { + // Generic interleaving. + for (uint64_t i = 0; i < alignedSampleCountPerChannel; ++i) { + for (unsigned int j = 0; j < channelCount; ++j) { + bufferOut[(i*channelCount)+j] = (pFlac->currentFrame.subframes[j].pDecodedSamples[firstAlignedSampleInFrame + i]) >> (pFlac->currentFrame.subframes[j].wastedBitsPerSample - unusedBitsPerSample); + } + } + } + } break; + } + } + + uint64_t alignedSamplesRead = alignedSampleCountPerChannel * channelCount; + samplesRead += alignedSamplesRead; + samplesReadFromFrameSoFar += alignedSamplesRead; + bufferOut += alignedSamplesRead; + samplesToRead -= alignedSamplesRead; + pFlac->currentFrame.samplesRemaining -= (unsigned int)alignedSamplesRead; + + + + // At this point we may still have some excess samples left to read. + if (samplesToRead > 0 && pFlac->currentFrame.samplesRemaining > 0) + { + uint64_t excessSamplesRead = 0; + if (samplesToRead < pFlac->currentFrame.samplesRemaining) { + excessSamplesRead = drflac__read_s16__misaligned(pFlac, samplesToRead, bufferOut); + } else { + excessSamplesRead = drflac__read_s16__misaligned(pFlac, pFlac->currentFrame.samplesRemaining, bufferOut); + } + + samplesRead += excessSamplesRead; + samplesReadFromFrameSoFar += excessSamplesRead; + bufferOut += excessSamplesRead; + samplesToRead -= excessSamplesRead; + } + } + } + + return samplesRead; +} + +static bool drflac_seek_to_sample(drflac* pFlac, uint64_t sampleIndex) +{ + if (pFlac == NULL) { + return false; + } + + if (sampleIndex == 0) { + return drflac__seek_to_first_frame(pFlac); + } + + // Clamp the sample to the end. + if (sampleIndex >= pFlac->totalSampleCount) { + sampleIndex = pFlac->totalSampleCount - 1; + } + + + // First try seeking via the seek table. If this fails, fall back to a brute force seek which is much slower. + if (!drflac__seek_to_sample__seek_table(pFlac, sampleIndex)) { + return drflac__seek_to_sample__brute_force(pFlac, sampleIndex); + } + + return true; +} + + +#endif //DR_FLAC_IMPLEMENTATION + + +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ diff --git a/panda/src/movies/flacAudio.I b/panda/src/movies/flacAudio.I new file mode 100644 index 0000000000..0c4a8926db --- /dev/null +++ b/panda/src/movies/flacAudio.I @@ -0,0 +1,12 @@ +/** + * 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 flacAudio.I + * @author rdb + * @date 2016-04-27 + */ diff --git a/panda/src/movies/flacAudio.cxx b/panda/src/movies/flacAudio.cxx new file mode 100644 index 0000000000..8bfbd56ad2 --- /dev/null +++ b/panda/src/movies/flacAudio.cxx @@ -0,0 +1,64 @@ +/** + * 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 flacAudio.cxx + * @author rdb + * @date 2016-04-27 + */ + +#include "flacAudio.h" +#include "flacAudioCursor.h" +#include "virtualFileSystem.h" +#include "dcast.h" + +TypeHandle FlacAudio::_type_handle; + +/** + * xxx + */ +FlacAudio:: +FlacAudio(const Filename &name) : + MovieAudio(name) +{ + _filename = name; +} + +/** + * xxx + */ +FlacAudio:: +~FlacAudio() { +} + +/** + * Open this audio, returning a MovieAudioCursor + */ +PT(MovieAudioCursor) FlacAudio:: +open() { + VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); + istream *stream = vfs->open_read_file(_filename, true); + + if (stream == NULL) { + return NULL; + } else { + PT(FlacAudioCursor) cursor = new FlacAudioCursor(this, stream); + if (cursor == NULL || !cursor->_is_valid) { + return NULL; + } else { + return DCAST(MovieAudioCursor, cursor); + } + } +} + +/** + * Obtains a MovieAudio that references a file. + */ +PT(MovieAudio) FlacAudio:: +make(const Filename &name) { + return DCAST(MovieAudio, new FlacAudio(name)); +} diff --git a/panda/src/movies/flacAudio.h b/panda/src/movies/flacAudio.h new file mode 100644 index 0000000000..4fb9818930 --- /dev/null +++ b/panda/src/movies/flacAudio.h @@ -0,0 +1,54 @@ +/** + * 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 flacAudio.h + * @author rdb + * @date 2016-04-27 + */ + +#ifndef FLACAUDIO_H +#define FLACAUDIO_H + +#include "pandabase.h" +#include "movieAudio.h" + +class FlacAudioCursor; + +/** + * Reads FLAC audio files. Ogg-encapsulated FLAC files are not supported. + */ +class EXPCL_PANDA_MOVIES FlacAudio : public MovieAudio { +PUBLISHED: + FlacAudio(const Filename &name); + virtual ~FlacAudio(); + virtual PT(MovieAudioCursor) open(); + + static PT(MovieAudio) make(const Filename &name); + +private: + friend class FlacAudioCursor; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + MovieAudio::init_type(); + register_type(_type_handle, "FlacAudio", + MovieAudio::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#endif // FLACAUDIO_H diff --git a/panda/src/movies/flacAudioCursor.I b/panda/src/movies/flacAudioCursor.I new file mode 100644 index 0000000000..c01b9a80fa --- /dev/null +++ b/panda/src/movies/flacAudioCursor.I @@ -0,0 +1,12 @@ +/** + * 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 vorbisAudioCursor.I + * @author rdb + * @date 2013-08-23 + */ diff --git a/panda/src/movies/flacAudioCursor.cxx b/panda/src/movies/flacAudioCursor.cxx new file mode 100644 index 0000000000..3ea294c7ce --- /dev/null +++ b/panda/src/movies/flacAudioCursor.cxx @@ -0,0 +1,120 @@ +/** + * 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 flacAudioCursor.cxx + * @author rdb + * @date 2013-08-23 + */ + +#include "flacAudioCursor.h" +#include "virtualFileSystem.h" + +#define DR_FLAC_IMPLEMENTATION +#define DR_FLAC_NO_STDIO +extern "C" { + #include "dr_flac.h" +} + +/** + * Callback passed to dr_flac to implement file I/O via the VirtualFileSystem. + */ +static size_t cb_read_proc(void *user, void *buffer, size_t size) { + istream *stream = (istream *)user; + nassertr(stream != NULL, false); + + stream->read((char *)buffer, size); + + if (stream->eof()) { + // Gracefully handle EOF. + stream->clear(); + } + + return stream->gcount(); +} + +/** + * Callback passed to dr_flac to implement file I/O via the VirtualFileSystem. + */ +static bool cb_seek_proc(void *user, int offset) { + istream *stream = (istream *)user; + nassertr(stream != NULL, false); + + stream->seekg(offset, ios::cur); + return !stream->fail(); +} + +TypeHandle FlacAudioCursor::_type_handle; + +/** + * Reads the .wav header from the indicated stream. This leaves the read + * pointer positioned at the start of the data. + */ +FlacAudioCursor:: +FlacAudioCursor(FlacAudio *src, istream *stream) : + MovieAudioCursor(src), + _is_valid(false), + _drflac(NULL) +{ + nassertv(stream != NULL); + nassertv(stream->good()); + + _drflac = drflac_open(&cb_read_proc, &cb_seek_proc, (void *)stream); + + if (_drflac == NULL) { + movies_cat.error() + << "Failed to open FLAC file.\n"; + _is_valid = false; + } + + _length = (_drflac->totalSampleCount / _drflac->channels) / (double)_drflac->sampleRate; + + _audio_channels = _drflac->channels; + _audio_rate = _drflac->sampleRate; + + _can_seek = true; + _can_seek_fast = _can_seek; + + _is_valid = true; +} + +/** + * xxx + */ +FlacAudioCursor:: +~FlacAudioCursor() { + if (_drflac != NULL) { + drflac_close(_drflac); + } +} + +/** + * Seeks to a target location. Afterward, the packet_time is guaranteed to be + * less than or equal to the specified time. + */ +void FlacAudioCursor:: +seek(double t) { + t = max(t, 0.0); + + uint64_t sample = t * _drflac->sampleRate; + + if (drflac_seek_to_sample(_drflac, sample * _drflac->channels)) { + _last_seek = sample / (double)_drflac->sampleRate; + _samples_read = 0; + } +} + +/** + * Read audio samples from the stream. N is the number of samples you wish to + * read. Your buffer must be equal in size to N * channels. Multiple-channel + * audio will be interleaved. + */ +void FlacAudioCursor:: +read_samples(int n, int16_t *data) { + int desired = n * _audio_channels; + _samples_read += drflac_read_s16(_drflac, desired, data) / _audio_channels; +} diff --git a/panda/src/movies/flacAudioCursor.h b/panda/src/movies/flacAudioCursor.h new file mode 100644 index 0000000000..4f68eb62a8 --- /dev/null +++ b/panda/src/movies/flacAudioCursor.h @@ -0,0 +1,65 @@ +/** + * 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 flacAudioCursor.h + * @author rdb + * @date 2013-08-23 + */ + +#ifndef FLACAUDIOCURSOR_H +#define FLACAUDIOCURSOR_H + +#include "pandabase.h" +#include "movieAudioCursor.h" + +#define DR_FLAC_NO_STDIO +extern "C" { + #include "dr_flac.h" +} + +class FlacAudio; + +/** + * Interfaces with the libvorbisfile library to implement decoding of Ogg + * Vorbis audio files. + */ +class EXPCL_PANDA_MOVIES FlacAudioCursor : public MovieAudioCursor { +PUBLISHED: + FlacAudioCursor(FlacAudio *src, istream *stream); + virtual ~FlacAudioCursor(); + virtual void seek(double offset); + +public: + virtual void read_samples(int n, int16_t *data); + + bool _is_valid; + +protected: + drflac *_drflac; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + MovieAudioCursor::init_type(); + register_type(_type_handle, "FlacAudioCursor", + MovieAudioCursor::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "flacAudioCursor.I" + +#endif // FLACAUDIOCURSOR_H diff --git a/panda/src/movies/microphoneAudio.h b/panda/src/movies/microphoneAudio.h index 2b617ce141..1b8e58bd03 100644 --- a/panda/src/movies/microphoneAudio.h +++ b/panda/src/movies/microphoneAudio.h @@ -34,6 +34,10 @@ class EXPCL_PANDA_MOVIES MicrophoneAudio : public MovieAudio { INLINE int get_channels() const; INLINE int get_rate() const; + MAKE_SEQ_PROPERTY(options, get_num_options, get_option); + MAKE_PROPERTY(channels, get_channels); + MAKE_PROPERTY(rate, get_rate); + virtual PT(MovieAudioCursor) open() = 0; public: diff --git a/panda/src/movies/microphoneAudioDS.cxx b/panda/src/movies/microphoneAudioDS.cxx index 6df15f1cfc..95412fb961 100644 --- a/panda/src/movies/microphoneAudioDS.cxx +++ b/panda/src/movies/microphoneAudioDS.cxx @@ -91,7 +91,7 @@ public: int _samples_per_buffer; public: - virtual void read_samples(int n, PN_int16 *data); + virtual void read_samples(int n, int16_t *data); virtual int ready() const; public: @@ -324,7 +324,7 @@ MicrophoneAudioCursorDS:: * */ void MicrophoneAudioCursorDS:: -read_samples(int n, PN_int16 *data) { +read_samples(int n, int16_t *data) { int orign = n; if (_handle) { while (1) { @@ -334,7 +334,7 @@ read_samples(int n, PN_int16 *data) { } // Find start of data in buffer. - PN_int16 *src = (PN_int16*)(_buffers[index]._storage); + int16_t *src = (int16_t*)(_buffers[index]._storage); src += (_offset * _audio_channels); // Decide how many samples to extract from this buffer. diff --git a/panda/src/movies/movieAudioCursor.I b/panda/src/movies/movieAudioCursor.I index adbb4dd7ba..64e14886fd 100644 --- a/panda/src/movies/movieAudioCursor.I +++ b/panda/src/movies/movieAudioCursor.I @@ -100,5 +100,5 @@ tell() const { */ INLINE void MovieAudioCursor:: skip_samples(int n) { - read_samples(n, (PN_int16*)0); + read_samples(n, (int16_t*)0); } diff --git a/panda/src/movies/movieAudioCursor.cxx b/panda/src/movies/movieAudioCursor.cxx index 2776dbe030..f386401103 100644 --- a/panda/src/movies/movieAudioCursor.cxx +++ b/panda/src/movies/movieAudioCursor.cxx @@ -46,7 +46,7 @@ MovieAudioCursor:: * audio will be interleaved. */ void MovieAudioCursor:: -read_samples(int n, PN_int16 *data) { +read_samples(int n, int16_t *data) { // This is the null implementation, which generates pure silence. Normally, // this method will be overridden by a subclass. @@ -71,7 +71,7 @@ read_samples(int n, PN_int16 *data) { */ void MovieAudioCursor:: read_samples(int n, Datagram *dg) { - PN_int16 tmp[4096]; + int16_t tmp[4096]; while (n > 0) { int blocksize = (4096 / _audio_channels); if (blocksize > n) blocksize = n; @@ -95,14 +95,14 @@ read_samples(int n, Datagram *dg) { string MovieAudioCursor:: read_samples(int n) { ostringstream result; - PN_int16 tmp[4096]; + int16_t tmp[4096]; while (n > 0) { int blocksize = (4096 / _audio_channels); if (blocksize > n) blocksize = n; int words = blocksize * _audio_channels; read_samples(blocksize, tmp); for (int i=0; i>8) & 255)); } diff --git a/panda/src/movies/movieAudioCursor.h b/panda/src/movies/movieAudioCursor.h index 731bc28f98..8d49c26ccf 100644 --- a/panda/src/movies/movieAudioCursor.h +++ b/panda/src/movies/movieAudioCursor.h @@ -51,7 +51,7 @@ PUBLISHED: string read_samples(int n); public: - virtual void read_samples(int n, PN_int16 *data); + virtual void read_samples(int n, int16_t *data); protected: PT(MovieAudio) _source; @@ -62,7 +62,7 @@ protected: bool _can_seek_fast; bool _aborted; double _last_seek; - PN_int64 _samples_read; + int64_t _samples_read; public: static TypeHandle get_class_type() { diff --git a/panda/src/movies/p3movies_composite1.cxx b/panda/src/movies/p3movies_composite1.cxx index ecb10339a6..ea526c30b1 100644 --- a/panda/src/movies/p3movies_composite1.cxx +++ b/panda/src/movies/p3movies_composite1.cxx @@ -1,4 +1,6 @@ #include "config_movies.cxx" +#include "flacAudio.cxx" +#include "flacAudioCursor.cxx" #include "inkblotVideo.cxx" #include "inkblotVideoCursor.cxx" #include "microphoneAudio.cxx" diff --git a/panda/src/movies/userDataAudio.cxx b/panda/src/movies/userDataAudio.cxx index ca71806f31..7575ad977b 100644 --- a/panda/src/movies/userDataAudio.cxx +++ b/panda/src/movies/userDataAudio.cxx @@ -58,7 +58,7 @@ open() { * audio will be interleaved. */ void UserDataAudio:: -read_samples(int n, PN_int16 *data) { +read_samples(int n, int16_t *data) { int ready = (_data.size() / _desired_channels); int desired = n * _desired_channels; int avail = ready * _desired_channels; @@ -78,7 +78,7 @@ read_samples(int n, PN_int16 *data) { * Appends audio samples to the buffer. */ void UserDataAudio:: -append(PN_int16 *data, int n) { +append(int16_t *data, int n) { nassertv(!_aborted); int words = n * _desired_channels; for (int i=0; i _data; + pdeque _data; bool _aborted; bool _remove_after_read; friend class UserDataAudioCursor; diff --git a/panda/src/movies/userDataAudioCursor.cxx b/panda/src/movies/userDataAudioCursor.cxx index d882195b2f..e0494cf53e 100644 --- a/panda/src/movies/userDataAudioCursor.cxx +++ b/panda/src/movies/userDataAudioCursor.cxx @@ -48,7 +48,7 @@ UserDataAudioCursor:: * audio will be interleaved. */ void UserDataAudioCursor:: -read_samples(int n, PN_int16 *data) { +read_samples(int n, int16_t *data) { UserDataAudio *source = (UserDataAudio*)(MovieAudio*)_source; if(source->_remove_after_read) { diff --git a/panda/src/movies/userDataAudioCursor.h b/panda/src/movies/userDataAudioCursor.h index 4c2ad96bb1..5e0d75b85f 100644 --- a/panda/src/movies/userDataAudioCursor.h +++ b/panda/src/movies/userDataAudioCursor.h @@ -33,7 +33,7 @@ PUBLISHED: virtual ~UserDataAudioCursor(); public: - virtual void read_samples(int n, PN_int16 *data); + virtual void read_samples(int n, int16_t *data); virtual int ready() const; virtual void seek(double offset); diff --git a/panda/src/movies/vorbisAudioCursor.cxx b/panda/src/movies/vorbisAudioCursor.cxx index d006c1878d..9d751629c2 100644 --- a/panda/src/movies/vorbisAudioCursor.cxx +++ b/panda/src/movies/vorbisAudioCursor.cxx @@ -109,7 +109,7 @@ seek(double t) { * audio will be interleaved. */ void VorbisAudioCursor:: -read_samples(int n, PN_int16 *data) { +read_samples(int n, int16_t *data) { int desired = n * _audio_channels; char *buffer = (char*) data; diff --git a/panda/src/movies/vorbisAudioCursor.h b/panda/src/movies/vorbisAudioCursor.h index 177b0a0fe4..2d16368dde 100644 --- a/panda/src/movies/vorbisAudioCursor.h +++ b/panda/src/movies/vorbisAudioCursor.h @@ -35,7 +35,7 @@ PUBLISHED: virtual void seek(double offset); public: - virtual void read_samples(int n, PN_int16 *data); + virtual void read_samples(int n, int16_t *data); bool _is_valid; diff --git a/panda/src/movies/wavAudioCursor.cxx b/panda/src/movies/wavAudioCursor.cxx index 2742b41a9d..3b220749c4 100644 --- a/panda/src/movies/wavAudioCursor.cxx +++ b/panda/src/movies/wavAudioCursor.cxx @@ -17,7 +17,7 @@ #include "wavAudio.h" // Tables for decompressing mu-law and A-law wav files. -static PN_int16 mulaw_table[256] = { +static int16_t mulaw_table[256] = { -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956, -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764, -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412, @@ -52,7 +52,7 @@ static PN_int16 mulaw_table[256] = { 56, 48, 40, 32, 24, 16, 8, 0 }; -static PN_int16 alaw_table[256] = { +static int16_t alaw_table[256] = { -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, @@ -143,7 +143,7 @@ WavAudioCursor(WavAudio *src, istream *stream) : _block_align = _reader.get_uint16(); // We can round up to next multiple of 8. - PN_uint16 bps = _reader.get_uint16(); + uint16_t bps = _reader.get_uint16(); bps = (bps + 7) & 0xfff8; // How many bytes in this chunk we've read so far. @@ -324,7 +324,7 @@ seek(double t) { * audio will be interleaved. */ void WavAudioCursor:: -read_samples(int n, PN_int16 *data) { +read_samples(int n, int16_t *data) { int desired = n * _audio_channels; int read_samples = min(desired, ((int) (_data_size - _data_pos)) / _bytes_per_sample); @@ -359,7 +359,7 @@ read_samples(int n, PN_int16 *data) { } case 4: { // Downsample. - const PN_int32 scale_factor = 0x7fffffff / 0x7fff; + const int32_t scale_factor = 0x7fffffff / 0x7fff; for (int i = 0; i < read_samples; ++i) { data[i] = _reader.get_int32() / scale_factor; @@ -368,7 +368,7 @@ read_samples(int n, PN_int16 *data) { } case 8: { // Downsample. - const PN_int64 scale_factor = 0x7fffffffffffffffLL / 0x7fffLL; + const int64_t scale_factor = 0x7fffffffffffffffLL / 0x7fffLL; for (int i = 0; i < read_samples; ++i) { data[i] = _reader.get_int64() / scale_factor; @@ -386,13 +386,13 @@ read_samples(int n, PN_int16 *data) { switch (_bytes_per_sample) { case 4: for (int i = 0; i < read_samples; ++i) { - data[i] = (PN_int16) (_reader.get_float32() * 0x7fff); + data[i] = (int16_t) (_reader.get_float32() * 0x7fff); } break; case 8: for (int i = 0; i < read_samples; ++i) { - data[i] = (PN_int16) (_reader.get_float64() * 0x7fff); + data[i] = (int16_t) (_reader.get_float64() * 0x7fff); } break; diff --git a/panda/src/movies/wavAudioCursor.h b/panda/src/movies/wavAudioCursor.h index 316dffedd9..e03ee5bdde 100644 --- a/panda/src/movies/wavAudioCursor.h +++ b/panda/src/movies/wavAudioCursor.h @@ -31,7 +31,7 @@ PUBLISHED: virtual void seek(double offset); public: - virtual void read_samples(int n, PN_int16 *data); + virtual void read_samples(int n, int16_t *data); bool _is_valid; diff --git a/panda/src/nativenet/p3nativenet_composite1.cxx b/panda/src/nativenet/p3nativenet_composite1.cxx index 51ddce8a5f..1c842ac105 100644 --- a/panda/src/nativenet/p3nativenet_composite1.cxx +++ b/panda/src/nativenet/p3nativenet_composite1.cxx @@ -1,5 +1,6 @@ #include "config_nativenet.cxx" #include "buffered_datagramconnection.cxx" +#include "socket_address.cxx" #include "socket_ip.cxx" #include "socket_tcp.cxx" #include "socket_tcp_listen.cxx" diff --git a/panda/src/nativenet/socket_address.I b/panda/src/nativenet/socket_address.I index 6a20ced62c..cb36122c2a 100644 --- a/panda/src/nativenet/socket_address.I +++ b/panda/src/nativenet/socket_address.I @@ -11,42 +11,69 @@ * @date 2014-10-19 */ -/** - * Return a RAW sockaddr_in - */ -INLINE unsigned long Socket_Address:: -GetIPAddressRaw() const { - return _addr.sin_addr.s_addr; -} - /** * Constructor that lets us set a port value */ INLINE Socket_Address:: Socket_Address(unsigned short port) { - _addr.sin_family = AF_INET; - _addr.sin_addr.s_addr = INADDR_ANY; - _addr.sin_port = htons(port); + _addr4.sin_family = AF_INET; + _addr4.sin_addr.s_addr = INADDR_ANY; + _addr4.sin_port = htons(port); } /** * */ INLINE Socket_Address:: -Socket_Address(const Socket_Address &inaddr) { - _addr.sin_family = inaddr._addr.sin_family; - _addr.sin_addr.s_addr = inaddr._addr.sin_addr.s_addr; - _addr.sin_port = inaddr._addr.sin_port; +Socket_Address(const Socket_Address &inaddr) : + _storage(inaddr._storage) { } /** * */ INLINE Socket_Address:: -Socket_Address(const AddressType &inaddr) { - _addr.sin_family = inaddr.sin_family; - _addr.sin_addr.s_addr = inaddr.sin_addr.s_addr; - _addr.sin_port = inaddr.sin_port; +Socket_Address(const struct sockaddr &inaddr) { + if (inaddr.sa_family == AF_INET) { + _addr4 = (const sockaddr_in &)inaddr; + + } else if (inaddr.sa_family == AF_INET6) { + _addr6 = (const sockaddr_in6 &)inaddr; + + } else { + nassertv(false); + clear(); + } +} + +/** + * + */ +INLINE Socket_Address:: +Socket_Address(const struct sockaddr_in &inaddr) : + _addr4(inaddr) { +} + +/** + * + */ +INLINE Socket_Address:: +Socket_Address(const struct sockaddr_in6 &inaddr) : + _addr6(inaddr) { + + if (IN6_IS_ADDR_V4MAPPED(&_addr6.sin6_addr) != 0) { + // This is really an IPv4 address disguised as an IPv6 address. + _addr4.sin_family = AF_INET; + _addr4.sin_addr.s_addr = ((uint32_t *)&_addr6.sin6_addr)[3]; + } +} + +/** + * + */ +INLINE Socket_Address:: +Socket_Address(const struct sockaddr_storage &inaddr) : + _storage(inaddr) { } /** @@ -61,9 +88,24 @@ INLINE Socket_Address:: */ INLINE bool Socket_Address:: operator == (const Socket_Address &in) const { - return ((_addr.sin_family == in._addr.sin_family) && - (_addr.sin_addr.s_addr == in._addr.sin_addr.s_addr) && - (_addr.sin_port == in._addr.sin_port)); + if (_storage.ss_family != in._storage.ss_family) { + return false; + } + + if (_storage.ss_family == AF_INET) { + return _addr4.sin_port == in._addr4.sin_port && + _addr4.sin_addr.s_addr == in._addr4.sin_addr.s_addr; + + } else if (_storage.ss_family == AF_INET6) { + return _addr6.sin6_port != in._addr6.sin6_port && + memcmp((char *) &_addr6.sin6_addr, + (char *) &in._addr6.sin6_addr, + sizeof(_addr6.sin6_addr)) == 0; + } + + // Unsupported address family. + nassertr(false, false); + return false; } /** @@ -71,9 +113,7 @@ operator == (const Socket_Address &in) const { */ INLINE bool Socket_Address:: operator != (const Socket_Address &in) const { - return ((_addr.sin_family != in._addr.sin_family) || - (_addr.sin_addr.s_addr != in._addr.sin_addr.s_addr) || - (_addr.sin_port != in._addr.sin_port)); + return !operator ==(in); } /** @@ -81,9 +121,9 @@ operator != (const Socket_Address &in) const { */ INLINE bool Socket_Address:: set_broadcast(unsigned short port) { - _addr.sin_family = AF_INET; - _addr.sin_addr.s_addr = 0xffffffff; - _addr.sin_port = htons(port); + _addr4.sin_family = AF_INET; + _addr4.sin_addr.s_addr = 0xffffffff; + _addr4.sin_port = htons(port); return true; } @@ -92,9 +132,21 @@ set_broadcast(unsigned short port) { */ INLINE bool Socket_Address:: set_any_IP(unsigned short port) { - _addr.sin_family = AF_INET; - _addr.sin_addr.s_addr = INADDR_ANY; - _addr.sin_port = htons(port); + _addr4.sin_family = AF_INET; + _addr4.sin_addr.s_addr = INADDR_ANY; + _addr4.sin_port = htons(port); + return true; +} + +/** + * Set to any IPv6 address and a specified port. + */ +INLINE bool Socket_Address:: +set_any_IPv6(unsigned short port) { + _addr6.sin6_family = AF_INET6; + _addr6.sin6_addr = in6addr_any; + _addr6.sin6_port = htons(port); + _addr6.sin6_scope_id = 0; return true; } @@ -103,7 +155,7 @@ set_any_IP(unsigned short port) { */ INLINE bool Socket_Address:: set_port(unsigned short port) { - _addr.sin_port = htons(port); + _addr4.sin_port = htons(port); return true; } @@ -112,9 +164,18 @@ set_port(unsigned short port) { */ INLINE void Socket_Address:: clear() { - _addr.sin_family = AF_INET; - _addr.sin_addr.s_addr = INADDR_ANY; - _addr.sin_port = htons(0); + _addr4.sin_family = AF_INET; + _addr4.sin_addr.s_addr = INADDR_ANY; + _addr4.sin_port = htons(0); +} + +/** + * Returns AF_INET if this is an IPv4 address, or AF_INET6 if this is an IPv6 + * address. + */ +INLINE sa_family_t Socket_Address:: +get_family() const { + return _storage.ss_family; } /** @@ -122,83 +183,17 @@ clear() { */ INLINE unsigned short Socket_Address:: get_port() const { - return ntohs(_addr.sin_port); -} - -/** - * Return the IP address portion in dot notation string - */ -INLINE std::string Socket_Address:: -get_ip() const { - return std::string(inet_ntoa(_addr.sin_addr)); -} - -/** - * Return the ip address/port in dot notation string - */ -INLINE std::string Socket_Address:: -get_ip_port() const { - char buf1[100]; // 100 is more than enough for any ip address:port combo.. - sprintf(buf1, "%s:%d", inet_ntoa(_addr.sin_addr), get_port()); - return std::string(buf1); -} - -/** - * This function will take a port and string-based TCP address and initialize - * the address with this information. Returns true on success; on failure, it - * returns false and the address may be undefined. - */ -INLINE bool Socket_Address:: -set_host(const std::string &hostname, unsigned short port) { - struct hostent *hp = NULL; - - // hmm inet_addr does not resolve 255.255.255.255 on ME98 ?? * HACK * ?? - if (hostname == "255.255.255.255") { - return set_broadcast(port); - } - - - PN_uint32 addr = (PN_uint32)inet_addr(hostname.c_str()); - if (addr == INADDR_NONE) { - hp = gethostbyname(hostname.c_str()); - if (hp == NULL) { - return false; - } else { - memcpy(&_addr.sin_addr, hp->h_addr_list[0], (unsigned int) hp->h_length); - } - } else { - memcpy(&_addr.sin_addr, &addr, sizeof(addr)); - } - - _addr.sin_port = htons(port); - _addr.sin_family = AF_INET; - return true; + return ntohs(_addr4.sin_port); } /** * */ INLINE bool Socket_Address:: -set_host(const std::string &hostname) { - std::string::size_type pos = hostname.find(':'); - if (pos == std::string::npos) - return false; - - std::string host = hostname.substr(0, pos); - std::string port = hostname.substr(pos + 1, 100);; - - unsigned short port_dig = (unsigned short)atoi(port.c_str()); - return set_host(host, port_dig); -} - -/** - * - */ -INLINE bool Socket_Address:: -set_host(PN_uint32 in_hostname, unsigned short port) { - memcpy(&_addr.sin_addr, &in_hostname, sizeof(in_hostname)); - _addr.sin_port = htons(port); - _addr.sin_family = AF_INET; +set_host(uint32_t in_hostname, unsigned short port) { + memcpy(&_addr4.sin_addr, &in_hostname, sizeof(in_hostname)); + _addr4.sin_port = htons(port); + _addr4.sin_family = AF_INET; return true; } @@ -207,27 +202,61 @@ set_host(PN_uint32 in_hostname, unsigned short port) { */ INLINE bool Socket_Address:: operator < (const Socket_Address &in) const { - if (_addr.sin_port < in._addr.sin_port) + if (_storage.ss_family != in._storage.ss_family) { + return _storage.ss_family < in._storage.ss_family; + } + + if (_storage.ss_family == AF_INET) { + if (_addr4.sin_port != in._addr4.sin_port) { + return _addr4.sin_port < in._addr4.sin_port; + } + + return _addr4.sin_addr.s_addr < in._addr4.sin_addr.s_addr; + + } else if (_storage.ss_family == AF_INET6) { + if (_addr6.sin6_port != in._addr6.sin6_port) { + return _addr6.sin6_port < in._addr6.sin6_port; + } + + return IN6_ARE_ADDR_EQUAL(&_addr6.sin6_addr, &in._addr6.sin6_addr) != 0; + } + + // Unsupported address family. + nassertr(false, false); + return false; +} + +/** + * True if the address is zero. + */ +INLINE bool Socket_Address:: +is_any() const { + if (_storage.ss_family == AF_INET) { + return (_addr4.sin_addr.s_addr == 0); + + } else if (_storage.ss_family == AF_INET6) { + return IN6_IS_ADDR_UNSPECIFIED(&_addr6.sin6_addr) != 0; + + } else { return true; - - if (_addr.sin_port > in._addr.sin_port) - return false; - - if (_addr.sin_addr.s_addr < in._addr.sin_addr.s_addr) - return true; - - if (_addr.sin_addr.s_addr > in._addr.sin_addr.s_addr) - return false; - - return (_addr.sin_family < in._addr.sin_family); + } } /** * True if the address is in the multicast range. */ INLINE bool Socket_Address:: -is_mcast_range(void) const { - PN_uint32 address = ntohl(_addr.sin_addr.s_addr); - // 224.0.0.0-239.255.255.255 .. e0,ef - return (address >= 0xe0000000 && address < 0xefffffff); +is_mcast_range() const { + if (_storage.ss_family == AF_INET) { + uint32_t address = ntohl(_addr4.sin_addr.s_addr); + // 224.0.0.0-239.255.255.255 .. e0,ef + return (address >= 0xe0000000 && address < 0xefffffff); + + } else if (_storage.ss_family == AF_INET6) { + // ff00::/8 + return IN6_IS_ADDR_MULTICAST(&_addr6.sin6_addr) != 0; + + } else { + return false; + } } diff --git a/panda/src/nativenet/socket_address.cxx b/panda/src/nativenet/socket_address.cxx new file mode 100755 index 0000000000..cf27b0771c --- /dev/null +++ b/panda/src/nativenet/socket_address.cxx @@ -0,0 +1,157 @@ +/** + * 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 socket_address.h + * @author rdb + * @date 2016-06-17 + */ + +#include "socket_address.h" +#include "config_downloader.h" + +/** + * This function will take a port and string-based TCP address and initialize + * the address with this information. Returns true on success; on failure, it + * returns false and the address may be undefined. + */ +bool Socket_Address:: +set_host(const std::string &hostname, unsigned short port) { + // hmm inet_addr4 does not resolve 255.255.255.255 on ME98 ?? * HACK * ?? + if (hostname == "255.255.255.255") { + return set_broadcast(port); + } + + struct addrinfo hints, *res = NULL; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG; + hints.ai_family = support_ipv6 ? AF_UNSPEC : AF_INET; + + if (getaddrinfo(hostname.c_str(), NULL, &hints, &res)) { + return false; + } + + nassertr(res->ai_addrlen <= sizeof(_storage), false); + memcpy(&_storage, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + + _addr4.sin_port = htons(port); + return true; +} + +/** + * Initializes the address from a string specifying both the address and port, + * separated by a colon. An IPv6 address must be enclosed in brackets. + */ +bool Socket_Address:: +set_host(const std::string &hostname) { + std::string::size_type pos = hostname.rfind(':'); + if (pos == std::string::npos) { + return false; + } + + std::string::size_type host_begin = 0; + std::string::size_type host_end = pos; + + // Strip spaces. + while (host_begin < host_end && isspace(hostname[host_begin])) { + ++host_begin; + } + + while (host_begin < host_end && isspace(hostname[host_end - 1])) { + --host_end; + } + + if (host_begin < host_end && hostname[host_begin] == '[') { + // Looks like an IPv6 address; extract from the brackets. + host_begin += 1; + if (hostname[host_end - 1] == ']') { + host_end -= 1; + } else { + return false; + } + } + + std::string host = hostname.substr(host_begin, host_end - host_begin); + std::string port = hostname.substr(pos + 1, 100); + + unsigned short port_dig = (unsigned short)atoi(port.c_str()); + return set_host(host, port_dig); +} + +/** + * Return the IP address portion in dot notation string. + */ +std::string Socket_Address:: +get_ip() const { + char buf[48]; + buf[0] = 0; + + if (_storage.ss_family == AF_INET) { + getnameinfo(&_addr, sizeof(sockaddr_in), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST); + + } else if (_storage.ss_family == AF_INET6) { + getnameinfo(&_addr, sizeof(sockaddr_in6), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST); + + } else { + nassertr(false, std::string()); + } + + return std::string(buf); +} + +/** + * Return the ip address/port in dot notation string. If this is an IPv6 + * address, it will be enclosed in square brackets. + */ +std::string Socket_Address:: +get_ip_port() const { + char buf[100]; // 100 is more than enough for any ip address:port combo.. + buf[0] = 0; + + if (_storage.ss_family == AF_INET) { + getnameinfo(&_addr, sizeof(sockaddr_in), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST); + sprintf(buf + strlen(buf), ":%hu", get_port()); + + } else if (_storage.ss_family == AF_INET6) { + // Protect the IPv6 address within square brackets. + buf[0] = '['; + getnameinfo(&_addr, sizeof(sockaddr_in6), buf + 1, sizeof(buf) - 1, NULL, 0, NI_NUMERICHOST); + sprintf(buf + strlen(buf), "]:%hu", get_port()); + + } else { + nassertr(false, std::string()); + } + + return std::string(buf); +} + +/** + * Returns a raw 32-bit unsigned integer representing the IPv4 address. + * @deprecated Does not work with IPv6 addresses. + */ +unsigned long Socket_Address:: +GetIPAddressRaw() const { + if (_addr.sa_family == AF_INET) { + return _addr4.sin_addr.s_addr; + } + if (_addr.sa_family == AF_INET6) { + // Okay, if we got here, something probably went wrong, but let's see if + // we can offer a meaningful translation for mapped addresses. + uint32_t *parts = (uint32_t *)&_addr6.sin6_addr; + if (parts[0] == 0 && parts[1] == 0 && (parts[2] == 0 || parts[2] == htonl(0xffff))) { + if (parts[2] == 0 && parts[3] == htonl(1)) { + // Special exception for localhost. + return 0x1000007f; + } else { + return parts[3]; + } + } + } + nassert_raise("GetIPAddressRaw() can only be called on an IPv4 address"); + return 0; +} diff --git a/panda/src/nativenet/socket_address.h b/panda/src/nativenet/socket_address.h index a185238e1d..20046e3d24 100644 --- a/panda/src/nativenet/socket_address.h +++ b/panda/src/nativenet/socket_address.h @@ -11,7 +11,6 @@ * @date 2014-10-19 */ - #ifndef SOCKET_ADDRESS_H #define SOCKET_ADDRESS_H @@ -20,15 +19,17 @@ #include "socket_portable.h" /** - * A simple place to store and munipulate tcp and port address for + * A simple place to store and manipulate tcp and port address for * communication layer */ class EXPCL_PANDA_NATIVENET Socket_Address { public: - typedef struct sockaddr_in AddressType; - Socket_Address(const AddressType &inaddr); - AddressType &GetAddressInfo() { return _addr; } - const AddressType &GetAddressInfo() const { return _addr; } + INLINE Socket_Address(const struct sockaddr &inaddr); + INLINE Socket_Address(const struct sockaddr_in &inaddr); + INLINE Socket_Address(const struct sockaddr_in6 &inaddr); + INLINE Socket_Address(const struct sockaddr_storage &inaddr); + INLINE struct sockaddr &GetAddressInfo() { return _addr; } + INLINE const struct sockaddr &GetAddressInfo() const { return _addr; } PUBLISHED: INLINE Socket_Address(unsigned short port = 0); @@ -37,27 +38,35 @@ PUBLISHED: INLINE virtual ~Socket_Address(); INLINE bool set_any_IP(unsigned short port); + INLINE bool set_any_IPv6(unsigned short port); INLINE bool set_port(unsigned short port); INLINE bool set_broadcast(unsigned short port); - INLINE bool set_host(const std::string &hostname, unsigned short port) ; - INLINE bool set_host(const std::string &hostname) ; - INLINE bool set_host(unsigned int ip4adr, unsigned short port); + bool set_host(const std::string &hostname, unsigned short port); + bool set_host(const std::string &hostname); + INLINE bool set_host(uint32_t ip4addr, unsigned short port); INLINE void clear(); + INLINE sa_family_t get_family() const; INLINE unsigned short get_port() const; - INLINE std::string get_ip() const ; - INLINE std::string get_ip_port() const; - INLINE unsigned long GetIPAddressRaw() const; + std::string get_ip() const ; + std::string get_ip_port() const; + unsigned long GetIPAddressRaw() const; INLINE bool operator ==(const Socket_Address &in) const; INLINE bool operator !=(const Socket_Address &in) const; INLINE bool operator < (const Socket_Address &in) const; + INLINE bool is_any() const; INLINE bool is_mcast_range() const; private: - AddressType _addr; + union { + sockaddr _addr; + sockaddr_in _addr4; + sockaddr_in6 _addr6; + sockaddr_storage _storage; + }; }; #include "socket_address.I" diff --git a/panda/src/nativenet/socket_fdset.h b/panda/src/nativenet/socket_fdset.h index 3f3edc711a..45c990bf27 100644 --- a/panda/src/nativenet/socket_fdset.h +++ b/panda/src/nativenet/socket_fdset.h @@ -18,9 +18,9 @@ PUBLISHED: inline Socket_fdset(); inline void setForSocket(const Socket_IP &incon); inline bool IsSetFor(const Socket_IP &incon) const; - inline int WaitForRead(bool zeroFds, PN_uint32 sleep_time = 0xffffffff); - inline int WaitForWrite(bool zeroFds, PN_uint32 sleep_time = 0xffffffff); - inline int WaitForError(bool zeroFds, PN_uint32 sleep_time = 0xffffffff); + inline int WaitForRead(bool zeroFds, uint32_t sleep_time = 0xffffffff); + inline int WaitForWrite(bool zeroFds, uint32_t sleep_time = 0xffffffff); + inline int WaitForError(bool zeroFds, uint32_t sleep_time = 0xffffffff); inline int WaitForRead(bool zeroFds, const Time_Span & timeout); inline void clear(); @@ -86,7 +86,7 @@ inline bool Socket_fdset::IsSetFor(const Socket_IP & incon) const /** * */ -inline int Socket_fdset::WaitForRead(bool zeroFds, PN_uint32 sleep_time) +inline int Socket_fdset::WaitForRead(bool zeroFds, uint32_t sleep_time) { int retVal = 0; if (sleep_time == 0xffffffff) { @@ -139,7 +139,7 @@ inline void Socket_fdset::setForSocket(const Socket_IP &incon) * This is the function that will wait till one of the sockets is ready for * writing */ -inline int Socket_fdset::WaitForWrite(bool zeroFds, PN_uint32 sleep_time) +inline int Socket_fdset::WaitForWrite(bool zeroFds, uint32_t sleep_time) { int retVal = 0; if (sleep_time == 0xffffffff) @@ -164,7 +164,7 @@ inline int Socket_fdset::WaitForWrite(bool zeroFds, PN_uint32 sleep_time) * This is the function that will wait till one of the sockets is in error * state */ -inline int Socket_fdset::WaitForError(bool zeroFds, PN_uint32 sleep_time) +inline int Socket_fdset::WaitForError(bool zeroFds, uint32_t sleep_time) { int retVal = 0; if (sleep_time == 0xffffffff) diff --git a/panda/src/nativenet/socket_ip.h b/panda/src/nativenet/socket_ip.h index 9094dac03b..3c03db2b3b 100644 --- a/panda/src/nativenet/socket_ip.h +++ b/panda/src/nativenet/socket_ip.h @@ -5,6 +5,7 @@ #include "socket_portable.h" #include "socket_address.h" #include "typedObject.h" +#include "config_downloader.h" // forward declarations for friends... class Socket_TCP; @@ -35,6 +36,7 @@ PUBLISHED: inline int SetNonBlocking(); inline int SetBlocking(); inline bool SetReuseAddress(bool flag = true); + inline bool SetV6Only(bool flag); inline bool Active(); inline int SetRecvBufferSize(int size); inline void SetSocket(SOCKET ins); @@ -44,7 +46,6 @@ PUBLISHED: inline static int InitNetworkDriver() { return init_network(); }; -public: private: inline bool ErrorClose(); @@ -194,7 +195,7 @@ SetBlocking() { fcntl(_socket, F_SETFL, flags); return ALL_OK; #else - unsigned long val = 0; + unsigned long val = 0; unsigned lanswer = 0; lanswer = SOCKIOCTL(_socket, LOCAL_FL_SET, &val); if (lanswer != 0) { @@ -209,8 +210,21 @@ SetBlocking() { */ inline bool Socket_IP:: SetReuseAddress(bool flag) { - int bOption = flag; - if (setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&bOption, sizeof(bOption)) != 0) { + int value = flag; + if (setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&value, sizeof(value)) != 0) { + return false; + } + return true; +} + +/** + * Sets a flag indicating whether this IPv6 socket should operate in + * dual-stack mode or not. + */ +inline bool Socket_IP:: +SetV6Only(bool flag) { + int value = flag ? 1 : 0; + if (setsockopt(_socket, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&value, sizeof(value))) { return false; } return true; @@ -237,7 +251,7 @@ GetSocket() const { */ inline Socket_Address Socket_IP:: GetPeerName(void) const { - sockaddr_in name; + sockaddr_storage name; socklen_t name_len = sizeof(name); memset(&name, 0, name_len); diff --git a/panda/src/nativenet/socket_portable.h b/panda/src/nativenet/socket_portable.h index 2a80c735f3..d4bdd1fa98 100644 --- a/panda/src/nativenet/socket_portable.h +++ b/panda/src/nativenet/socket_portable.h @@ -6,10 +6,13 @@ const int ALL_OK = 0; const int BASIC_ERROR = -1; +#define SA_SIZEOF(addr) (((addr)->sa_family == AF_INET6) ? sizeof(sockaddr_in6) : sizeof(sockaddr_in)) + #if defined(CPPPARSER) // Interrogate doesn't need to parse any of this. typedef unsigned long SOCKET; +typedef unsigned short sa_family_t; /************************************************************************ * HP SOCKET LIBRARY STUFF @@ -46,91 +49,77 @@ typedef unsigned long SOCKET; /************************************************************************ * WINSOCK 32 bit STUFF ************************************************************************/ -#elif defined(WIN32) || defined(WIN32_VC) || defined(WIN64_VC) +#elif defined(_WIN32) #include #include +typedef u_short sa_family_t; -inline int DO_SELECT(SOCKET n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,struct timeval *timeout) -{ - return select((int) n, readfds, writefds, exceptfds,timeout); +inline int DO_SELECT(SOCKET n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { + return select((int)n, readfds, writefds, exceptfds, timeout); } -inline int DO_CONNECT( const SOCKET a, const struct sockaddr_in *b) -{ - return connect(a, reinterpret_cast(b), sizeof(sockaddr)); +inline int DO_CONNECT(const SOCKET a, const struct sockaddr *b) { + return connect(a, b, SA_SIZEOF(b)); } -inline int DO_SOCKET_READ(const SOCKET a, char * buf, const int size) -{ - return recv(a, buf, size, 0); +inline int DO_SOCKET_READ(const SOCKET a, char *buf, const int size) { + return recv(a, buf, size, 0); } -inline int DO_SOCKET_WRITE(const SOCKET a, const char * buff, const int len) -{ - return send(a, buff, len, 0); +inline int DO_SOCKET_WRITE(const SOCKET a, const char *buff, const int len) { + return send(a, buff, len, 0); } -inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char * buffer, const int buf_len, const sockaddr_in * addr) -{ - return sendto(a, buffer, buf_len, 0, reinterpret_cast(addr), sizeof(sockaddr)); +inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char *buffer, const int buf_len, const sockaddr *addr) { + return sendto(a, buffer, buf_len, 0, addr, SA_SIZEOF(addr)); } -inline SOCKET DO_NEWUDP() -{ - return socket(AF_INET, SOCK_DGRAM, 0); +inline SOCKET DO_NEWUDP(sa_family_t family) { + return socket(family, SOCK_DGRAM, 0); } -inline SOCKET DO_NEWTCP() -{ - return socket(AF_INET, SOCK_STREAM, 0); +inline SOCKET DO_NEWTCP(sa_family_t family) { + return socket(family, SOCK_STREAM, 0); } -inline int DO_BIND(const SOCKET a, const sockaddr_in *b) -{ - return ::bind(a, reinterpret_cast(b), sizeof(sockaddr)); +inline int DO_BIND(const SOCKET a, const sockaddr *b) { + return ::bind(a, b, SA_SIZEOF(b)); } -inline int DO_CLOSE(const SOCKET a) -{ - return closesocket(a); +inline int DO_CLOSE(const SOCKET a) { + return closesocket(a); } -inline SOCKET DO_ACCEPT(SOCKET sck, sockaddr_in * adr) -{ - int adrlen = sizeof(sockaddr); - return accept(sck, reinterpret_cast(adr), &adrlen); -}; -inline int DO_RECV_FROM(SOCKET sck, char * data, int len, sockaddr_in * addr) -{ - int plen = sizeof(sockaddr); - return recvfrom(sck, data, len, 0, reinterpret_cast(addr), &plen); +inline SOCKET DO_ACCEPT(SOCKET sck, sockaddr *addr) { + socklen_t addrlen = sizeof(sockaddr_storage); + return accept(sck, addr, &addrlen); } -inline int DO_LISTEN(const SOCKET a, const int size) -{ - return listen(a, size); +inline int DO_RECV_FROM(SOCKET sck, char *data, int len, sockaddr *addr) { + socklen_t plen = sizeof(sockaddr_storage); + return recvfrom(sck, data, len, 0, addr, &plen); +} +inline int DO_LISTEN(const SOCKET a, const int size) { + return listen(a, size); } -inline int GETERROR() -{ - return WSAGetLastError(); +inline int GETERROR() { + return WSAGetLastError(); } -inline int SOCKIOCTL(const SOCKET s, const long flags, unsigned long * val) -{ - return ioctlsocket(s, flags, val); +inline int SOCKIOCTL(const SOCKET s, const long flags, unsigned long *val) { + return ioctlsocket(s, flags, val); } -inline int init_network() -{ - static struct WSAData mydata; - int answer = WSAStartup(0x0101, &mydata); - if (answer != 0) - return BASIC_ERROR; +inline int init_network() { + static struct WSAData mydata; + int answer = WSAStartup(0x0101, &mydata); + if (answer != 0) { + return BASIC_ERROR; + } - return ALL_OK; + return ALL_OK; } -inline bool do_shutdown_send(SOCKET s) -{ - return (shutdown(s,SD_SEND) == 0); -}; +inline bool do_shutdown_send(SOCKET s) { + return (shutdown(s, SD_SEND) == 0); +} -typedef int socklen_t ; +typedef int socklen_t; const long LOCAL_NONBLOCK = 1; -const long LOCAL_FL_SET = FIONBIO ; +const long LOCAL_FL_SET = FIONBIO; const int LOCAL_BLOCKING_ERROR = WSAEWOULDBLOCK; const int LOCAL_CONNECT_BLOCKING = WSAEWOULDBLOCK; const int LOCAL_NOTCONNECTED_ERROR = WSAENOTCONN; @@ -162,84 +151,61 @@ const SOCKET BAD_SOCKET = (SOCKET)-1; typedef int SOCKET; const SOCKET BAD_SOCKET = 0xffffffff; -// #define DO_CONNECT(a,b) connect(a,(sockaddr -// *)b,sizeof(sockaddr)) #define DO_SOCKET_READ(a,b,c) recv(a,b,c,0) -// #define DO_SOCKET_WRITE(a,b,c) send(a,b,c,0) - -inline int DO_CONNECT(const SOCKET a, const sockaddr_in *b) -{ - return connect(a, reinterpret_cast(b), sizeof(sockaddr)); +inline int DO_CONNECT(const SOCKET a, const sockaddr *b) { + return connect(a, b, SA_SIZEOF(b)); } -inline int DO_SOCKET_READ(const SOCKET a, char * buf, const int size) -{ - return recv(a, buf, size, 0); +inline int DO_SOCKET_READ(const SOCKET a, char *buf, const int size) { + return recv(a, buf, size, 0); } -inline int DO_SOCKET_WRITE(const SOCKET a, const char * buff, const int len) -{ - return send(a, buff, len, 0); +inline int DO_SOCKET_WRITE(const SOCKET a, const char *buff, const int len) { + return send(a, buff, len, 0); } -// #define DO_SOCKET_WRITE_TO(a,b,c,d) sendto(a,b,c,0,(sockaddr -// *)d,sizeof(sockaddr)) #define DO_NEWUDP() socket(AF_INET, -// SOCK_DGRAM, 0) #define DO_NEWTCP() socket(AF_INET, SOCK_STREAM, 0) -// #define DO_BIND(a,b) ::bind(a,(sockaddr *)b,sizeof(sockaddr)) #define -// DO_CLOSE(a) close(a) -inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char * buffer, const int buf_len, const sockaddr_in * addr) -{ - return sendto(a, buffer, buf_len, 0, reinterpret_cast(addr), sizeof(sockaddr)); +inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char *buffer, const int buf_len, const sockaddr *addr) { + return sendto(a, buffer, buf_len, 0, addr, SA_SIZEOF(addr)); } -inline SOCKET DO_NEWUDP() -{ - return socket(AF_INET, SOCK_DGRAM, 0); +inline SOCKET DO_NEWUDP(sa_family_t family) { + return socket(family, SOCK_DGRAM, 0); } -inline SOCKET DO_NEWTCP() -{ - return socket(AF_INET, SOCK_STREAM, 0); +inline SOCKET DO_NEWTCP(sa_family_t family) { + return socket(family, SOCK_STREAM, 0); } -inline int DO_BIND(const SOCKET a, const sockaddr_in *b) -{ - return ::bind(a, reinterpret_cast(b), sizeof(sockaddr)); +inline int DO_BIND(const SOCKET a, const sockaddr *b) { + return ::bind(a, b, SA_SIZEOF(b)); } -inline int DO_CLOSE(const SOCKET a) -{ - return close(a); +inline int DO_CLOSE(const SOCKET a) { + return close(a); } -inline int DO_ACCEPT(SOCKET sck, sockaddr_in * adr) -{ - int adrlen = sizeof(sockaddr); - return accept(sck, ( sockaddr *)adr, &adrlen); -}; - -inline int DO_RECV_FROM(SOCKET sck, char * data, int len, sockaddr_in * addr) -{ - int plen = sizeof(sockaddr); - return recvfrom(sck, data, len, 0, (sockaddr *)addr, &plen); -} -inline int DO_LISTEN(const SOCKET a, const int size) -{ - return listen(a, size); +inline int DO_ACCEPT(SOCKET sck, sockaddr *addr) { + socklen_t addrlen = sizeof(sockaddr_storage); + return accept(sck, (sockaddr *)addr, &addrlen); } -inline int GETERROR() -{ - return errno; +inline int DO_RECV_FROM(SOCKET sck, char *data, int len, sockaddr *addr) { + socklen_t plen = sizeof(sockaddr_storage); + return recvfrom(sck, data, len, 0, (sockaddr *)addr, &plen); +} +inline int DO_LISTEN(const SOCKET a, const int size) { + return listen(a, size); } -inline int SOCKIOCTL(const SOCKET s, const long flags, void * val) -{ - return ioctl(s, flags, val); +inline int GETERROR() { + return errno; } -inline int init_network() -{ - return ALL_OK; +inline int SOCKIOCTL(const SOCKET s, const long flags, void *val) { + return ioctl(s, flags, val); +} + +inline int init_network() { + return ALL_OK; } #ifndef INADDR_NONE const INADDR_NONE = -1; #endif const long LOCAL_NONBLOCK = 1; -const long LOCAL_FL_SET = FIONBIO ; +const long LOCAL_FL_SET = FIONBIO; const int LOCAL_BLOCKING_ERROR = EAGAIN; const int LOCAL_CONNECT_BLOCKING = EINPROGRESS; @@ -267,94 +233,75 @@ const int LOCAL_CONNECT_BLOCKING = EINPROGRESS; #include #include -typedef struct sockaddr_in AddressType; - typedef int SOCKET; const SOCKET BAD_SOCKET = -1; -inline int DO_SELECT(SOCKET n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,struct timeval *timeout) -{ - return select((int) n, readfds, writefds, exceptfds,timeout); +inline int DO_SELECT(SOCKET n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { + return select((int)n, readfds, writefds, exceptfds, timeout); } -inline int DO_CONNECT(const SOCKET a, const sockaddr_in *b) -{ - return connect(a, reinterpret_cast(b), sizeof(sockaddr)); +inline int DO_CONNECT(const SOCKET a, const sockaddr *b) { + return connect(a, b, SA_SIZEOF(b)); } -inline int DO_SOCKET_READ(const SOCKET a, char * buf, const int size) -{ - return (int)recv(a, buf, (size_t)size, 0); +inline int DO_SOCKET_READ(const SOCKET a, char *buf, const int size) { + return (int)recv(a, buf, (size_t)size, 0); } -inline int DO_SOCKET_WRITE(const SOCKET a, const char * buff, const int len) -{ - return (int)send(a, buff, (size_t)len, 0); +inline int DO_SOCKET_WRITE(const SOCKET a, const char *buff, const int len) { + return (int)send(a, buff, (size_t)len, 0); } -inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char * buffer, const int buf_len, const sockaddr_in * addr) -{ - return (int)sendto(a, buffer, (size_t)buf_len, 0, reinterpret_cast(addr), sizeof(sockaddr)); +inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char *buffer, const int buf_len, const sockaddr *addr) { + return (int)sendto(a, buffer, (size_t)buf_len, 0, addr, SA_SIZEOF(addr)); } -inline SOCKET DO_NEWUDP() -{ - return socket(AF_INET, SOCK_DGRAM, 0); +inline SOCKET DO_NEWUDP(sa_family_t family) { + return socket(family, SOCK_DGRAM, 0); } -inline SOCKET DO_NEWTCP() -{ - return socket(AF_INET, SOCK_STREAM, 0); +inline SOCKET DO_NEWTCP(sa_family_t family) { + return socket(family, SOCK_STREAM, 0); } -inline int DO_BIND(const SOCKET a, const sockaddr_in *b) -{ - return ::bind(a, reinterpret_cast(b), sizeof(sockaddr)); +inline int DO_BIND(const SOCKET a, const sockaddr *b) { + return ::bind(a, b, SA_SIZEOF(b)); } -inline int DO_CLOSE(const SOCKET a) -{ - return close(a); +inline int DO_CLOSE(const SOCKET a) { + return close(a); } -inline int DO_ACCEPT(SOCKET sck, sockaddr_in * adr) -{ - socklen_t adrlen = sizeof(sockaddr); - return accept(sck, ( sockaddr *)adr, &adrlen); -}; +inline int DO_ACCEPT(SOCKET sck, sockaddr *addr) { + socklen_t addrlen = sizeof(sockaddr_storage); + return accept(sck, (sockaddr *)addr, &addrlen); +} -inline int DO_RECV_FROM(SOCKET sck, char * data, int len, sockaddr_in * addr) -{ - socklen_t plen = sizeof(sockaddr); - return (int)recvfrom(sck, data, (size_t)len, 0, (sockaddr *)addr, &plen); +inline int DO_RECV_FROM(SOCKET sck, char *data, int len, sockaddr *addr) { + socklen_t plen = sizeof(sockaddr_storage); + return (int)recvfrom(sck, data, (size_t)len, 0, (sockaddr *)addr, &plen); } -inline int init_network() -{ - signal(SIGPIPE, SIG_IGN); // hmm do i still need this ... - return ALL_OK; +inline int init_network() { + signal(SIGPIPE, SIG_IGN); // hmm do i still need this ... + return ALL_OK; } -inline int DO_LISTEN(const SOCKET a, const int size) -{ - return listen(a, size); +inline int DO_LISTEN(const SOCKET a, const int size) { + return listen(a, size); } -inline int GETERROR() -{ - return errno; +inline int GETERROR() { + return errno; } -inline int SOCKIOCTL(const SOCKET s, const long flags, void * val) -{ - return ioctl(s, (unsigned long)flags, val); +inline int SOCKIOCTL(const SOCKET s, const long flags, void *val) { + return ioctl(s, (unsigned long)flags, val); } -inline bool do_shutdown_send(SOCKET s) -{ - return (shutdown(s,SHUT_WR) == 0); -}; - +inline bool do_shutdown_send(SOCKET s) { + return (shutdown(s, SHUT_WR) == 0); +} #define BSDBLOCK const long LOCAL_NONBLOCK = 1; // With BSDBLOCK defined, we don't need FIONBIO. Solaris doesn't provide it. -// const long LOCAL_FL_SET = FIONBIO ; +// const long LOCAL_FL_SET = FIONBIO; const int LOCAL_BLOCKING_ERROR = EAGAIN; const int LOCAL_CONNECT_BLOCKING = EINPROGRESS; @@ -366,6 +313,4 @@ No Host Type defined !! #error Fatal #endif - - #endif //__SOCKET_PORTABLE_H__ diff --git a/panda/src/nativenet/socket_tcp.h b/panda/src/nativenet/socket_tcp.h index d1d0051d6a..62b624a0b1 100644 --- a/panda/src/nativenet/socket_tcp.h +++ b/panda/src/nativenet/socket_tcp.h @@ -8,30 +8,27 @@ * Base functionality for a TCP connected socket This class is pretty useless * by itself but it does hide some of the platform differences from machine to * machine - * */ -class EXPCL_PANDA_NATIVENET Socket_TCP : public Socket_IP -{ -public: +class EXPCL_PANDA_NATIVENET Socket_TCP : public Socket_IP { PUBLISHED: - inline Socket_TCP(SOCKET); - inline Socket_TCP() { }; - inline int SetNoDelay(bool flag = true); - inline int SetLinger(int interval_seconds = 0); - inline int DontLinger(); - inline int SetSendBufferSize(int insize); - // inline bool ActiveOpen(const Socket_Address & theaddress); - inline bool ActiveOpen(const Socket_Address & theaddress, bool setdelay); - inline bool ActiveOpenNonBlocking(const Socket_Address & theaddress); - inline bool ErrorIs_WouldBlocking(int err); - inline bool ShutdownSend(); - inline int SendData(const std::string &str); + inline Socket_TCP(SOCKET); + inline Socket_TCP() {}; + inline int SetNoDelay(bool flag = true); + inline int SetLinger(int interval_seconds = 0); + inline int DontLinger(); + inline int SetSendBufferSize(int insize); + // inline bool ActiveOpen(const Socket_Address &theaddress); + inline bool ActiveOpen(const Socket_Address &theaddress, bool setdelay); + inline bool ActiveOpenNonBlocking(const Socket_Address &theaddress); + inline bool ErrorIs_WouldBlocking(int err); + inline bool ShutdownSend(); + inline int SendData(const std::string &str); // inline int RecvData( std::string &str, int max_len); - std::string RecvData(int max_len); + std::string RecvData(int max_len); public: - inline int SendData(const char * data, int size); - inline int RecvData(char * data, int size); + inline int SendData(const char *data, int size); + inline int RecvData(char *data, int size); public: static TypeHandle get_class_type() { @@ -54,37 +51,35 @@ private: /** * */ -inline Socket_TCP::Socket_TCP(SOCKET sck) : ::Socket_IP(sck) -{ +inline Socket_TCP:: +Socket_TCP(SOCKET sck) : ::Socket_IP(sck) { } /** * Disable Nagle algorithm. Don't delay send to coalesce packets */ -inline int Socket_TCP::SetNoDelay(bool flag) -{ - int nodel = flag; - int ret1; - ret1 = setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char *) & nodel, sizeof(nodel)); - - if (ret1 != 0) - return BASIC_ERROR; - - return ALL_OK; +inline int Socket_TCP:: +SetNoDelay(bool flag) { + int value = flag ? 1 : 0; + if (setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (const char *)&value, sizeof(value))) { + return BASIC_ERROR; + } + return ALL_OK; } /** * will control the behavior of SO_LINGER for a TCP socket */ -int Socket_TCP::SetLinger(int interval_seconds) -{ - linger ll; - ll.l_linger = interval_seconds; - ll.l_onoff = 1; - int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger)); - if (ret1 != 0) - return BASIC_ERROR; - return ALL_OK; +int Socket_TCP:: +SetLinger(int interval_seconds) { + linger ll; + ll.l_linger = interval_seconds; + ll.l_onoff = 1; + int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *)&ll, sizeof(linger)); + if (ret1 != 0) { + return BASIC_ERROR; + } + return ALL_OK; } /** @@ -92,45 +87,50 @@ int Socket_TCP::SetLinger(int interval_seconds) * and free up OS resources. You may lose a stream if you use this flag and * do not negotiate the close at the application layer. */ -int Socket_TCP::DontLinger() -{ - linger ll; - ll.l_linger = 0; - ll.l_onoff = 0; - int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger)); - if (ret1 != 0) - return BASIC_ERROR; - return ALL_OK; +int Socket_TCP:: +DontLinger() { + linger ll; + ll.l_linger = 0; + ll.l_onoff = 0; + int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *)&ll, sizeof(linger)); + if (ret1 != 0) { + return BASIC_ERROR; + } + return ALL_OK; } /** * Just like it sounds. Sets a buffered socket recv buffer size. This * function does not refuse ranges outside hard-coded OS limits */ -int Socket_TCP::SetSendBufferSize(int insize) -{ - if (setsockopt(_socket, (int) SOL_SOCKET, (int) SO_SNDBUF, (char *) &insize, sizeof(int))) - return BASIC_ERROR; - return ALL_OK; +int Socket_TCP:: +SetSendBufferSize(int insize) { + if (setsockopt(_socket, SOL_SOCKET, SO_SNDBUF, (char *)&insize, sizeof(int))) { + return BASIC_ERROR; + } + return ALL_OK; } /** * This function will try and set the socket up for active open to a specified * address and port provided by the input parameter */ -bool Socket_TCP::ActiveOpen(const Socket_Address & theaddress, bool setdelay) -{ - _socket = DO_NEWTCP(); - if (_socket == BAD_SOCKET) - return false; +bool Socket_TCP:: +ActiveOpen(const Socket_Address &theaddress, bool setdelay) { + _socket = DO_NEWTCP(theaddress.get_family()); + if (_socket == BAD_SOCKET) { + return false; + } - if(setdelay) - SetNoDelay(); + if (setdelay) { + SetNoDelay(); + } - if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) - return ErrorClose(); + if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) { + return ErrorClose(); + } - return true; + return true; } @@ -138,85 +138,87 @@ bool Socket_TCP::ActiveOpen(const Socket_Address & theaddress, bool setdelay) * This function will try and set the socket up for active open to a specified * address and port provided by the input parameter (non-blocking version) */ -bool Socket_TCP::ActiveOpenNonBlocking(const Socket_Address & theaddress) -{ - _socket = DO_NEWTCP(); - if (_socket == BAD_SOCKET) - return false; +bool Socket_TCP:: +ActiveOpenNonBlocking(const Socket_Address &theaddress) { + _socket = DO_NEWTCP(theaddress.get_family()); + if (_socket == BAD_SOCKET) { + return false; + } - SetNonBlocking(); - SetReuseAddress(); + SetNonBlocking(); + SetReuseAddress(); - if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) { - if (GETERROR() != LOCAL_CONNECT_BLOCKING) - { - printf(" None Blockign Connect Error %d",GETERROR()); - return ErrorClose(); - } + if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) { + if (GETERROR() != LOCAL_CONNECT_BLOCKING) { + printf("Non Blocking Connect Error %d", GETERROR()); + return ErrorClose(); } + } - return true; + return true; } /** * Ok Lets Send the Data - if error 0 if socket closed for write or lengh is 0 * + bytes writen ( May be smaller than requested) */ -inline int Socket_TCP::SendData(const char * data, int size) -{ - return DO_SOCKET_WRITE(_socket, data, size); +inline int Socket_TCP:: +SendData(const char *data, int size) { + return DO_SOCKET_WRITE(_socket, data, size); } /** * Read the data from the connection - if error 0 if socket closed for read or * length is 0 + bytes read ( May be smaller than requested) */ -inline int Socket_TCP::RecvData(char * data, int len) -{ - int ecode = DO_SOCKET_READ(_socket, data, len); - return ecode; +inline int Socket_TCP:: +RecvData(char *data, int len) { + int ecode = DO_SOCKET_READ(_socket, data, len); + return ecode; } /** * Read the data from the connection - if error 0 if socket closed for read or - * length is 0 + bytes read ( May be smaller than requested) + * length is 0 + bytes read (May be smaller than requested) */ -inline std::string Socket_TCP::RecvData(int max_len) -{ - std::string str; - char *buffer = (char *) malloc(max_len+1); - int ecode = RecvData(buffer,max_len); - if(ecode > 0) - str.assign(buffer,ecode); +inline std::string Socket_TCP:: +RecvData(int max_len) { + std::string str; + char *buffer = (char *)malloc(max_len + 1); + int ecode = RecvData(buffer, max_len); + if (ecode > 0) { + str.assign(buffer, ecode); + } - free(buffer); - return str; -}; - - -inline bool Socket_TCP::ErrorIs_WouldBlocking(int err) -{ - return (GETERROR() == LOCAL_BLOCKING_ERROR); + free(buffer); + return str; } -inline bool Socket_TCP::ShutdownSend() -{ - return do_shutdown_send(_socket); -}; + +inline bool Socket_TCP:: +ErrorIs_WouldBlocking(int err) { + return (GETERROR() == LOCAL_BLOCKING_ERROR); +} + +inline bool Socket_TCP:: +ShutdownSend() { + return do_shutdown_send(_socket); +} /* -inline bool Socket_TCP::DoNotLinger() -{ - int bOption = 1; - if (setsockopt(_socket, SOL_SOCKET, SO_DONTLINGER, (const char *)&bOption, sizeof(bOption)) != 0) - return false; - return true; +inline bool Socket_TCP:: +DoNotLinger() { + int bOption = 1; + if (setsockopt(_socket, SOL_SOCKET, SO_DONTLINGER, (const char *)&bOption, sizeof(bOption)) != 0) { + return false; + } + return true; } */ -inline int Socket_TCP::SendData(const std::string &str) -{ - return SendData(str.data(), str.size()); -}; +inline int Socket_TCP:: +SendData(const std::string &str) { + return SendData(str.data(), str.size()); +} #endif //__SOCKET_TCP_H__ diff --git a/panda/src/nativenet/socket_tcp_listen.h b/panda/src/nativenet/socket_tcp_listen.h index 6091d5114d..7dc9115402 100644 --- a/panda/src/nativenet/socket_tcp_listen.h +++ b/panda/src/nativenet/socket_tcp_listen.h @@ -8,16 +8,17 @@ /** * Base functionality for a TCP rendezvous socket */ -class EXPCL_PANDA_NATIVENET Socket_TCP_Listen : public Socket_IP -{ +class EXPCL_PANDA_NATIVENET Socket_TCP_Listen : public Socket_IP { public: PUBLISHED: - Socket_TCP_Listen() {}; - ~Socket_TCP_Listen() {}; - inline bool OpenForListen(const Socket_Address & Inaddess, int backlog_size = 1024); - inline bool GetIncomingConnection(Socket_TCP & newsession, Socket_Address &address); + Socket_TCP_Listen() {}; + ~Socket_TCP_Listen() {}; + inline bool OpenForListen(unsigned short port, int backlog_size = 1024); + inline bool OpenForListen(const Socket_Address &address, int backlog_size = 1024); + inline bool GetIncomingConnection(Socket_TCP &newsession, Socket_Address &address); + public: - inline bool GetIncomingConnection(SOCKET & newsession, Socket_Address &address); + inline bool GetIncomingConnection(SOCKET &newsession, Socket_Address &address); public: static TypeHandle get_class_type() { @@ -40,43 +41,77 @@ private: /** * This function will initialize a listening Socket */ -inline bool Socket_TCP_Listen::OpenForListen(const Socket_Address & Inaddess, int backlog_size ) -{ - ErrorClose(); - _socket = DO_NEWTCP(); +inline bool Socket_TCP_Listen:: +OpenForListen(unsigned short port, int backlog_size) { + ErrorClose(); - SetReuseAddress(); + Socket_Address address; + if (support_ipv6) { + // Create a socket supporting both IPv4 and IPv6. + address.set_any_IPv6(port); + _socket = DO_NEWTCP(AF_INET6); + SetV6Only(false); + } else { + address.set_any_IP(port); + _socket = DO_NEWTCP(AF_INET); + } - if (DO_BIND(_socket, &Inaddess.GetAddressInfo()) != 0) { - return ErrorClose(); - } + SetReuseAddress(); - if (DO_LISTEN(_socket, backlog_size) != 0) { - return ErrorClose(); - } + if (DO_BIND(_socket, &address.GetAddressInfo()) != 0) { + return ErrorClose(); + } - return true; + if (DO_LISTEN(_socket, backlog_size) != 0) { + return ErrorClose(); + } + + return true; } + +/** + * This function will initialize a listening Socket + */ +inline bool Socket_TCP_Listen:: +OpenForListen(const Socket_Address &address, int backlog_size) { + ErrorClose(); + + _socket = DO_NEWTCP(address.get_family()); + + SetReuseAddress(); + + if (DO_BIND(_socket, &address.GetAddressInfo()) != 0) { + return ErrorClose(); + } + + if (DO_LISTEN(_socket, backlog_size) != 0) { + return ErrorClose(); + } + + return true; +} + /** * This function is used to accept new connections */ -inline bool Socket_TCP_Listen::GetIncomingConnection(SOCKET & newsession, Socket_Address &address) -{ - newsession = DO_ACCEPT(_socket, &address.GetAddressInfo()); - if (newsession == BAD_SOCKET) - return false; - return true; +inline bool Socket_TCP_Listen:: +GetIncomingConnection(SOCKET &newsession, Socket_Address &address) { + newsession = DO_ACCEPT(_socket, &address.GetAddressInfo()); + if (newsession == BAD_SOCKET) { + return false; + } + return true; } +inline bool Socket_TCP_Listen:: +GetIncomingConnection(Socket_TCP &newsession, Socket_Address &address) { + SOCKET sck; + if (!GetIncomingConnection(sck, address)) { + return false; + } -inline bool Socket_TCP_Listen::GetIncomingConnection(Socket_TCP & newsession, Socket_Address &address) -{ - SOCKET sck; - if(!GetIncomingConnection(sck,address)) - return false; - - newsession.SetSocket(sck); - return true; + newsession.SetSocket(sck); + return true; } #endif //__SOCKET_TCP_LISTEN_H__ diff --git a/panda/src/nativenet/socket_tcp_ssl.h b/panda/src/nativenet/socket_tcp_ssl.h index e80e0d5647..83b45b4389 100644 --- a/panda/src/nativenet/socket_tcp_ssl.h +++ b/panda/src/nativenet/socket_tcp_ssl.h @@ -15,76 +15,64 @@ #include #include -/** - * - - * - */ - extern EXPCL_PANDA_NATIVENET SSL_CTX *global_ssl_ctx; +struct SSlStartup { + SSlStartup() { + const SSL_METHOD *meth; + SSLeay_add_ssl_algorithms(); + // meth = SSLv23_server_method(); + meth = SSLv23_method(); + SSL_load_error_strings(); + // I hate this cast, but older versions of OpenSSL need it. + global_ssl_ctx = SSL_CTX_new((SSL_METHOD *) meth); + } -struct SSlStartup -{ - SSlStartup() - { - const SSL_METHOD *meth; - SSLeay_add_ssl_algorithms(); - // meth = SSLv23_server_method(); - meth = SSLv23_method(); - SSL_load_error_strings(); - // I hate this cast, but older versions of OpenSSL need it. - global_ssl_ctx = SSL_CTX_new ((SSL_METHOD *) meth); - } + ~SSlStartup() { + SSL_CTX_free (global_ssl_ctx); + global_ssl_ctx = NULL; + } - ~SSlStartup() - { - SSL_CTX_free (global_ssl_ctx); - global_ssl_ctx = NULL; - } - - - bool isactive() { return global_ssl_ctx != NULL; }; + bool isactive() { return global_ssl_ctx != NULL; }; }; - -class EXPCL_PANDA_NATIVENET Socket_TCP_SSL : public Socket_IP -{ +/** + * + */ +class EXPCL_PANDA_NATIVENET Socket_TCP_SSL : public Socket_IP { public: + inline Socket_TCP_SSL(SOCKET); + inline Socket_TCP_SSL() : _ssl(NULL) {} - inline Socket_TCP_SSL(SOCKET); - inline Socket_TCP_SSL() : _ssl(NULL) {} + virtual inline ~Socket_TCP_SSL() + { + CleanSslUp(); + } - virtual inline ~Socket_TCP_SSL() - { - CleanSslUp(); - } + inline int SetNoDelay(); + inline int SetLinger(int interval_seconds = 0); + inline int DontLinger(); - inline int SetNoDelay(); - inline int SetLinger(int interval_seconds = 0); - inline int DontLinger(); + inline int SetSendBufferSize(int insize); + inline bool ActiveOpen(const Socket_Address &theaddress); + inline int SendData(const char *data, int size); + inline int RecvData(char *data, int size); + inline bool ErrorIs_WouldBlocking(int err); - inline int SetSendBufferSize(int insize); - inline bool ActiveOpen(const Socket_Address & theaddress); - inline int SendData(const char * data, int size); - inline int RecvData(char * data, int size); - inline bool ErrorIs_WouldBlocking(int err); + inline SSL *get_ssl() { return _ssl; }; - inline SSL * get_ssl() { return _ssl; }; + inline void DetailErrorFormat(void); - inline void DetailErrorFormat(void); private: - SSL* _ssl; + SSL *_ssl; - void CleanSslUp() - { - if(_ssl != NULL) - { - SSL_shutdown(_ssl); - SSL_free(_ssl); - _ssl = NULL; - } - } + void CleanSslUp() { + if (_ssl != NULL) { + SSL_shutdown(_ssl); + SSL_free(_ssl); + _ssl = NULL; + } + } public: static TypeHandle get_class_type() { @@ -128,30 +116,31 @@ Socket_TCP_SSL(SOCKET sck) : ::Socket_IP(sck) { /** * Disable Nagle algorithm. Don't delay send to coalesce packets */ -inline int Socket_TCP_SSL::SetNoDelay() -{ - int nodel = 1; - int ret1; - ret1 = setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char *) & nodel, sizeof(nodel)); +inline int Socket_TCP_SSL:: +SetNoDelay() { + int nodel = 1; + int ret1; + ret1 = setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char *)&nodel, sizeof(nodel)); - if (ret1 != 0) - return BASIC_ERROR; - - return ALL_OK; + if (ret1 != 0) { + return BASIC_ERROR; + } + return ALL_OK; } /** * will control the behavior of SO_LINGER for a TCP socket */ -int Socket_TCP_SSL::SetLinger(int interval_seconds) -{ - linger ll; - ll.l_linger = interval_seconds; - ll.l_onoff = 1; - int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger)); - if (ret1 != 0) - return BASIC_ERROR; - return ALL_OK; +int Socket_TCP_SSL:: +SetLinger(int interval_seconds) { + linger ll; + ll.l_linger = interval_seconds; + ll.l_onoff = 1; + int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *)&ll, sizeof(linger)); + if (ret1 != 0) { + return BASIC_ERROR; + } + return ALL_OK; } /** @@ -159,147 +148,150 @@ int Socket_TCP_SSL::SetLinger(int interval_seconds) * and free up OS resources. You may lose a stream if you use this flag and * do not negotiate the close at the application layer. */ -int Socket_TCP_SSL::DontLinger() -{ - linger ll; - ll.l_linger = 0; - ll.l_onoff = 0; - int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger)); - if (ret1 != 0) - return BASIC_ERROR; - return ALL_OK; +int Socket_TCP_SSL:: +DontLinger() { + linger ll; + ll.l_linger = 0; + ll.l_onoff = 0; + int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *)&ll, sizeof(linger)); + if (ret1 != 0) { + return BASIC_ERROR; + } + return ALL_OK; } /** * Just like it sounds. Sets a buffered socket recv buffer size. This * function does not refuse ranges outside hard-coded OS limits */ -int Socket_TCP_SSL::SetSendBufferSize(int insize) -{ - if (setsockopt(_socket, (int) SOL_SOCKET, (int) SO_SNDBUF, (char *) &insize, sizeof(int))) - return BASIC_ERROR; - return ALL_OK; +int Socket_TCP_SSL:: +SetSendBufferSize(int insize) { + if (setsockopt(_socket, (int) SOL_SOCKET, (int) SO_SNDBUF, (char *) &insize, sizeof(int))) { + return BASIC_ERROR; + } + return ALL_OK; } /** - * This function will try and set the socket up for active open to a specified - * address and port provided by the input parameter - */ -bool Socket_TCP_SSL::ActiveOpen(const Socket_Address & theaddress) -{ - _socket = DO_NEWTCP(); - if (_socket == BAD_SOCKET) - return false; +* This function will try and set the socket up for active open to a specified +* address and port provided by the input parameter +*/ +bool Socket_TCP_SSL:: +ActiveOpen(const Socket_Address &theaddress) { + _socket = DO_NEWTCP(theaddress.get_family()); + if (_socket == BAD_SOCKET) { + return false; + } - if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) - return ErrorClose(); + if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) { + return ErrorClose(); + } + _ssl = SSL_new(global_ssl_ctx); + if (_ssl == NULL) { + return false; + } + SSL_set_fd(_ssl, (int)GetSocket()); + if (SSL_connect(_ssl) == -1) { + return false; + } + return true; - _ssl = SSL_new (global_ssl_ctx); - if(_ssl == NULL) - return false; - SSL_set_fd (_ssl,(int)GetSocket() ); - if(SSL_connect(_ssl) == -1) - return false; - return true; - - // return SetSslUp(); + // return SetSslUp(); } /** * Ok Lets Send the Data - if error 0 if socket closed for write or lengh is 0 * + bytes writen ( May be smaller than requested) */ -inline int Socket_TCP_SSL::SendData(const char * data, int size) -{ - if(_ssl == NULL) - return -1; +inline int Socket_TCP_SSL:: +SendData(const char *data, int size) { + if (_ssl == NULL) { + return -1; + } // ERR_clear_error(); - return SSL_write(_ssl, data, size); + return SSL_write(_ssl, data, size); } /** * Read the data from the connection - if error 0 if socket closed for read or * length is 0 + bytes read ( May be smaller than requested) */ -inline int Socket_TCP_SSL::RecvData(char * data, int len) -{ - if(_ssl == NULL) - return -1; +inline int Socket_TCP_SSL:: +RecvData(char *data, int len) { + if (_ssl == NULL) { + return -1; + } - ERR_clear_error(); + ERR_clear_error(); - return SSL_read(_ssl, data, len); + return SSL_read(_ssl, data, len); } /** * Is last error a blocking error ?? True is last error was a blocking error */ -inline bool Socket_TCP_SSL::ErrorIs_WouldBlocking(int err) -{ - if(_ssl == NULL || err >= 0) - { - nativenet_cat.warning() - << "Socket_TCP_SSL::ErrorIs_WouldBlocking->Called With Error number " - << err << " or _ssl is NULL\n"; - return false; - } +inline bool Socket_TCP_SSL:: +ErrorIs_WouldBlocking(int err) { + if (_ssl == NULL || err >= 0) { + nativenet_cat.warning() + << "Socket_TCP_SSL::ErrorIs_WouldBlocking->Called With Error number " + << err << " or _ssl is NULL\n"; + return false; + } - int ssl_error_code = SSL_get_error(_ssl,err); - bool answer = false; + int ssl_error_code = SSL_get_error(_ssl,err); + bool answer = false; - switch(ssl_error_code) - { - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - case SSL_ERROR_WANT_CONNECT: + switch(ssl_error_code) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_CONNECT: // case SSL_ERROR_WANT_ACCEPT: - answer = true; - break; + answer = true; + break; // hmm not sure we need this .. hmmmm - case SSL_ERROR_SYSCALL: - if(GETERROR() == LOCAL_BLOCKING_ERROR) - answer = true; - else - { - DetailErrorFormat(); + case SSL_ERROR_SYSCALL: + if(GETERROR() == LOCAL_BLOCKING_ERROR) { + answer = true; + } else { + DetailErrorFormat(); // LOGWARNING("Socket_TCP_SSL::ErrorIs_WouldBlocking-> Not A blocking Error1 // SSl_CODe=[%d] OS=[%d]",ssl_error_code,GETERROR()); - } - break; - default: - DetailErrorFormat(); + } + break; + default: + DetailErrorFormat(); // LOGWARNING("Socket_TCP_SSL::ErrorIs_WouldBlocking-> Not A blocking Error2 // SSl_CODe=[%d] OS=[%d]",ssl_error_code,GETERROR()); - answer = false; - break; - } + answer = false; + break; + } // ERR_clear_error(); - return answer; + return answer; } -inline void Socket_TCP_SSL::DetailErrorFormat(void) -{ - return; // turn on fir debuging +inline void Socket_TCP_SSL:: +DetailErrorFormat(void) { + return; // turn on for debuging - PN_uint32 l; - char buf[256]; - char buf2[4096]; - const char *file,*data; - int line,flags; - PN_uint32 es; + uint32_t l; + char buf[256]; + char buf2[4096]; + const char *file,*data; + int line,flags; + uint32_t es; - es=CRYPTO_thread_id(); - while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) - { - ERR_error_string_n(l, buf, sizeof( buf) ); - BIO_snprintf(buf2, sizeof(buf2), "***%lu:%s:%s:%d:%s\n", (unsigned long) es, buf,file, line, (flags & ERR_TXT_STRING) ? data : "NoText"); - nativenet_cat.warning() - << "Socket_TCP_SSL::DetailErrorFormat->[" << buf2 << "]\n"; - } + es = CRYPTO_thread_id(); + while ((l = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) { + ERR_error_string_n(l, buf, sizeof(buf)); + BIO_snprintf(buf2, sizeof(buf2), "***%lu:%s:%s:%d:%s\n", (unsigned long) es, buf, file, line, (flags & ERR_TXT_STRING) ? data : "NoText"); + nativenet_cat.warning() + << "Socket_TCP_SSL::DetailErrorFormat->[" << buf2 << "]\n"; + } } #endif // HAVE_OPENSSL diff --git a/panda/src/nativenet/socket_udp.h b/panda/src/nativenet/socket_udp.h index aa271d336d..58c410dd97 100644 --- a/panda/src/nativenet/socket_udp.h +++ b/panda/src/nativenet/socket_udp.h @@ -21,25 +21,22 @@ * duplicates code from Socket_UDP_Outgoing, to avoid the problems of multiple * inheritance. */ -class EXPCL_PANDA_NATIVENET Socket_UDP : public Socket_UDP_Incoming -{ +class EXPCL_PANDA_NATIVENET Socket_UDP : public Socket_UDP_Incoming { public: PUBLISHED: - inline Socket_UDP() { } + inline Socket_UDP() {} - // use this interface for a tagreted UDP connection - inline bool InitToAddress(const Socket_Address & address); + // use this interface for a tagreted UDP connection + inline bool InitToAddress(const Socket_Address &address); public: - inline bool Send(const char * data, int len); + inline bool Send(const char *data, int len); PUBLISHED: - inline bool Send(const string &data); - // use this interface for a none tagreted UDP connection - inline bool InitNoAddress(); + inline bool Send(const string &data); public: - inline bool SendTo(const char * data, int len, const Socket_Address & address); + inline bool SendTo(const char *data, int len, const Socket_Address &address); PUBLISHED: - inline bool SendTo(const string &data, const Socket_Address & address); - inline bool SetToBroadCast(); + inline bool SendTo(const string &data, const Socket_Address &address); + inline bool SetToBroadCast(); public: static TypeHandle get_class_type() { @@ -58,72 +55,64 @@ public: private: static TypeHandle _type_handle; }; -/** - * Ask the OS to let us receive BROADCASt packets on this port.. - */ -inline bool Socket_UDP::SetToBroadCast() -{ - int optval = 1; - if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) - return false; - return true; +/** + * Ask the OS to let us receive broadcast packets on this port. + */ +inline bool Socket_UDP:: +SetToBroadCast() { + int optval = 1; + + if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) { + return false; + } + return true; } + /** - * Connects the Socket to a Specified address + * Connects the socket to a Specified address */ -inline bool Socket_UDP::InitToAddress(const Socket_Address & address) -{ - if (InitNoAddress() != true) - return false; +inline bool Socket_UDP:: +InitToAddress(const Socket_Address &address) { + if (InitNoAddress() != true) { + return false; + } - if (DO_CONNECT(_socket, &address.GetAddressInfo()) != 0) - return ErrorClose(); - - return true; -} -/** - * This will set a udp up for targeted sends.. - */ -inline bool Socket_UDP::InitNoAddress() -{ - Close(); - _socket = DO_NEWUDP(); - if (_socket == BAD_SOCKET) - return false; - - return true; + if (DO_CONNECT(_socket, &address.GetAddressInfo()) != 0) { + return ErrorClose(); + } + return true; } /** * Send data to connected address */ -inline bool Socket_UDP::Send(const char * data, int len) -{ +inline bool Socket_UDP:: +Send(const char *data, int len) { return (DO_SOCKET_WRITE(_socket, data, len) == len); } /** * Send data to connected address */ -inline bool Socket_UDP::Send(const string &data) -{ +inline bool Socket_UDP:: +Send(const string &data) { return Send(data.data(), data.size()); } /** * Send data to specified address */ -inline bool Socket_UDP::SendTo(const char * data, int len, const Socket_Address & address) -{ - return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len); +inline bool Socket_UDP:: +SendTo(const char *data, int len, const Socket_Address &address) { + return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len); } /** * Send data to specified address */ -inline bool Socket_UDP::SendTo(const string &data, const Socket_Address & address) -{ +inline bool Socket_UDP:: +SendTo(const string &data, const Socket_Address &address) { return SendTo(data.data(), data.size(), address); } diff --git a/panda/src/nativenet/socket_udp_incoming.h b/panda/src/nativenet/socket_udp_incoming.h index 3fb83785d5..cf8454b9d2 100644 --- a/panda/src/nativenet/socket_udp_incoming.h +++ b/panda/src/nativenet/socket_udp_incoming.h @@ -6,21 +6,18 @@ /** * Base functionality for a UDP Reader - * - - * */ -class EXPCL_PANDA_NATIVENET Socket_UDP_Incoming : public Socket_IP -{ +class EXPCL_PANDA_NATIVENET Socket_UDP_Incoming : public Socket_IP { PUBLISHED: - inline Socket_UDP_Incoming() { } + inline Socket_UDP_Incoming() {} - inline bool OpenForInput(const Socket_Address & address); - inline bool OpenForInputMCast(const Socket_Address & address ); - inline bool GetPacket(char * data, int *max_len, Socket_Address & address); - inline bool SendTo(const char * data, int len, const Socket_Address & address); - inline bool InitNoAddress(); - inline bool SetToBroadCast(); + inline bool OpenForInput(unsigned short port); + inline bool OpenForInput(const Socket_Address &address); + inline bool OpenForInputMCast(const Socket_Address &address); + inline bool GetPacket(char *data, int *max_len, Socket_Address &address); + inline bool SendTo(const char *data, int len, const Socket_Address &address); + inline bool InitNoAddress(); + inline bool SetToBroadCast(); public: static TypeHandle get_class_type() { @@ -41,71 +38,123 @@ private: }; /** - * Flips the OS bits that allow for brodcast packets to com in on this port - * + * Flips the OS bits that allow for brodcast packets to come in on this port. */ -inline bool Socket_UDP_Incoming::SetToBroadCast() -{ - int optval = 1; +inline bool Socket_UDP_Incoming:: +SetToBroadCast() { + int optval = 1; - if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) - return false; - return true; + if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) { + return false; + } + return true; } -/** - * Set this socket to work with out a bound external address.. - */ -inline bool Socket_UDP_Incoming::InitNoAddress() -{ - Close(); - _socket = DO_NEWUDP(); - if (_socket == BAD_SOCKET) - return false; - return true; +/** + * Set this socket to work without a bound external address. + */ +inline bool Socket_UDP_Incoming:: +InitNoAddress() { + Close(); + + if (support_ipv6) { + // Create a socket supporting both IPv4 and IPv6. + _socket = DO_NEWUDP(AF_INET6); + SetV6Only(false); + } else { + _socket = DO_NEWUDP(AF_INET); + } + + return (_socket != BAD_SOCKET); } /** * Starts a UDP socket listening on a port */ -inline bool Socket_UDP_Incoming::OpenForInput(const Socket_Address & address) -{ - Close(); - _socket = DO_NEWUDP(); - if (_socket == BAD_SOCKET) - return ErrorClose(); +inline bool Socket_UDP_Incoming:: +OpenForInput(unsigned short port) { + Close(); - if (DO_BIND(_socket, &address.GetAddressInfo()) != 0) - return ErrorClose(); + Socket_Address address; + if (support_ipv6) { + // Create a socket supporting both IPv4 and IPv6. + address.set_any_IPv6(port); + _socket = DO_NEWUDP(AF_INET6); + SetV6Only(false); + } else { + address.set_any_IP(port); + _socket = DO_NEWUDP(AF_INET); + } - return true; + if (_socket == BAD_SOCKET) { + return ErrorClose(); + } + + if (DO_BIND(_socket, &address.GetAddressInfo()) != 0) { + return ErrorClose(); + } + + return true; } /** * Starts a UDP socket listening on a port */ -inline bool Socket_UDP_Incoming::OpenForInputMCast(const Socket_Address & address) -{ - Close(); - _socket = DO_NEWUDP(); - if (_socket == BAD_SOCKET) - return ErrorClose(); +inline bool Socket_UDP_Incoming:: +OpenForInput(const Socket_Address &address) { + Close(); + _socket = DO_NEWUDP(address.get_family()); + if (_socket == BAD_SOCKET) { + return ErrorClose(); + } - Socket_Address wa1(address.get_port()); - if (DO_BIND(_socket, &wa1.GetAddressInfo()) != 0) - return ErrorClose(); + if (DO_BIND(_socket, &address.GetAddressInfo()) != 0) { + return ErrorClose(); + } - struct ip_mreq imreq; - memset(&imreq,0,sizeof(imreq)); - imreq.imr_multiaddr.s_addr = address.GetAddressInfo().sin_addr.s_addr; - imreq.imr_interface.s_addr = INADDR_ANY; // use DEFAULT interface + return true; +} - int status = setsockopt(GetSocket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, - (const char *)&imreq, sizeof(struct ip_mreq)); +/** + * Starts a UDP socket listening on a port + */ +inline bool Socket_UDP_Incoming:: +OpenForInputMCast(const Socket_Address &address) { + Close(); + _socket = DO_NEWUDP(address.get_family()); + if (_socket == BAD_SOCKET) { + return ErrorClose(); + } - if(status != 0) - return false; - return true; + Socket_Address wa1(address.get_port()); + if (DO_BIND(_socket, &wa1.GetAddressInfo()) != 0) { + return ErrorClose(); + } + + int status = -1; + + const sockaddr *addr = &address.GetAddressInfo(); + if (addr->sa_family == AF_INET) { + struct ip_mreq imreq; + memset(&imreq, 0, sizeof(imreq)); + imreq.imr_multiaddr.s_addr = ((sockaddr_in*)addr)->sin_addr.s_addr; + imreq.imr_interface.s_addr = INADDR_ANY; // use DEFAULT interface + + status = setsockopt(GetSocket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, + (const char *)&imreq, sizeof(imreq)); + + } else if (addr->sa_family == AF_INET6) { + struct ipv6_mreq imreq; + memcpy(&imreq.ipv6mr_multiaddr, + &(((struct sockaddr_in6 *)addr)->sin6_addr), + sizeof(struct in6_addr)); + imreq.ipv6mr_interface = 0; // use DEFAULT interface + + status = setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_JOIN_GROUP, + (const char *)&imreq, sizeof(imreq)); + } + + return (status == 0); } /** @@ -113,30 +162,28 @@ inline bool Socket_UDP_Incoming::OpenForInputMCast(const Socket_Address & addres * address information * */ -inline bool Socket_UDP_Incoming::GetPacket(char * data, int *max_len, Socket_Address & address) -{ - int val = DO_RECV_FROM(_socket, data, *max_len, &address.GetAddressInfo()); - *max_len = 0; +inline bool Socket_UDP_Incoming:: +GetPacket(char *data, int *max_len, Socket_Address &address) { + int val = DO_RECV_FROM(_socket, data, *max_len, &address.GetAddressInfo()); + *max_len = 0; - if (val <= 0) - { - if (GetLastError() != LOCAL_BLOCKING_ERROR) // im treating a blocking error as a 0 lenght read - return false; - } else - *max_len = val; + if (val <= 0) { + if (GetLastError() != LOCAL_BLOCKING_ERROR) { // im treating a blocking error as a 0 lenght read + return false; + } + } else { + *max_len = val; + } - return true; + return true; } /** * Send data to specified address */ -inline bool Socket_UDP_Incoming::SendTo(const char * data, int len, const Socket_Address & address) -{ - return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len); +inline bool Socket_UDP_Incoming:: +SendTo(const char *data, int len, const Socket_Address &address) { + return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len); } - - - #endif //__SOCKET_UDP_INCOMING_H__ diff --git a/panda/src/nativenet/socket_udp_outgoing.h b/panda/src/nativenet/socket_udp_outgoing.h index be7b2b9f8f..3d1c9bb688 100644 --- a/panda/src/nativenet/socket_udp_outgoing.h +++ b/panda/src/nativenet/socket_udp_outgoing.h @@ -5,30 +5,25 @@ #include "socket_ip.h" /** - * Base functionality for a UDP Sending Socket - * - - * + * Base functionality for a UDP sending socket */ -class EXPCL_PANDA_NATIVENET Socket_UDP_Outgoing : public Socket_IP -{ -public: +class EXPCL_PANDA_NATIVENET Socket_UDP_Outgoing : public Socket_IP { PUBLISHED: - inline Socket_UDP_Outgoing() { } + inline Socket_UDP_Outgoing() {} - // use this interface for a tagreted UDP connection - inline bool InitToAddress(const Socket_Address & address); + // use this interface for a tagreted UDP connection + inline bool InitToAddress(const Socket_Address &address); public: - inline bool Send(const char * data, int len); + inline bool Send(const char *data, int len); PUBLISHED: - inline bool Send(const string &data); - // use this interface for a none tagreted UDP connection - inline bool InitNoAddress(); + inline bool Send(const string &data); + // use this interface for a none tagreted UDP connection + inline bool InitNoAddress(); public: - inline bool SendTo(const char * data, int len, const Socket_Address & address); + inline bool SendTo(const char *data, int len, const Socket_Address &address); PUBLISHED: - inline bool SendTo(const string &data, const Socket_Address & address); - inline bool SetToBroadCast(); + inline bool SendTo(const string &data, const Socket_Address &address); + inline bool SetToBroadCast(); public: static TypeHandle get_class_type() { @@ -47,72 +42,79 @@ public: private: static TypeHandle _type_handle; }; -/** - * Ask the OS to let us receive BROADCASt packets on this port.. - */ -inline bool Socket_UDP_Outgoing::SetToBroadCast() -{ - int optval = 1; - if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) - return false; - return true; +/** + * Ask the OS to let us receive broadcast packets on this port. + */ +inline bool Socket_UDP_Outgoing:: +SetToBroadCast() { + int optval = 1; + + if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) { + return false; + } + return true; } + /** - * Connects the Socket to a Specified address + * Connects the Socket to a specified address */ -inline bool Socket_UDP_Outgoing::InitToAddress(const Socket_Address & address) -{ - if (InitNoAddress() != true) - return false; +inline bool Socket_UDP_Outgoing:: +InitToAddress(const Socket_Address &address) { + if (InitNoAddress() != true) { + return false; + } - if (DO_CONNECT(_socket, &address.GetAddressInfo()) != 0) - return ErrorClose(); + if (DO_CONNECT(_socket, &address.GetAddressInfo()) != 0) { + return ErrorClose(); + } - return true; + return true; } -/** - * This will set a udp up for targeted sends.. - */ -inline bool Socket_UDP_Outgoing::InitNoAddress() -{ - Close(); - _socket = DO_NEWUDP(); - if (_socket == BAD_SOCKET) - return false; - return true; +/** + * This will set a udp up for targeted sends. + */ +inline bool Socket_UDP_Outgoing:: +InitNoAddress() { + Close(); + _socket = DO_NEWUDP(AF_INET); + if (_socket == BAD_SOCKET) { + return false; + } + + return true; } /** * Send data to connected address */ -inline bool Socket_UDP_Outgoing::Send(const char * data, int len) -{ +inline bool Socket_UDP_Outgoing:: +Send(const char *data, int len) { return (DO_SOCKET_WRITE(_socket, data, len) == len); } /** * Send data to connected address */ -inline bool Socket_UDP_Outgoing::Send(const string &data) -{ +inline bool Socket_UDP_Outgoing:: +Send(const string &data) { return Send(data.data(), data.size()); } /** * Send data to specified address */ -inline bool Socket_UDP_Outgoing::SendTo(const char * data, int len, const Socket_Address & address) -{ - return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len); +inline bool Socket_UDP_Outgoing:: +SendTo(const char *data, int len, const Socket_Address &address) { + return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len); } /** * Send data to specified address */ -inline bool Socket_UDP_Outgoing::SendTo(const string &data, const Socket_Address & address) -{ +inline bool Socket_UDP_Outgoing:: +SendTo(const string &data, const Socket_Address &address) { return SendTo(data.data(), data.size(), address); } diff --git a/panda/src/nativenet/time_clock.h b/panda/src/nativenet/time_clock.h index b02d4af01c..2c326fd7da 100644 --- a/panda/src/nativenet/time_clock.h +++ b/panda/src/nativenet/time_clock.h @@ -1,182 +1,176 @@ #ifndef __Time_H__ #define __Time_H__ -/** - * This class is to provide a consistant interface and storage to clock time - * .. Epoch based time to the second - * - * jan-2000 .. rhh changing all time to use sub second timing... - * - */ - #include class Time_Span; -class Time_Clock -{ - friend class Time_Span; +/** + * This class is to provide a consistant interface and storage to clock time + * .. Epoch based time to the second + * + * jan-2000 .. rhh changing all time to use sub second timing... + */ +class Time_Clock { + friend class Time_Span; public: - // Constructors - static Time_Clock GetCurrentTime(); - void ToCurrentTime(); - Time_Clock( timeval &in_mytime) - { - _my_time = in_mytime; - }; - Time_Clock(); - Time_Clock(time_t time); - Time_Clock(long secs, long usecs); - Time_Clock(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, long microseconds = 0, int nDST = -1); - Time_Clock(const Time_Clock& timeSrc); + // Constructors + static Time_Clock GetCurrentTime(); + void ToCurrentTime(); + inline Time_Clock(const timeval &in_mytime) { + _my_time = in_mytime; + } + Time_Clock(); + Time_Clock(time_t time); + Time_Clock(long secs, long usecs); + Time_Clock(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, long microseconds = 0, int nDST = -1); + Time_Clock(const Time_Clock& timeSrc); - inline const Time_Clock& operator=(const Time_Clock& timeSrc); - inline const Time_Clock& operator=(time_t t); + inline const Time_Clock &operator=(const Time_Clock& timeSrc); + inline const Time_Clock &operator=(time_t t); - // Attributes - struct tm* GetGmtTm(struct tm* ptm = NULL) const; - struct tm* GetLocalTm(struct tm* ptm = NULL) const; + // Attributes + struct tm *GetGmtTm(struct tm *ptm) const; + struct tm *GetLocalTm(struct tm *ptm) const; - time_t GetTime() const; - int GetYear() const; - int GetMonth() const; // month of year (1 = Jan) - int GetDay() const; // day of month - int GetHour() const; - int GetMinute() const; - int GetSecond() const; - int GetDayOfWeek() const; // 1=Sun, 2=Mon, ..., 7=Sat + time_t GetTime() const; + int GetYear() const; + int GetMonth() const; // month of year (1 = Jan) + int GetDay() const; // day of month + int GetHour() const; + int GetMinute() const; + int GetSecond() const; + int GetDayOfWeek() const; // 1=Sun, 2=Mon, ..., 7=Sat - void Set(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, long microseconds = 0, int nDST = -1); + void Set(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, long microseconds = 0, int nDST = -1); + // Operations time math + const Time_Clock& operator+=(const Time_Span &Time_Span); + const Time_Clock& operator-=(const Time_Span &Time_Span); + bool operator==(const Time_Clock &time) const; + bool operator!=(const Time_Clock &time) const; + bool operator<(const Time_Clock &time) const; + bool operator>(const Time_Clock &time) const; + bool operator<=(const Time_Clock &time) const; + bool operator>=(const Time_Clock &time) const; - // Operations time math - const Time_Clock& operator+=(const Time_Span &Time_Span); - const Time_Clock& operator-=(const Time_Span &Time_Span); - bool operator==(const Time_Clock &time) const; - bool operator!=(const Time_Clock &time) const; - bool operator<(const Time_Clock &time) const; - bool operator>(const Time_Clock &time) const; - bool operator<=(const Time_Clock &time) const; - bool operator>=(const Time_Clock &time) const; + inline time_t GetTime_t() { + return _my_time.tv_sec; + } + inline long GetUsecPart() { + return _my_time.tv_usec; + } + // formatting using "C" strftime + std::string Format(const char *pFormat) const; + std::string FormatGmt(const char *pFormat) const; - time_t GetTime_t() - { - return _my_time.tv_sec; - }; - long GetUsecPart() - { - return _my_time.tv_usec; - }; + const timeval &GetTval() { + return _my_time; + } + const timeval &GetTval() const { + return _my_time; + } - // formatting using "C" strftime - std::string Format(const char * pFormat) const; - std::string FormatGmt(const char * pFormat) const; - const timeval & GetTval() - { - return _my_time; - }; - const timeval & GetTval() const - { - return _my_time; - } ; - private: - struct timeval _my_time; +private: + struct timeval _my_time; }; /** * Construction from parts */ -inline Time_Clock::Time_Clock(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, long microseconds , int nDST) -{ - struct tm atm; - atm.tm_sec = nSec; - atm.tm_min = nMin; - atm.tm_hour = nHour; - assert(nDay >= 1 && nDay <= 31); - atm.tm_mday = nDay; - assert(nMonth >= 1 && nMonth <= 12); - atm.tm_mon = nMonth - 1; // tm_mon is 0 based - assert(nYear >= 1900); - atm.tm_year = nYear - 1900; // tm_year is 1900 based - atm.tm_isdst = nDST; - _my_time.tv_sec = (long)mktime(&atm); - assert(_my_time.tv_sec != -1); // indicates an illegal input time - _my_time.tv_usec = microseconds; - assert(_my_time.tv_usec < 1000000); +inline Time_Clock:: +Time_Clock(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, long microseconds, int nDST) { + struct tm atm; + atm.tm_sec = nSec; + atm.tm_min = nMin; + atm.tm_hour = nHour; + assert(nDay >= 1 && nDay <= 31); + atm.tm_mday = nDay; + assert(nMonth >= 1 && nMonth <= 12); + atm.tm_mon = nMonth - 1; // tm_mon is 0 based + assert(nYear >= 1900); + atm.tm_year = nYear - 1900; // tm_year is 1900 based + atm.tm_isdst = nDST; + _my_time.tv_sec = (long)mktime(&atm); + assert(_my_time.tv_sec != -1); // indicates an illegal input time + _my_time.tv_usec = microseconds; + assert(_my_time.tv_usec < 1000000); } + /** * */ -inline void Time_Clock::Set(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, long microseconds , int nDST) -{ - struct tm atm; - atm.tm_sec = nSec; - atm.tm_min = nMin; - atm.tm_hour = nHour; - assert(nDay >= 1 && nDay <= 31); - atm.tm_mday = nDay; - assert(nMonth >= 1 && nMonth <= 12); - atm.tm_mon = nMonth - 1; // tm_mon is 0 based - assert(nYear >= 1900); - atm.tm_year = nYear - 1900; // tm_year is 1900 based - atm.tm_isdst = nDST; - _my_time.tv_sec = (long)mktime(&atm); - assert(_my_time.tv_sec != -1); // indicates an illegal input time - _my_time.tv_usec = microseconds; - assert(_my_time.tv_usec < 1000000); +inline void Time_Clock:: +Set(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, long microseconds , int nDST) { + struct tm atm; + atm.tm_sec = nSec; + atm.tm_min = nMin; + atm.tm_hour = nHour; + assert(nDay >= 1 && nDay <= 31); + atm.tm_mday = nDay; + assert(nMonth >= 1 && nMonth <= 12); + atm.tm_mon = nMonth - 1; // tm_mon is 0 based + assert(nYear >= 1900); + atm.tm_year = nYear - 1900; // tm_year is 1900 based + atm.tm_isdst = nDST; + _my_time.tv_sec = (long)mktime(&atm); + assert(_my_time.tv_sec != -1); // indicates an illegal input time + _my_time.tv_usec = microseconds; + assert(_my_time.tv_usec < 1000000); } + /** * The Default no param constructor.. Will set time to current system time */ -inline Time_Clock Time_Clock::GetCurrentTime() -{ - return Time_Clock(); +inline Time_Clock Time_Clock:: +GetCurrentTime() { + return Time_Clock(); } + /** * */ -inline Time_Clock::Time_Clock() -{ - gettimeofday(&_my_time, NULL); +inline Time_Clock:: +Time_Clock() { + gettimeofday(&_my_time, NULL); } + /** * Load this object with the current OS time */ -inline void Time_Clock::ToCurrentTime() -{ - gettimeofday(&_my_time, NULL); +inline void Time_Clock:: +ToCurrentTime() { + gettimeofday(&_my_time, NULL); } + /** * Access the stored time and converts to a struct tm format If storage * location is specified then it will stor information in the provided buffer * else it will use the library's internal buffer space */ -inline struct tm* Time_Clock::GetGmtTm(struct tm* ptm) const -{ - if (ptm != NULL) - { - *ptm = *gmtime((const time_t *)&_my_time.tv_sec); - return ptm; - } else - return gmtime((const time_t *)&_my_time.tv_sec); +inline struct tm *Time_Clock:: +GetGmtTm(struct tm *ptm) const { + nassertr(ptm != NULL, NULL); +#ifdef _WIN32 + return (gmtime_s(ptm, (const time_t *)&_my_time.tv_sec) == 0) ? ptm : NULL; +#else + return gmtime_r((const time_t *)&_my_time.tv_sec, ptm); +#endif } /** * Gets The local time in a tm structre from the internal time value */ -inline struct tm* Time_Clock::GetLocalTm(struct tm* ptm) const -{ - if (ptm != NULL) - { - struct tm* ptmTemp = localtime((const time_t *)&_my_time.tv_sec); - if (ptmTemp == NULL) - return NULL; // indicates the _my_time.tv_sec was not initialized! - *ptm = *ptmTemp; - return ptm; - } else - return localtime((const time_t *)&_my_time.tv_sec); +inline struct tm *Time_Clock:: +GetLocalTm(struct tm *ptm) const { + nassertr(ptm != NULL, NULL); +#ifdef _WIN32 + return (localtime_s(ptm, (const time_t *)&_my_time.tv_sec) == 0) ? ptm : NULL; +#else + return localtime_r((const time_t *)&_my_time.tv_sec, ptm); +#endif } // String formatting Verifies will fail if the needed buffer size is too large #define maxTimeBufferSize 4096 @@ -184,235 +178,260 @@ inline struct tm* Time_Clock::GetLocalTm(struct tm* ptm) const /** * Used to allow access to the "C" library strftime functions.. */ -inline std::string Time_Clock::Format(const char * pFormat) const -{ +inline std::string Time_Clock:: +Format(const char *pFormat) const { + char szBuffer[maxTimeBufferSize]; + char ch, ch1; + char *pch = szBuffer; - char szBuffer[maxTimeBufferSize]; - char ch, ch1; - char * pch = szBuffer; - - while ((ch = *pFormat++) != '\0') - { - assert(pch < &szBuffer[maxTimeBufferSize]); - if (ch == '%') - { - switch (ch1 = *pFormat++) - { - default: - *pch++ = ch; - *pch++ = ch1; - break; - case 'N': - pch += sprintf(pch, "%03ld", (long)(_my_time.tv_usec / 1000)); - break; - } - } - else - { - *pch++ = ch; - } + while ((ch = *pFormat++) != '\0') { + assert(pch < &szBuffer[maxTimeBufferSize]); + if (ch == '%') { + switch (ch1 = *pFormat++) { + default: + *pch++ = ch; + *pch++ = ch1; + break; + case 'N': +#ifdef _WIN32 + pch += sprintf_s(pch, maxTimeBufferSize, "%03ld", (long)(_my_time.tv_usec / 1000)); +#else + pch += snprintf(pch, maxTimeBufferSize, "%03ld", (long)(_my_time.tv_usec / 1000)); +#endif + break; + } + } else { + *pch++ = ch; } + } - *pch = '\0'; + *pch = '\0'; - char szBuffer1[maxTimeBufferSize]; + char szBuffer1[maxTimeBufferSize]; - struct tm* ptmTemp = localtime((const time_t *)&_my_time.tv_sec); - if (ptmTemp == NULL || - !strftime(szBuffer1, sizeof(szBuffer1), szBuffer, ptmTemp)) - szBuffer1[0] = '\0'; - return std::string(szBuffer1); + struct tm tmTemp; + if (GetLocalTm(&tmTemp) == NULL || + !strftime(szBuffer1, sizeof(szBuffer1), szBuffer, &tmTemp)) { + szBuffer1[0] = '\0'; + } + return std::string(szBuffer1); } + /** * A Wraper to size_t strftime( char *strDest, size_t maxsize, const char * *format, const struct tm *timeptr ); * */ -inline std::string Time_Clock::FormatGmt(const char * pFormat) const -{ +inline std::string Time_Clock:: +FormatGmt(const char *pFormat) const { + char szBuffer[maxTimeBufferSize]; + char ch, ch1; + char *pch = szBuffer; - char szBuffer[maxTimeBufferSize]; - char ch, ch1; - char * pch = szBuffer; - - while ((ch = *pFormat++) != '\0') - { - assert(pch < &szBuffer[maxTimeBufferSize]); - if (ch == '%') - { - switch (ch1 = *pFormat++) - { - default: - *pch++ = ch; - *pch++ = ch1; - break; - case 'N': - pch += sprintf(pch, "%03ld", (long)(_my_time.tv_usec / 1000)); - break; - } - } - else - { - *pch++ = ch; - } + while ((ch = *pFormat++) != '\0') { + assert(pch < &szBuffer[maxTimeBufferSize]); + if (ch == '%') { + switch (ch1 = *pFormat++) { + default: + *pch++ = ch; + *pch++ = ch1; + break; + case 'N': +#ifdef _WIN32 + pch += sprintf_s(pch, maxTimeBufferSize, "%03ld", (long)(_my_time.tv_usec / 1000)); +#else + pch += snprintf(pch, maxTimeBufferSize, "%03ld", (long)(_my_time.tv_usec / 1000)); +#endif + break; + } + } else { + *pch++ = ch; } - *pch = '\0'; + } + *pch = '\0'; - char szBuffer1[maxTimeBufferSize]; + char szBuffer1[maxTimeBufferSize]; - struct tm* ptmTemp = gmtime((const time_t *)&_my_time.tv_sec); - if (ptmTemp == NULL || - !strftime(szBuffer1, sizeof(szBuffer1), szBuffer, ptmTemp)) - szBuffer1[0] = '\0'; - return std::string(szBuffer1); + struct tm tmTemp; + if (GetGmtTm(&tmTemp) == NULL || + !strftime(szBuffer1, sizeof(szBuffer1), szBuffer, &tmTemp)) { + szBuffer1[0] = '\0'; + } + return std::string(szBuffer1); } + /** * The Constructor that take a time_t objext */ -inline Time_Clock::Time_Clock(time_t time) -{ - _my_time.tv_sec = (long)time; - _my_time.tv_usec = 0; -}; +inline Time_Clock:: +Time_Clock(time_t time) { + _my_time.tv_sec = (long)time; + _my_time.tv_usec = 0; +} + /** * Constructor that takes in sec and usecs.. */ -inline Time_Clock::Time_Clock(long secs, long usecs) -{ - _my_time.tv_sec = secs; - _my_time.tv_usec = usecs; - NormalizeTime(_my_time); -}; +inline Time_Clock:: +Time_Clock(long secs, long usecs) { + _my_time.tv_sec = secs; + _my_time.tv_usec = usecs; + NormalizeTime(_my_time); +} + /** * yet another constructor */ -inline Time_Clock::Time_Clock(const Time_Clock& timeSrc) -{ - _my_time.tv_sec = timeSrc._my_time.tv_sec; - _my_time.tv_usec = timeSrc._my_time.tv_usec; +inline Time_Clock:: +Time_Clock(const Time_Clock& timeSrc) { + _my_time.tv_sec = timeSrc._my_time.tv_sec; + _my_time.tv_usec = timeSrc._my_time.tv_usec; } + /** * .. is time equal */ -inline bool Time_Clock::operator==(const Time_Clock &time) const -{ - return ((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec == time._my_time.tv_usec)); +inline bool Time_Clock:: +operator==(const Time_Clock &time) const { + return ((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec == time._my_time.tv_usec)); } + /** * .is time != */ -inline bool Time_Clock::operator!=(const Time_Clock &time) const -{ - return ((_my_time.tv_sec != time._my_time.tv_sec) || (_my_time.tv_usec != time._my_time.tv_usec)); +inline bool Time_Clock:: +operator!=(const Time_Clock &time) const { + return ((_my_time.tv_sec != time._my_time.tv_sec) || (_my_time.tv_usec != time._my_time.tv_usec)); } /** * */ -inline bool Time_Clock::operator<(const Time_Clock &time) const -{ - return ((_my_time.tv_sec < time._my_time.tv_sec) || - ((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec < time._my_time.tv_usec))); +inline bool Time_Clock:: +operator<(const Time_Clock &time) const { + return ((_my_time.tv_sec < time._my_time.tv_sec) || + ((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec < time._my_time.tv_usec))); } -/** - * - */ -inline bool Time_Clock::operator>(const Time_Clock &time) const -{ - return ((_my_time.tv_sec > time._my_time.tv_sec) || - ((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec > time._my_time.tv_usec))); -} -/** - * - */ -inline bool Time_Clock::operator<=(const Time_Clock &time) const -{ - return ((_my_time.tv_sec < time._my_time.tv_sec) || - ((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec <= time._my_time.tv_usec))); -} -/** - * - */ -inline bool Time_Clock::operator>=(const Time_Clock &time) const -{ - return ((_my_time.tv_sec > time._my_time.tv_sec) || - ((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec >= time._my_time.tv_usec))); -} -/** - * - */ -inline const Time_Clock& Time_Clock::operator=(const Time_Clock& timeSrc) -{ - if (&timeSrc == this) - return * this; - _my_time = timeSrc._my_time; +/** + * + */ +inline bool Time_Clock:: +operator>(const Time_Clock &time) const { + return ((_my_time.tv_sec > time._my_time.tv_sec) || + ((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec > time._my_time.tv_usec))); +} + +/** + * + */ +inline bool Time_Clock:: +operator<=(const Time_Clock &time) const { + return ((_my_time.tv_sec < time._my_time.tv_sec) || + ((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec <= time._my_time.tv_usec))); +} + +/** + * + */ +inline bool Time_Clock:: +operator>=(const Time_Clock &time) const { + return ((_my_time.tv_sec > time._my_time.tv_sec) || + ((_my_time.tv_sec == time._my_time.tv_sec) && (_my_time.tv_usec >= time._my_time.tv_usec))); +} + +/** + * + */ +inline const Time_Clock& Time_Clock:: +operator=(const Time_Clock& timeSrc) { + if (&timeSrc == this) { return *this; + } + + _my_time = timeSrc._my_time; + return *this; } + /** * */ -inline const Time_Clock& Time_Clock::operator=(time_t t) -{ - _my_time.tv_sec = (long)t; - _my_time.tv_usec = 0; - return *this; +inline const Time_Clock& Time_Clock:: +operator=(time_t t) { + _my_time.tv_sec = (long)t; + _my_time.tv_usec = 0; + return *this; } + /** * */ -inline time_t Time_Clock::GetTime() const -{ - return _my_time.tv_sec; +inline time_t Time_Clock:: +GetTime() const { + return _my_time.tv_sec; } + /** * */ -inline int Time_Clock::GetYear() const -{ - return (GetLocalTm(NULL)->tm_year) + 1900; +inline int Time_Clock:: +GetYear() const { + struct tm atm; + return (GetLocalTm(&atm)->tm_year) + 1900; } + /** * */ -inline int Time_Clock::GetMonth() const -{ - return GetLocalTm(NULL)->tm_mon + 1; +inline int Time_Clock:: +GetMonth() const { + struct tm atm; + return GetLocalTm(&atm)->tm_mon + 1; } + /** * */ -inline int Time_Clock::GetDay() const -{ - return GetLocalTm(NULL)->tm_mday; +inline int Time_Clock:: +GetDay() const { + struct tm atm; + return GetLocalTm(&atm)->tm_mday; } + /** * */ -inline int Time_Clock::GetHour() const -{ - return GetLocalTm(NULL)->tm_hour; +inline int Time_Clock:: +GetHour() const { + struct tm atm; + return GetLocalTm(&atm)->tm_hour; } + /** * */ -inline int Time_Clock::GetMinute() const -{ - return GetLocalTm(NULL)->tm_min; +inline int Time_Clock:: +GetMinute() const { + struct tm atm; + return GetLocalTm(&atm)->tm_min; } + /** * */ -inline int Time_Clock::GetSecond() const -{ - return GetLocalTm(NULL)->tm_sec; +inline int Time_Clock:: +GetSecond() const { + struct tm atm; + return GetLocalTm(&atm)->tm_sec; } + /** * */ -inline int Time_Clock::GetDayOfWeek() const -{ - return GetLocalTm(NULL)->tm_wday + 1; +inline int Time_Clock:: +GetDayOfWeek() const { + struct tm atm; + return GetLocalTm(&atm)->tm_wday + 1; } #endif //__Time_H__ diff --git a/panda/src/nativenet/time_general.h b/panda/src/nativenet/time_general.h index cb7a756ea9..5fac081a32 100644 --- a/panda/src/nativenet/time_general.h +++ b/panda/src/nativenet/time_general.h @@ -1,128 +1,82 @@ #ifndef __TIME_GENERAL_H__ #define __TIME_GENERAL_H__ - Time_Span TimeDifference(const Time_Clock &time1, const Time_Clock &time2); -Time_Clock TimeDifference( const Time_Clock &time1, const Time_Span &Time_Span); +Time_Clock TimeDifference(const Time_Clock &time1, const Time_Span &Time_Span); Time_Clock TimeAddition(const Time_Clock &time1, Time_Span &Time_Span); - Time_Clock operator+(const Time_Clock &tm, const Time_Span &ts); Time_Clock operator-(const Time_Clock &tm, const Time_Span &ts); - -bool SetFromTimeStr(const char * str, Time_Clock & outtime); -std::string GetTimeStr(const Time_Clock & intime); +/** + * + */ +inline Time_Span TimeDifference(const Time_Clock &time1, const Time_Clock &time2) { + timeval ans; + TimeDif(time2.GetTval(), time1.GetTval(), ans); + return Time_Span(ans); +} /** * */ -inline Time_Span TimeDifference(const Time_Clock &time1, const Time_Clock &time2) -{ - timeval ans; - TimeDif(time2.GetTval(), time1.GetTval(), ans); - return Time_Span(ans); -} -/** - * - */ -inline Time_Clock TimeDifference( const Time_Clock &time1, const Time_Span &Time_Span) -{ - timeval ans; - TimeDif(Time_Span.GetTval(), time1.GetTval(), ans); - return Time_Clock(ans); +inline Time_Clock TimeDifference(const Time_Clock &time1, const Time_Span &Time_Span) { + timeval ans; + TimeDif(Time_Span.GetTval(), time1.GetTval(), ans); + return Time_Clock(ans); } + /** * */ inline Time_Clock TimeAddition(const Time_Clock &time1, Time_Span &Time_Span) { - timeval ans; - TimeAdd(time1.GetTval(), Time_Span.GetTval(), ans); - return Time_Clock(ans); + timeval ans; + TimeAdd(time1.GetTval(), Time_Span.GetTval(), ans); + return Time_Clock(ans); } -/** - * - */ -inline const Time_Clock& Time_Clock::operator+=(const Time_Span &Time_Span) -{ - _my_time.tv_usec += Time_Span._my_time.tv_usec; - _my_time.tv_sec += Time_Span._my_time.tv_sec; - NormalizeTime(_my_time); - return *this; -} -/** - * - */ -inline Time_Clock operator+(const Time_Clock &tm, const Time_Span &ts) -{ - Time_Clock work(tm); - work += ts; - return work; -} -/** - * - */ -inline Time_Clock operator-(const Time_Clock &tm, const Time_Span &ts) -{ - return TimeDifference(tm, ts); -} -/** - * - */ -inline const Time_Clock& Time_Clock::operator-=(const Time_Span &Time_Span) -{ - _my_time.tv_usec -= Time_Span._my_time.tv_usec; - _my_time.tv_sec -= Time_Span._my_time.tv_sec; - NormalizeTime(_my_time); - return *this; -} -/** - * - */ -inline Time_Span operator-(const Time_Clock &tm1, const Time_Clock &tm2) -{ - return TimeDifference(tm1, tm2); -} -/** - * - */ -inline std::string GetTimeStr(const Time_Clock & intime) -{ - static std::string ts; - static Time_Clock prev_time; - if (prev_time != intime || ts.empty()) - { - ts = intime.Format("%Y-%m-%d %H:%M:%S"); - prev_time = intime; - } - return ts; -} /** * */ -inline std::string GetTimeStr() -{ - return GetTimeStr(Time_Clock::GetCurrentTime()); +inline const Time_Clock &Time_Clock::operator+=(const Time_Span &Time_Span) { + _my_time.tv_usec += Time_Span._my_time.tv_usec; + _my_time.tv_sec += Time_Span._my_time.tv_sec; + NormalizeTime(_my_time); + return *this; } + /** * */ -inline bool SetFromTimeStr(const char * str, Time_Clock & outtime) -{ - int year = 0; - int month = 0; - int day = 0; - int hour = 0; - int min = 0; - int sec = 0; +inline Time_Clock operator+(const Time_Clock &tm, const Time_Span &ts) { + Time_Clock work(tm); + work += ts; + return work; +} - if (sscanf(str, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &min, &sec) != 6) - return false; +/** + * + */ +inline Time_Clock operator-(const Time_Clock &tm, const Time_Span &ts) { + return TimeDifference(tm, ts); +} - outtime.Set(year, month, day, hour, min, sec); - return true; +/** + * + */ +inline const Time_Clock& Time_Clock::operator-=(const Time_Span &Time_Span) { + _my_time.tv_usec -= Time_Span._my_time.tv_usec; + _my_time.tv_sec -= Time_Span._my_time.tv_sec; + NormalizeTime(_my_time); + return *this; +} + +/** + * + */ +inline Time_Span operator-(const Time_Clock &tm1, const Time_Clock &tm2) { + return TimeDifference(tm1, tm2); } #endif //__TIME_GENERAL_H__ diff --git a/panda/src/nativenet/time_span.h b/panda/src/nativenet/time_span.h index f27d7401ab..4633ffef3c 100644 --- a/panda/src/nativenet/time_span.h +++ b/panda/src/nativenet/time_span.h @@ -1,360 +1,376 @@ #ifndef __TIME_SPAN_H__ #define __TIME_SPAN_H__ + /** * */ -class Time_Span -{ +class Time_Span { public: - // Constructors - Time_Span() - { - } + // Constructors + Time_Span() {} - Time_Span(struct timeval time) - { - _my_time = time;NormalizeTime(_my_time); - } + Time_Span(struct timeval time) { + _my_time = time; + NormalizeTime(_my_time); + } - Time_Span(time_t time); - Time_Span(long lDays, int nHours, int nMins, int nSecs, int usecs); - Time_Span(long seconds, int usecs ) ; - Time_Span(const Time_Span& Time_SpanSrc); - Time_Span(const Time_Clock& Time_SpanSrc); - Time_Span(PN_stdfloat Seconds); + Time_Span(time_t time); + Time_Span(long lDays, int nHours, int nMins, int nSecs, int usecs); + Time_Span(long seconds, int usecs); + Time_Span(const Time_Span &Time_SpanSrc); + Time_Span(const Time_Clock &Time_SpanSrc); + Time_Span(PN_stdfloat Seconds); + const Time_Span &operator=(const Time_Span &Time_SpanSrc); - const Time_Span& operator=(const Time_Span& Time_SpanSrc); + // Attributes extract parts + long GetDays() const; // total # of days + long GetTotalHours() const; + int GetHours() const; + long GetTotalMinutes() const; + int GetMinutes() const; + long GetTotalSeconds() const; + int GetSeconds() const; + long GetTotalMSeconds() const; + long GetTotal100Seconds() const; + long GetMSeconds() const; - // Attributes extract parts - long GetDays() const; // total # of days - long GetTotalHours() const; - int GetHours() const; - long GetTotalMinutes() const; - int GetMinutes() const; - long GetTotalSeconds() const; - int GetSeconds() const; - long GetTotalMSeconds() const; - long GetTotal100Seconds() const; - long GetMSeconds() const; + // Operations time math + const Time_Span &operator+=(Time_Span &Time_Span); + const Time_Span &operator-=(Time_Span &Time_Span); + bool operator==(Time_Span &Time_Span) const; + bool operator!=(Time_Span &Time_Span) const; + bool operator<(Time_Span &Time_Span) const; + bool operator>(Time_Span &Time_Span) const; + bool operator<=(Time_Span &Time_Span) const; + bool operator>=(Time_Span &Time_Span) const; + const timeval &GetTval() const { + return _my_time; + } - // Operations time math - const Time_Span& operator+=(Time_Span &Time_Span); - const Time_Span& operator-=(Time_Span &Time_Span); - bool operator==(Time_Span &Time_Span) const; - bool operator!=(Time_Span &Time_Span) const; - bool operator<(Time_Span &Time_Span) const; - bool operator>(Time_Span &Time_Span) const; - bool operator<=(Time_Span &Time_Span) const; - bool operator>=(Time_Span &Time_Span) const; - const timeval & GetTval() const - { - return _my_time; - } + void Set(long lDays, int nHours, int nMins, int nSecs, int usecs); + std::string Format(char *pFormat) const; - void Set(long lDays, int nHours, int nMins, int nSecs, int usecs); - - std::string Format(char *pFormat) const; private: - struct timeval _my_time; - friend class Time_Clock; + struct timeval _my_time; + friend class Time_Clock; }; + /** * */ -inline Time_Span::Time_Span(long seconds, int usecs) -{ - _my_time.tv_sec = seconds; - _my_time.tv_usec = usecs; - NormalizeTime(_my_time); +inline Time_Span:: +Time_Span(long seconds, int usecs) { + _my_time.tv_sec = seconds; + _my_time.tv_usec = usecs; + NormalizeTime(_my_time); } + /** * */ -inline Time_Span::Time_Span(time_t time) -{ - _my_time.tv_usec = 0; - _my_time.tv_sec = (long)time; +inline Time_Span:: +Time_Span(time_t time) { + _my_time.tv_usec = 0; + _my_time.tv_sec = (long)time; } + /** * */ -inline Time_Span::Time_Span(PN_stdfloat Seconds) -{ - _my_time.tv_sec = (long)Seconds; // this truncats .. desired result.. - _my_time.tv_usec = (long)((Seconds - (double)_my_time.tv_sec) * (double)USEC); +inline Time_Span:: +Time_Span(PN_stdfloat Seconds) { + _my_time.tv_sec = (long)Seconds; // this truncats .. desired result.. + _my_time.tv_usec = (long)((Seconds - (double)_my_time.tv_sec) * (double)USEC); } + /** * */ -inline Time_Span::Time_Span(long lDays, int nHours, int nMins, int nSecs, int usecs) -{ - _my_time.tv_sec = nSecs + 60 * (nMins + 60 * (nHours + 24 * lDays)); - _my_time.tv_usec = usecs; +inline Time_Span:: +Time_Span(long lDays, int nHours, int nMins, int nSecs, int usecs) { + _my_time.tv_sec = nSecs + 60 * (nMins + 60 * (nHours + 24 * lDays)); + _my_time.tv_usec = usecs; } /** * */ -inline void Time_Span::Set(long lDays, int nHours, int nMins, int nSecs, int usecs) -{ - _my_time.tv_sec = nSecs + 60 * (nMins + 60 * (nHours + 24 * lDays)); - _my_time.tv_usec = usecs; +inline void Time_Span:: +Set(long lDays, int nHours, int nMins, int nSecs, int usecs) { + _my_time.tv_sec = nSecs + 60 * (nMins + 60 * (nHours + 24 * lDays)); + _my_time.tv_usec = usecs; } /** * */ -inline Time_Span::Time_Span(const Time_Span& Time_SpanSrc) -{ - _my_time = Time_SpanSrc._my_time; +inline Time_Span:: +Time_Span(const Time_Span &Time_SpanSrc) { + _my_time = Time_SpanSrc._my_time; } /** * */ -inline Time_Span::Time_Span(const Time_Clock& Time_SpanSrc) -{ - _my_time = Time_SpanSrc._my_time; +inline Time_Span:: +Time_Span(const Time_Clock &Time_SpanSrc) { + _my_time = Time_SpanSrc._my_time; } /** * */ -inline const Time_Span& Time_Span::operator=(const Time_Span& Time_SpanSrc) -{ - if (&Time_SpanSrc == this) - return * this; - _my_time = Time_SpanSrc._my_time; return *this; -} - -/** - * - */ -inline long Time_Span::GetDays() const -{ - return _my_time.tv_sec / (24*3600L); -} - -/** - * - */ -inline long Time_Span::GetTotalHours() const -{ - return _my_time.tv_sec / 3600; -} - -/** - * - */ -inline int Time_Span::GetHours() const -{ - return (int)(GetTotalHours() - GetDays()*24); -} - -/** - * - */ -inline long Time_Span::GetTotalMinutes() const -{ - return _my_time.tv_sec / 60; -} - -/** - * - */ -inline int Time_Span::GetMinutes() const -{ - return (int)(GetTotalMinutes() - GetTotalHours()*60); -} - -/** - * - */ -inline long Time_Span::GetTotalSeconds() const -{ - return _my_time.tv_sec; -} - -/** - * - */ -inline long Time_Span::GetTotalMSeconds() const -{ - return (_my_time.tv_sec * 1000) + (_my_time.tv_usec / 1000); -} - - -inline long Time_Span::GetTotal100Seconds() const -{ - return (_my_time.tv_sec * 100) + (_my_time.tv_usec / 10000); -} - - - -/** - * - */ -inline long Time_Span::GetMSeconds() const -{ - return (_my_time.tv_usec / 1000); -} - - -/** - * - */ -inline int Time_Span::GetSeconds() const -{ - return (int)(GetTotalSeconds() - GetTotalMinutes()*60); -} - -/** - * - */ -inline Time_Span TimeDifference(const Time_Span &Time_Span1, const Time_Span &Time_Span2) -{ - timeval ans; - TimeDif(Time_Span2.GetTval(), Time_Span1.GetTval(), ans); - return Time_Span(ans); -} - -/** - * - */ -inline Time_Span TimeAddition(const Time_Span &Time_Span1, const Time_Span &Time_Span2) -{ - timeval ans; - TimeAdd(Time_Span2.GetTval(), Time_Span1.GetTval(), ans); - return Time_Span(ans); -} - -/** - * - */ -inline const Time_Span& Time_Span::operator+=(Time_Span &Time_Span) -{ - _my_time.tv_usec += Time_Span._my_time.tv_usec; - _my_time.tv_sec += Time_Span._my_time.tv_sec; - NormalizeTime(_my_time); +inline const Time_Span &Time_Span:: +operator=(const Time_Span &Time_SpanSrc) { + if (&Time_SpanSrc == this) { return *this; + } + _my_time = Time_SpanSrc._my_time; + return *this; } /** * */ -inline const Time_Span& Time_Span::operator-=(Time_Span &Time_Span) -{ - _my_time.tv_usec -= Time_Span._my_time.tv_usec; - _my_time.tv_sec -= Time_Span._my_time.tv_sec; - NormalizeTime(_my_time); - return *this; +inline long Time_Span:: +GetDays() const { + return _my_time.tv_sec / (24*3600L); } /** * */ -inline bool Time_Span::operator==(Time_Span &Time_Span) const -{ - return ((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec == Time_Span._my_time.tv_usec)); +inline long Time_Span:: +GetTotalHours() const { + return _my_time.tv_sec / 3600; } /** * */ -inline bool Time_Span::operator!=(Time_Span &Time_Span) const -{ - return ((_my_time.tv_sec != Time_Span._my_time.tv_sec) || (_my_time.tv_usec != Time_Span._my_time.tv_usec)); +inline int Time_Span:: +GetHours() const { + return (int)(GetTotalHours() - GetDays()*24); } /** * */ -inline bool Time_Span::operator<(Time_Span &Time_Span) const -{ - return ((_my_time.tv_sec < Time_Span._my_time.tv_sec) || - ((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec < Time_Span._my_time.tv_usec))); +inline long Time_Span:: +GetTotalMinutes() const { + return _my_time.tv_sec / 60; } /** * */ -inline bool Time_Span::operator>(Time_Span &Time_Span) const -{ - return ((_my_time.tv_sec > Time_Span._my_time.tv_sec) || - ((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec > Time_Span._my_time.tv_usec))); +inline int Time_Span:: +GetMinutes() const { + return (int)(GetTotalMinutes() - GetTotalHours()*60); } /** * */ -inline bool Time_Span::operator<=(Time_Span &Time_Span) const -{ - return ((_my_time.tv_sec < Time_Span._my_time.tv_sec) || - ((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec <= Time_Span._my_time.tv_usec))); +inline long Time_Span:: +GetTotalSeconds() const { + return _my_time.tv_sec; } /** * */ -inline bool Time_Span::operator>=(Time_Span &Time_Span) const -{ - return ((_my_time.tv_sec > Time_Span._my_time.tv_sec) || - ((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec >= Time_Span._my_time.tv_usec))); +inline long Time_Span:: +GetTotalMSeconds() const { + return (_my_time.tv_sec * 1000) + (_my_time.tv_usec / 1000); +} + +inline long Time_Span:: +GetTotal100Seconds() const { + return (_my_time.tv_sec * 100) + (_my_time.tv_usec / 10000); } /** * */ -inline std::string Time_Span::Format(char * pFormat) const +inline long Time_Span:: +GetMSeconds() const { + return (_my_time.tv_usec / 1000); +} + +/** + * + */ +inline int Time_Span:: +GetSeconds() const { + return (int)(GetTotalSeconds() - GetTotalMinutes()*60); +} + +/** + * + */ +inline Time_Span TimeDifference(const Time_Span &Time_Span1, const Time_Span &Time_Span2) { + timeval ans; + TimeDif(Time_Span2.GetTval(), Time_Span1.GetTval(), ans); + return Time_Span(ans); +} + +/** + * + */ +inline Time_Span TimeAddition(const Time_Span &Time_Span1, const Time_Span &Time_Span2) { + timeval ans; + TimeAdd(Time_Span2.GetTval(), Time_Span1.GetTval(), ans); + return Time_Span(ans); +} + +/** + * + */ +inline const Time_Span &Time_Span:: +operator+=(Time_Span &Time_Span) { + _my_time.tv_usec += Time_Span._my_time.tv_usec; + _my_time.tv_sec += Time_Span._my_time.tv_sec; + NormalizeTime(_my_time); + return *this; +} + +/** + * + */ +inline const Time_Span &Time_Span:: +operator-=(Time_Span &Time_Span) { + _my_time.tv_usec -= Time_Span._my_time.tv_usec; + _my_time.tv_sec -= Time_Span._my_time.tv_sec; + NormalizeTime(_my_time); + return *this; +} + +/** + * + */ +inline bool Time_Span:: +operator==(Time_Span &Time_Span) const { + return ((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec == Time_Span._my_time.tv_usec)); +} + +/** + * + */ +inline bool Time_Span:: +operator!=(Time_Span &Time_Span) const { + return ((_my_time.tv_sec != Time_Span._my_time.tv_sec) || (_my_time.tv_usec != Time_Span._my_time.tv_usec)); +} + +/** + * + */ +inline bool Time_Span:: +operator<(Time_Span &Time_Span) const { + return ((_my_time.tv_sec < Time_Span._my_time.tv_sec) || + ((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec < Time_Span._my_time.tv_usec))); +} + +/** + * + */ +inline bool Time_Span:: +operator>(Time_Span &Time_Span) const { + return ((_my_time.tv_sec > Time_Span._my_time.tv_sec) || + ((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec > Time_Span._my_time.tv_usec))); +} + +/** + * + */ +inline bool Time_Span:: +operator<=(Time_Span &Time_Span) const { + return ((_my_time.tv_sec < Time_Span._my_time.tv_sec) || + ((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec <= Time_Span._my_time.tv_usec))); +} + +/** + * + */ +inline bool Time_Span:: +operator>=(Time_Span &Time_Span) const { + return ((_my_time.tv_sec > Time_Span._my_time.tv_sec) || + ((_my_time.tv_sec == Time_Span._my_time.tv_sec) && (_my_time.tv_usec >= Time_Span._my_time.tv_usec))); +} + +/** + * + */ +inline std::string Time_Span:: +Format(char *pFormat) const { /* - * formatting Time_Spans is a little trickier than formatting * we are only - * interested in relative time formats, ie. it is illegal to format anything - * dealing with absolute time (i.e. years, months, day of week, day of year, - * timezones, ...) * the only valid formats: %D - # of days -- NEW !!! %H - - * hour in 24 hour format %M - minute (0-59) %S - seconds (0-59) %% - percent - * sign %N - nanosecs - */ -{ - char szBuffer[maxTimeBufferSize]; - char ch; - char * pch = szBuffer; +* formatting Time_Spans is a little trickier than formatting * we are only +* interested in relative time formats, ie. it is illegal to format anything +* dealing with absolute time (i.e. years, months, day of week, day of year, +* timezones, ...) * the only valid formats: %D - # of days -- NEW !!! %H - +* hour in 24 hour format %M - minute (0-59) %S - seconds (0-59) %% - percent +* sign %N - nanosecs +*/ + char szBuffer[maxTimeBufferSize]; + char ch; + char *pch = szBuffer; - while ((ch = *pFormat++) != '\0') { - assert(pch < &szBuffer[maxTimeBufferSize]); - if (ch == '%') { - switch (ch = *pFormat++) { - default: - assert(false); // probably a bad format character - case '%': - *pch++ = ch; - break; - case 'D': - pch += sprintf(pch, "%ld", GetDays()); - break; - case 'H': - pch += sprintf(pch, "%02d", GetHours()); - break; - case 'M': - pch += sprintf(pch, "%02d", GetMinutes()); - break; - case 'S': - pch += sprintf(pch, "%02d", GetSeconds()); - break; - case 'N': - pch += sprintf(pch, "%03ld", (long)(_my_time.tv_usec / 1000)); - break; - } - } else { - *pch++ = ch; - } + while ((ch = *pFormat++) != '\0') { + assert(pch < &szBuffer[maxTimeBufferSize]); + if (ch == '%') { + switch (ch = *pFormat++) { + default: + assert(false); // probably a bad format character + case '%': + *pch++ = ch; + break; + case 'D': +#ifdef _WIN32 + pch += sprintf_s(pch, maxTimeBufferSize, "%ld", GetDays()); +#else + pch += snprintf(pch, maxTimeBufferSize, "%ld", GetDays()); +#endif + break; + case 'H': +#ifdef _WIN32 + pch += sprintf_s(pch, maxTimeBufferSize, "%02d", GetHours()); +#else + pch += snprintf(pch, maxTimeBufferSize, "%02d", GetHours()); +#endif + break; + case 'M': +#ifdef _WIN32 + pch += sprintf_s(pch, maxTimeBufferSize, "%02d", GetMinutes()); +#else + pch += snprintf(pch, maxTimeBufferSize, "%02d", GetMinutes()); +#endif + break; + case 'S': +#ifdef _WIN32 + pch += sprintf_s(pch, maxTimeBufferSize, "%02d", GetSeconds()); +#else + pch += snprintf(pch, maxTimeBufferSize, "%02d", GetSeconds()); +#endif + break; + case 'N': +#ifdef _WIN32 + pch += sprintf_s(pch, maxTimeBufferSize, "%03ld", (long)(_my_time.tv_usec / 1000)); +#else + pch += snprintf(pch, maxTimeBufferSize, "%03ld", (long)(_my_time.tv_usec / 1000)); +#endif + break; + } + } else { + *pch++ = ch; } + } - *pch = '\0'; - return std::string(szBuffer); + *pch = '\0'; + return std::string(szBuffer); } #endif //__TIME_SPAN_H__ diff --git a/panda/src/net/connectionListener.cxx b/panda/src/net/connectionListener.cxx index a6e816683d..c959051653 100644 --- a/panda/src/net/connectionListener.cxx +++ b/panda/src/net/connectionListener.cxx @@ -77,7 +77,7 @@ process_incoming_data(SocketInfo *sinfo) { NetAddress net_addr(addr); net_cat.info() - << "Received TCP connection from client " << net_addr.get_ip_string() + << "Received TCP connection from client " << net_addr << " on port " << sinfo->_connection->get_address().get_port() << "\n"; diff --git a/panda/src/net/connectionManager.cxx b/panda/src/net/connectionManager.cxx index abfdc2f541..f7fdbe7e3e 100644 --- a/panda/src/net/connectionManager.cxx +++ b/panda/src/net/connectionManager.cxx @@ -69,7 +69,7 @@ ConnectionManager:: * communication. */ PT(Connection) ConnectionManager:: -open_UDP_connection(int port) { +open_UDP_connection(uint16_t port) { return open_UDP_connection("", port); } @@ -80,7 +80,8 @@ open_UDP_connection(int port) { * sending. * * This variant accepts both a hostname and port to listen on a particular - * interface; if the hostname is empty, all interfaces will be available. + * interface; if the hostname is empty, all interfaces will be available, + * both IPv4 and IPv6. * * If for_broadcast is true, this UDP connection will be configured to send * and/or receive messages on the broadcast address (255.255.255.255); @@ -90,24 +91,27 @@ open_UDP_connection(int port) { * communication. */ PT(Connection) ConnectionManager:: -open_UDP_connection(const string &hostname, int port, bool for_broadcast) { +open_UDP_connection(const string &hostname, uint16_t port, bool for_broadcast) { Socket_UDP *socket = new Socket_UDP; if (port > 0) { + bool okflag; NetAddress address; if (hostname.empty()) { - address.set_any(port); + // The empty string means to listen on both IPv4 and IPv6 interfaces. + okflag = socket->OpenForInput(port); } else { address.set_host(hostname, port); + okflag = socket->OpenForInput(address.get_addr()); } - if (!socket->OpenForInput(address.get_addr())) { + if (!okflag) { if (hostname.empty()) { net_cat.error() << "Unable to bind to port " << port << " for UDP.\n"; } else { net_cat.error() - << "Unable to bind to " << hostname << ":" << port << " for UDP.\n"; + << "Unable to bind to " << address << " for UDP.\n"; } delete socket; return PT(Connection)(); @@ -124,7 +128,7 @@ open_UDP_connection(const string &hostname, int port, bool for_broadcast) { << "Creating UDP " << broadcast_note << "connection for port " << port << "\n"; } else { net_cat.info() - << "Creating UDP " << broadcast_note << "connection for " << hostname << ":" << port << "\n"; + << "Creating UDP " << broadcast_note << "connection for " << address << "\n"; } } else { @@ -150,23 +154,32 @@ open_UDP_connection(const string &hostname, int port, bool for_broadcast) { return connection; } - - /** * Creates a socket to be used as a rendezvous socket for a server to listen * for TCP connections. The socket returned by this call should only be added * to a ConnectionListener (not to a generic ConnectionReader). * * This variant of this method accepts a single port, and will listen to that - * port on all available interfaces. + * port on all available interfaces, both IPv4 and IPv6. * * backlog is the maximum length of the queue of pending connections. */ PT(Connection) ConnectionManager:: -open_TCP_server_rendezvous(int port, int backlog) { - NetAddress address; - address.set_any(port); - return open_TCP_server_rendezvous(address, backlog); +open_TCP_server_rendezvous(uint16_t port, int backlog) { + Socket_TCP_Listen *socket = new Socket_TCP_Listen; + if (!socket->OpenForListen(port, backlog)) { + net_cat.info() + << "Unable to listen to port " << port << " for TCP.\n"; + delete socket; + return PT(Connection)(); + } + + net_cat.info() + << "Listening for TCP connections on port " << port << "\n"; + + PT(Connection) connection = new Connection(this, socket); + new_connection(connection); + return connection; } /** @@ -182,14 +195,14 @@ open_TCP_server_rendezvous(int port, int backlog) { * backlog is the maximum length of the queue of pending connections. */ PT(Connection) ConnectionManager:: -open_TCP_server_rendezvous(const string &hostname, int port, int backlog) { - NetAddress address; +open_TCP_server_rendezvous(const string &hostname, uint16_t port, int backlog) { if (hostname.empty()) { - address.set_any(port); + return open_TCP_server_rendezvous(port, backlog); } else { + NetAddress address; address.set_host(hostname, port); + return open_TCP_server_rendezvous(address, backlog); } - return open_TCP_server_rendezvous(address, backlog); } /** @@ -204,24 +217,16 @@ open_TCP_server_rendezvous(const string &hostname, int port, int backlog) { */ PT(Connection) ConnectionManager:: open_TCP_server_rendezvous(const NetAddress &address, int backlog) { - ostringstream strm; - if (address.get_ip() == 0) { - strm << "port " << address.get_port(); - } else { - strm << address.get_ip_string() << ":" << address.get_port(); - } - Socket_TCP_Listen *socket = new Socket_TCP_Listen; - bool okflag = socket->OpenForListen(address.get_addr(), backlog); - if (!okflag) { + if (!socket->OpenForListen(address.get_addr(), backlog)) { net_cat.info() - << "Unable to listen to " << strm.str() << " for TCP.\n"; + << "Unable to listen to " << address << " for TCP.\n"; delete socket; return PT(Connection)(); } net_cat.info() - << "Listening for TCP connections on " << strm.str() << "\n"; + << "Listening for TCP connections on " << address << "\n"; PT(Connection) connection = new Connection(this, socket); new_connection(connection); @@ -263,7 +268,7 @@ open_TCP_client_connection(const NetAddress &address, int timeout_ms) { if (okflag) { // So, the connect() operation finished, but did it succeed or fail? - if (socket->GetPeerName().GetIPAddressRaw() == 0) { + if (socket->GetPeerName().is_any()) { // No peer means it failed. okflag = false; } @@ -271,8 +276,7 @@ open_TCP_client_connection(const NetAddress &address, int timeout_ms) { if (!okflag) { net_cat.error() - << "Unable to open TCP connection to server " - << address.get_ip_string() << " on port " << address.get_port() << "\n"; + << "Unable to open TCP connection to server " << address << "\n"; delete socket; return PT(Connection)(); } @@ -286,8 +290,7 @@ open_TCP_client_connection(const NetAddress &address, int timeout_ms) { #endif // SIMPLE_THREADS net_cat.info() - << "Opened TCP connection to server " << address.get_ip_string() - << " on port " << address.get_port() << "\n"; + << "Opened TCP connection to server " << address << "\n"; PT(Connection) connection = new Connection(this, socket); new_connection(connection); @@ -299,7 +302,7 @@ open_TCP_client_connection(const NetAddress &address, int timeout_ms) { * communications to a named host and port. */ PT(Connection) ConnectionManager:: -open_TCP_client_connection(const string &hostname, int port, +open_TCP_client_connection(const string &hostname, uint16_t port, int timeout_ms) { NetAddress address; if (!address.set_host(hostname, port)) { @@ -412,7 +415,7 @@ wait_for_readers(double timeout) { wait_timeout = min(wait_timeout, stop - now); } - PN_uint32 wait_timeout_ms = (PN_uint32)(wait_timeout * 1000.0); + uint32_t wait_timeout_ms = (uint32_t)(wait_timeout * 1000.0); if (any_threaded) { // If there are any threaded ConnectionReaders, we can't block at all. wait_timeout_ms = 0; @@ -474,11 +477,12 @@ scan_interfaces() { #ifdef WIN32_VC int flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER; + ULONG family = support_ipv6 ? AF_UNSPEC : AF_INET; ULONG buffer_size = 0; - ULONG result = GetAdaptersAddresses(AF_INET, flags, NULL, NULL, &buffer_size); + ULONG result = GetAdaptersAddresses(family, flags, NULL, NULL, &buffer_size); if (result == ERROR_BUFFER_OVERFLOW) { IP_ADAPTER_ADDRESSES *addresses = (IP_ADAPTER_ADDRESSES *)PANDA_MALLOC_ARRAY(buffer_size); - result = GetAdaptersAddresses(AF_INET, flags, NULL, addresses, &buffer_size); + result = GetAdaptersAddresses(family, flags, NULL, addresses, &buffer_size); if (result == ERROR_SUCCESS) { IP_ADAPTER_ADDRESSES *p = addresses; while (p != NULL) { @@ -502,7 +506,7 @@ scan_interfaces() { IP_ADAPTER_PREFIX *m = p->FirstPrefix; int mc = 0; while (m != NULL && mc < 3) { - addresses[mc] = NetAddress(Socket_Address(*(sockaddr_in *)m->Address.lpSockaddr)); + addresses[mc] = NetAddress(Socket_Address(*m->Address.lpSockaddr)); m = m->Next; ++mc; } @@ -517,10 +521,13 @@ scan_interfaces() { // Now, we can infer the netmask by the difference between the // network address (the first address) and the broadcast address // (the last address). - PN_uint32 netmask = addresses[0].get_ip() - addresses[2].get_ip() - 1; - Socket_Address sa; - sa.set_host(netmask, 0); - iface.set_netmask(NetAddress(sa)); + if (addresses[0].get_addr().get_family() == AF_INET && + addresses[2].get_addr().get_family() == AF_INET) { + uint32_t netmask = addresses[0].get_ip() - addresses[2].get_ip() - 1; + Socket_Address sa; + sa.set_host(netmask, 0); + iface.set_netmask(NetAddress(sa)); + } } } @@ -545,19 +552,20 @@ scan_interfaces() { struct ifaddrs *p = ifa; while (p != NULL) { - if (p->ifa_addr->sa_family == AF_INET) { + if (p->ifa_addr->sa_family == AF_INET || + (support_ipv6 && p->ifa_addr->sa_family == AF_INET6)) { Interface iface; iface.set_name(p->ifa_name); if (p->ifa_addr != NULL) { - iface.set_ip(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_addr))); + iface.set_ip(NetAddress(Socket_Address(*p->ifa_addr))); } if (p->ifa_netmask != NULL) { - iface.set_netmask(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_netmask))); + iface.set_netmask(NetAddress(Socket_Address(*p->ifa_netmask))); } if ((p->ifa_flags & IFF_BROADCAST) && p->ifa_broadaddr != NULL) { - iface.set_broadcast(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_broadaddr))); + iface.set_broadcast(NetAddress(Socket_Address(*p->ifa_broadaddr))); } else if ((p->ifa_flags & IFF_POINTOPOINT) && p->ifa_dstaddr != NULL) { - iface.set_p2p(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_dstaddr))); + iface.set_p2p(NetAddress(Socket_Address(*p->ifa_dstaddr))); } _interfaces.push_back(iface); } @@ -572,10 +580,9 @@ scan_interfaces() { /** * This returns the number of usable network interfaces detected on this - * machine. (Currently, only IPv4 interfaces are reported.) See - * scan_interfaces() to repopulate this list. + * machine. See scan_interfaces() to repopulate this list. */ -int ConnectionManager:: +size_t ConnectionManager:: get_num_interfaces() { if (!_interfaces_scanned) { scan_interfaces(); @@ -586,16 +593,15 @@ get_num_interfaces() { /** * Returns the nth usable network interface detected on this machine. - * (Currently, only IPv4 interfaces are reported.) See scan_interfaces() to - * repopulate this list. + * See scan_interfaces() to repopulate this list. */ const ConnectionManager::Interface &ConnectionManager:: -get_interface(int n) { +get_interface(size_t n) { if (!_interfaces_scanned) { scan_interfaces(); } LightMutexHolder holder(_set_mutex); - nassertr(n >= 0 && n < (int)_interfaces.size(), _interfaces[0]); + nassertr(n < _interfaces.size(), _interfaces[0]); return _interfaces[n]; } @@ -709,9 +715,9 @@ remove_writer(ConnectionWriter *writer) { * Formats a device's MAC address into a string. */ string ConnectionManager:: -format_mac_address(const unsigned char *data, int data_size) { +format_mac_address(const unsigned char *data, size_t data_size) { stringstream strm; - for (int di = 0; di < data_size; ++di) { + for (size_t di = 0; di < data_size; ++di) { if (di != 0) { strm << "-"; } @@ -728,16 +734,16 @@ void ConnectionManager::Interface:: output(ostream &out) const { out << get_name() << " ["; if (has_ip()) { - out << " " << get_ip(); + out << " " << get_ip().get_ip_string(); } if (has_netmask()) { - out << " netmask " << get_netmask(); + out << " netmask " << get_netmask().get_ip_string(); } if (has_broadcast()) { - out << " broadcast " << get_broadcast(); + out << " broadcast " << get_broadcast().get_ip_string(); } if (has_p2p()) { - out << " p2p " << get_p2p(); + out << " p2p " << get_p2p().get_ip_string(); } out << " ]"; } diff --git a/panda/src/net/connectionManager.h b/panda/src/net/connectionManager.h index cf5772386c..1b00268d6c 100644 --- a/panda/src/net/connectionManager.h +++ b/panda/src/net/connectionManager.h @@ -43,18 +43,18 @@ PUBLISHED: ConnectionManager(); virtual ~ConnectionManager(); - PT(Connection) open_UDP_connection(int port = 0); - PT(Connection) open_UDP_connection(const string &hostname, int port, bool for_broadcast = false); + PT(Connection) open_UDP_connection(uint16_t port = 0); + PT(Connection) open_UDP_connection(const string &hostname, uint16_t port, bool for_broadcast = false); - BLOCKING PT(Connection) open_TCP_server_rendezvous(int port, int backlog); + BLOCKING PT(Connection) open_TCP_server_rendezvous(uint16_t port, int backlog); BLOCKING PT(Connection) open_TCP_server_rendezvous(const string &hostname, - int port, int backlog); + uint16_t port, int backlog); BLOCKING PT(Connection) open_TCP_server_rendezvous(const NetAddress &address, int backlog); BLOCKING PT(Connection) open_TCP_client_connection(const NetAddress &address, int timeout_ms); - BLOCKING PT(Connection) open_TCP_client_connection(const string &hostname, int port, - int timeout_ms); + BLOCKING PT(Connection) open_TCP_client_connection(const string &hostname, + uint16_t port, int timeout_ms); bool close_connection(const PT(Connection) &connection); BLOCKING bool wait_for_readers(double timeout); @@ -104,10 +104,13 @@ PUBLISHED: }; void scan_interfaces(); - int get_num_interfaces(); - const Interface &get_interface(int n); + size_t get_num_interfaces(); + const Interface &get_interface(size_t n); MAKE_SEQ(get_interfaces, get_num_interfaces, get_interface); + MAKE_PROPERTY(host_name, get_host_name); + MAKE_SEQ_PROPERTY(interfaces, get_num_interfaces, get_interface); + protected: void new_connection(const PT(Connection) &connection); virtual void flush_read_connection(Connection *connection); @@ -119,7 +122,7 @@ protected: void add_writer(ConnectionWriter *writer); void remove_writer(ConnectionWriter *writer); - string format_mac_address(const unsigned char *data, int data_size); + string format_mac_address(const unsigned char *data, size_t data_size); typedef phash_set< PT(Connection) > Connections; typedef phash_set Readers; diff --git a/panda/src/net/connectionReader.cxx b/panda/src/net/connectionReader.cxx index 7a63d90833..0ca114e476 100644 --- a/panda/src/net/connectionReader.cxx +++ b/panda/src/net/connectionReader.cxx @@ -834,7 +834,7 @@ get_next_available_socket(bool allow_block, int current_thread_index) { _next_index = 0; if (!_shutdown) { - PN_uint32 timeout = (PN_uint32)(get_net_max_block() * 1000.0); + uint32_t timeout = (uint32_t)(get_net_max_block() * 1000.0); if (!allow_block) { timeout = 0; } diff --git a/panda/src/net/datagramTCPHeader.cxx b/panda/src/net/datagramTCPHeader.cxx index 3ad1d53f5b..533e3e671b 100644 --- a/panda/src/net/datagramTCPHeader.cxx +++ b/panda/src/net/datagramTCPHeader.cxx @@ -31,7 +31,7 @@ DatagramTCPHeader(const NetDatagram &datagram, int header_size) { case datagram_tcp16_header_size: { - PN_uint16 size = str.length(); + uint16_t size = str.length(); nassertv(size == str.length()); _header.add_uint16(size); } @@ -39,7 +39,7 @@ DatagramTCPHeader(const NetDatagram &datagram, int header_size) { case datagram_tcp32_header_size: { - PN_uint32 size = str.length(); + uint32_t size = str.length(); nassertv(size == str.length()); _header.add_uint32(size); } diff --git a/panda/src/net/datagramTCPHeader.h b/panda/src/net/datagramTCPHeader.h index ac8119f4fa..51f489e3ed 100644 --- a/panda/src/net/datagramTCPHeader.h +++ b/panda/src/net/datagramTCPHeader.h @@ -21,8 +21,8 @@ #include "datagramIterator.h" #include "numeric_types.h" -static const int datagram_tcp16_header_size = sizeof(PN_uint16); -static const int datagram_tcp32_header_size = sizeof(PN_uint32); +static const int datagram_tcp16_header_size = sizeof(uint16_t); +static const int datagram_tcp32_header_size = sizeof(uint32_t); class NetDatagram; diff --git a/panda/src/net/datagramUDPHeader.cxx b/panda/src/net/datagramUDPHeader.cxx index b9b0938021..b491190187 100644 --- a/panda/src/net/datagramUDPHeader.cxx +++ b/panda/src/net/datagramUDPHeader.cxx @@ -25,9 +25,9 @@ DatagramUDPHeader:: DatagramUDPHeader(const NetDatagram &datagram) { const string &str = datagram.get_message(); - PN_uint16 checksum = 0; + uint16_t checksum = 0; for (size_t p = 0; p < str.size(); p++) { - checksum += (PN_uint16)(PN_uint8)str[p]; + checksum += (uint16_t)(uint8_t)str[p]; } // Now pack the header. @@ -51,9 +51,9 @@ bool DatagramUDPHeader:: verify_datagram(const NetDatagram &datagram) const { const string &str = datagram.get_message(); - PN_uint16 checksum = 0; + uint16_t checksum = 0; for (size_t p = 0; p < str.size(); p++) { - checksum += (PN_uint16)(PN_uint8)str[p]; + checksum += (uint16_t)(uint8_t)str[p]; } if (checksum == get_datagram_checksum()) { diff --git a/panda/src/net/datagramUDPHeader.h b/panda/src/net/datagramUDPHeader.h index fd2abbaa47..e8ee0b8b1a 100644 --- a/panda/src/net/datagramUDPHeader.h +++ b/panda/src/net/datagramUDPHeader.h @@ -21,7 +21,7 @@ #include "datagramIterator.h" #include "numeric_types.h" -static const int datagram_udp_header_size = sizeof(PN_uint16); +static const int datagram_udp_header_size = sizeof(uint16_t); class NetDatagram; diff --git a/panda/src/net/netAddress.cxx b/panda/src/net/netAddress.cxx index 4ae75f3434..0f0404dc45 100644 --- a/panda/src/net/netAddress.cxx +++ b/panda/src/net/netAddress.cxx @@ -91,6 +91,14 @@ set_port(int port) { _addr.set_port(port); } +/** + * Returns true if the IP address has only zeroes. + */ +bool NetAddress:: +is_any() const { + return _addr.is_any(); +} + /** * Returns the IP address to which this address refers, formatted as a string. */ @@ -102,8 +110,9 @@ get_ip_string() const { /** * Returns the IP address to which this address refers, as a 32-bit integer, * in host byte order. + * @deprecated Does not work with IPv6 addresses. */ -PN_uint32 NetAddress:: +uint32_t NetAddress:: get_ip() const { return _addr.GetIPAddressRaw(); } @@ -113,11 +122,11 @@ get_ip() const { * components; component 0 is the first (leftmost), and component 3 is the * last (rightmost) in the dotted number convention. */ -PN_uint8 NetAddress:: +uint8_t NetAddress:: get_ip_component(int n) const { nassertr(n >= 0 && n < 4, 0); - PN_uint32 ip_long = _addr.GetIPAddressRaw(); - const PN_uint8 *ip = (const PN_uint8 *)&ip_long; + uint32_t ip_long = _addr.GetIPAddressRaw(); + const uint8_t *ip = (const uint8_t *)&ip_long; return ip[n]; } @@ -135,7 +144,7 @@ get_addr() const { */ void NetAddress:: output(ostream &out) const { - out << get_ip_string(); + out << _addr.get_ip_port(); } /** diff --git a/panda/src/net/netAddress.h b/panda/src/net/netAddress.h index e28a7d2443..d6b15b307e 100644 --- a/panda/src/net/netAddress.h +++ b/panda/src/net/netAddress.h @@ -37,8 +37,9 @@ PUBLISHED: int get_port() const; void set_port(int port); string get_ip_string() const; - PN_uint32 get_ip() const; - PN_uint8 get_ip_component(int n) const; + bool is_any() const; + uint32_t get_ip() const; + uint8_t get_ip_component(int n) const; const Socket_Address &get_addr() const; diff --git a/panda/src/ode/odeWorld.cxx b/panda/src/ode/odeWorld.cxx index 5e3986b6f5..30b98ddd8b 100644 --- a/panda/src/ode/odeWorld.cxx +++ b/panda/src/ode/odeWorld.cxx @@ -63,7 +63,7 @@ add_body_dampening(OdeBody& body, int surface) { void OdeWorld:: -init_surface_table(PN_uint8 num_surfaces) { +init_surface_table(uint8_t num_surfaces) { _surface_table = new sSurfaceParams[num_surfaces * num_surfaces]; // _dampen_table = new sSurfaceParams[num_surfaces * num_surfaces]; _num_surfaces = num_surfaces; @@ -92,7 +92,7 @@ set_surface(int pos1, int pos2, sSurfaceParams& entry) { sSurfaceParams& OdeWorld:: -get_surface(PN_uint8 surface1, PN_uint8 surface2) { +get_surface(uint8_t surface1, uint8_t surface2) { int true_pos = 0; if(surface1 >= surface2) { true_pos = (surface1 * _num_surfaces) + surface2; @@ -108,7 +108,7 @@ get_surface(PN_uint8 surface1, PN_uint8 surface2) { } void OdeWorld:: -set_surface_entry(PN_uint8 pos1, PN_uint8 pos2, +set_surface_entry(uint8_t pos1, uint8_t pos2, dReal mu, dReal bounce, dReal bounce_vel, diff --git a/panda/src/ode/odeWorld.h b/panda/src/ode/odeWorld.h index 4238700af9..fc17382115 100644 --- a/panda/src/ode/odeWorld.h +++ b/panda/src/ode/odeWorld.h @@ -77,10 +77,10 @@ PUBLISHED: INLINE int compare_to(const OdeWorld &other) const; - void init_surface_table(PN_uint8 num_surfaces); + void init_surface_table(uint8_t num_surfaces); // void assign_surface_body(OdeBody& body, int surface); void add_body_dampening(OdeBody& body, int surface); - void set_surface_entry(PN_uint8 pos1, PN_uint8 pos2, + void set_surface_entry(uint8_t pos1, uint8_t pos2, dReal mu, dReal bounce, dReal bounce_vel, @@ -93,7 +93,7 @@ PUBLISHED: operator bool () const; public: - sSurfaceParams& get_surface(PN_uint8 surface1, PN_uint8 surface2); + sSurfaceParams& get_surface(uint8_t surface1, uint8_t surface2); void set_surface(int pos1, int pos2, sSurfaceParams& entry); sBodyParams get_surface_body(dBodyID id); void set_dampen_on_bodies(dBodyID id1, dBodyID id2,dReal damp); @@ -102,7 +102,7 @@ public: private: dWorldID _id; sSurfaceParams *_surface_table; - PN_uint8 _num_surfaces; + uint8_t _num_surfaces; typedef pmap BodyDampenMap; BodyDampenMap _body_dampen_map; diff --git a/panda/src/parametrics/nurbsSurfaceEvaluator.h b/panda/src/parametrics/nurbsSurfaceEvaluator.h index ebba47bbc5..a2f468d716 100644 --- a/panda/src/parametrics/nurbsSurfaceEvaluator.h +++ b/panda/src/parametrics/nurbsSurfaceEvaluator.h @@ -79,6 +79,11 @@ PUBLISHED: void output(ostream &out) const; + MAKE_PROPERTY(u_order, get_u_order, set_u_order); + MAKE_PROPERTY(v_order, get_v_order, set_v_order); + MAKE_SEQ_PROPERTY(u_knots, get_num_u_knots, get_u_knot, set_u_knot); + MAKE_SEQ_PROPERTY(v_knots, get_num_v_knots, get_v_knot, set_v_knot); + public: typedef epvector Vert4Array; typedef pvector Vert3Array; diff --git a/panda/src/parametrics/parametricCurveCollection.cxx b/panda/src/parametrics/parametricCurveCollection.cxx index 98e9a0459e..2778161e34 100644 --- a/panda/src/parametrics/parametricCurveCollection.cxx +++ b/panda/src/parametrics/parametricCurveCollection.cxx @@ -87,6 +87,7 @@ remove_curve(ParametricCurve *curve) { return true; } + /** * Removes the indicated ParametricCurve from the collection, by its index * number. @@ -100,6 +101,20 @@ remove_curve(int index) { redraw(); } + +/** + * Replaces the indicated ParametricCurve from the collection, by its index + * number. + */ +void ParametricCurveCollection:: +set_curve(int index, ParametricCurve *curve) { + nassertv(index >= 0 && index < (int)_curves.size()); + prepare_remove_curve(_curves[index]); + prepare_add_curve(curve); + _curves[index] = curve; + redraw(); +} + /** * Returns true if the indicated ParametricCurve appears in this collection, * false otherwise. diff --git a/panda/src/parametrics/parametricCurveCollection.h b/panda/src/parametrics/parametricCurveCollection.h index 446c0a4e8d..42a84c7861 100644 --- a/panda/src/parametrics/parametricCurveCollection.h +++ b/panda/src/parametrics/parametricCurveCollection.h @@ -44,6 +44,7 @@ PUBLISHED: int add_curves(PandaNode *node); bool remove_curve(ParametricCurve *curve); void remove_curve(int index); + void set_curve(int index, ParametricCurve *curve); bool has_curve(ParametricCurve *curve) const; void clear(); void clear_timewarps(); @@ -61,6 +62,13 @@ PUBLISHED: INLINE PN_stdfloat get_max_t() const; + MAKE_SEQ_PROPERTY(curves, get_num_curves, get_curve, set_curve, remove_curve); + MAKE_PROPERTY(xyz_curve, get_xyz_curve); + MAKE_PROPERTY(hpr_curve, get_hpr_curve); + MAKE_PROPERTY(default_curve, get_default_curve); + MAKE_SEQ_PROPERTY(timewarp_curves, get_num_timewarps, get_timewarp_curve); + MAKE_PROPERTY(max_t, get_max_t); + void make_even(PN_stdfloat max_t, PN_stdfloat segments_per_unit); void face_forward(PN_stdfloat segments_per_unit); void reset_max_t(PN_stdfloat max_t); diff --git a/panda/src/pgraph/alphaTestAttrib.h b/panda/src/pgraph/alphaTestAttrib.h index 8d620e66e7..5c38727347 100644 --- a/panda/src/pgraph/alphaTestAttrib.h +++ b/panda/src/pgraph/alphaTestAttrib.h @@ -36,6 +36,10 @@ PUBLISHED: INLINE PN_stdfloat get_reference_alpha() const; INLINE PandaCompareFunc get_mode() const; +PUBLISHED: + MAKE_PROPERTY(reference_alpha, get_reference_alpha); + MAKE_PROPERTY(mode, get_mode); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/antialiasAttrib.h b/panda/src/pgraph/antialiasAttrib.h index 146561407d..30a72bb535 100644 --- a/panda/src/pgraph/antialiasAttrib.h +++ b/panda/src/pgraph/antialiasAttrib.h @@ -52,6 +52,11 @@ PUBLISHED: INLINE unsigned short get_mode_type() const; INLINE unsigned short get_mode_quality() const; +PUBLISHED: + MAKE_PROPERTY(mode, get_mode); + MAKE_PROPERTY(mode_type, get_mode_type); + MAKE_PROPERTY(mode_quality, get_mode_quality); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/audioVolumeAttrib.h b/panda/src/pgraph/audioVolumeAttrib.h index 29ccf23563..3b2120462f 100644 --- a/panda/src/pgraph/audioVolumeAttrib.h +++ b/panda/src/pgraph/audioVolumeAttrib.h @@ -40,6 +40,9 @@ PUBLISHED: INLINE PN_stdfloat get_volume() const; CPT(RenderAttrib) set_volume(PN_stdfloat volume) const; +PUBLISHED: + MAKE_PROPERTY2(volume, has_volume, get_volume); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/auxBitplaneAttrib.h b/panda/src/pgraph/auxBitplaneAttrib.h index 75ac6aee01..4c5866c49c 100644 --- a/panda/src/pgraph/auxBitplaneAttrib.h +++ b/panda/src/pgraph/auxBitplaneAttrib.h @@ -63,6 +63,9 @@ PUBLISHED: INLINE int get_outputs() const; +PUBLISHED: + MAKE_PROPERTY(outputs, get_outputs); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/camera.cxx b/panda/src/pgraph/camera.cxx index 575b5236ed..d15e9a2bf3 100644 --- a/panda/src/pgraph/camera.cxx +++ b/panda/src/pgraph/camera.cxx @@ -272,8 +272,10 @@ write_datagram(BamWriter *manager, Datagram &dg) { dg.add_bool(_active); dg.add_uint32(_camera_mask.get_word()); - manager->write_pointer(dg, _initial_state); - dg.add_stdfloat(_lod_scale); + if (manager->get_file_minor_ver() >= 41) { + manager->write_pointer(dg, _initial_state); + dg.add_stdfloat(_lod_scale); + } } //////////////////////////////////////////////////////////////////// @@ -286,7 +288,10 @@ write_datagram(BamWriter *manager, Datagram &dg) { int Camera:: complete_pointers(TypedWritable **p_list, BamReader *manager) { int pi = LensNode::complete_pointers(p_list, manager); - _initial_state = DCAST(RenderState, p_list[pi++]); + + if (manager->get_file_minor_ver() >= 41) { + _initial_state = DCAST(RenderState, p_list[pi++]); + } return pi; } diff --git a/panda/src/pgraph/camera.h b/panda/src/pgraph/camera.h index 8d30d146da..826000fbae 100644 --- a/panda/src/pgraph/camera.h +++ b/panda/src/pgraph/camera.h @@ -55,6 +55,7 @@ PUBLISHED: INLINE int get_num_display_regions() const; INLINE DisplayRegionBase *get_display_region(int n) const; MAKE_SEQ(get_display_regions, get_num_display_regions, get_display_region); + MAKE_SEQ_PROPERTY(display_regions, get_num_display_regions, get_display_region); INLINE void set_camera_mask(DrawMask mask); INLINE DrawMask get_camera_mask() const; diff --git a/panda/src/pgraph/clipPlaneAttrib.cxx b/panda/src/pgraph/clipPlaneAttrib.cxx index d36817a20d..7fd2da2d83 100644 --- a/panda/src/pgraph/clipPlaneAttrib.cxx +++ b/panda/src/pgraph/clipPlaneAttrib.cxx @@ -872,18 +872,32 @@ write_datagram(BamWriter *manager, Datagram &dg) { // write the number of off_planes dg.add_uint16(get_num_off_planes()); + // write the off planes pointers if any Planes::const_iterator fi; - for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) { - (*fi).write_datagram(manager, dg); + if (manager->get_file_minor_ver() < 40) { + for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) { + manager->write_pointer(dg, fi->node()); + } + } else { + for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) { + (*fi).write_datagram(manager, dg); + } } // write the number of on planes dg.add_uint16(get_num_on_planes()); + // write the on planes pointers if any Planes::const_iterator nti; - for (nti = _on_planes.begin(); nti != _on_planes.end(); ++nti) { - (*nti).write_datagram(manager, dg); + if (manager->get_file_minor_ver() < 40) { + for (nti = _on_planes.begin(); nti != _on_planes.end(); ++nti) { + manager->write_pointer(dg, nti->node()); + } + } else { + for (nti = _on_planes.begin(); nti != _on_planes.end(); ++nti) { + (*nti).write_datagram(manager, dg); + } } } diff --git a/panda/src/pgraph/colorAttrib.h b/panda/src/pgraph/colorAttrib.h index e2f38f46ed..54b57b8abb 100644 --- a/panda/src/pgraph/colorAttrib.h +++ b/panda/src/pgraph/colorAttrib.h @@ -42,6 +42,10 @@ PUBLISHED: INLINE Type get_color_type() const; INLINE const LColor &get_color() const; +PUBLISHED: + MAKE_PROPERTY(color_type, get_color_type); + MAKE_PROPERTY(color, get_color); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/colorBlendAttrib.I b/panda/src/pgraph/colorBlendAttrib.I index fa2aca94ff..1df1f9eb6c 100644 --- a/panda/src/pgraph/colorBlendAttrib.I +++ b/panda/src/pgraph/colorBlendAttrib.I @@ -19,6 +19,9 @@ ColorBlendAttrib() : _mode(M_none), _a(O_one), _b(O_one), + _alpha_mode(M_none), + _alpha_a(O_one), + _alpha_b(O_one), _color(LColor::zero()), _involves_constant_color(false), _involves_color_scale(false) @@ -31,18 +34,29 @@ ColorBlendAttrib() : INLINE ColorBlendAttrib:: ColorBlendAttrib(ColorBlendAttrib::Mode mode, ColorBlendAttrib::Operand a, ColorBlendAttrib::Operand b, + ColorBlendAttrib::Mode alpha_mode, + ColorBlendAttrib::Operand alpha_a, ColorBlendAttrib::Operand alpha_b, const LColor &color) : _mode(mode), _a(a), _b(b), + _alpha_mode(alpha_mode), + _alpha_a(alpha_a), + _alpha_b(alpha_b), _color(color), - _involves_constant_color(involves_constant_color(a) || involves_constant_color(b)), - _involves_color_scale(involves_color_scale(a) || involves_color_scale(b)) + _involves_constant_color(involves_constant_color(a) || + involves_constant_color(b) || + involves_constant_color(alpha_a) || + involves_constant_color(alpha_b)), + _involves_color_scale(involves_color_scale(a) || + involves_color_scale(b) || + involves_color_scale(alpha_a) || + involves_color_scale(alpha_b)) { } /** - * Returns the colorBlend mode. + * Returns the blending mode for the RGB channels. */ INLINE ColorBlendAttrib::Mode ColorBlendAttrib:: get_mode() const { @@ -50,7 +64,7 @@ get_mode() const { } /** - * Returns the multiplier for the first component. + * Returns the RGB multiplier for the first component. */ INLINE ColorBlendAttrib::Operand ColorBlendAttrib:: get_operand_a() const { @@ -58,13 +72,37 @@ get_operand_a() const { } /** - * Returns the multiplier for the second component. + * Returns the RGB multiplier for the second component. */ INLINE ColorBlendAttrib::Operand ColorBlendAttrib:: get_operand_b() const { return _b; } +/** + * Returns the blending mode for the alpha channel. + */ +INLINE ColorBlendAttrib::Mode ColorBlendAttrib:: +get_alpha_mode() const { + return _alpha_mode; +} + +/** + * Returns the alpha multiplier for the first component. + */ +INLINE ColorBlendAttrib::Operand ColorBlendAttrib:: +get_alpha_operand_a() const { + return _alpha_a; +} + +/** + * Returns the alpha multiplier for the second component. + */ +INLINE ColorBlendAttrib::Operand ColorBlendAttrib:: +get_alpha_operand_b() const { + return _alpha_b; +} + /** * Returns the constant color associated with the attrib. */ @@ -114,14 +152,5 @@ involves_constant_color(ColorBlendAttrib::Operand operand) { */ INLINE bool ColorBlendAttrib:: involves_color_scale(ColorBlendAttrib::Operand operand) { - switch (operand) { - case O_color_scale: - case O_one_minus_color_scale: - case O_alpha_scale: - case O_one_minus_alpha_scale: - return true; - - default: - return false; - } + return (operand >= O_color_scale); } diff --git a/panda/src/pgraph/colorBlendAttrib.cxx b/panda/src/pgraph/colorBlendAttrib.cxx index ef5d934976..92fe98ab79 100644 --- a/panda/src/pgraph/colorBlendAttrib.cxx +++ b/panda/src/pgraph/colorBlendAttrib.cxx @@ -39,19 +39,38 @@ make_off() { CPT(RenderAttrib) ColorBlendAttrib:: make(ColorBlendAttrib::Mode mode) { ColorBlendAttrib *attrib = new ColorBlendAttrib(mode, O_one, O_one, + mode, O_one, O_one, LColor::zero()); return return_new(attrib); } /** * Constructs a new ColorBlendAttrib object that enables special-effect - * blending. This supercedes transparency. + * blending. This supercedes transparency. The given mode and operands are + * used for both the RGB and alpha channels. */ CPT(RenderAttrib) ColorBlendAttrib:: make(ColorBlendAttrib::Mode mode, ColorBlendAttrib::Operand a, ColorBlendAttrib::Operand b, const LColor &color) { - ColorBlendAttrib *attrib = new ColorBlendAttrib(mode, a, b, color); + ColorBlendAttrib *attrib = new ColorBlendAttrib(mode, a, b, mode, a, b, color); + return return_new(attrib); +} + +/** + * Constructs a new ColorBlendAttrib object that enables special-effect + * blending. This supercedes transparency. This form is used to specify + * separate blending parameters for the RGB and alpha channels. + */ +CPT(RenderAttrib) ColorBlendAttrib:: +make(ColorBlendAttrib::Mode mode, + ColorBlendAttrib::Operand a, ColorBlendAttrib::Operand b, + ColorBlendAttrib::Mode alpha_mode, + ColorBlendAttrib::Operand alpha_a, ColorBlendAttrib::Operand alpha_b, + const LColor &color) { + ColorBlendAttrib *attrib = new ColorBlendAttrib(mode, a, b, + alpha_mode, alpha_a, alpha_b, + color); return return_new(attrib); } @@ -156,6 +175,13 @@ write_datagram(BamWriter *manager, Datagram &dg) { dg.add_uint8(_mode); dg.add_uint8(_a); dg.add_uint8(_b); + + if (manager->get_file_minor_ver() >= 42) { + dg.add_uint8(_alpha_mode); + dg.add_uint8(_alpha_a); + dg.add_uint8(_alpha_b); + } + _color.write_datagram(dg); } @@ -187,10 +213,34 @@ fillin(DatagramIterator &scan, BamReader *manager) { _mode = (Mode)scan.get_uint8(); _a = (Operand)scan.get_uint8(); _b = (Operand)scan.get_uint8(); + + if (manager->get_file_minor_ver() >= 42) { + _alpha_mode = (Mode)scan.get_uint8(); + _alpha_a = (Operand)scan.get_uint8(); + _alpha_b = (Operand)scan.get_uint8(); + } else { + // Before bam 6.42, these were shifted by four. + if (_a >= O_incoming1_color) { + _a = (Operand)(_a + 4); + } + if (_b >= O_incoming1_color) { + _b = (Operand)(_b + 4); + } + + // And there was only one set of blend constants for both RGB and alpha. + _alpha_mode = _mode; + _alpha_a = _a; + _alpha_b = _b; + } + _color.read_datagram(scan); - _involves_constant_color = involves_constant_color(_a) || involves_constant_color(_b); - _involves_color_scale = involves_color_scale(_a) || involves_color_scale(_b); + _involves_constant_color = + involves_constant_color(_a) || involves_constant_color(_alpha_a) || + involves_constant_color(_b) || involves_constant_color(_alpha_b); + _involves_color_scale = + involves_color_scale(_a) || involves_color_scale(_alpha_a) || + involves_color_scale(_b) || involves_color_scale(_alpha_b); } /** @@ -234,7 +284,7 @@ operator << (ostream &out, ColorBlendAttrib::Operand operand) { return out << "one"; case ColorBlendAttrib::O_incoming_color: - return out << "incomfing_color"; + return out << "incoming_color"; case ColorBlendAttrib::O_one_minus_incoming_color: return out << "one_minus_incoming_color"; @@ -283,6 +333,18 @@ operator << (ostream &out, ColorBlendAttrib::Operand operand) { case ColorBlendAttrib::O_one_minus_alpha_scale: return out << "one_minus_alpha_scale"; + + case ColorBlendAttrib::O_incoming1_color: + return out << "incoming1_color"; + + case ColorBlendAttrib::O_one_minus_incoming1_color: + return out << "one_minus_incoming1_color"; + + case ColorBlendAttrib::O_incoming1_alpha: + return out << "incoming1_alpha"; + + case ColorBlendAttrib::O_one_minus_incoming1_alpha: + return out << "one_minus_incoming1_alpha"; } return out << "**invalid ColorBlendAttrib::Operand(" << (int)operand << ")**"; diff --git a/panda/src/pgraph/colorBlendAttrib.h b/panda/src/pgraph/colorBlendAttrib.h index 3e836fdb45..6d66747218 100644 --- a/panda/src/pgraph/colorBlendAttrib.h +++ b/panda/src/pgraph/colorBlendAttrib.h @@ -52,11 +52,20 @@ PUBLISHED: O_one_minus_constant_alpha, O_incoming_color_saturate, // valid only for operand a - // If you set either of the operands to any of the below, the blend color - // is taken from the current ColorScaleAttrib. This also inhibits the - // normal behavior of the ColorScaleAttrib; it no longer directly scales - // the vertex colors, on the assumption that you will instead take care of - // the scale here, in the blend mode. + // The following are used for dual-source blending, where the fragment + // shader outputs a second color that will be used for blending. + O_incoming1_color, + O_one_minus_incoming1_color, + O_incoming1_alpha, + O_one_minus_incoming1_alpha, + + // If you set any of the operands to any of the below, the blend color is + // taken from the current ColorScaleAttrib. This also inhibits the normal + // behavior of the ColorScaleAttrib; it no longer directly scales the + // vertex colors, on the assumption that you will instead take care of the + // scale here, in the blend mode. + // + // These modes are being considered for deprecation. O_color_scale, O_one_minus_color_scale, O_alpha_scale, @@ -66,6 +75,7 @@ PUBLISHED: private: INLINE ColorBlendAttrib(); INLINE ColorBlendAttrib(Mode mode, Operand a, Operand b, + Mode alpha_mode, Operand alpha_a, Operand alpha_b, const LColor &color); PUBLISHED: @@ -73,11 +83,19 @@ PUBLISHED: static CPT(RenderAttrib) make(Mode mode); static CPT(RenderAttrib) make(Mode mode, Operand a, Operand b, const LColor &color = LColor::zero()); + static CPT(RenderAttrib) make(Mode rgb_mode, Operand rgb_a, Operand rgb_b, + Mode alpha_mode, Operand alpha_a, Operand alpha_b, + const LColor &color = LColor::zero()); static CPT(RenderAttrib) make_default(); INLINE Mode get_mode() const; INLINE Operand get_operand_a() const; INLINE Operand get_operand_b() const; + + INLINE Mode get_alpha_mode() const; + INLINE Operand get_alpha_operand_a() const; + INLINE Operand get_alpha_operand_b() const; + INLINE LColor get_color() const; INLINE bool involves_constant_color() const; @@ -86,6 +104,17 @@ PUBLISHED: INLINE static bool involves_constant_color(Operand operand); INLINE static bool involves_color_scale(Operand operand); +PUBLISHED: + MAKE_PROPERTY(rgb_mode, get_mode); + MAKE_PROPERTY(rgb_operand_a, get_operand_a); + MAKE_PROPERTY(rgb_operand_b, get_operand_b); + + MAKE_PROPERTY(alpha_mode, get_alpha_mode); + MAKE_PROPERTY(alpha_operand_a, get_alpha_operand_a); + MAKE_PROPERTY(alpha_operand_b, get_alpha_operand_b); + + MAKE_PROPERTY(color, get_color); + public: virtual void output(ostream &out) const; @@ -97,6 +126,8 @@ protected: private: Mode _mode; Operand _a, _b; + Mode _alpha_mode; + Operand _alpha_a, _alpha_b; LColor _color; bool _involves_constant_color; bool _involves_color_scale; diff --git a/panda/src/pgraph/colorScaleAttrib.h b/panda/src/pgraph/colorScaleAttrib.h index 060b2721a1..aa3ace8738 100644 --- a/panda/src/pgraph/colorScaleAttrib.h +++ b/panda/src/pgraph/colorScaleAttrib.h @@ -43,6 +43,9 @@ PUBLISHED: INLINE const LVecBase4 &get_scale() const; CPT(RenderAttrib) set_scale(const LVecBase4 &scale) const; +PUBLISHED: + MAKE_PROPERTY2(scale, has_scale, get_scale); + public: virtual bool lower_attrib_can_override() const; virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/colorWriteAttrib.h b/panda/src/pgraph/colorWriteAttrib.h index 76d9d5c1db..b7dcb7eb37 100644 --- a/panda/src/pgraph/colorWriteAttrib.h +++ b/panda/src/pgraph/colorWriteAttrib.h @@ -48,6 +48,9 @@ PUBLISHED: INLINE unsigned int get_channels() const; +PUBLISHED: + MAKE_PROPERTY(channels, get_channels); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/cullBinAttrib.h b/panda/src/pgraph/cullBinAttrib.h index c61fd2ebfc..f17a9876c6 100644 --- a/panda/src/pgraph/cullBinAttrib.h +++ b/panda/src/pgraph/cullBinAttrib.h @@ -35,6 +35,10 @@ PUBLISHED: INLINE const string &get_bin_name() const; INLINE int get_draw_order() const; +PUBLISHED: + MAKE_PROPERTY(bin_name, get_bin_name); + MAKE_PROPERTY(draw_order, get_draw_order); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/cullFaceAttrib.h b/panda/src/pgraph/cullFaceAttrib.h index 1dc2d8147e..5f6589a52a 100644 --- a/panda/src/pgraph/cullFaceAttrib.h +++ b/panda/src/pgraph/cullFaceAttrib.h @@ -44,6 +44,11 @@ PUBLISHED: INLINE bool get_reverse() const; Mode get_effective_mode() const; +PUBLISHED: + MAKE_PROPERTY(mode, get_actual_mode); + MAKE_PROPERTY(reverse, get_reverse); + MAKE_PROPERTY(effective_mode, get_effective_mode); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/depthOffsetAttrib.cxx b/panda/src/pgraph/depthOffsetAttrib.cxx index a4339c333a..ed6f942b1c 100644 --- a/panda/src/pgraph/depthOffsetAttrib.cxx +++ b/panda/src/pgraph/depthOffsetAttrib.cxx @@ -162,8 +162,10 @@ write_datagram(BamWriter *manager, Datagram &dg) { RenderAttrib::write_datagram(manager, dg); dg.add_int32(_offset); - dg.add_stdfloat(_min_value); - dg.add_stdfloat(_max_value); + if (manager->get_file_minor_ver() >= 31) { + dg.add_stdfloat(_min_value); + dg.add_stdfloat(_max_value); + } } /** diff --git a/panda/src/pgraph/depthOffsetAttrib.h b/panda/src/pgraph/depthOffsetAttrib.h index fe617fa56a..0976e2025a 100644 --- a/panda/src/pgraph/depthOffsetAttrib.h +++ b/panda/src/pgraph/depthOffsetAttrib.h @@ -60,6 +60,11 @@ PUBLISHED: INLINE PN_stdfloat get_min_value() const; INLINE PN_stdfloat get_max_value() const; +PUBLISHED: + MAKE_PROPERTY(offset, get_offset); + MAKE_PROPERTY(min_value, get_min_value); + MAKE_PROPERTY(max_value, get_max_value); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/depthTestAttrib.h b/panda/src/pgraph/depthTestAttrib.h index 66eb9fb135..6380a197d9 100644 --- a/panda/src/pgraph/depthTestAttrib.h +++ b/panda/src/pgraph/depthTestAttrib.h @@ -33,6 +33,9 @@ PUBLISHED: INLINE PandaCompareFunc get_mode() const; +PUBLISHED: + MAKE_PROPERTY(mode, get_mode); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/depthWriteAttrib.h b/panda/src/pgraph/depthWriteAttrib.h index 7efdf4a70f..9cd96b40f9 100644 --- a/panda/src/pgraph/depthWriteAttrib.h +++ b/panda/src/pgraph/depthWriteAttrib.h @@ -39,6 +39,9 @@ PUBLISHED: INLINE Mode get_mode() const; +PUBLISHED: + MAKE_PROPERTY(mode, get_mode); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/fogAttrib.h b/panda/src/pgraph/fogAttrib.h index 1762fb09ee..28a84600e0 100644 --- a/panda/src/pgraph/fogAttrib.h +++ b/panda/src/pgraph/fogAttrib.h @@ -34,6 +34,9 @@ PUBLISHED: INLINE bool is_off() const; INLINE Fog *get_fog() const; +PUBLISHED: + MAKE_PROPERTY(fog, get_fog); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index bfbd24f04f..f0000d4ebb 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -1099,7 +1099,7 @@ void GeomNode::CData:: write_datagram(BamWriter *manager, Datagram &dg) const { CPT(GeomList) geoms = _geoms.get_read_pointer(); int num_geoms = geoms->size(); - nassertv(num_geoms == (int)(PN_uint16)num_geoms); + nassertv(num_geoms == (int)(uint16_t)num_geoms); dg.add_uint16(num_geoms); GeomList::const_iterator gi; diff --git a/panda/src/pgraph/light.cxx b/panda/src/pgraph/light.cxx index 705469591e..b159450142 100644 --- a/panda/src/pgraph/light.cxx +++ b/panda/src/pgraph/light.cxx @@ -206,9 +206,13 @@ fill_viz_geom(GeomNode *) { */ void Light:: write_datagram(BamWriter *manager, Datagram &dg) { - dg.add_bool(_has_color_temperature); - if (_has_color_temperature) { - dg.add_stdfloat(_color_temperature); + if (manager->get_file_minor_ver() >= 39) { + dg.add_bool(_has_color_temperature); + if (_has_color_temperature) { + dg.add_stdfloat(_color_temperature); + } else { + manager->write_cdata(dg, _cycler); + } } else { manager->write_cdata(dg, _cycler); } diff --git a/panda/src/pgraph/lightAttrib.cxx b/panda/src/pgraph/lightAttrib.cxx index 459d3e6991..a677345b8a 100644 --- a/panda/src/pgraph/lightAttrib.cxx +++ b/panda/src/pgraph/lightAttrib.cxx @@ -898,18 +898,31 @@ write_datagram(BamWriter *manager, Datagram &dg) { // write the number of off_lights dg.add_uint16(get_num_off_lights()); + // write the off lights pointers if any Lights::const_iterator fi; - for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) { - (*fi).write_datagram(manager, dg); + if (manager->get_file_minor_ver() < 40) { + for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) { + manager->write_pointer(dg, fi->node()); + } + } else { + for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) { + (*fi).write_datagram(manager, dg); + } } // write the number of on lights dg.add_uint16(get_num_on_lights()); // write the on lights pointers if any Lights::const_iterator nti; - for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) { - (*nti).write_datagram(manager, dg); + if (manager->get_file_minor_ver() < 40) { + for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) { + manager->write_pointer(dg, nti->node()); + } + } else { + for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) { + (*nti).write_datagram(manager, dg); + } } } diff --git a/panda/src/pgraph/lightRampAttrib.h b/panda/src/pgraph/lightRampAttrib.h index 08c3a1ea84..b1ac147376 100644 --- a/panda/src/pgraph/lightRampAttrib.h +++ b/panda/src/pgraph/lightRampAttrib.h @@ -52,6 +52,9 @@ PUBLISHED: INLINE PN_stdfloat get_level(int n) const; INLINE PN_stdfloat get_threshold(int n) const; +PUBLISHED: + MAKE_PROPERTY(mode, get_mode); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/loader.cxx b/panda/src/pgraph/loader.cxx index 3b3042ba48..671a40c638 100644 --- a/panda/src/pgraph/loader.cxx +++ b/panda/src/pgraph/loader.cxx @@ -140,10 +140,10 @@ load_file(const Filename &filename, const LoaderOptions &options) const { extension = this_filename.get_extension(); } - bool pz_file = false; + bool compressed = false; #ifdef HAVE_ZLIB - if (extension == "pz") { - pz_file = true; + if (extension == "pz" || extension == "gz") { + compressed = true; extension = Filename(this_filename.get_basename_wo_extension()).get_extension(); } #endif // HAVE_ZLIB @@ -182,7 +182,7 @@ load_file(const Filename &filename, const LoaderOptions &options) const { << extension << ") does not support loading.\n"; } return NULL; - } else if (pz_file && !requested_type->supports_compressed()) { + } else if (compressed && !requested_type->supports_compressed()) { if (report_errors) { loader_cat.error() << requested_type->get_name() << " file type (." @@ -382,10 +382,10 @@ save_file(const Filename &filename, const LoaderOptions &options, extension = this_filename.get_extension(); } - bool pz_file = false; + bool compressed = false; #ifdef HAVE_ZLIB - if (extension == "pz") { - pz_file = true; + if (extension == "pz" || extension == "gz") { + compressed = true; extension = Filename(this_filename.get_basename_wo_extension()).get_extension(); } #endif // HAVE_ZLIB @@ -422,7 +422,7 @@ save_file(const Filename &filename, const LoaderOptions &options, } return false; - } else if (pz_file && !requested_type->supports_compressed()) { + } else if (compressed && !requested_type->supports_compressed()) { if (report_errors) { loader_cat.error() << requested_type->get_name() << " file type (." diff --git a/panda/src/pgraph/loaderFileType.cxx b/panda/src/pgraph/loaderFileType.cxx index c064361a68..326dce8720 100644 --- a/panda/src/pgraph/loaderFileType.cxx +++ b/panda/src/pgraph/loaderFileType.cxx @@ -48,7 +48,7 @@ get_additional_extensions() const { /** * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. + * (with a .pz or .gz extension), false otherwise. */ bool LoaderFileType:: supports_compressed() const { diff --git a/panda/src/pgraph/loaderFileTypeBam.cxx b/panda/src/pgraph/loaderFileTypeBam.cxx index 6859ff9306..9394c69357 100644 --- a/panda/src/pgraph/loaderFileTypeBam.cxx +++ b/panda/src/pgraph/loaderFileTypeBam.cxx @@ -47,7 +47,7 @@ get_extension() const { /** * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. + * (with a .pz or .gz extension), false otherwise. */ bool LoaderFileTypeBam:: supports_compressed() const { diff --git a/panda/src/pgraph/loaderFileTypeRegistry.h b/panda/src/pgraph/loaderFileTypeRegistry.h index 8ae64a51ea..6fedc09406 100644 --- a/panda/src/pgraph/loaderFileTypeRegistry.h +++ b/panda/src/pgraph/loaderFileTypeRegistry.h @@ -39,6 +39,7 @@ PUBLISHED: int get_num_types() const; LoaderFileType *get_type(int n) const; MAKE_SEQ(get_types, get_num_types, get_type); + MAKE_SEQ_PROPERTY(types, get_num_types, get_type); LoaderFileType *get_type_from_extension(const string &extension); void write(ostream &out, int indent_level = 0) const; diff --git a/panda/src/pgraph/materialAttrib.h b/panda/src/pgraph/materialAttrib.h index 729e9ac345..f984b699b3 100644 --- a/panda/src/pgraph/materialAttrib.h +++ b/panda/src/pgraph/materialAttrib.h @@ -36,6 +36,9 @@ PUBLISHED: INLINE bool is_off() const; INLINE Material *get_material() const; +PUBLISHED: + MAKE_PROPERTY(material, get_material); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index 4f39aa28bb..78c2520faa 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -203,10 +203,13 @@ PUBLISHED: int get_num_nodes(Thread *current_thread = Thread::get_current_thread()) const; PandaNode *get_node(int index, Thread *current_thread = Thread::get_current_thread()) const; MAKE_SEQ(get_nodes, get_num_nodes, get_node); + MAKE_SEQ_PROPERTY(nodes, get_num_nodes, get_node); NodePath get_ancestor(int index, Thread *current_thread = Thread::get_current_thread()) const; MAKE_SEQ(get_ancestors, get_num_nodes, get_ancestor); + MAKE_SEQ_PROPERTY(ancestors, get_num_nodes, get_ancestor); INLINE ErrorType get_error_type() const; + MAKE_PROPERTY(error_type, get_error_type); INLINE PandaNode *get_top_node(Thread *current_thread = Thread::get_current_thread()) const; NodePath get_top(Thread *current_thread = Thread::get_current_thread()) const; @@ -228,12 +231,18 @@ PUBLISHED: INLINE NodePath get_child(int n, Thread *current_thread = Thread::get_current_thread()) const; NodePathCollection get_stashed_children(Thread *current_thread = Thread::get_current_thread()) const; + MAKE_PROPERTY(children, get_children); + MAKE_PROPERTY(stashed_children, get_stashed_children); + INLINE int count_num_descendants() const; INLINE bool has_parent(Thread *current_thread = Thread::get_current_thread()) const; INLINE NodePath get_parent(Thread *current_thread = Thread::get_current_thread()) const; int get_sort(Thread *current_thread = Thread::get_current_thread()) const; + MAKE_PROPERTY2(parent, has_parent, get_parent); + MAKE_PROPERTY(sort, get_sort); + NodePath find(const string &path) const; NodePath find_path_to(PandaNode *node) const; NodePathCollection find_all_matches(const string &path) const; @@ -910,6 +919,7 @@ PUBLISHED: INLINE void set_name(const string &name); INLINE string get_name() const; + MAKE_PROPERTY(name, get_name, set_name); BLOCKING bool write_bam_file(const Filename &filename) const; BLOCKING bool write_bam_stream(ostream &out) const; diff --git a/panda/src/pgraph/nodePath_ext.cxx b/panda/src/pgraph/nodePath_ext.cxx index c13ec6326d..656802b8f0 100644 --- a/panda/src/pgraph/nodePath_ext.cxx +++ b/panda/src/pgraph/nodePath_ext.cxx @@ -156,7 +156,11 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const { } } +#if PY_MAJOR_VERSION >= 3 + PyObject *result = Py_BuildValue("(O(y#))", func, bam_stream.data(), (Py_ssize_t) bam_stream.size()); +#else PyObject *result = Py_BuildValue("(O(s#))", func, bam_stream.data(), (Py_ssize_t) bam_stream.size()); +#endif Py_DECREF(func); Py_DECREF(this_class); return result; diff --git a/panda/src/pgraph/occluderEffect.cxx b/panda/src/pgraph/occluderEffect.cxx index d66c5d75ed..36c874a1f2 100644 --- a/panda/src/pgraph/occluderEffect.cxx +++ b/panda/src/pgraph/occluderEffect.cxx @@ -146,10 +146,17 @@ write_datagram(BamWriter *manager, Datagram &dg) { // write the number of on occluders dg.add_uint16(get_num_on_occluders()); + // write the on occluders pointers if any Occluders::const_iterator nti; - for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) { - (*nti).write_datagram(manager, dg); + if (manager->get_file_minor_ver() < 40) { + for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) { + manager->write_pointer(dg, nti->node()); + } + } else { + for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) { + (*nti).write_datagram(manager, dg); + } } } diff --git a/panda/src/pgraph/occluderNode.I b/panda/src/pgraph/occluderNode.I index 11ecea9b5c..f84b864b68 100644 --- a/panda/src/pgraph/occluderNode.I +++ b/panda/src/pgraph/occluderNode.I @@ -31,7 +31,7 @@ set_vertices(const LPoint3 &v0, const LPoint3 &v1, * Returns the number of vertices in the occluder polygon. This should always * return 4. */ -INLINE int OccluderNode:: +INLINE size_t OccluderNode:: get_num_vertices() const { return _vertices.size(); } @@ -40,11 +40,20 @@ get_num_vertices() const { * Returns the nth vertex of the occluder polygon. */ INLINE const LPoint3 &OccluderNode:: -get_vertex(int n) const { - nassertr(n >= 0 && n < (int)_vertices.size(), LPoint3::zero()); +get_vertex(size_t n) const { + nassertr(n < _vertices.size(), LPoint3::zero()); return _vertices[n]; } +/** + * Sets the nth vertex of the occluder polygon. + */ +INLINE void OccluderNode:: +set_vertex(size_t n, const LPoint3 &v) { + nassertv(n < _vertices.size()); + _vertices[n] = v; +} + /** * If true, the back-face will also be used to occlude */ diff --git a/panda/src/pgraph/occluderNode.h b/panda/src/pgraph/occluderNode.h index 92e15e4b8d..e9d8c67165 100644 --- a/panda/src/pgraph/occluderNode.h +++ b/panda/src/pgraph/occluderNode.h @@ -53,10 +53,15 @@ PUBLISHED: INLINE PN_stdfloat get_min_coverage(); INLINE void set_vertices(const LPoint3 &v0, const LPoint3 &v1, const LPoint3 &v2, const LPoint3 &v3); - INLINE int get_num_vertices() const; - INLINE const LPoint3 &get_vertex(int n) const; + INLINE size_t get_num_vertices() const; + INLINE const LPoint3 &get_vertex(size_t n) const; + INLINE void set_vertex(size_t n, const LPoint3 &v); MAKE_SEQ(get_vertices, get_num_vertices, get_vertex); + MAKE_PROPERTY(double_sided, is_double_sided, set_double_sided); + MAKE_PROPERTY(min_coverage, get_min_coverage, set_min_coverage); + MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex, set_vertex); + protected: virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, int &internal_vertices, diff --git a/panda/src/pgraph/pandaNode.I b/panda/src/pgraph/pandaNode.I index c493ef08f3..fa60e11b41 100644 --- a/panda/src/pgraph/pandaNode.I +++ b/panda/src/pgraph/pandaNode.I @@ -932,7 +932,7 @@ operator = (PandaNode::Children &&from) NOEXCEPT { /** * Returns the number of children of the node. */ -INLINE int PandaNode::Children:: +INLINE size_t PandaNode::Children:: get_num_children() const { nassertr(_down != (Down *)NULL, 0); return _down->size(); @@ -942,9 +942,9 @@ get_num_children() const { * Returns the nth child of the node. */ INLINE PandaNode *PandaNode::Children:: -get_child(int n) const { +get_child(size_t n) const { nassertr(_down != (Down *)NULL, NULL); - nassertr(n >= 0 && n < (int)_down->size(), NULL); + nassertr(n < (size_t)_down->size(), NULL); return (*_down)[n].get_child(); } @@ -953,9 +953,9 @@ get_child(int n) const { * number that was passed to add_child()). See get_num_children(). */ INLINE int PandaNode::Children:: -get_child_sort(int n) const { +get_child_sort(size_t n) const { nassertr(_down != (Down *)NULL, -1); - nassertr(n >= 0 && n < (int)_down->size(), -1); + nassertr(n < _down->size(), -1); return (*_down)[n].get_sort(); } @@ -1014,7 +1014,7 @@ operator = (PandaNode::Stashed &&from) NOEXCEPT { /** * Returns the number of stashed children of the node. */ -INLINE int PandaNode::Stashed:: +INLINE size_t PandaNode::Stashed:: get_num_stashed() const { nassertr(_stashed != (Down *)NULL, 0); return _stashed->size(); @@ -1024,9 +1024,9 @@ get_num_stashed() const { * Returns the nth stashed child of the node. */ INLINE PandaNode *PandaNode::Stashed:: -get_stashed(int n) const { +get_stashed(size_t n) const { nassertr(_stashed != (Down *)NULL, NULL); - nassertr(n >= 0 && n < (int)_stashed->size(), NULL); + nassertr(n < _stashed->size(), NULL); return (*_stashed)[n].get_child(); } @@ -1035,9 +1035,9 @@ get_stashed(int n) const { * number that was passed to add_child()). See get_num_stashed(). */ INLINE int PandaNode::Stashed:: -get_stashed_sort(int n) const { +get_stashed_sort(size_t n) const { nassertr(_stashed != (Down *)NULL, -1); - nassertr(n >= 0 && n < (int)_stashed->size(), -1); + nassertr(n < _stashed->size(), -1); return (*_stashed)[n].get_sort(); } @@ -1096,7 +1096,7 @@ operator = (PandaNode::Parents &&from) NOEXCEPT { /** * Returns the number of parents of the node. */ -INLINE int PandaNode::Parents:: +INLINE size_t PandaNode::Parents:: get_num_parents() const { nassertr(_up != (Up *)NULL, 0); return _up->size(); @@ -1106,9 +1106,9 @@ get_num_parents() const { * Returns the nth parent of the node. */ INLINE PandaNode *PandaNode::Parents:: -get_parent(int n) const { +get_parent(size_t n) const { nassertr(_up != (Up *)NULL, NULL); - nassertr(n >= 0 && n < (int)_up->size(), NULL); + nassertr(n < _up->size(), NULL); return (*_up)[n].get_parent(); } diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index 827ae89c31..38a1c5f096 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -4109,7 +4109,7 @@ write_up_list(const PandaNode::Up &up_list, num_parents++; } } - nassertv(num_parents == (int)(PN_uint16)num_parents); + nassertv(num_parents == (int)(uint16_t)num_parents); dg.add_uint16(num_parents); for (ui = up_list.begin(); ui != up_list.end(); ++ui) { PandaNode *parent_node = (*ui).get_parent(); @@ -4126,7 +4126,7 @@ void PandaNode::CData:: write_down_list(const PandaNode::Down &down_list, BamWriter *manager, Datagram &dg) const { int num_children = down_list.size(); - nassertv(num_children == (int)(PN_uint16)num_children); + nassertv(num_children == (int)(uint16_t)num_children); dg.add_uint16(num_children); // Should we smarten up the writing of the sort number? Most of the time diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index 94a5912e8c..05bbcaadba 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -680,10 +680,10 @@ private: static PStatCollector _reset_prev_pcollector; static PStatCollector _update_bounds_pcollector; -public: +PUBLISHED: // This class is returned from get_children(). Use it to walk through the // list of children. This is faster, and safer, than walking through the - // children one at a time via get_num_children()get_child(), since the list + // children one at a time via get_num_children()/get_child(), since the list // of children is saved out ahead of time, rather than having to reacquire // the lock with each iteration, or to keep the lock held for the entire // pass. @@ -699,9 +699,13 @@ public: INLINE void operator = (Children &&from) NOEXCEPT; #endif - INLINE int get_num_children() const; - INLINE PandaNode *get_child(int n) const; - INLINE int get_child_sort(int n) const; + INLINE size_t get_num_children() const; + INLINE PandaNode *get_child(size_t n) const; + INLINE int get_child_sort(size_t n) const; + + PUBLISHED: + INLINE PandaNode *operator [](size_t n) const { return get_child(n); } + INLINE size_t size() const { return get_num_children(); } private: CPT(Down) _down; @@ -720,9 +724,13 @@ public: INLINE void operator = (Stashed &&from) NOEXCEPT; #endif - INLINE int get_num_stashed() const; - INLINE PandaNode *get_stashed(int n) const; - INLINE int get_stashed_sort(int n) const; + INLINE size_t get_num_stashed() const; + INLINE PandaNode *get_stashed(size_t n) const; + INLINE int get_stashed_sort(size_t n) const; + + PUBLISHED: + INLINE PandaNode *operator [](size_t n) const { return get_stashed(n); } + INLINE size_t size() const { return get_num_stashed(); } private: CPT(Down) _stashed; @@ -741,13 +749,18 @@ public: INLINE void operator = (Parents &&from) NOEXCEPT; #endif - INLINE int get_num_parents() const; - INLINE PandaNode *get_parent(int n) const; + INLINE size_t get_num_parents() const; + INLINE PandaNode *get_parent(size_t n) const; + + PUBLISHED: + INLINE PandaNode *operator [](size_t n) const { return get_parent(n); } + INLINE size_t size() const { return get_num_parents(); } private: CPT(Up) _up; }; +public: INLINE Children get_children(Thread *current_thread = Thread::get_current_thread()) const; INLINE Stashed get_stashed(Thread *current_thread = Thread::get_current_thread()) const; INLINE Parents get_parents(Thread *current_thread = Thread::get_current_thread()) const; @@ -755,6 +768,11 @@ public: typedef bool SceneRootFunc(const PandaNode *); static void set_scene_root_func(SceneRootFunc *func); +PUBLISHED: + MAKE_PROPERTY(children, get_children); + MAKE_PROPERTY(stashed, get_stashed); + MAKE_PROPERTY(parents, get_parents); + private: static SceneRootFunc *_scene_root_func; diff --git a/panda/src/pgraph/pandaNode_ext.cxx b/panda/src/pgraph/pandaNode_ext.cxx index 9a12edabd0..9395a56e3b 100644 --- a/panda/src/pgraph/pandaNode_ext.cxx +++ b/panda/src/pgraph/pandaNode_ext.cxx @@ -187,15 +187,9 @@ get_tag_keys() const { vector_string keys; _this->get_tag_keys(keys); - PyObject *result = PyList_New(keys.size()); + PyObject *result = PyTuple_New(keys.size()); for (size_t i = 0; i < keys.size(); ++i) { - const string &tag_name = keys[i]; -#if PY_MAJOR_VERSION >= 3 - PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size()); -#else - PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size()); -#endif - PyList_SET_ITEM(result, i, str); + PyTuple_SET_ITEM(result, i, Dtool_WrapValue(keys[i])); } return result; @@ -209,15 +203,9 @@ get_python_tag_keys() const { vector_string keys; get_python_tag_keys(keys); - PyObject *result = PyList_New(keys.size()); + PyObject *result = PyTuple_New(keys.size()); for (size_t i = 0; i < keys.size(); ++i) { - const string &tag_name = keys[i]; -#if PY_MAJOR_VERSION >= 3 - PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size()); -#else - PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size()); -#endif - PyList_SET_ITEM(result, i, str); + PyTuple_SET_ITEM(result, i, Dtool_WrapValue(keys[i])); } return result; diff --git a/panda/src/pgraph/paramNodePath.cxx b/panda/src/pgraph/paramNodePath.cxx index c243997955..a620144a14 100644 --- a/panda/src/pgraph/paramNodePath.cxx +++ b/panda/src/pgraph/paramNodePath.cxx @@ -40,7 +40,18 @@ register_with_read_factory() { void ParamNodePath:: write_datagram(BamWriter *manager, Datagram &dg) { ParamValueBase::write_datagram(manager, dg); - _node_path.write_datagram(manager, dg); + + if (manager->get_file_minor_ver() < 40) { + // Before bam 6.40, we did not support writing NodePaths. Instaed, we + // write the PandaNode pointer and pray there is an unambiguous path. + if (_node_path.is_empty()) { + manager->write_pointer(dg, NULL); + } else { + manager->write_pointer(dg, _node_path.node()); + } + } else { + _node_path.write_datagram(manager, dg); + } } /** diff --git a/panda/src/pgraph/portalNode.h b/panda/src/pgraph/portalNode.h index b315b8abff..3b5c9ae7a3 100644 --- a/panda/src/pgraph/portalNode.h +++ b/panda/src/pgraph/portalNode.h @@ -86,6 +86,17 @@ PUBLISHED: // void draw () const; + MAKE_PROPERTY(into_portal_mask, get_into_portal_mask, set_into_portal_mask); + MAKE_PROPERTY(from_portal_mask, get_from_portal_mask, set_from_portal_mask); + MAKE_PROPERTY(portal_geom, get_portal_geom, set_portal_geom); + MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex); + MAKE_PROPERTY(cell_in, get_cell_in, set_cell_in); + MAKE_PROPERTY(cell_out, get_cell_out, set_cell_out); + MAKE_PROPERTY(clip_plane, is_clip_plane, set_clip_plane); + MAKE_PROPERTY(visible, is_visible, set_visible); + MAKE_PROPERTY(max_depth, get_max_depth, set_max_depth); + MAKE_PROPERTY(open, is_open, set_open); + protected: virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, int &internal_vertices, diff --git a/panda/src/pgraph/renderEffects.cxx b/panda/src/pgraph/renderEffects.cxx index 077c496e04..18c7565a3f 100644 --- a/panda/src/pgraph/renderEffects.cxx +++ b/panda/src/pgraph/renderEffects.cxx @@ -685,7 +685,7 @@ write_datagram(BamWriter *manager, Datagram &dg) { TypedWritable::write_datagram(manager, dg); int num_effects = _effects.size(); - nassertv(num_effects == (int)(PN_uint16)num_effects); + nassertv(num_effects == (int)(uint16_t)num_effects); dg.add_uint16(num_effects); Effects::const_iterator ai; diff --git a/panda/src/pgraph/renderModeAttrib.h b/panda/src/pgraph/renderModeAttrib.h index 0306de9737..631789dd60 100644 --- a/panda/src/pgraph/renderModeAttrib.h +++ b/panda/src/pgraph/renderModeAttrib.h @@ -63,9 +63,14 @@ PUBLISHED: INLINE PN_stdfloat get_thickness() const; INLINE bool get_perspective() const; INLINE const LColor &get_wireframe_color() const; - INLINE int get_geom_rendering(int geom_rendering) const; +PUBLISHED: + MAKE_PROPERTY(mode, get_mode); + MAKE_PROPERTY(thickness, get_thickness); + MAKE_PROPERTY(perspective, get_perspective); + MAKE_PROPERTY(wireframe_color, get_wireframe_color); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index 0555d300a3..de3a58b2ba 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -1996,7 +1996,7 @@ write_datagram(BamWriter *manager, Datagram &dg) { TypedWritable::write_datagram(manager, dg); int num_attribs = _filled_slots.get_num_on_bits(); - nassertv(num_attribs == (int)(PN_uint16)num_attribs); + nassertv(num_attribs == (int)(uint16_t)num_attribs); dg.add_uint16(num_attribs); // **** We should smarten up the writing of the override number--most of the diff --git a/panda/src/pgraph/rescaleNormalAttrib.h b/panda/src/pgraph/rescaleNormalAttrib.h index 3017c9a879..d76d51e6de 100644 --- a/panda/src/pgraph/rescaleNormalAttrib.h +++ b/panda/src/pgraph/rescaleNormalAttrib.h @@ -49,6 +49,7 @@ PUBLISHED: INLINE static CPT(RenderAttrib) make_default(); INLINE Mode get_mode() const; + MAKE_PROPERTY(mode, get_mode); public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/scissorAttrib.cxx b/panda/src/pgraph/scissorAttrib.cxx index 599fab1e1d..e1c3c29e01 100644 --- a/panda/src/pgraph/scissorAttrib.cxx +++ b/panda/src/pgraph/scissorAttrib.cxx @@ -177,7 +177,9 @@ write_datagram(BamWriter *manager, Datagram &dg) { RenderAttrib::write_datagram(manager, dg); _frame.write_datagram(dg); - dg.add_bool(_off); + if (manager->get_file_minor_ver() >= 34) { + dg.add_bool(_off); + } } /** diff --git a/panda/src/pgraph/scissorAttrib.h b/panda/src/pgraph/scissorAttrib.h index 941d704a7c..48a4b87a7c 100644 --- a/panda/src/pgraph/scissorAttrib.h +++ b/panda/src/pgraph/scissorAttrib.h @@ -47,6 +47,9 @@ PUBLISHED: INLINE const LVecBase4 &get_frame() const; +PUBLISHED: + MAKE_PROPERTY(frame, get_frame); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/shadeModelAttrib.h b/panda/src/pgraph/shadeModelAttrib.h index c9550bccac..067555207a 100644 --- a/panda/src/pgraph/shadeModelAttrib.h +++ b/panda/src/pgraph/shadeModelAttrib.h @@ -39,6 +39,7 @@ PUBLISHED: static CPT(RenderAttrib) make_default(); INLINE Mode get_mode() const; + MAKE_PROPERTY(mode, get_mode); public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/shaderAttrib.h b/panda/src/pgraph/shaderAttrib.h index 9159d52e18..08676286f5 100644 --- a/panda/src/pgraph/shaderAttrib.h +++ b/panda/src/pgraph/shaderAttrib.h @@ -114,6 +114,10 @@ PUBLISHED: static void register_with_read_factory(); +PUBLISHED: + MAKE_PROPERTY(shader, get_shader); + MAKE_PROPERTY(instance_count, get_instance_count); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/stencilAttrib.cxx b/panda/src/pgraph/stencilAttrib.cxx index c5ef20e78a..13a00165ed 100644 --- a/panda/src/pgraph/stencilAttrib.cxx +++ b/panda/src/pgraph/stencilAttrib.cxx @@ -338,8 +338,26 @@ void StencilAttrib:: write_datagram(BamWriter *manager, Datagram &dg) { RenderAttrib::write_datagram(manager, dg); - for (int index = 0; index < SRS_total; ++index) { - dg.add_uint32(_stencil_render_states[index]); + if (manager->get_file_minor_ver() < 35) { + dg.add_int32(_stencil_render_states[SRS_front_comparison_function] != M_none); + dg.add_int32(_stencil_render_states[SRS_back_comparison_function] != M_none); + + for (int index = 0; index < SRS_total; ++index) { + if (index == SRS_front_comparison_function || + index == SRS_back_comparison_function) { + if (_stencil_render_states[index] == M_none) { + dg.add_uint32(7); + } else { + dg.add_uint32(_stencil_render_states[index] - 1); + } + } else { + dg.add_uint32(_stencil_render_states[index]); + } + } + } else { + for (int index = 0; index < SRS_total; ++index) { + dg.add_uint32(_stencil_render_states[index]); + } } } diff --git a/panda/src/pgraph/texMatrixAttrib.cxx b/panda/src/pgraph/texMatrixAttrib.cxx index eca96e95b3..84538033fd 100644 --- a/panda/src/pgraph/texMatrixAttrib.cxx +++ b/panda/src/pgraph/texMatrixAttrib.cxx @@ -461,7 +461,10 @@ write_datagram(BamWriter *manager, Datagram &dg) { manager->write_pointer(dg, sn._stage); manager->write_pointer(dg, sn._transform); - dg.add_int32(sn._override); + + if (manager->get_file_minor_ver() >= 24) { + dg.add_int32(sn._override); + } } } diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index 694a4ca00e..157bf1d146 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -778,10 +778,16 @@ write_datagram(BamWriter *manager, Datagram &dg) { manager->write_pointer(dg, stage); manager->write_pointer(dg, tex); dg.add_uint16((*si)._implicit_sort); - dg.add_int32((*si)._override); - dg.add_bool((*si)._has_sampler); - if ((*si)._has_sampler) { - (*si)._sampler.write_datagram(dg); + + if (manager->get_file_minor_ver() >= 23) { + dg.add_int32((*si)._override); + } + + if (manager->get_file_minor_ver() >= 36) { + dg.add_bool((*si)._has_sampler); + if ((*si)._has_sampler) { + (*si)._sampler.write_datagram(dg); + } } } } diff --git a/panda/src/pgraph/transparencyAttrib.h b/panda/src/pgraph/transparencyAttrib.h index 2baf3710a1..ebd7f4f157 100644 --- a/panda/src/pgraph/transparencyAttrib.h +++ b/panda/src/pgraph/transparencyAttrib.h @@ -51,6 +51,7 @@ PUBLISHED: static CPT(RenderAttrib) make_default(); INLINE Mode get_mode() const; + MAKE_PROPERTY(mode, get_mode); public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraphnodes/computeNode.I b/panda/src/pgraphnodes/computeNode.I index 80d93e73ac..06e022515e 100644 --- a/panda/src/pgraphnodes/computeNode.I +++ b/panda/src/pgraphnodes/computeNode.I @@ -45,7 +45,7 @@ clear_dispatches() { /** * Returns the number of times add_dispatch has been called on this object. */ -INLINE int ComputeNode:: +INLINE size_t ComputeNode:: get_num_dispatches() const { Dispatcher::CDReader cdata(_dispatcher->_cycler); return cdata->_dispatches.size(); @@ -55,12 +55,32 @@ get_num_dispatches() const { * Returns the group counts of the nth dispatch associated with this object. */ INLINE const LVecBase3i &ComputeNode:: -get_dispatch(int n) const { +get_dispatch(size_t n) const { Dispatcher::CDReader cdata(_dispatcher->_cycler); - nassertr(n >= 0 && (size_t)n < cdata->_dispatches.size(), LVecBase3i::zero()); + nassertr(n < cdata->_dispatches.size(), LVecBase3i::zero()); return cdata->_dispatches[n]; } +/** + * Sets the group counts of the nth dispatch associated with this object. + */ +INLINE void ComputeNode:: +set_dispatch(size_t n, const LVecBase3i &dispatch) { + Dispatcher::CDWriter cdata(_dispatcher->_cycler); + nassertv(n < cdata->_dispatches.size()); + cdata->_dispatches[n] = dispatch; +} + +/** + * Erases the given dispatch index from the list. + */ +INLINE void ComputeNode:: +remove_dispatch(size_t n) { + Dispatcher::CDWriter cdata(_dispatcher->_cycler); + nassertv(n < cdata->_dispatches.size()); + cdata->_dispatches.erase(cdata->_dispatches.begin() + n); +} + /** * */ diff --git a/panda/src/pgraphnodes/computeNode.h b/panda/src/pgraphnodes/computeNode.h index feeea69006..3210fba40f 100644 --- a/panda/src/pgraphnodes/computeNode.h +++ b/panda/src/pgraphnodes/computeNode.h @@ -31,11 +31,14 @@ PUBLISHED: INLINE void add_dispatch(const LVecBase3i &num_groups); INLINE void add_dispatch(int num_groups_x, int num_groups_y, int num_groups_z); - INLINE int get_num_dispatches() const; - INLINE const LVecBase3i &get_dispatch(int i) const; + INLINE size_t get_num_dispatches() const; + INLINE const LVecBase3i &get_dispatch(size_t i) const; + INLINE void set_dispatch(size_t i, const LVecBase3i &num_groups); + INLINE void remove_dispatch(size_t i); INLINE void clear_dispatches(); MAKE_SEQ(get_dispatches, get_num_dispatches, get_dispatch); + MAKE_SEQ_PROPERTY(dispatches, get_num_dispatches, get_dispatch, set_dispatch, remove_dispatch); public: ComputeNode(const ComputeNode ©); diff --git a/panda/src/pgraphnodes/config_pgraphnodes.cxx b/panda/src/pgraphnodes/config_pgraphnodes.cxx index 4623b44d78..47b0ed3baf 100644 --- a/panda/src/pgraphnodes/config_pgraphnodes.cxx +++ b/panda/src/pgraphnodes/config_pgraphnodes.cxx @@ -29,6 +29,7 @@ #include "selectiveChildNode.h" #include "sequenceNode.h" #include "shaderGenerator.h" +#include "sphereLight.h" #include "spotlight.h" #include "switchNode.h" #include "uvScrollNode.h" @@ -123,6 +124,7 @@ init_libpgraphnodes() { SelectiveChildNode::init_type(); SequenceNode::init_type(); ShaderGenerator::init_type(); + SphereLight::init_type(); Spotlight::init_type(); SwitchNode::init_type(); UvScrollNode::init_type(); @@ -137,6 +139,7 @@ init_libpgraphnodes() { PointLight::register_with_read_factory(); SelectiveChildNode::register_with_read_factory(); SequenceNode::register_with_read_factory(); + SphereLight::register_with_read_factory(); Spotlight::register_with_read_factory(); SwitchNode::register_with_read_factory(); UvScrollNode::register_with_read_factory(); diff --git a/panda/src/pgraphnodes/directionalLight.cxx b/panda/src/pgraphnodes/directionalLight.cxx index 3c9481afa3..127f994fbb 100644 --- a/panda/src/pgraphnodes/directionalLight.cxx +++ b/panda/src/pgraphnodes/directionalLight.cxx @@ -167,7 +167,9 @@ register_with_read_factory() { void DirectionalLight:: write_datagram(BamWriter *manager, Datagram &dg) { LightLensNode::write_datagram(manager, dg); - dg.add_bool(_has_specular_color); + if (manager->get_file_minor_ver() >= 39) { + dg.add_bool(_has_specular_color); + } manager->write_cdata(dg, _cycler); } diff --git a/panda/src/pgraphnodes/lodNode.h b/panda/src/pgraphnodes/lodNode.h index 50b17d26e1..6348b4c23a 100644 --- a/panda/src/pgraphnodes/lodNode.h +++ b/panda/src/pgraphnodes/lodNode.h @@ -75,6 +75,13 @@ PUBLISHED: INLINE void set_center(const LPoint3 ¢er); INLINE const LPoint3 &get_center() const; + MAKE_SEQ_PROPERTY(ins, get_num_switches, get_in); + MAKE_SEQ_PROPERTY(outs, get_num_switches, get_out); + MAKE_PROPERTY(lowest_switch, get_lowest_switch); + MAKE_PROPERTY(highest_switch, get_highest_switch); + MAKE_PROPERTY(lod_scale, get_lod_scale, set_lod_scale); + MAKE_PROPERTY(center, get_center, set_center); + void show_switch(int index); void show_switch(int index, const LColor &color); void hide_switch(int index); diff --git a/panda/src/pgraphnodes/p3pgraphnodes_composite1.cxx b/panda/src/pgraphnodes/p3pgraphnodes_composite1.cxx index 67f6fff97c..eb6199d7f0 100644 --- a/panda/src/pgraphnodes/p3pgraphnodes_composite1.cxx +++ b/panda/src/pgraphnodes/p3pgraphnodes_composite1.cxx @@ -7,3 +7,5 @@ #include "fadeLodNodeData.cxx" #include "lightLensNode.cxx" #include "lightNode.cxx" +#include "lodNode.cxx" +#include "lodNodeType.cxx" diff --git a/panda/src/pgraphnodes/p3pgraphnodes_composite2.cxx b/panda/src/pgraphnodes/p3pgraphnodes_composite2.cxx index 1d67ee3d44..952a2448c9 100644 --- a/panda/src/pgraphnodes/p3pgraphnodes_composite2.cxx +++ b/panda/src/pgraphnodes/p3pgraphnodes_composite2.cxx @@ -1,11 +1,10 @@ -#include "lodNode.cxx" -#include "lodNodeType.cxx" #include "nodeCullCallbackData.cxx" #include "pointLight.cxx" #include "sceneGraphAnalyzer.cxx" #include "selectiveChildNode.cxx" #include "sequenceNode.cxx" #include "shaderGenerator.cxx" +#include "sphereLight.cxx" #include "spotlight.cxx" #include "switchNode.cxx" #include "uvScrollNode.cxx" diff --git a/panda/src/pgraphnodes/pointLight.cxx b/panda/src/pgraphnodes/pointLight.cxx index ecb93bc768..564116ecac 100644 --- a/panda/src/pgraphnodes/pointLight.cxx +++ b/panda/src/pgraphnodes/pointLight.cxx @@ -196,7 +196,9 @@ register_with_read_factory() { void PointLight:: write_datagram(BamWriter *manager, Datagram &dg) { LightLensNode::write_datagram(manager, dg); - dg.add_bool(_has_specular_color); + if (manager->get_file_minor_ver() >= 39) { + dg.add_bool(_has_specular_color); + } manager->write_cdata(dg, _cycler); } diff --git a/panda/src/pgraphnodes/sphereLight.I b/panda/src/pgraphnodes/sphereLight.I new file mode 100644 index 0000000000..7f1c1955b3 --- /dev/null +++ b/panda/src/pgraphnodes/sphereLight.I @@ -0,0 +1,48 @@ +/** + * 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 sphereLight.I + * @author rdb + * @date 2016-04-15 + */ + +/** + * + */ +INLINE SphereLight::CData:: +CData() : + _radius(0.01f) +{ +} + +/** + * + */ +INLINE SphereLight::CData:: +CData(const SphereLight::CData ©) : + _radius(copy._radius) +{ +} + +/** + * Returns the radius of the sphere. + */ +INLINE PN_stdfloat SphereLight:: +get_radius() const { + CDReader cdata(_cycler); + return cdata->_radius; +} + +/** + * Sets the radius of the sphere. + */ +INLINE void SphereLight:: +set_radius(PN_stdfloat radius) { + CDWriter cdata(_cycler); + cdata->_radius = radius; +} diff --git a/panda/src/pgraphnodes/sphereLight.cxx b/panda/src/pgraphnodes/sphereLight.cxx new file mode 100644 index 0000000000..c4cf01be5a --- /dev/null +++ b/panda/src/pgraphnodes/sphereLight.cxx @@ -0,0 +1,146 @@ +/** + * 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 sphereLight.cxx + * @author rdb + * @date 2016-04-15 + */ + +#include "sphereLight.h" +#include "graphicsStateGuardianBase.h" +#include "bamWriter.h" +#include "bamReader.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle SphereLight::_type_handle; + +/** + * + */ +CycleData *SphereLight::CData:: +make_copy() const { + return new CData(*this); +} + +/** + * Writes the contents of this object to the datagram for shipping out to a + * Bam file. + */ +void SphereLight::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { + dg.add_stdfloat(_radius); +} + +/** + * This internal function is called by make_from_bam to read in all of the + * relevant data from the BamFile for the new Light. + */ +void SphereLight::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { + _radius = scan.get_stdfloat(); +} + +/** + * + */ +SphereLight:: +SphereLight(const string &name) : + PointLight(name) +{ +} + +/** + * Do not call the copy constructor directly; instead, use make_copy() or + * copy_subgraph() to make a copy of a node. + */ +SphereLight:: +SphereLight(const SphereLight ©) : + PointLight(copy), + _cycler(copy._cycler) +{ +} + +/** + * Returns a newly-allocated PandaNode that is a shallow copy of this one. It + * will be a different pointer, but its internal data may or may not be shared + * with that of the original PandaNode. No children will be copied. + */ +PandaNode *SphereLight:: +make_copy() const { + return new SphereLight(*this); +} + +/** + * Transforms the contents of this PandaNode by the indicated matrix, if it + * means anything to do so. For most kinds of PandaNodes, this does nothing. + */ +void SphereLight:: +xform(const LMatrix4 &mat) { + PointLight::xform(mat); + CDWriter cdata(_cycler); + cdata->_radius = mat.xform_vec(LVector3(0, 0, cdata->_radius)).length(); + mark_viz_stale(); +} + +/** + * + */ +void SphereLight:: +write(ostream &out, int indent_level) const { + PointLight::write(out, indent_level); + indent(out, indent_level) << *this << ":\n"; + indent(out, indent_level + 2) + << "radius " << get_radius() << "\n"; +} + +/** + * Tells the BamReader how to create objects of type SphereLight. + */ +void SphereLight:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +/** + * Writes the contents of this object to the datagram for shipping out to a + * Bam file. + */ +void SphereLight:: +write_datagram(BamWriter *manager, Datagram &dg) { + PointLight::write_datagram(manager, dg); + manager->write_cdata(dg, _cycler); +} + +/** + * This function is called by the BamReader's factory when a new object of + * type SphereLight is encountered in the Bam file. It should create the + * SphereLight and extract its information from the file. + */ +TypedWritable *SphereLight:: +make_from_bam(const FactoryParams ¶ms) { + SphereLight *node = new SphereLight(""); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + node->fillin(scan, manager); + + return node; +} + +/** + * This internal function is called by make_from_bam to read in all of the + * relevant data from the BamFile for the new SphereLight. + */ +void SphereLight:: +fillin(DatagramIterator &scan, BamReader *manager) { + PointLight::fillin(scan, manager); + + manager->read_cdata(scan, _cycler); +} diff --git a/panda/src/pgraphnodes/sphereLight.h b/panda/src/pgraphnodes/sphereLight.h new file mode 100644 index 0000000000..da36d71fc2 --- /dev/null +++ b/panda/src/pgraphnodes/sphereLight.h @@ -0,0 +1,90 @@ +/** + * 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 sphereLight.h + * @author rdb + * @date 2016-04-15 + */ + +#ifndef SPHERELIGHT_H +#define SPHERELIGHT_H + +#include "pandabase.h" + +#include "lightLensNode.h" + +/** + * A sphere light is like a point light, except that it represents a sphere + * with a radius, rather than being an infinitely thin point in space. + */ +class EXPCL_PANDA_PGRAPHNODES SphereLight : public PointLight { +PUBLISHED: + SphereLight(const string &name); + +protected: + SphereLight(const SphereLight ©); + +public: + virtual PandaNode *make_copy() const; + virtual void xform(const LMatrix4 &mat); + virtual void write(ostream &out, int indent_level) const; + +PUBLISHED: + INLINE PN_stdfloat get_radius() const; + INLINE void set_radius(PN_stdfloat radius); + MAKE_PROPERTY(radius, get_radius, set_radius); + +private: + // This is the data that must be cycled between pipeline stages. + class EXPCL_PANDA_PGRAPHNODES CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual void fillin(DatagramIterator &scan, BamReader *manager); + virtual TypeHandle get_parent_type() const { + return SphereLight::get_class_type(); + } + + PN_stdfloat _radius; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + PointLight::init_type(); + register_type(_type_handle, "SphereLight", + PointLight::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "sphereLight.I" + +#endif diff --git a/panda/src/pgraphnodes/spotlight.cxx b/panda/src/pgraphnodes/spotlight.cxx index 8e46ab213e..638f89f93c 100644 --- a/panda/src/pgraphnodes/spotlight.cxx +++ b/panda/src/pgraphnodes/spotlight.cxx @@ -252,7 +252,9 @@ register_with_read_factory() { void Spotlight:: write_datagram(BamWriter *manager, Datagram &dg) { LightLensNode::write_datagram(manager, dg); - dg.add_bool(_has_specular_color); + if (manager->get_file_minor_ver() >= 39) { + dg.add_bool(_has_specular_color); + } manager->write_cdata(dg, _cycler); } diff --git a/panda/src/pgraphnodes/uvScrollNode.cxx b/panda/src/pgraphnodes/uvScrollNode.cxx index caa9e55635..f5b7bc534a 100644 --- a/panda/src/pgraphnodes/uvScrollNode.cxx +++ b/panda/src/pgraphnodes/uvScrollNode.cxx @@ -53,8 +53,12 @@ write_datagram(BamWriter *manager, Datagram &dg) { PandaNode::write_datagram(manager, dg); dg.add_stdfloat(_u_speed); dg.add_stdfloat(_v_speed); - dg.add_stdfloat(_w_speed); - dg.add_stdfloat(_r_speed); + if (manager->get_file_minor_ver() >= 33) { + dg.add_stdfloat(_w_speed); + } + if (manager->get_file_minor_ver() >= 22) { + dg.add_stdfloat(_r_speed); + } } /** diff --git a/panda/src/physics/forceNode.I b/panda/src/physics/forceNode.I index 43ac5be849..8fd6845727 100644 --- a/panda/src/physics/forceNode.I +++ b/panda/src/physics/forceNode.I @@ -23,16 +23,15 @@ clear() { */ INLINE BaseForce *ForceNode:: -get_force(int index) const { - nassertr(index >= 0 && index < (int)_forces.size(), - (BaseForce *) NULL); +get_force(size_t index) const { + nassertr(index < _forces.size(), (BaseForce *) NULL); return _forces[index]; } /** */ -INLINE int ForceNode:: +INLINE size_t ForceNode:: get_num_forces() const { return _forces.size(); } diff --git a/panda/src/physics/forceNode.cxx b/panda/src/physics/forceNode.cxx index 09a0b3bc27..c5a998a47e 100644 --- a/panda/src/physics/forceNode.cxx +++ b/panda/src/physics/forceNode.cxx @@ -64,6 +64,20 @@ add_forces_from(const ForceNode &other) { } } +/** + * replace operation + */ +void ForceNode:: +set_force(size_t index, BaseForce *force) { + nassertv(index <= _forces.size()); + + _forces[index]->_force_node = (ForceNode *)NULL; + _forces[index]->_force_node_path.clear(); + _forces[index] = force; + force->_force_node = this; + force->_force_node_path = NodePath(this); +} + /** * remove operation */ @@ -81,8 +95,8 @@ remove_force(BaseForce *f) { * remove operation */ void ForceNode:: -remove_force(int index) { - nassertv(index >= 0 && index <= (int)_forces.size()); +remove_force(size_t index) { + nassertv(index <= _forces.size()); pvector< PT(BaseForce) >::iterator remove; remove = _forces.begin() + index; diff --git a/panda/src/physics/forceNode.h b/panda/src/physics/forceNode.h index 2000e9b0bc..574987ff1a 100644 --- a/panda/src/physics/forceNode.h +++ b/panda/src/physics/forceNode.h @@ -28,14 +28,17 @@ class EXPCL_PANDAPHYSICS ForceNode : public PandaNode { PUBLISHED: ForceNode(const string &name); INLINE void clear(); - INLINE BaseForce *get_force(int index) const; - INLINE int get_num_forces() const; + INLINE BaseForce *get_force(size_t index) const; + INLINE size_t get_num_forces() const; MAKE_SEQ(get_forces, get_num_forces, get_force); INLINE void add_force(BaseForce *force); void add_forces_from(const ForceNode &other); - void remove_force(BaseForce *f); - void remove_force(int index); + void set_force(size_t index, BaseForce *force); + void remove_force(BaseForce *force); + void remove_force(size_t index); + + MAKE_SEQ_PROPERTY(forces, get_num_forces, get_force, set_force, remove_force); virtual void output(ostream &out) const; virtual void write_forces(ostream &out, unsigned int indent=0) const; diff --git a/panda/src/physics/physicalNode.I b/panda/src/physics/physicalNode.I index 6296926055..92e5961ae8 100644 --- a/panda/src/physics/physicalNode.I +++ b/panda/src/physics/physicalNode.I @@ -23,16 +23,15 @@ clear() { */ INLINE Physical *PhysicalNode:: -get_physical(int index) const { - nassertr(index >= 0 && index < (int)_physicals.size(), - (Physical *) NULL); +get_physical(size_t index) const { + nassertr(index < _physicals.size(), (Physical *) NULL); return _physicals[index]; } /** */ -INLINE int PhysicalNode:: +INLINE size_t PhysicalNode:: get_num_physicals() const { return _physicals.size(); } diff --git a/panda/src/physics/physicalNode.cxx b/panda/src/physics/physicalNode.cxx index e10c29b625..381ceeff4f 100644 --- a/panda/src/physics/physicalNode.cxx +++ b/panda/src/physics/physicalNode.cxx @@ -63,6 +63,18 @@ add_physicals_from(const PhysicalNode &other) { } } +/** + * replace operation + */ +void PhysicalNode:: +set_physical(size_t index, Physical *physical) { + nassertv(index <= _physicals.size()); + + _physicals[index]->_physical_node = (PhysicalNode *) NULL; + _physicals[index] = physical; + physical->_physical_node = this; +} + /** * remove operation */ @@ -80,8 +92,8 @@ remove_physical(Physical *physical) { * remove operation */ void PhysicalNode:: -remove_physical(int index) { - nassertv(index >= 0 && index <= (int)_physicals.size()); +remove_physical(size_t index) { + nassertv(index <= _physicals.size()); pvector< PT(Physical) >::iterator remove; remove = _physicals.begin() + index; diff --git a/panda/src/physics/physicalNode.h b/panda/src/physics/physicalNode.h index 80e925dc13..5ab9f36372 100644 --- a/panda/src/physics/physicalNode.h +++ b/panda/src/physics/physicalNode.h @@ -29,14 +29,17 @@ class EXPCL_PANDAPHYSICS PhysicalNode : public PandaNode { PUBLISHED: PhysicalNode(const string &name); INLINE void clear(); - INLINE Physical *get_physical(int index) const; - INLINE int get_num_physicals() const; + INLINE Physical *get_physical(size_t index) const; + INLINE size_t get_num_physicals() const; MAKE_SEQ(get_physicals, get_num_physicals, get_physical); INLINE void add_physical(Physical *physical); void add_physicals_from(const PhysicalNode &other); + void set_physical(size_t index, Physical *physical); void remove_physical(Physical *physical); - void remove_physical(int index); + void remove_physical(size_t index); + + MAKE_SEQ_PROPERTY(physicals, get_num_physicals, get_physical, set_physical, remove_physical); virtual void write(ostream &out, unsigned int indent=0) const; diff --git a/panda/src/pnmimage/pnmFileType.h b/panda/src/pnmimage/pnmFileType.h index d6433ef304..48e4a533fb 100644 --- a/panda/src/pnmimage/pnmFileType.h +++ b/panda/src/pnmimage/pnmFileType.h @@ -44,6 +44,10 @@ PUBLISHED: MAKE_SEQ(get_extensions, get_num_extensions, get_extension); virtual string get_suggested_extension() const; + MAKE_PROPERTY(name, get_name); + MAKE_SEQ_PROPERTY(extensions, get_num_extensions, get_extension); + MAKE_PROPERTY(suggested_extension, get_suggested_extension); + public: virtual bool has_magic_number() const; virtual bool matches_magic_number(const string &magic_number) const; diff --git a/panda/src/pnmimage/pnmFileTypeRegistry.cxx b/panda/src/pnmimage/pnmFileTypeRegistry.cxx index f3cf8c5291..261f311f11 100644 --- a/panda/src/pnmimage/pnmFileTypeRegistry.cxx +++ b/panda/src/pnmimage/pnmFileTypeRegistry.cxx @@ -127,7 +127,7 @@ get_type_from_extension(const string &filename) const { } #ifdef HAVE_ZLIB - if (extension == "pz") { + if (extension == "pz" || extension == "gz") { // If the extension is .pz, then we've got a Panda-compressed image file. // Back up some more and get the extension before that. size_t prev_dot = filename.rfind('.', dot - 1); diff --git a/panda/src/pnmimage/pnmFileTypeRegistry.h b/panda/src/pnmimage/pnmFileTypeRegistry.h index 35c8bcbb20..aec9327d49 100644 --- a/panda/src/pnmimage/pnmFileTypeRegistry.h +++ b/panda/src/pnmimage/pnmFileTypeRegistry.h @@ -38,6 +38,7 @@ PUBLISHED: int get_num_types() const; PNMFileType *get_type(int n) const; MAKE_SEQ(get_types, get_num_types, get_type); + MAKE_SEQ_PROPERTY(types, get_num_types, get_type); PNMFileType *get_type_from_extension(const string &filename) const; PNMFileType *get_type_from_magic_number(const string &magic_number) const; diff --git a/panda/src/pnmimage/pnmImage.h b/panda/src/pnmimage/pnmImage.h index 6c32d42225..2c45492029 100644 --- a/panda/src/pnmimage/pnmImage.h +++ b/panda/src/pnmimage/pnmImage.h @@ -366,6 +366,7 @@ PUBLISHED: private: friend class Row; + friend class Texture; xel *_array; xelval *_alpha; diff --git a/panda/src/pnmimage/pnmImageHeader.cxx b/panda/src/pnmimage/pnmImageHeader.cxx index a73c11d297..a0098b58f7 100644 --- a/panda/src/pnmimage/pnmImageHeader.cxx +++ b/panda/src/pnmimage/pnmImageHeader.cxx @@ -181,7 +181,8 @@ make_reader(istream *file, bool owns_file, const Filename &filename, << type->get_name() << ".\n"; } else { pnmimage_cat.debug() - << "Unable to guess image file type from its extension.\n"; + << "Unable to guess image file type from its extension (" + << filename.get_extension() << ").\n"; } } } @@ -342,7 +343,7 @@ make_writer(ostream *file, bool owns_file, const Filename &filename, delete file; } - if (!writer->is_valid()) { + if (writer != NULL && !writer->is_valid()) { delete writer; writer = NULL; } diff --git a/panda/src/pnmimagetypes/config_pnmimagetypes.cxx b/panda/src/pnmimagetypes/config_pnmimagetypes.cxx index 99c290bb74..c498951f3f 100644 --- a/panda/src/pnmimagetypes/config_pnmimagetypes.cxx +++ b/panda/src/pnmimagetypes/config_pnmimagetypes.cxx @@ -22,6 +22,8 @@ #include "pnmFileTypePNM.h" #include "pnmFileTypePfm.h" #include "pnmFileTypeTIFF.h" +#include "pnmFileTypeEXR.h" +#include "pnmFileTypeStbImage.h" #include "sgi.h" #include "config_pnmimage.h" @@ -40,6 +42,7 @@ NotifyCategoryDefName(pnmimage_jpg, "jpg", pnmimage_cat); NotifyCategoryDefName(pnmimage_png, "png", pnmimage_cat); NotifyCategoryDefName(pnmimage_pnm, "pnm", pnmimage_cat); NotifyCategoryDefName(pnmimage_tiff, "tiff", pnmimage_cat); +NotifyCategoryDefName(pnmimage_exr, "exr", pnmimage_cat); ConfigVariableEnum sgi_storage_type ("sgi-storage-type", SST_rle, @@ -240,6 +243,18 @@ init_libpnmimagetypes() { tr->register_type(new PNMFileTypeTIFF); #endif +#ifdef HAVE_OPENEXR + PNMFileTypeEXR::init_type(); + PNMFileTypeEXR::register_with_read_factory(); + tr->register_type(new PNMFileTypeEXR); +#endif + +#ifdef HAVE_STB_IMAGE + PNMFileTypeStbImage::init_type(); + PNMFileTypeStbImage::register_with_read_factory(); + tr->register_type(new PNMFileTypeStbImage); +#endif + // And register with the PandaSystem. PandaSystem *ps = PandaSystem::get_global_ptr(); @@ -252,4 +267,7 @@ init_libpnmimagetypes() { #ifdef HAVE_TIFF ps->add_system("libtiff"); #endif +#ifdef HAVE_OPENEXR + ps->add_system("openexr"); +#endif } diff --git a/panda/src/pnmimagetypes/config_pnmimagetypes.h b/panda/src/pnmimagetypes/config_pnmimagetypes.h index bca20cb449..dca563a683 100644 --- a/panda/src/pnmimagetypes/config_pnmimagetypes.h +++ b/panda/src/pnmimagetypes/config_pnmimagetypes.h @@ -32,6 +32,7 @@ NotifyCategoryDecl(pnmimage_sgi, EXPCL_PANDA_PNMIMAGETYPES, EXPTP_PANDA_PNMIMAGETYPES); NotifyCategoryDecl(pnmimage_tiff, EXPCL_PANDA_PNMIMAGETYPES, EXPTP_PANDA_PNMIMAGETYPES); +NotifyCategoryDecl(pnmimage_exr, EXPCL_PANDA_PNMIMAGETYPES, EXPTP_PANDA_PNMIMAGETYPES); NotifyCategoryDecl(pnmimage_tga, EXPCL_PANDA_PNMIMAGETYPES, EXPTP_PANDA_PNMIMAGETYPES); NotifyCategoryDecl(pnmimage_img, EXPCL_PANDA_PNMIMAGETYPES, EXPTP_PANDA_PNMIMAGETYPES); NotifyCategoryDecl(pnmimage_soft, EXPCL_PANDA_PNMIMAGETYPES, EXPTP_PANDA_PNMIMAGETYPES); diff --git a/panda/src/pnmimagetypes/p3pnmimagetypes_composite1.cxx b/panda/src/pnmimagetypes/p3pnmimagetypes_composite1.cxx index 6f6cee3cf0..97b57a79a8 100644 --- a/panda/src/pnmimagetypes/p3pnmimagetypes_composite1.cxx +++ b/panda/src/pnmimagetypes/p3pnmimagetypes_composite1.cxx @@ -1,8 +1,9 @@ #include "config_pnmimagetypes.cxx" #include "pnmFileTypeBMPReader.cxx" #include "pnmFileTypeBMPWriter.cxx" -#include "pnmFileTypeIMG.cxx" #include "pnmFileTypeBMP.cxx" +#include "pnmFileTypeEXR.cxx" +#include "pnmFileTypeIMG.cxx" #include "pnmFileTypeJPG.cxx" #include "pnmFileTypeJPGReader.cxx" #include "pnmFileTypeJPGWriter.cxx" diff --git a/panda/src/pnmimagetypes/p3pnmimagetypes_composite2.cxx b/panda/src/pnmimagetypes/p3pnmimagetypes_composite2.cxx index 7e22a6b6ea..90f811de62 100644 --- a/panda/src/pnmimagetypes/p3pnmimagetypes_composite2.cxx +++ b/panda/src/pnmimagetypes/p3pnmimagetypes_composite2.cxx @@ -6,5 +6,6 @@ #include "pnmFileTypeSGIReader.cxx" #include "pnmFileTypeSGIWriter.cxx" #include "pnmFileTypeSoftImage.cxx" +#include "pnmFileTypeStbImage.cxx" #include "pnmFileTypeTGA.cxx" diff --git a/panda/src/pnmimagetypes/pnmFileTypeBMPReader.cxx b/panda/src/pnmimagetypes/pnmFileTypeBMPReader.cxx index 8d5336b75b..5d33812216 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeBMPReader.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeBMPReader.cxx @@ -226,7 +226,7 @@ BMPreadinfoheader( * for the required total. */ if (classv != C_OS2) { - for (int i = 0; i < cbFix - 16; i += 4) { + for (int i = 0; i < (int)cbFix - 16; i += 4) { GetLong(fp); } } diff --git a/panda/src/pnmimagetypes/pnmFileTypeEXR.cxx b/panda/src/pnmimagetypes/pnmFileTypeEXR.cxx new file mode 100644 index 0000000000..6f27c5e09a --- /dev/null +++ b/panda/src/pnmimagetypes/pnmFileTypeEXR.cxx @@ -0,0 +1,475 @@ +/** + * 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 pnmFileTypeEXR.cxx + * @author drose + * @date 2000-06-19 + */ + +#include "pnmFileTypeEXR.h" + +#ifdef HAVE_OPENEXR + +#include "config_pnmimagetypes.h" + +#include "pnmFileTypeRegistry.h" +#include "bamReader.h" +#include "pfmFile.h" + +#include +#include +#include +#include + +#ifndef IMATH_NAMESPACE +#define IMATH_NAMESPACE Imath +#endif + +TypeHandle PNMFileTypeEXR::_type_handle; + +static const char * const extensions_exr[] = { + "exr" +}; +static const int num_extensions_exr = sizeof(extensions_exr) / sizeof(const char *); + +// A wrapper class to map OpenEXR's OStream class onto std::ostream. +class ImfStdOstream : public IMF::OStream { +public: + ImfStdOstream(std::ostream &strm) : IMF::OStream("ostream"), _strm(strm) {} + + virtual void write(const char c[/*n*/], int n) { + _strm.write(c, n); + } + + virtual IMF::Int64 tellp() { + return _strm.tellp(); + } + + virtual void seekp(IMF::Int64 pos) { + _strm.seekp(pos); + } + +private: + std::ostream &_strm; +}; + +// A wrapper class to map OpenEXR's IStream class onto std::istream. +class ImfStdIstream : public IMF::IStream { +public: + ImfStdIstream(std::istream &strm, const std::string &magic_number) : IMF::IStream("istream"), _strm(strm) { + // Start by putting back the magic number. + for (std::string::const_reverse_iterator mi = magic_number.rbegin(); + mi != magic_number.rend(); + mi++) { + _strm.putback(*mi); + } + } + + virtual bool isMemoryMapped () const { + return false; + } + + virtual bool read (char c[/*n*/], int n) { + _strm.read(c, n); + if (_strm.gcount() != n) { + throw std::exception(); + } + + bool not_eof = !_strm.eof(); + return not_eof; + } + + virtual IMF::Int64 tellg() { + return _strm.tellg(); + } + + virtual void seekg(IMF::Int64 pos) { + _strm.seekg(pos); + } + + virtual void clear() { + _strm.clear(); + } + +private: + std::istream &_strm; +}; + +PNMFileTypeEXR:: +PNMFileTypeEXR() { +} + +/** + * Returns a few words describing the file type. + */ +string PNMFileTypeEXR:: +get_name() const { + return "OpenEXR"; +} + +/** + * Returns the number of different possible filename extensions associated + * with this particular file type. + */ +int PNMFileTypeEXR:: +get_num_extensions() const { + return num_extensions_exr; +} + +/** + * Returns the nth possible filename extension associated with this particular + * file type, without a leading dot. + */ +string PNMFileTypeEXR:: +get_extension(int n) const { + nassertr(n >= 0 && n < num_extensions_exr, string()); + return extensions_exr[n]; +} + +/** + * Returns a suitable filename extension (without a leading dot) to suggest + * for files of this type, or empty string if no suggestions are available. + */ +string PNMFileTypeEXR:: +get_suggested_extension() const { + return "exr"; +} + +/** + * Returns true if this particular file type uses a magic number to identify + * it, false otherwise. + */ +bool PNMFileTypeEXR:: +has_magic_number() const { + return true; +} + +/** + * Returns true if the indicated "magic number" byte stream (the initial few + * bytes read from the file) matches this particular file type, false + * otherwise. + */ +bool PNMFileTypeEXR:: +matches_magic_number(const string &magic_number) const { + nassertr(magic_number.size() >= 2, false); + + if (magic_number.size() >= 4) { + // If we have already read all four bytes, use the built-in + // function to check them. + return IMF::isImfMagic(magic_number.data()); + } else { + // Otherwise, check only the first two bytes and call it good enough. + return magic_number[0] == ((IMF::MAGIC >> 0) & 0x00ff) && + magic_number[1] == ((IMF::MAGIC >> 8) & 0x00ff); + } +} + +/** + * Allocates and returns a new PNMReader suitable for reading from this file + * type, if possible. If reading from this file type is not supported, + * returns NULL. + */ +PNMReader *PNMFileTypeEXR:: +make_reader(istream *file, bool owns_file, const string &magic_number) { + init_pnm(); + return new Reader(this, file, owns_file, magic_number); +} + +/** + * Allocates and returns a new PNMWriter suitable for reading from this file + * type, if possible. If writing files of this type is not supported, returns + * NULL. + */ +PNMWriter *PNMFileTypeEXR:: +make_writer(ostream *file, bool owns_file) { + init_pnm(); + return new Writer(this, file, owns_file); +} + +/** + * + */ +PNMFileTypeEXR::Reader:: +Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) : + PNMReader(type, file, owns_file), + _strm(new ImfStdIstream(*_file, magic_number)), + _imf_file(*_strm) +{ + const IMF::Header &header = _imf_file.header(); + + IMATH_NAMESPACE::Box2i dw = header.dataWindow(); + _x_size = dw.max.x - dw.min.x + 1; + _y_size = dw.max.y - dw.min.y + 1; + + // Find the channels we care about, and ensure they're placed in the + // correct order. + _channel_names.clear(); + + const IMF::ChannelList &channels = header.channels(); + + // Note: including Y in this list allows us to handle grayscale or + // grayscale/alpha images correctly, but also incorrectly detects + // luminance/chroma images as grayscale only. However, these kind + // of images are a pain to handle anyway, so maybe that's OK. + const char *possible_channel_names[] = { "R", "G", "B", "Y", "A", NULL }; + for (const char **pni = possible_channel_names; *pni != NULL; ++pni) { + std::string name = *pni; + IMF::ChannelList::ConstIterator ci = channels.find(name.c_str()); + if (ci != channels.end()) { + // Found a match. + if (name == "Y" && !_channel_names.empty()) { + // Y is luminance or grayscale. Ignore Y if there are + // already any RGB channels. + } else { + _channel_names.push_back(name); + } + } + } + + if (_channel_names.empty()) { + // Didn't find any channel names that match R, G, B, A, so just + // ask for RGB anyway and trust the OpenEXR library to do the + // right thing. Actually, it just fills them with black, but + // whatever. + _channel_names.push_back("R"); + _channel_names.push_back("G"); + _channel_names.push_back("B"); + } + + _num_channels = (int)_channel_names.size(); + if (_num_channels == 0 || _num_channels > 4) { + _is_valid = false; + return; + } + // We read all OpenEXR files to floating-point, even UINT type, so + // _maxval doesn't matter. But we set it anyway. + _maxval = 65535; + + _is_valid = true; +} + +/** + * + */ +PNMFileTypeEXR::Reader:: +~Reader() { + delete _strm; +} + +/** + * Returns true if this PNMFileType represents a floating-point image type, + * false if it is a normal, integer type. If this returns true, read_pfm() is + * implemented instead of read_data(). + */ +bool PNMFileTypeEXR::Reader:: +is_floating_point() { + // We read everything to floating-point, since even the UINT type is + // 32 bits, more fidelity than we can represent in our 16-bit + // PNMImage. + return true; +} + +/** + * Reads floating-point data directly into the indicated PfmFile. Returns + * true on success, false on failure. + */ +bool PNMFileTypeEXR::Reader:: +read_pfm(PfmFile &pfm) { + pfm.clear(_x_size, _y_size, _num_channels); + vector_float table; + pfm.swap_table(table); + + PN_float32 *table_data = table.data(); + size_t x_stride = sizeof(PN_float32) * pfm.get_num_channels(); + size_t y_stride = x_stride * pfm.get_x_size(); + nassertr(y_stride * pfm.get_y_size() <= table.size() * sizeof(PN_float32), false); + + const IMF::Header &header = _imf_file.header(); + IMATH_NAMESPACE::Box2i dw = header.dataWindow(); + + IMF::FrameBuffer frameBuffer; + for (int ci = 0; ci < pfm.get_num_channels(); ++ci) { + char *base = (char *)(table_data - (dw.min.x + dw.min.y * pfm.get_x_size()) * pfm.get_num_channels() + ci); + frameBuffer.insert(_channel_names[ci].c_str(), + IMF::Slice(IMF::FLOAT, base, x_stride, y_stride, + 1, 1, 0.0)); + } + + _imf_file.setFrameBuffer(frameBuffer); + + try { + _imf_file.readPixels(dw.min.y, dw.max.y); + } catch (const std::exception &exc) { + pnmimage_exr_cat.error() + << exc.what() << "\n"; + return false; + } + + pfm.swap_table(table); + return true; +} + +/** + * Reads in an entire image all at once, storing it in the pre-allocated + * _x_size * _y_size array and alpha pointers. (If the image type has no + * alpha channel, alpha is ignored.) Returns the number of rows correctly + * read. + * + * Derived classes need not override this if they instead provide + * supports_read_row() and read_row(), below. + */ +int PNMFileTypeEXR::Reader:: +read_data(xel *array, xelval *alpha) { + // This should never come here, since we always read to + // floating-point data. + nassertr(false, 0); + return 0; +} + +/** + * + */ +PNMFileTypeEXR::Writer:: +Writer(PNMFileType *type, ostream *file, bool owns_file) : + PNMWriter(type, file, owns_file) +{ +} + +/** + * Returns true if this PNMFileType can accept a floating-point image type, + * false if it can only accept a normal, integer type. If this returns true, + * write_pfm() is implemented. + */ +bool PNMFileTypeEXR::Writer:: +supports_floating_point() { + return true; +} + +/** + * Returns true if this PNMFileType can accept an integer image type, false if + * it can only accept a floating-point type. If this returns true, + * write_data() or write_row() is implemented. + */ +bool PNMFileTypeEXR::Writer:: +supports_integer() { + return false; +} + +/** + * Writes floating-point data from the indicated PfmFile. Returns true on + * success, false on failure. + */ +bool PNMFileTypeEXR::Writer:: +write_pfm(const PfmFile &pfm) { + const vector_float &table = pfm.get_table(); + const PN_float32 *table_data = table.data(); + size_t x_stride = sizeof(PN_float32) * pfm.get_num_channels(); + size_t y_stride = x_stride * pfm.get_x_size(); + nassertr(y_stride * pfm.get_y_size() <= table.size() * sizeof(PN_float32), false); + + const char *channel_names_1[] = { "G" }; + const char *channel_names_2[] = { "G", "A" }; + const char *channel_names_3[] = { "R", "G", "B" }; + const char *channel_names_4[] = { "R", "G", "B", "A" }; + const char **channel_names = NULL; + + switch (pfm.get_num_channels()) { + case 1: + channel_names = channel_names_1; + break; + + case 2: + channel_names = channel_names_2; + break; + + case 3: + channel_names = channel_names_3; + break; + + case 4: + channel_names = channel_names_4; + break; + + default: + return false; + }; + + IMF::Header header(pfm.get_x_size(), pfm.get_y_size()); + for (int ci = 0; ci < pfm.get_num_channels(); ++ci) { + header.channels().insert(channel_names[ci], IMF::Channel(IMF::FLOAT)); + } + + IMF::FrameBuffer frameBuffer; + for (int ci = 0; ci < pfm.get_num_channels(); ++ci) { + const char *base = (const char *)(table_data + ci); + frameBuffer.insert(channel_names[ci], + IMF::Slice(IMF::FLOAT, (char *)base, x_stride, y_stride)); + } + + ImfStdOstream strm(*_file); + IMF::OutputFile file(strm, header); + file.setFrameBuffer(frameBuffer); + + try { + file.writePixels(pfm.get_y_size()); + } catch (const std::exception &exc) { + pnmimage_exr_cat.error() + << exc.what() << "\n"; + return false; + } + + return true; +} + +/** + * Writes out an entire image all at once, including the header, based on the + * image data stored in the given _x_size * _y_size array and alpha pointers. + * (If the image type has no alpha channel, alpha is ignored.) Returns the + * number of rows correctly written. + * + * It is the user's responsibility to fill in the header data via calls to + * set_x_size(), set_num_channels(), etc., or copy_header_from(), before + * calling write_data(). + * + * It is important to delete the PNMWriter class after successfully writing + * the data. Failing to do this may result in some data not getting flushed! + * + * Derived classes need not override this if they instead provide + * supports_streaming() and write_row(), below. + */ +int PNMFileTypeEXR::Writer:: +write_data(xel *array, xelval *alpha) { + // This should never come here, since we always write to + // floating-point data. + nassertr(false, 0); + return 0; +} + +/** + * Registers the current object as something that can be read from a Bam file. + */ +void PNMFileTypeEXR:: +register_with_read_factory() { + BamReader::get_factory()-> + register_factory(get_class_type(), make_PNMFileTypeEXR); +} + +/** + * This method is called by the BamReader when an object of this type is + * encountered in a Bam file; it should allocate and return a new object with + * all the data read. + * + * In the case of the PNMFileType objects, since these objects are all shared, + * we just pull the object from the registry. + */ +TypedWritable *PNMFileTypeEXR:: +make_PNMFileTypeEXR(const FactoryParams ¶ms) { + return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); +} + +#endif // HAVE_OPENEXR diff --git a/panda/src/pnmimagetypes/pnmFileTypeEXR.h b/panda/src/pnmimagetypes/pnmFileTypeEXR.h new file mode 100644 index 0000000000..3a0827a74e --- /dev/null +++ b/panda/src/pnmimagetypes/pnmFileTypeEXR.h @@ -0,0 +1,114 @@ +/** + * 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 pnmFileTypeEXR.h + * @author drose + * @date 2000-06-17 + */ + +#ifndef PNMFILETYPEEXR_H +#define PNMFILETYPEEXR_H + +#include "pandabase.h" + +#ifdef HAVE_OPENEXR + +#include "pnmFileType.h" +#include "pnmReader.h" +#include "pnmWriter.h" + +#include +#include + +#ifdef OPENEXR_IMF_NAMESPACE +namespace IMF = OPENEXR_IMF_NAMESPACE; +#else +namespace IMF = Imf; +#endif + +class ImfStdIstream; + +/** + * For reading and writing EXR floating-point or integer files. + */ +class EXPCL_PANDA_PNMIMAGETYPES PNMFileTypeEXR : public PNMFileType { +public: + PNMFileTypeEXR(); + + virtual string get_name() const; + + virtual int get_num_extensions() const; + virtual string get_extension(int n) const; + virtual string get_suggested_extension() const; + + virtual bool has_magic_number() const; + virtual bool matches_magic_number(const string &magic_number) const; + + virtual PNMReader *make_reader(istream *file, bool owns_file = true, + const string &magic_number = string()); + virtual PNMWriter *make_writer(ostream *file, bool owns_file = true); + +public: + class Reader : public PNMReader { + public: + Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number); + virtual ~Reader(); + + virtual bool is_floating_point(); + virtual bool read_pfm(PfmFile &pfm); + virtual int read_data(xel *array, xelval *alpha); + + private: + class ImfStdIstream *_strm; + IMF::InputFile _imf_file; + + typedef std::vector ChannelNames; + ChannelNames _channel_names; + IMF::PixelType _best_pixel_type; + }; + + class Writer : public PNMWriter { + public: + Writer(PNMFileType *type, ostream *file, bool owns_file); + + virtual bool supports_floating_point(); + virtual bool supports_integer(); + virtual bool write_pfm(const PfmFile &pfm); + virtual int write_data(xel *array, xelval *alpha); + }; + +private: + + // The TypedWritable interface follows. +public: + static void register_with_read_factory(); + +protected: + static TypedWritable *make_PNMFileTypeEXR(const FactoryParams ¶ms); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + PNMFileType::init_type(); + register_type(_type_handle, "PNMFileTypeEXR", + PNMFileType::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#endif // HAVE_OPENEXR + +#endif diff --git a/panda/src/pnmimagetypes/pnmFileTypePNM.cxx b/panda/src/pnmimagetypes/pnmFileTypePNM.cxx index d1ada1a078..efbee9e646 100644 --- a/panda/src/pnmimagetypes/pnmFileTypePNM.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypePNM.cxx @@ -649,10 +649,10 @@ writePackedRawRow(ostream * const fileP, const unsigned char * const packed_bits, int const cols) { - int bytesWritten; fileP->write((const char *)packed_bits, pbm_packed_bytes(cols)); - if (fileP->fail()) + if (fileP->fail()) { pm_error("I/O error writing packed row to raw PBM file."); + } } static void diff --git a/panda/src/pnmimagetypes/pnmFileTypeStbImage.cxx b/panda/src/pnmimagetypes/pnmFileTypeStbImage.cxx new file mode 100644 index 0000000000..2c8932f7c9 --- /dev/null +++ b/panda/src/pnmimagetypes/pnmFileTypeStbImage.cxx @@ -0,0 +1,509 @@ +/** + * 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 pnmFileTypeStbImage.cxx + * @author rdb + * @date 2016-03-31 + */ + +#include "pnmFileTypeStbImage.h" + +#ifdef HAVE_STB_IMAGE + +#include "config_pnmimagetypes.h" +#include "pnmFileTypeRegistry.h" +#include "bamReader.h" + +// We use the public domain stb_image library for loading images. Define the +// stb_image implementation. We only use it in this unit. +#define STB_IMAGE_STATIC +#define STB_IMAGE_IMPLEMENTATION + +// Disable the stb_image implementation of these formats if we already support +// it through different loaders. +#ifndef HAVE_JPEG +#define STBI_ONLY_JPEG +#endif +#ifndef HAVE_PNG +#define STBI_ONLY_PNG +#endif +#ifndef HAVE_BMP +#define STBI_ONLY_BMP +#endif +#ifndef HAVE_TGA +#define STBI_ONLY_TGA +#endif +#ifndef HAVE_SOFTIMAGE_PIC +#define STBI_ONLY_PIC +#endif +#ifndef HAVE_PNM +#define STBI_ONLY_PNM +#endif + +// These are always enabled because we don't support these via other means. +#define STBI_ONLY_PSD +#define STBI_ONLY_HDR +#define STBI_ONLY_GIF + +#ifndef NDEBUG +// Get friendlier error messages in development builds. +#define STBI_FAILURE_USERMSG +#endif + +// We read via callbacks, so no need for stbi_load_from_file. +#define STBI_NO_STDIO + +#include "stb_image.h" + +static const char *const stb_extensions[] = { + // Expose the extensions that we don't already expose through other loaders. +#ifndef HAVE_JPEG + "jpg", "jpeg", +#endif +#ifndef HAVE_PNG + "png", +#endif +#ifndef HAVE_BMP + "bmp", +#endif +#ifndef HAVE_TGA + "tga", +#endif +#ifndef HAVE_SOFTIMAGE_PIC + "pic", +#endif +#ifndef HAVE_PNM + "ppm", "pgm", +#endif + + // We don't have other loaders for these, so add them unconditionally. + "psd", + "hdr", + "gif", +}; +static const int num_stb_extensions = sizeof(stb_extensions) / sizeof(const char *); + +// Callbacks to allow stb_image to read from VFS. +static int cb_read(void *user, char *data, int size) { + istream *in = (istream *)user; + nassertr(in != NULL, 0); + + in->read(data, size); + + if (in->eof()) { + // Gracefully handle EOF. + in->clear(); + } + + return (int)in->gcount(); +} + +static void cb_skip(void *user, int n) { + istream *in = (istream *)user; + nassertv(in != NULL); + + in->seekg(n, ios::cur); + + if (in->fail()) { + in->clear(); + + // Implement skip by just reading and discarding the result. + static const int size = 4096; + char data[4096]; + while (n > 4096) { + in->read(data, 4096); + n -= 4096; + } + if (n > 0) { + in->read(data, n); + } + } +} + +static int cb_eof(void *user) { + istream *in = (istream *)user; + nassertr(in != NULL, 1); + + return in->eof(); +} + +static stbi_io_callbacks io_callbacks = {cb_read, cb_skip, cb_eof}; + +/** + * This is defined in the .cxx file so we have access to stbi_context. + */ +class StbImageReader : public PNMReader { +public: + StbImageReader(PNMFileType *type, istream *file, bool owns_file, string magic_number); + + virtual bool is_floating_point(); + virtual bool read_pfm(PfmFile &pfm); + virtual int read_data(xel *array, xelval *alpha); + +private: + bool _is_float; + stbi__context _context; +}; + +TypeHandle PNMFileTypeStbImage::_type_handle; + +/** + * + */ +PNMFileTypeStbImage:: +PNMFileTypeStbImage() { +} + +/** + * Returns a few words describing the file type. + */ +string PNMFileTypeStbImage:: +get_name() const { + return "stb_image"; +} + +/** + * Returns the number of different possible filename extensions associated + * with this particular file type. + */ +int PNMFileTypeStbImage:: +get_num_extensions() const { + return num_stb_extensions; +} + +/** + * Returns the nth possible filename extension associated with this particular + * file type, without a leading dot. + */ +string PNMFileTypeStbImage:: +get_extension(int n) const { + nassertr(n >= 0 && n < num_stb_extensions, string()); + return stb_extensions[n]; +} + +/** + * Returns true if this particular file type uses a magic number to identify + * it, false otherwise. + */ +bool PNMFileTypeStbImage:: +has_magic_number() const { + return false; +} + +/** + * Returns true if the indicated "magic number" byte stream (the initial few + * bytes read from the file) matches this particular file type, false + * otherwise. + */ +bool PNMFileTypeStbImage:: +matches_magic_number(const string &magic_number) const { + return false; +} + +/** + * Allocates and returns a new PNMReader suitable for reading from this file + * type, if possible. If reading from this file type is not supported, + * returns NULL. + */ +PNMReader *PNMFileTypeStbImage:: +make_reader(istream *file, bool owns_file, const string &magic_number) { + init_pnm(); + return new StbImageReader(this, file, owns_file, magic_number); +} + +/** + * + */ +StbImageReader:: +StbImageReader(PNMFileType *type, istream *file, bool owns_file, string magic_number) : + PNMReader(type, file, owns_file), + _is_float(false) +{ + // Hope we can putback() more than one character. + for (string::reverse_iterator mi = magic_number.rbegin(); + mi != magic_number.rend(); + mi++) { + _file->putback(*mi); + } + if (_file->fail()) { + pnmimage_cat.error() + << "Unable to put back magic number.\n"; + _is_valid = false; + return; + } + + stbi__start_callbacks(&_context, &io_callbacks, (void *)file); + + if (strncmp(magic_number.c_str(), "#?", 2) == 0 && + stbi__hdr_info(&_context, &_x_size, &_y_size, &_num_channels)) { + _is_valid = true; + _is_float = true; + } else if (stbi__info_main(&_context, &_x_size, &_y_size, &_num_channels)) { + _is_valid = true; + } else { + _is_valid = false; + pnmimage_cat.error() + << "stb_info failure: " << stbi_failure_reason() << "\n"; + } + + _maxval = 255; +} + +/** + * Returns true if this PNMFileType represents a floating-point image type, + * false if it is a normal, integer type. If this returns true, read_pfm() is + * implemented instead of read_data(). + */ +bool StbImageReader:: +is_floating_point() { + return _is_float; +} + +/** + * Reads floating-point data directly into the indicated PfmFile. Returns + * true on success, false on failure. + */ +bool StbImageReader:: +read_pfm(PfmFile &pfm) { + if (!is_valid()) { + return false; + } + + // Reposition the file at the beginning. + _file->seekg(0, ios::beg); + if (_file->tellg() != (streampos)0) { + pnmimage_cat.error() + << "Could not reposition file pointer to the beginning.\n"; + return false; + } + + stbi__start_callbacks(&_context, &io_callbacks, (void *)_file); + + nassertr(_num_channels == 3, false); + + // This next bit is copied and pasted from stbi__hdr_load so that we can + // avoid making an unnecessary extra copy of the data. + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + int len; + unsigned char count, value; + int i, j, k, c1, c2, z; + + // Check identifier + if (strcmp(stbi__hdr_gettoken(&_context, buffer), "#?RADIANCE") != 0) { + pnmimage_cat.error() + << "Missing #?RADIANCE header.\n"; + return false; + } + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(&_context, buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + pnmimage_cat.error() << "Unsupported HDR format.\n"; + return false; + } + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(&_context, buffer); + if (strncmp(token, "-Y ", 3)) { + pnmimage_cat.error() << "Unsupported HDR data layout.\n"; + return false; + } + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + pnmimage_cat.error() << "Unsupported HDR data layout.\n"; + return false; + } + token += 3; + width = (int) strtol(token, NULL, 10); + + // Read data + pfm.clear(width, height, 3); + vector_float table; + pfm.swap_table(table); + float *hdr_data = (float *)&table[0]; + + // Load image data + // image data is stored as some number of sca + if (width < 8 || width >= 32768) { + // Read flat data + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + stbi_uc rgbe[4]; +main_decode_loop: + stbi__getn(&_context, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * 3 + i * 3, rgbe, 3); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(&_context); + c2 = stbi__get8(&_context); + len = stbi__get8(&_context); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(&_context); + stbi__hdr_convert(hdr_data, rgbe, 3); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(&_context); + if (len != width) { + STBI_FREE(scanline); + pnmimage_cat.error() << "Corrupt HDR: invalid decoded scanline length.\n"; + return false; + } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc(width * 4); + } + + for (k = 0; k < 4; ++k) { + i = 0; + while (i < width) { + count = stbi__get8(&_context); + if (count > 128) { + // Run + value = stbi__get8(&_context); + count -= 128; + for (z = 0; z < count; ++z) { + scanline[i++ * 4 + k] = value; + } + } else { + // Dump + for (z = 0; z < count; ++z) { + scanline[i++ * 4 + k] = stbi__get8(&_context); + } + } + } + } + for (i = 0; i < width; ++i) { + stbi__hdr_convert(hdr_data+(j*width + i)*3, scanline + i*4, 3); + } + } + STBI_FREE(scanline); + } + + pfm.swap_table(table); + return true; +} + +/** + * Reads in an entire image all at once, storing it in the pre-allocated + * _x_size * _y_size array and alpha pointers. (If the image type has no + * alpha channel, alpha is ignored.) Returns the number of rows correctly + * read. + * + * Derived classes need not override this if they instead provide + * supports_read_row() and read_row(), below. + */ +int StbImageReader:: +read_data(xel *array, xelval *alpha) { + // Reposition the file at the beginning. + _file->seekg(0, ios::beg); + if (_file->tellg() != (streampos)0) { + pnmimage_cat.error() + << "Could not reposition file pointer to the beginning.\n"; + return 0; + } + + stbi__start_callbacks(&_context, &io_callbacks, (void *)_file); + + int cols = 0; + int rows = 0; + stbi_uc *data = stbi__load_main(&_context, &cols, &rows, NULL, _num_channels); + + if (data == NULL) { + pnmimage_cat.error() + << "stbi_load failure: " << stbi_failure_reason() << "\n"; + return 0; + } + + nassertr(cols == _x_size, 0); + + size_t pixels = (size_t)_x_size * (size_t)rows; + stbi_uc *ptr = data; + switch (_num_channels) { + case 1: + for (size_t i = 0; i < pixels; ++i) { + PPM_ASSIGN(array[i], ptr[i], ptr[i], ptr[i]); + } + break; + + case 2: + for (size_t i = 0; i < pixels; ++i) { + PPM_ASSIGN(array[i], ptr[0], ptr[0], ptr[0]); + alpha[i] = ptr[1]; + ptr += 2; + } + break; + + case 3: + for (size_t i = 0; i < pixels; ++i) { + PPM_ASSIGN(array[i], ptr[0], ptr[1], ptr[2]); + ptr += 3; + } + break; + + case 4: + for (size_t i = 0; i < pixels; ++i) { + PPM_ASSIGN(array[i], ptr[0], ptr[1], ptr[2]); + alpha[i] = ptr[3]; + ptr += 4; + } + break; + } + + stbi_image_free(data); + return rows; +} + +/** + * Registers the current object as something that can be read from a Bam file. + */ +void PNMFileTypeStbImage:: +register_with_read_factory() { + BamReader::get_factory()-> + register_factory(get_class_type(), make_PNMFileTypeStbImage); +} + +/** + * This method is called by the BamReader when an object of this type is + * encountered in a Bam file; it should allocate and return a new object with + * all the data read. + * + * In the case of the PNMFileType objects, since these objects are all shared, + * we just pull the object from the registry. + */ +TypedWritable *PNMFileTypeStbImage:: +make_PNMFileTypeStbImage(const FactoryParams ¶ms) { + return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); +} + +#endif // HAVE_STB_IMAGE diff --git a/panda/src/pnmimagetypes/pnmFileTypeStbImage.h b/panda/src/pnmimagetypes/pnmFileTypeStbImage.h new file mode 100644 index 0000000000..08cf62e247 --- /dev/null +++ b/panda/src/pnmimagetypes/pnmFileTypeStbImage.h @@ -0,0 +1,71 @@ +/** + * 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 pnmFileTypeStbImage.h + * @author rdb + * @date 2016-03-31 + */ + +#ifndef PNMFILETYPESTBIMAGE_H +#define PNMFILETYPESTBIMAGE_H + +#include "pandabase.h" + +#ifdef HAVE_STB_IMAGE + +#include "pnmFileType.h" +#include "pnmReader.h" +#include "pnmWriter.h" + +/** + * For reading images via the public domain stb_image.h library. This is used + * when compiling without support for more specific libraries that are more + * full-featured, such as libpng or libjpeg. + */ +class EXPCL_PANDA_PNMIMAGETYPES PNMFileTypeStbImage : public PNMFileType { +public: + PNMFileTypeStbImage(); + + virtual string get_name() const; + + virtual int get_num_extensions() const; + virtual string get_extension(int n) const; + + virtual bool has_magic_number() const; + virtual bool matches_magic_number(const string &magic_number) const; + + virtual PNMReader *make_reader(istream *file, bool owns_file = true, + const string &magic_number = string()); + +public: + static void register_with_read_factory(); + +protected: + static TypedWritable *make_PNMFileTypeStbImage(const FactoryParams ¶ms); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + PNMFileType::init_type(); + register_type(_type_handle, "PNMFileTypeStbImage", + PNMFileType::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#endif // HAVE_STB_IMAGE + +#endif diff --git a/panda/src/pnmimagetypes/stb_image.h b/panda/src/pnmimagetypes/stb_image.h new file mode 100644 index 0000000000..a3c1129932 --- /dev/null +++ b/panda/src/pnmimagetypes/stb_image.h @@ -0,0 +1,6755 @@ +/* stb_image - v2.12 - public domain image loader - http://nothings.org/stb_image.h + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8-bit-per-channel (16 bpc not supported) + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + + Revision 2.00 release notes: + + - Progressive JPEG is now supported. + + - PPM and PGM binary formats are now supported, thanks to Ken Miller. + + - x86 platforms now make use of SSE2 SIMD instructions for + JPEG decoding, and ARM platforms can use NEON SIMD if requested. + This work was done by Fabian "ryg" Giesen. SSE2 is used by + default, but NEON must be enabled explicitly; see docs. + + With other JPEG optimizations included in this version, we see + 2x speedup on a JPEG on an x86 machine, and a 1.5x speedup + on a JPEG on an ARM machine, relative to previous versions of this + library. The same results will not obtain for all JPGs and for all + x86/ARM machines. (Note that progressive JPEGs are significantly + slower to decode than regular JPEGs.) This doesn't mean that this + is the fastest JPEG decoder in the land; rather, it brings it + closer to parity with standard libraries. If you want the fastest + decode, look elsewhere. (See "Philosophy" section of docs below.) + + See final bullet items below for more info on SIMD. + + - Added STBI_MALLOC, STBI_REALLOC, and STBI_FREE macros for replacing + the memory allocator. Unlike other STBI libraries, these macros don't + support a context parameter, so if you need to pass a context in to + the allocator, you'll have to store it in a global or a thread-local + variable. + + - Split existing STBI_NO_HDR flag into two flags, STBI_NO_HDR and + STBI_NO_LINEAR. + STBI_NO_HDR: suppress implementation of .hdr reader format + STBI_NO_LINEAR: suppress high-dynamic-range light-linear float API + + - You can suppress implementation of any of the decoders to reduce + your code footprint by #defining one or more of the following + symbols before creating the implementation. + + STBI_NO_JPEG + STBI_NO_PNG + STBI_NO_BMP + STBI_NO_PSD + STBI_NO_TGA + STBI_NO_GIF + STBI_NO_HDR + STBI_NO_PIC + STBI_NO_PNM (.ppm and .pgm) + + - You can request *only* certain decoders and suppress all other ones + (this will be more forward-compatible, as addition of new decoders + doesn't require you to disable them explicitly): + + STBI_ONLY_JPEG + STBI_ONLY_PNG + STBI_ONLY_BMP + STBI_ONLY_PSD + STBI_ONLY_TGA + STBI_ONLY_GIF + STBI_ONLY_HDR + STBI_ONLY_PIC + STBI_ONLY_PNM (.ppm and .pgm) + + Note that you can define multiples of these, and you will get all + of them ("only x" and "only y" is interpreted to mean "only x&y"). + + - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still + want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB + + - Compilation of all SIMD code can be suppressed with + #define STBI_NO_SIMD + It should not be necessary to disable SIMD unless you have issues + compiling (e.g. using an x86 compiler which doesn't support SSE + intrinsics or that doesn't support the method used to detect + SSE2 support at run-time), and even those can be reported as + bugs so I can refine the built-in compile-time checking to be + smarter. + + - The old STBI_SIMD system which allowed installing a user-defined + IDCT etc. has been removed. If you need this, don't upgrade. My + assumption is that almost nobody was doing this, and those who + were will find the built-in SIMD more satisfactory anyway. + + - RGB values computed for JPEG images are slightly different from + previous versions of stb_image. (This is due to using less + integer precision in SIMD.) The C code has been adjusted so + that the same RGB values will be computed regardless of whether + SIMD support is available, so your app should always produce + consistent results. But these results are slightly different from + previous versions. (Specifically, about 3% of available YCbCr values + will compute different RGB results from pre-1.49 versions by +-1; + most of the deviating values are one smaller in the G channel.) + + - If you must produce consistent results with previous versions of + stb_image, #define STBI_JPEG_OLD and you will get the same results + you used to; however, you will not get the SIMD speedups for + the YCbCr-to-RGB conversion step (although you should still see + significant JPEG speedup from the other changes). + + Please note that STBI_JPEG_OLD is a temporary feature; it will be + removed in future versions of the library. It is only intended for + near-term back-compatibility use. + + + Latest revision history: + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) partial animated GIF support + limited 16-bit PSD support + minor bugs, code cleanup, and compiler warnings + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) additional corruption checking + stbi_set_flip_vertically_on_load + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPEG, including x86 SSE2 & ARM NEON SIMD + progressive JPEG + PGM/PPM support + STBI_MALLOC,STBI_REALLOC,STBI_FREE + STBI_NO_*, STBI_ONLY_* + GIF bugfix + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + urraka@github (animated gif) Junggon Kim (PNM comments) + Daniel Gibson (16-bit TGA) + + Optimizations & bugfixes + Fabian "ryg" Giesen + Arseny Kapoulkine + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Martin Golini Jerry Jansson Joseph Thomson + Dave Moore Roy Eltham Hayaki Saito Phil Jordan + Won Chun Luke Graham Johan Duparc Nathan Reed + the Horde3D community Thomas Ruf Ronny Chevalier Nick Verigakis + Janez Zemva John Bartholomew Michal Cichon svdijk@github + Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson + Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github + Aruelien Pocheville Thibault Reuille Cass Everitt Matthew Gregan + Ryamond Barbiero Paul Du Bois Engin Manap snagar@github + Michaelangel007@github Oriol Ferrer Mesia socks-the-fox + Blazej Dariusz Roszkowski + + +LICENSE + +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. + +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 16-bit-per-channel PNG +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - no 1-bit BMP +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *comp -- outputs # of image components in image file +// int req_comp -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise. +// If req_comp is non-zero, *comp has the number of components that _would_ +// have been output otherwise. E.g. if you set req_comp to 4, you will always +// get RGBA output, but you can check *comp to see if it's trivially opaque +// because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *comp will be unchanged. The function stbi_failure_reason() +// can be queried for an extremely brief, end-user unfriendly explanation +// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid +// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy to use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries do not emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// make more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// The output of the JPEG decoder is slightly different from versions where +// SIMD support was introduced (that is, for versions before 1.49). The +// difference is only +-1 in the 8-bit RGB channels, and only on a small +// fraction of pixels. You can force the pre-1.49 behavior by defining +// STBI_JPEG_OLD, but this will disable some of the SIMD decoding path +// and hence cost some performance. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image now supports loading HDR images in general, and currently +// the Radiance .HDR file format, although the support is provided +// generically. You can still load any file through the existing interface; +// if you attempt to load an HDR file, it will be automatically remapped to +// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// By default we convert iphone-formatted PNGs back to RGB, even though +// they are internally encoded differently. You can disable this conversion +// by by calling stbi_convert_iphone_png_to_rgb(0), in which case +// you will always just get the native iphone "format" through (which +// is BGR stored in RGB). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// + + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for req_comp + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +typedef unsigned char stbi_uc; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *comp, int req_comp); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *comp, int req_comp); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// NOT THREADSAFE +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); + +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +#ifdef _MSC_VER +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// NOTE: not clear do we actually need this for the 64-bit path? +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// (but compiling with -msse2 allows the compiler to use SSE2 everywhere; +// this is just broken and gcc are jerks for not fixing it properly +// http://www.virtualdub.org/blog/pivot/entry.php?id=363 ) +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +static int stbi__sse2_available() +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +static int stbi__sse2_available() +{ +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later + // GCC 4.8+ has a nice way to do this + return __builtin_cpu_supports("sse2"); +#else + // portable way to do this, preferably without using GCC inline ASM? + // just bail for now. + return 0; +#endif +} +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +// assume GCC or Clang on ARM targets +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static stbi_uc *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static stbi_uc *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static stbi_uc *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +// this is not threadsafe +static const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load = flag_true_if_should_flip; +} + +static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static unsigned char *stbi__load_flip(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result = stbi__load_main(s, x, y, comp, req_comp); + + if (stbi__vertically_flip_on_load && result != NULL) { + int w = *x, h = *y; + int depth = req_comp ? req_comp : *comp; + int row,col,z; + stbi_uc temp; + + // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once + for (row = 0; row < (h>>1); row++) { + for (col = 0; col < w; col++) { + for (z = 0; z < depth; z++) { + temp = result[(row * w + col) * depth + z]; + result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; + result[((h - row - 1) * w + col) * depth + z] = temp; + } + } + } + } + + return result; +} + +#ifndef STBI_NO_HDR +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int w = *x, h = *y; + int depth = req_comp ? req_comp : *comp; + int row,col,z; + float temp; + + // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once + for (row = 0; row < (h>>1); row++) { + for (col = 0; col < w; col++) { + for (z = 0; z < depth; z++) { + temp = result[(row * w + col) * depth + z]; + result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; + result[((h - row - 1) * w + col) * depth + z] = temp; + } + } + } + } +} +#endif + +#ifndef STBI_NO_STDIO + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_flip(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} +#endif //!STBI_NO_STDIO + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_flip(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_flip(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_flip(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_file(&s,f); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +static void stbi__skip(stbi__context *s, int n) +{ + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} + +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + return z + (stbi__get16le(s) << 16); +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc(req_comp * x * y); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define COMBO(a,b) ((a)*8+(b)) + #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (COMBO(img_n, req_comp)) { + CASE(1,2) dest[0]=src[0], dest[1]=255; break; + CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; + CASE(2,1) dest[0]=src[0]; break; + CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; + CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; + CASE(3,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; + CASE(3,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; break; + CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; + CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; + CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + default: STBI_ASSERT(0); + } + #undef CASE + } + + STBI_FREE(data); + return good; +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output = (float *) stbi__malloc(x * y * comp * sizeof(float)); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi_uc dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0,code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (stbi_uc) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1 << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (-1 << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k << 8) + (run << 4) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + + sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB + k = stbi_lrot(j->code_buffer, n); + STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & ~sgn); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi_uc *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + diff = t ? stbi__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc << j->succ_low); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) << shift); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) << shift); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) << 12) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0] << 2; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi_uc *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4; + int t = q & 15,i; + if (p != 0) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = stbi__get8(z->s); + L -= 65; + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + stbi__skip(z->s, stbi__get16be(z->s)-2); + return 1; + } + return 0; +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + c = stbi__get8(s); + if (c != 3 && c != 1) return stbi__err("bad component count","Corrupt JPEG"); // JFIF requires + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (z->img_comp[i].id != i+1) // JFIF requires + if (z->img_comp[i].id != i) { // some version of jpegtran outputs non-JFIF-compliant files! + // somethings output this (see http://fileformats.archiveteam.org/wiki/JPEG#Color_format) + if (z->img_comp[i].id != rgb[i]) + return stbi__err("bad component ID","Corrupt JPEG"); + ++z->rgb; + } + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].raw_data = stbi__malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); + + if (z->img_comp[i].raw_data == NULL) { + for(--i; i >= 0; --i) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + } + return stbi__err("outofmem", "Out of memory"); + } + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + z->img_comp[i].linebuf = NULL; + if (z->progressive) { + z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3; + z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3; + z->img_comp[i].raw_coeff = STBI_MALLOC(z->img_comp[i].coeff_w * z->img_comp[i].coeff_h * 64 * sizeof(short) + 15); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } else { + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } else if (x != 0) { + return stbi__err("junk before marker", "Corrupt JPEG"); + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } else { + if (!stbi__process_marker(j, m)) return 0; + } + m = stbi__get_marker(j); + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +#ifdef STBI_JPEG_OLD +// this is the same YCbCr-to-RGB calculation that stb_image has used +// historically before the algorithm changes in 1.49 +#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 16) + 32768; // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr*float2fixed(1.40200f); + g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); + b = y_fixed + cb*float2fixed(1.77200f); + r >>= 16; + g >>= 16; + b >>= 16; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#else +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* float2fixed(1.40200f); + g = y_fixed + (cr*-float2fixed(0.71414f)) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* float2fixed(1.40200f); + g = y_fixed + cr*-float2fixed(0.71414f) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + #ifndef STBI_JPEG_OLD + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + #endif + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + #ifndef STBI_JPEG_OLD + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + #endif + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + int i; + for (i=0; i < j->s->img_n; ++i) { + if (j->img_comp[i].raw_data) { + STBI_FREE(j->img_comp[i].raw_data); + j->img_comp[i].raw_data = NULL; + j->img_comp[i].data = NULL; + } + if (j->img_comp[i].raw_coeff) { + STBI_FREE(j->img_comp[i].raw_coeff); + j->img_comp[i].raw_coeff = 0; + j->img_comp[i].coeff = 0; + } + if (j->img_comp[i].linebuf) { + STBI_FREE(j->img_comp[i].linebuf); + j->img_comp[i].linebuf = NULL; + } + } +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n; + + if (z->s->img_n == 3 && n < 3) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4]; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc(n * z->s->img_x * z->s->img_y + 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (z->rgb == 3) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n; // report original components, not output + return output; + } +} + +static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg j; + j.s = s; + stbi__setup_jpeg(&j); + r = stbi__decode_jpeg_header(&j, STBI__SCAN_type); + stbi__rewind(s); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[288]; + stbi__uint16 value[288]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + STBI_ASSERT(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) stbi__fill_bits(a); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = old_limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < hlit + hdist) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else if (c == 16) { + c = stbi__zreceive(a,2)+3; + memset(lencodes+n, lencodes[n-1], c); + n += c; + } else if (c == 17) { + c = stbi__zreceive(a,3)+3; + memset(lencodes+n, 0, c); + n += c; + } else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + memset(lencodes+n, 0, c); + n += c; + } + } + if (n != hlit+hdist) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + STBI_ASSERT(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +// @TODO: should statically initialize these for optimal thread safety +static stbi_uc stbi__zdefault_length[288], stbi__zdefault_distance[32]; +static void stbi__init_zdefaults(void) +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zdefault_distance[31]) stbi__init_zdefaults(); + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc(x * y * output_bytes); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + if (s->img_x == x && s->img_y == y) { + if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG"); + } else { // interlaced: + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + } + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior = cur - stride; + int filter = *raw++; + + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + STBI_ASSERT(img_width_bytes <= x); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; + } + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else if (depth == 16) { + if (img_n != out_n) { + cur[filter_bytes] = 255; // first pixel top byte + cur[filter_bytes+1] = 255; // first pixel bottom byte + } + raw += filter_bytes; + cur += output_bytes; + prior += output_bytes; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + // this is a little gross, so that we don't switch per-pixel or per-component + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*filter_bytes; + #define CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break; + CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break; + CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); break; + CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break; + CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); break; + } + #undef CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ + for (k=0; k < filter_bytes; ++k) + switch (filter) { + CASE(STBI__F_none) cur[k] = raw[k]; break; + CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); break; + CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); break; + CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); break; + CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); break; + CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); break; + } + #undef CASE + + // the loop above sets the high byte of the pixels' alpha, but for + // 16 bit png files we also need the low byte set. we'll do that here. + if (depth == 16) { + cur = a->out + stride*j; // start at the beginning of the row again + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } + } + } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + // insert alpha = 255 + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } else if (depth == 16) { + // force the image data from big-endian to platform-native. + // this is done in a separate pass due to the decoding relying + // on the data being untouched, but could probably be done + // per-line during decode if care is taken. + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_n + out_x*out_n, + a->out + (j*x+i)*out_n, out_n); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__reduce_png(stbi__png *p) +{ + int i; + int img_len = p->s->img_x * p->s->img_y * p->s->img_out_n; + stbi_uc *reduced; + stbi__uint16 *orig = (stbi__uint16*)p->out; + + if (p->depth != 16) return 1; // don't need to do anything if not 16-bit data + + reduced = (stbi_uc *)stbi__malloc(img_len); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling + + p->out = reduced; + STBI_FREE(orig); + + return 1; +} + +static int stbi__unpremultiply_on_load = 0; +static int stbi__de_iphone_flag = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + p[0] = p[2] * 255 / a; + p[1] = p[1] * 255 / a; + p[2] = t * 255 / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == STBI__SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } + STBI_FREE(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp) +{ + unsigned char *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth == 16) { + if (!stbi__reduce_png(p)) { + return result; + } + } + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + result = stbi__convert_format(result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static unsigned char *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) n += 16, z >>= 16; + if (z >= 0x00100) n += 8, z >>= 8; + if (z >= 0x00010) n += 4, z >>= 4; + if (z >= 0x00004) n += 2, z >>= 2; + if (z >= 0x00002) n += 1, z >>= 1; + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +static int stbi__shiftsigned(int v, int shift, int bits) +{ + int result; + int z=0; + + if (shift < 0) v <<= -shift; + else v >>= shift; + result = v; + + z = bits; + while (z < 8) { + result += v >> z; + z += bits; + } + return result; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; +} stbi__bmp_data; + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (info->bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit"); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - 14 - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - 14 - info.hsz) >> 2; + } + + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - 14 - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i], p1[i] = p2[i], p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if(is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // else: fall-through + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fall-through + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (r * 255)/31; + out[1] = (g * 255)/31; + out[2] = (b * 255)/31; + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4]; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + tga_data = (unsigned char*)stbi__malloc( (size_t)tga_width * tga_height * tga_comp ); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_comp ); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + int pixelCount; + int channelCount, compression; + int channel, i, count, len; + int bitdepth; + int w,h; + stbi_uc *out; + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Create the destination image. + out = (stbi_uc *) stbi__malloc(4 * w*h); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + count = 0; + while (count < pixelCount) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len ^= 0x0FF; + len += 2; + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out + channel; + if (channel >= channelCount) { + // Fill this channel with default data. + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } else { + // Read the data. + if (bitdepth == 16) { + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + + if (channelCount >= 4) { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + // remove weird white matte from PSD + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + + if (req_comp && req_comp != 4) { + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp) +{ + stbi_uc *result; + int i, x,y; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if ((1 << 28) / x < y) return stbi__errpuc("too large", "Image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc(x*y*4); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out, *old_out; // output buffer (always 4 components) + int flags, bgindex, ratio, transparent, eflags, delay; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[4096]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + p = &g->out[g->cur_x + g->cur_y]; + c = &g->color_table[g->codes[code].suffix * 4]; + + if (c[3] >= 128) { + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) return stbi__errpuc("no clear code", "Corrupt GIF"); + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 4096) return stbi__errpuc("too many codes", "Corrupt GIF"); + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +static void stbi__fill_gif_background(stbi__gif *g, int x0, int y0, int x1, int y1) +{ + int x, y; + stbi_uc *c = g->pal[g->bgindex]; + for (y = y0; y < y1; y += 4 * g->w) { + for (x = x0; x < x1; x += 4) { + stbi_uc *p = &g->out[y + x]; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = 0; + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp) +{ + int i; + stbi_uc *prev_out = 0; + + if (g->out == 0 && !stbi__gif_header(s, g, comp,0)) + return 0; // stbi__g_failure_reason set by stbi__gif_header + + prev_out = g->out; + g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + + switch ((g->eflags & 0x1C) >> 2) { + case 0: // unspecified (also always used on 1st frame) + stbi__fill_gif_background(g, 0, 0, 4 * g->w, 4 * g->w * g->h); + break; + case 1: // do not dispose + if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); + g->old_out = prev_out; + break; + case 2: // dispose to background + if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); + stbi__fill_gif_background(g, g->start_x, g->start_y, g->max_x, g->max_y); + break; + case 3: // dispose to previous + if (g->old_out) { + for (i = g->start_y; i < g->max_y; i += 4 * g->w) + memcpy(&g->out[i + g->start_x], &g->old_out[i + g->start_x], g->max_x - g->start_x); + } + break; + } + + for (;;) { + switch (stbi__get8(s)) { + case 0x2C: /* Image Descriptor */ + { + int prev_trans = -1; + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + if (g->transparent >= 0 && (g->eflags & 0x01)) { + prev_trans = g->pal[g->transparent][3]; + g->pal[g->transparent][3] = 0; + } + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (o == NULL) return NULL; + + if (prev_trans != -1) + g->pal[g->transparent][3] = (stbi_uc) prev_trans; + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + if (stbi__get8(s) == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = stbi__get16le(s); + g->transparent = stbi__get8(s); + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) + stbi__skip(s, len); + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } + + STBI_NOTUSED(req_comp); +} + +static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *u = 0; + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + memset(g, 0, sizeof(*g)); + + u = stbi__gif_load_next(s, g, comp, req_comp); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g->w; + *y = g->h; + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g->w, g->h); + } + else if (g->out) + STBI_FREE(g->out); + STBI_FREE(g); + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s) +{ + const char *signature = "#?RADIANCE\n"; + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s); + stbi__rewind(s); + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + + + // Check identifier + if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + // Read data + hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float)); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4); + + for (k = 0; k < 4; ++k) { + i = 0; + while (i < width) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + stbi__rewind( s ); + if (p == NULL) + return 0; + *x = s->img_x; + *y = s->img_y; + *comp = info.ma ? 4 : 3; + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + if (stbi__get16be(s) != 8) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained; + stbi__pic_packet packets[10]; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) +// Does not support 16-bit-per-channel + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *out; + if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + return 0; + *x = s->img_x; + *y = s->img_y; + *comp = s->img_n; + + out = (stbi_uc *) stbi__malloc(s->img_n * s->img_x * s->img_y); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + + if (req_comp && req_comp != s->img_n) { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv; + char c, p, t; + + stbi__rewind( s ); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + + if (maxv > 255) + return stbi__err("max value > 255", "PPM image not 8-bit"); + else + return 1; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ diff --git a/panda/src/pstatclient/pStatClient.I b/panda/src/pstatclient/pStatClient.I index 5416b31234..8ce9381978 100644 --- a/panda/src/pstatclient/pStatClient.I +++ b/panda/src/pstatclient/pStatClient.I @@ -11,47 +11,6 @@ * @date 2000-07-16 */ -/** - * Sets the name of the client. This is reported to the PStatsServer, and - * will presumably be written in the title bar or something. - */ -INLINE void PStatClient:: -set_client_name(const string &name) { - get_impl()->set_client_name(name); -} - -/** - * Retrieves the name of the client as set. - */ -INLINE string PStatClient:: -get_client_name() const { - return get_impl()->get_client_name(); -} - -/** - * Controls the number of packets that will be sent to the server. Normally, - * one packet is sent per frame, but this can flood the server with more - * packets than it can handle if the frame rate is especially good (e.g. if - * nothing is onscreen at the moment). Set this parameter to a reasonable - * number to prevent this from happening. - * - * This number specifies the maximum number of packets that will be sent to - * the server per second, per thread. - */ -INLINE void PStatClient:: -set_max_rate(double rate) { - get_impl()->set_max_rate(rate); -} - -/** - * Returns the maximum number of packets that will be sent to the server per - * second, per thread. See set_max_rate(). - */ -INLINE double PStatClient:: -get_max_rate() const { - return get_impl()->get_max_rate(); -} - /** * Returns the total number of collectors the Client knows about. */ @@ -111,20 +70,6 @@ get_thread_object(int index) const { return thread->_thread; } -/** - * Returns the time according to to the PStatClient's clock object. It keeps - * its own clock, instead of using the global clock object, so the stats won't - * get mucked up if you put the global clock in non-real-time mode or - * something. - */ -INLINE double PStatClient:: -get_real_time() const { - if (has_impl()) { - return _impl->get_real_time(); - } - return 0.0f; -} - /** * Attempts to establish a connection to the indicated PStatServer. Returns * true if successful, false on failure. @@ -161,36 +106,6 @@ resume_after_pause() { get_global_pstats()->client_resume_after_pause(); } -/** - * The nonstatic implementation of connect(). - */ -INLINE bool PStatClient:: -client_connect(string hostname, int port) { - ReMutexHolder holder(_lock); - client_disconnect(); - return get_impl()->client_connect(hostname, port); -} - -/** - * The nonstatic implementation of is_connected(). - */ -INLINE bool PStatClient:: -client_is_connected() const { - return has_impl() && _impl->client_is_connected(); -} - -/** - * Resumes the PStatClient after the simulation has been paused for a while. - * This allows the stats to continue exactly where it left off, instead of - * leaving a big gap that would represent a chug. - */ -INLINE void PStatClient:: -client_resume_after_pause() { - if (has_impl()) { - _impl->client_resume_after_pause(); - } -} - /** * Returns true if the PStatClientImpl object has been created for this object * yet, false otherwise. @@ -208,9 +123,8 @@ INLINE PStatClientImpl *PStatClient:: get_impl() { ReMutexHolder holder(_lock); if (_impl == (PStatClientImpl *)NULL) { - _impl = new PStatClientImpl(this); + make_impl(); } - return _impl; } @@ -220,7 +134,11 @@ get_impl() { */ INLINE const PStatClientImpl *PStatClient:: get_impl() const { - return ((PStatClient *)this)->get_impl(); + ReMutexHolder holder(_lock); + if (_impl == (PStatClientImpl *)NULL) { + make_impl(); + } + return _impl; } /** diff --git a/panda/src/pstatclient/pStatClient.cxx b/panda/src/pstatclient/pStatClient.cxx index 9d87a13036..906d99a29a 100644 --- a/panda/src/pstatclient/pStatClient.cxx +++ b/panda/src/pstatclient/pStatClient.cxx @@ -104,6 +104,47 @@ PStatClient:: disconnect(); } +/** + * Sets the name of the client. This is reported to the PStatsServer, and + * will presumably be written in the title bar or something. + */ +void PStatClient:: +set_client_name(const string &name) { + get_impl()->set_client_name(name); +} + +/** + * Retrieves the name of the client as set. + */ +string PStatClient:: +get_client_name() const { + return get_impl()->get_client_name(); +} + +/** + * Controls the number of packets that will be sent to the server. Normally, + * one packet is sent per frame, but this can flood the server with more + * packets than it can handle if the frame rate is especially good (e.g. if + * nothing is onscreen at the moment). Set this parameter to a reasonable + * number to prevent this from happening. + * + * This number specifies the maximum number of packets that will be sent to + * the server per second, per thread. + */ +void PStatClient:: +set_max_rate(double rate) { + get_impl()->set_max_rate(rate); +} + +/** + * Returns the maximum number of packets that will be sent to the server per + * second, per thread. See set_max_rate(). + */ +double PStatClient:: +get_max_rate() const { + return get_impl()->get_max_rate(); +} + /** * Returns the nth collector. */ @@ -175,6 +216,20 @@ get_current_thread() const { return PStatThread(Thread::get_current_thread(), (PStatClient *)this); } +/** + * Returns the time according to to the PStatClient's clock object. It keeps + * its own clock, instead of using the global clock object, so the stats won't + * get mucked up if you put the global clock in non-real-time mode or + * something. + */ +double PStatClient:: +get_real_time() const { + if (has_impl()) { + return _impl->get_real_time(); + } + return 0.0f; +} + /** * A convenience function to call new_frame() on the global PStatClient's main * thread, and any other threads with a sync_name of "Main". @@ -383,6 +438,16 @@ client_thread_tick(const string &sync_name) { } } +/** + * The nonstatic implementation of connect(). + */ +bool PStatClient:: +client_connect(string hostname, int port) { + ReMutexHolder holder(_lock); + client_disconnect(); + return get_impl()->client_connect(hostname, port); +} + /** * The nonstatic implementation of disconnect(). */ @@ -416,6 +481,26 @@ client_disconnect() { } } +/** + * The nonstatic implementation of is_connected(). + */ +bool PStatClient:: +client_is_connected() const { + return has_impl() && _impl->client_is_connected(); +} + +/** + * Resumes the PStatClient after the simulation has been paused for a while. + * This allows the stats to continue exactly where it left off, instead of + * leaving a big gap that would represent a chug. + */ +void PStatClient:: +client_resume_after_pause() { + if (has_impl()) { + _impl->client_resume_after_pause(); + } +} + /** * Returns a pointer to the global PStatClient object. It's legal to declare * your own PStatClient locally, but it's also convenient to have a global one @@ -433,6 +518,14 @@ get_global_pstats() { return _global_pstats; } +/** + * Creates the PStatClientImpl class for this PStatClient. + */ +void PStatClient:: +make_impl() const { + _impl = new PStatClientImpl((PStatClient *)this); +} + /** * Returns a PStatCollector suitable for measuring categories with the * indicated name. This is normally called by a PStatCollector constructor. diff --git a/panda/src/pstatclient/pStatClient.h b/panda/src/pstatclient/pStatClient.h index c88ef8f5af..2d285c6f8a 100644 --- a/panda/src/pstatclient/pStatClient.h +++ b/panda/src/pstatclient/pStatClient.h @@ -17,7 +17,6 @@ #include "pandabase.h" #include "pStatFrameData.h" -#include "pStatClientImpl.h" #include "pStatCollectorDef.h" #include "reMutex.h" #include "lightMutex.h" @@ -31,6 +30,7 @@ #include "numeric_types.h" #include "bitArray.h" +class PStatClientImpl; class PStatCollector; class PStatCollectorDef; class PStatThread; @@ -50,16 +50,16 @@ class GraphicsStateGuardian; * is therefore defined as a stub class. */ #ifdef DO_PSTATS -class EXPCL_PANDA_PSTATCLIENT PStatClient : public ConnectionManager, public Thread::PStatsCallback { +class EXPCL_PANDA_PSTATCLIENT PStatClient : public Thread::PStatsCallback { public: PStatClient(); ~PStatClient(); PUBLISHED: - INLINE void set_client_name(const string &name); - INLINE string get_client_name() const; - INLINE void set_max_rate(double rate); - INLINE double get_max_rate() const; + void set_client_name(const string &name); + string get_client_name() const; + void set_max_rate(double rate); + double get_max_rate() const; INLINE int get_num_collectors() const; PStatCollector get_collector(int index) const; @@ -78,7 +78,15 @@ PUBLISHED: PStatThread get_main_thread() const; PStatThread get_current_thread() const; - INLINE double get_real_time() const; + double get_real_time() const; + + MAKE_PROPERTY(client_name, get_client_name, set_client_name); + MAKE_PROPERTY(max_rate, get_max_rate, set_max_rate); + MAKE_SEQ_PROPERTY(collectors, get_num_collectors, get_collector); + MAKE_SEQ_PROPERTY(threads, get_num_threads, get_thread); + MAKE_PROPERTY(main_thread, get_main_thread); + MAKE_PROPERTY(current_thread, get_current_thread); + MAKE_PROPERTY(real_time, get_real_time); INLINE static bool connect(const string &hostname = string(), int port = -1); INLINE static void disconnect(); @@ -91,11 +99,11 @@ PUBLISHED: void client_main_tick(); void client_thread_tick(const string &sync_name); - INLINE bool client_connect(string hostname, int port); + bool client_connect(string hostname, int port); void client_disconnect(); - INLINE bool client_is_connected() const; + bool client_is_connected() const; - INLINE void client_resume_after_pause(); + void client_resume_after_pause(); static PStatClient *get_global_pstats(); @@ -103,6 +111,7 @@ private: INLINE bool has_impl() const; INLINE PStatClientImpl *get_impl(); INLINE const PStatClientImpl *get_impl() const; + void make_impl() const; PStatCollector make_collector_with_relname(int parent_index, string relname); PStatCollector make_collector_with_name(int parent_index, const string &name); @@ -219,7 +228,7 @@ private: AtomicAdjust::Integer _threads_size; // size of the allocated array AtomicAdjust::Integer _num_threads; // number of in-use elements within the array - PStatClientImpl *_impl; + mutable PStatClientImpl *_impl; static PStatCollector _heap_total_size_pcollector; static PStatCollector _heap_overhead_size_pcollector; diff --git a/panda/src/pstatclient/pStatThread.I b/panda/src/pstatclient/pStatThread.I index fcfa992576..4fd43c5669 100644 --- a/panda/src/pstatclient/pStatThread.I +++ b/panda/src/pstatclient/pStatThread.I @@ -75,32 +75,6 @@ operator = (const PStatThread ©) { _index = copy._index; } -/** - * This must be called at the start of every "frame", whatever a frame may be - * deemed to be, to accumulate all the stats that have collected so far for - * the thread and ship them off to the server. - * - * Calling PStatClient::thread_tick() will automatically call this for any - * threads with the indicated sync name. - */ -INLINE void PStatThread:: -new_frame() { -#ifdef DO_PSTATS - _client->get_impl()->new_frame(_index); -#endif -} - -/** - * This is a slightly lower-level version of new_frame that also specifies the - * data to send for this frame. - */ -INLINE void PStatThread:: -add_frame(const PStatFrameData &frame_data) { -#ifdef DO_PSTATS - _client->get_impl()->add_frame(_index, frame_data); -#endif -} - /** * Returns the index number of this particular thread within the PStatClient. */ diff --git a/panda/src/pstatclient/pStatThread.cxx b/panda/src/pstatclient/pStatThread.cxx index 533fd10789..e263ac089a 100644 --- a/panda/src/pstatclient/pStatThread.cxx +++ b/panda/src/pstatclient/pStatThread.cxx @@ -13,6 +13,33 @@ #include "pStatThread.h" #include "pStatClient.h" +#include "pStatClientImpl.h" + +/** + * This must be called at the start of every "frame", whatever a frame may be + * deemed to be, to accumulate all the stats that have collected so far for + * the thread and ship them off to the server. + * + * Calling PStatClient::thread_tick() will automatically call this for any + * threads with the indicated sync name. + */ +void PStatThread:: +new_frame() { +#ifdef DO_PSTATS + _client->get_impl()->new_frame(_index); +#endif +} + +/** + * This is a slightly lower-level version of new_frame that also specifies the + * data to send for this frame. + */ +void PStatThread:: +add_frame(const PStatFrameData &frame_data) { +#ifdef DO_PSTATS + _client->get_impl()->add_frame(_index, frame_data); +#endif +} /** * Returns the Panda Thread object associated with this particular diff --git a/panda/src/pstatclient/pStatThread.h b/panda/src/pstatclient/pStatThread.h index 23ba20af8e..0ad8567c7a 100644 --- a/panda/src/pstatclient/pStatThread.h +++ b/panda/src/pstatclient/pStatThread.h @@ -36,8 +36,8 @@ PUBLISHED: INLINE PStatThread(const PStatThread ©); INLINE void operator = (const PStatThread ©); - INLINE void new_frame(); - INLINE void add_frame(const PStatFrameData &frame_data); + void new_frame(); + void add_frame(const PStatFrameData &frame_data); Thread *get_thread() const; INLINE int get_index() const; diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index 4251751135..2755f0f25d 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -32,7 +32,7 @@ static const unsigned short _bam_major_ver = 6; // Bumped to major version 6 on 2006-02-11 to factor out PandaNode::CData. static const unsigned short _bam_first_minor_ver = 14; -static const unsigned short _bam_minor_ver = 41; +static const unsigned short _bam_minor_ver = 42; // Bumped to minor version 14 on 2007-12-19 to change default ColorAttrib. // Bumped to minor version 15 on 2008-04-09 to add TextureAttrib::_implicit_sort. // Bumped to minor version 16 on 2008-05-13 to add Texture::_quality_level. @@ -61,5 +61,6 @@ static const unsigned short _bam_minor_ver = 41; // Bumped to minor version 39 on 2016-01-09 to change lights and materials. // Bumped to minor version 40 on 2016-01-11 to make NodePaths writable. // Bumped to minor version 41 on 2016-03-02 to change LensNode, Lens, and Camera. +// Bumped to minor version 42 on 2016-04-08 to expand ColorBlendAttrib. #endif diff --git a/panda/src/putil/bamCacheRecord.cxx b/panda/src/putil/bamCacheRecord.cxx index b13f1807ef..487d2b1e5d 100644 --- a/panda/src/putil/bamCacheRecord.cxx +++ b/panda/src/putil/bamCacheRecord.cxx @@ -232,15 +232,20 @@ format_timestamp(time_t timestamp) { } time_t now = time(NULL); - struct tm *tm_p = localtime(×tamp); + struct tm atm; +#ifdef _WIN32 + localtime_s(&atm, ×tamp); +#else + localtime_r(×tamp, &atm); +#endif if (timestamp > now || (now - timestamp > 86400 * 365)) { // A timestamp in the future, or more than a year in the past, gets a year // appended. - strftime(buffer, buffer_size, "%b %d %Y", tm_p); + strftime(buffer, buffer_size, "%b %d %Y", &atm); } else { // Otherwise, within the past year, show the date and time. - strftime(buffer, buffer_size, "%b %d %H:%M", tm_p); + strftime(buffer, buffer_size, "%b %d %H:%M", &atm); } return buffer; diff --git a/panda/src/putil/bamReader.I b/panda/src/putil/bamReader.I index 19f1a37a9d..ece2676956 100644 --- a/panda/src/putil/bamReader.I +++ b/panda/src/putil/bamReader.I @@ -159,6 +159,17 @@ get_file_pos() { return _source->get_file_pos(); } +/** + * Registers a factory function that is called when an object of the given + * type is encountered within the .bam stream. + * + * @param user_data an optional pointer to be passed along to the function. + */ +void BamReader:: +register_factory(TypeHandle handle, WritableFactory::CreateFunc *func, void *user_data) { + get_factory()->register_factory(handle, func, user_data); +} + /** * Returns the global WritableFactory for generating TypedWritable objects */ diff --git a/panda/src/putil/bamReader.h b/panda/src/putil/bamReader.h index 885fddaffb..4785a4d4fc 100644 --- a/panda/src/putil/bamReader.h +++ b/panda/src/putil/bamReader.h @@ -148,11 +148,14 @@ PUBLISHED: INLINE int get_current_major_ver() const; INLINE int get_current_minor_ver() const; + EXTENSION(PyObject *get_file_version() const); + PUBLISHED: MAKE_PROPERTY(source, get_source, set_source); MAKE_PROPERTY(filename, get_filename); MAKE_PROPERTY(loader_options, get_loader_options, set_loader_options); + MAKE_PROPERTY(file_version, get_file_version); MAKE_PROPERTY(file_endian, get_file_endian); MAKE_PROPERTY(file_stdfloat_double, get_file_stdfloat_double); @@ -194,7 +197,13 @@ public: INLINE streampos get_file_pos(); public: + INLINE static void register_factory(TypeHandle type, WritableFactory::CreateFunc *func, + void *user_data = NULL); INLINE static WritableFactory *get_factory(); + +PUBLISHED: + EXTENSION(static void register_factory(TypeHandle handle, PyObject *func)); + private: INLINE static void create_factory(); diff --git a/panda/src/putil/bamReader_ext.cxx b/panda/src/putil/bamReader_ext.cxx new file mode 100644 index 0000000000..4a490f90d9 --- /dev/null +++ b/panda/src/putil/bamReader_ext.cxx @@ -0,0 +1,123 @@ +/** + * 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 bamReader_ext.cxx + * @author rdb + * @date 2016-04-09 + */ + +#include "bamReader_ext.h" +#include "config_util.h" + +#ifdef HAVE_PYTHON + +#ifndef CPPPARSER +extern Dtool_PyTypedObject Dtool_BamReader; +extern Dtool_PyTypedObject Dtool_DatagramIterator; +extern Dtool_PyTypedObject Dtool_TypedWritable; +#endif // CPPPARSER + +/** + * Factory function that calls the registered Python function. + */ +static TypedWritable *factory_callback(const FactoryParams ¶ms){ + PyObject *func = (PyObject *)params.get_user_data(); + nassertr(func != NULL, NULL); + +#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) + // Use PyGILState to protect this asynchronous call. + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); +#endif + + // Extract the parameters we will pass to the Python function. + DatagramIterator scan; + BamReader *manager; + parse_params(params, scan, manager); + + PyObject *py_scan = DTool_CreatePyInstance(&scan, Dtool_DatagramIterator, false, false); + PyObject *py_manager = DTool_CreatePyInstance(manager, Dtool_BamReader, false, false); + PyObject *args = PyTuple_Pack(2, py_scan, py_manager); + + // Now call the Python function. + Thread *current_thread = Thread::get_current_thread(); + PyObject *result = current_thread->call_python_func(func, args); + Py_DECREF(args); + Py_DECREF(py_scan); + Py_DECREF(py_manager); + + if (result == (PyObject *)NULL) { + util_cat.error() + << "Exception occurred in Python factory function\n"; + + } else if (result == Py_None) { + util_cat.error() + << "Python factory function returned None\n"; + Py_DECREF(result); + result = NULL; + } + +#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) + PyGILState_Release(gstate); +#endif + + // Unwrap the returned TypedWritable object. + if (result == (PyObject *)NULL) { + return (TypedWritable *)NULL; + } else { + void *object = NULL; + Dtool_Call_ExtractThisPointer(result, Dtool_TypedWritable, &object); + + TypedWritable *ptr = (TypedWritable *)object; + ReferenceCount *ref_count = ptr->as_reference_count(); + if (ref_count != NULL) { + // If the Python pointer is the last reference to it, make sure that the + // object isn't destroyed. We do this by calling unref(), which + // decreases the reference count without destroying the object. + if (result->ob_refcnt <= 1) { + ref_count->unref(); + + // Tell the Python wrapper object that it shouldn't try to delete the + // object when it is destroyed. + ((Dtool_PyInstDef *)result)->_memory_rules = false; + } + Py_DECREF(result); + } + + return (TypedWritable *)object; + } +} + +/** + * Returns the version number of the Bam file currently being read. + */ +PyObject *Extension:: +get_file_version() const { + return Py_BuildValue("(ii)", _this->get_file_major_ver(), + _this->get_file_minor_ver()); +} + +/** + * Registers a Python function as factory function for the given type. This + * should be a function (or class object) that takes a DatagramIterator and a + * BamReader as arguments, and should return a TypedWritable object. + */ +void Extension:: +register_factory(TypeHandle handle, PyObject *func) { + nassertv(func != NULL); + + if (!PyCallable_Check(func)) { + Dtool_Raise_TypeError("second argument to register_factory must be callable"); + return; + } + + Py_INCREF(func); + BamReader::get_factory()->register_factory(handle, &factory_callback, (void *)func); +} + +#endif diff --git a/panda/src/putil/bamReader_ext.h b/panda/src/putil/bamReader_ext.h new file mode 100644 index 0000000000..d7905c617f --- /dev/null +++ b/panda/src/putil/bamReader_ext.h @@ -0,0 +1,39 @@ +/** + * 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 bamReader_ext.h + * @author rdb + * @date 2016-04-09 + */ + +#ifndef BAMREADER_EXT_H +#define BAMREADER_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "bamReader.h" +#include "py_panda.h" + +/** + * This class defines the extension methods for BamReader, which are called + * instead of any C++ methods with the same prototype. + */ +template<> +class Extension : public ExtensionBase { +public: + PyObject *get_file_version() const; + + static void register_factory(TypeHandle handle, PyObject *func); +}; + +#endif // HAVE_PYTHON + +#endif // BAMREADER_EXT_H diff --git a/panda/src/putil/bamWriter.I b/panda/src/putil/bamWriter.I index e620ade5bf..b2fa51d146 100644 --- a/panda/src/putil/bamWriter.I +++ b/panda/src/putil/bamWriter.I @@ -42,6 +42,16 @@ get_file_major_ver() const { return _file_major; } +/** + * Changes the minor .bam version to write. This should be called before + * init(). Each Panda version has only a fairly narrow range of versions it + * is able to write; consult the .bam documentation for more information. + */ +INLINE void BamWriter:: +set_file_minor_ver(int minor_ver) { + _file_minor = minor_ver; +} + /** * Returns the minor version number of the Bam file currently being written. */ diff --git a/panda/src/putil/bamWriter.cxx b/panda/src/putil/bamWriter.cxx index 9ad37a798f..679600b664 100644 --- a/panda/src/putil/bamWriter.cxx +++ b/panda/src/putil/bamWriter.cxx @@ -41,8 +41,43 @@ BamWriter(DatagramSink *target) : _next_pta_id = 1; _long_pta_id = false; - _file_major = _bam_major_ver; - _file_minor = _bam_minor_ver; + // Check which version .bam files we should write. + if (bam_version.get_num_words() > 0) { + if (bam_version.get_num_words() != 2) { + util_cat.error() + << "bam-version configuration variable requires two arguments.\n"; + } + _file_major = bam_version[0]; + _file_minor = bam_version[1]; + + if (_file_major < _bam_major_ver || _file_minor < 21) { + util_cat.error() + << "bam-version is set to " << bam_version << ", but this version of " + "Panda3D cannot produce .bam files older than 6.21. Set " + "bam-version to 6 21 in Config.prc to suppress this error, or " + "leave it blank to write version " << _bam_major_ver << "." + << _bam_minor_ver << " files.\n"; + _file_major = 6; + _file_minor = 21; + bam_version.set_string_value("6 21"); + + } else if (_file_major > _bam_major_ver || _file_minor > _bam_minor_ver) { + util_cat.error() + << "bam-version is set to " << bam_version << ", but this version of " + "Panda3D cannot produce .bam files newer than " << _bam_major_ver + << "." << _bam_minor_ver << ". Set bam-version to a supported " + "version or leave it blank to write version " << _bam_major_ver + << "." << _bam_minor_ver << " files.\n"; + + _file_major = _bam_major_ver; + _file_minor = _bam_minor_ver; + bam_version.set_word(0, _bam_major_ver); + bam_version.set_word(1, _bam_minor_ver); + } + } else { + _file_major = _bam_major_ver; + _file_minor = _bam_minor_ver; + } _file_endian = bam_endian; _file_stdfloat_double = bam_stdfloat_double; _file_texture_mode = bam_texture_mode; @@ -98,18 +133,24 @@ init() { _next_pta_id = 1; _long_pta_id = false; - _file_major = _bam_major_ver; - _file_minor = _bam_minor_ver; + nassertr_always(_file_major == _bam_major_ver, false); + nassertr_always(_file_minor <= _bam_minor_ver && _file_minor >= 21, false); + _file_endian = bam_endian; _file_texture_mode = bam_texture_mode; // Write out the current major and minor BAM file version numbers. Datagram header; - header.add_uint16(_bam_major_ver); - header.add_uint16(_bam_minor_ver); + header.add_uint16(_file_major); + header.add_uint16(_file_minor); header.add_uint8(_file_endian); - header.add_bool(_file_stdfloat_double); + + if (_file_major >= 6 || _file_minor >= 27) { + header.add_bool(_file_stdfloat_double); + } else { + _file_stdfloat_double = false; + } if (!_target->put_datagram(header)) { util_cat.error() @@ -448,7 +489,7 @@ write_handle(Datagram &packet, TypeHandle type) { // TypeHandle. Why not? int index = type.get_index(); - // Also make sure the index number fits within a PN_uint16. + // Also make sure the index number fits within a uint16_t. nassertv(index <= 0xffff); packet.add_uint16(index); diff --git a/panda/src/putil/bamWriter.h b/panda/src/putil/bamWriter.h index dc04a22f20..3436457e9e 100644 --- a/panda/src/putil/bamWriter.h +++ b/panda/src/putil/bamWriter.h @@ -76,6 +76,7 @@ PUBLISHED: INLINE int get_file_major_ver() const; INLINE int get_file_minor_ver() const; + INLINE void set_file_minor_ver(int minor_ver); INLINE BamEndian get_file_endian() const; INLINE bool get_file_stdfloat_double() const; diff --git a/panda/src/putil/bitMask.cxx b/panda/src/putil/bitMask.cxx index 22b7370f95..385d773695 100644 --- a/panda/src/putil/bitMask.cxx +++ b/panda/src/putil/bitMask.cxx @@ -18,6 +18,6 @@ #pragma implementation #endif -template class BitMask; -template class BitMask; -template class BitMask; +template class BitMask; +template class BitMask; +template class BitMask; diff --git a/panda/src/putil/bitMask.h b/panda/src/putil/bitMask.h index a2b2bdab13..17c1c9f69d 100644 --- a/panda/src/putil/bitMask.h +++ b/panda/src/putil/bitMask.h @@ -157,16 +157,16 @@ INLINE ostream &operator << (ostream &out, const BitMask &bitmask) // We need to define this temporary macro so we can pass a parameter // containing a comma through the macro. -#define BITMASK16_DEF BitMask -#define BITMASK32_DEF BitMask -#define BITMASK64_DEF BitMask +#define BITMASK16_DEF BitMask +#define BITMASK32_DEF BitMask +#define BITMASK64_DEF BitMask EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_PUTIL, EXPTP_PANDA_PUTIL, BITMASK16_DEF); EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_PUTIL, EXPTP_PANDA_PUTIL, BITMASK32_DEF); EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_PUTIL, EXPTP_PANDA_PUTIL, BITMASK64_DEF); -typedef BitMask BitMask16; -typedef BitMask BitMask32; -typedef BitMask BitMask64; +typedef BitMask BitMask16; +typedef BitMask BitMask32; +typedef BitMask BitMask64; #if NATIVE_WORDSIZE == 32 typedef BitMask32 BitMaskNative; diff --git a/panda/src/putil/buttonHandle.I b/panda/src/putil/buttonHandle.I index 40e157baa8..5701ccb395 100644 --- a/panda/src/putil/buttonHandle.I +++ b/panda/src/putil/buttonHandle.I @@ -11,16 +11,6 @@ * @date 2000-03-01 */ -/** - * The default constructor must do nothing, because we can't guarantee - * ordering of static initializers. If the constructor tried to initialize - * its value, it might happen after the value had already been set previously - * by another static initializer! - */ -INLINE ButtonHandle:: -ButtonHandle() { -} - /** * Constructs a ButtonHandle with the corresponding index number, which may * have been returned by an earlier call to ButtonHandle::get_index(). diff --git a/panda/src/putil/buttonHandle.h b/panda/src/putil/buttonHandle.h index d4961f8b50..d2b97be36a 100644 --- a/panda/src/putil/buttonHandle.h +++ b/panda/src/putil/buttonHandle.h @@ -25,7 +25,11 @@ */ class EXPCL_PANDA_PUTIL ButtonHandle FINAL { PUBLISHED: - INLINE ButtonHandle(); + // The default constructor must do nothing, because we can't guarantee + // ordering of static initializers. If the constructor tried to initialize + // its value, it might happen after the value had already been set + // previously by another static initializer! + INLINE ButtonHandle() DEFAULT_CTOR; CONSTEXPR ButtonHandle(int index); INLINE ButtonHandle(const ButtonHandle ©); ButtonHandle(const string &name); diff --git a/panda/src/putil/config_util.cxx b/panda/src/putil/config_util.cxx index 3325b4d2ec..ef8bd5f6d2 100644 --- a/panda/src/putil/config_util.cxx +++ b/panda/src/putil/config_util.cxx @@ -52,6 +52,12 @@ ConfigureDef(config_util); NotifyCategoryDef(util, ""); NotifyCategoryDef(bam, util_cat); +ConfigVariableInt bam_version +("bam-version", "", + PRC_DESC("Set this to specify which version .bam files to generate. Each " + "Panda version only supports outputting a limited number of .bam " + "versions. The default is to use the latest supported version.")); + ConfigVariableEnum bam_endian ("bam-endian", BamEnums::BE_native, PRC_DESC("The default endianness to use for writing major numeric data " diff --git a/panda/src/putil/config_util.h b/panda/src/putil/config_util.h index 5fb669d86c..34ff4abc2d 100644 --- a/panda/src/putil/config_util.h +++ b/panda/src/putil/config_util.h @@ -33,6 +33,7 @@ NotifyCategoryDecl(bam, EXPCL_PANDA_PUTIL, EXPTP_PANDA_PUTIL); // a global constant, we'll make it a member of MemoryUsage. extern // EXPCL_PANDA_PUTIL const bool track_memory_usage; +extern EXPCL_PANDA_PUTIL ConfigVariableInt bam_version; extern EXPCL_PANDA_PUTIL ConfigVariableEnum bam_endian; extern EXPCL_PANDA_PUTIL ConfigVariableBool bam_stdfloat_double; extern EXPCL_PANDA_PUTIL ConfigVariableEnum bam_texture_mode; diff --git a/panda/src/putil/datagramInputFile.cxx b/panda/src/putil/datagramInputFile.cxx index 64fa369231..1ac14b58ed 100644 --- a/panda/src/putil/datagramInputFile.cxx +++ b/panda/src/putil/datagramInputFile.cxx @@ -126,7 +126,7 @@ get_datagram(Datagram &data) { // First, get the size of the upcoming datagram. StreamReader reader(_in, false); - PN_uint32 num_bytes_32 = reader.get_uint32(); + uint32_t num_bytes_32 = reader.get_uint32(); if (_in->fail() || _in->eof()) { return false; } @@ -139,7 +139,7 @@ get_datagram(Datagram &data) { } streamsize num_bytes = (streamsize)num_bytes_32; - if (num_bytes_32 == (PN_uint32)-1) { + if (num_bytes_32 == (uint32_t)-1) { // Another special case for a value larger than 32 bits. num_bytes = reader.get_uint64(); } @@ -205,7 +205,7 @@ save_datagram(SubfileInfo &info) { } streamsize num_bytes = (streamsize)num_bytes_32; - if (num_bytes_32 == (PN_uint32)-1) { + if (num_bytes_32 == (uint32_t)-1) { // Another special case for a value larger than 32 bits. num_bytes = reader.get_uint64(); } diff --git a/panda/src/putil/datagramOutputFile.cxx b/panda/src/putil/datagramOutputFile.cxx index 4ead1274c1..cd9a1af2fc 100644 --- a/panda/src/putil/datagramOutputFile.cxx +++ b/panda/src/putil/datagramOutputFile.cxx @@ -110,13 +110,13 @@ put_datagram(const Datagram &data) { // First, write the size of the upcoming datagram. StreamWriter writer(_out, false); size_t num_bytes = data.get_length(); - if (num_bytes == (PN_uint32)-1 || num_bytes != (PN_uint32)num_bytes) { + if (num_bytes == (uint32_t)-1 || num_bytes != (uint32_t)num_bytes) { // Write a large value as a 64-bit size. - writer.add_uint32((PN_uint32)-1); + writer.add_uint32((uint32_t)-1); writer.add_uint64(num_bytes); } else { // Write a value that fits in 32 bits. - writer.add_uint32((PN_uint32)num_bytes); + writer.add_uint32((uint32_t)num_bytes); } // Now, write the datagram itself. @@ -154,13 +154,13 @@ copy_datagram(SubfileInfo &result, const Filename &filename) { streamsize num_remaining = size; StreamWriter writer(_out, false); - if (num_remaining == (PN_uint32)-1 || num_remaining != (PN_uint32)num_remaining) { + if (num_remaining == (uint32_t)-1 || num_remaining != (uint32_t)num_remaining) { // Write a large value as a 64-bit size. - writer.add_uint32((PN_uint32)-1); + writer.add_uint32((uint32_t)-1); writer.add_uint64(num_remaining); } else { // Write a value that fits in 32 bits. - writer.add_uint32((PN_uint32)num_remaining); + writer.add_uint32((uint32_t)num_remaining); } static const size_t buffer_size = 4096; @@ -217,13 +217,13 @@ copy_datagram(SubfileInfo &result, const SubfileInfo &source) { streamsize num_remaining = source.get_size(); StreamWriter writer(_out, false); - if (num_remaining == (PN_uint32)-1 || num_remaining != (PN_uint32)num_remaining) { + if (num_remaining == (uint32_t)-1 || num_remaining != (uint32_t)num_remaining) { // Write a large value as a 64-bit size. - writer.add_uint32((PN_uint32)-1); + writer.add_uint32((uint32_t)-1); writer.add_uint64(num_remaining); } else { // Write a value that fits in 32 bits. - writer.add_uint32((PN_uint32)num_remaining); + writer.add_uint32((uint32_t)num_remaining); } static const size_t buffer_size = 4096; diff --git a/panda/src/putil/factory.I b/panda/src/putil/factory.I index 37da03c686..57d3fadff5 100644 --- a/panda/src/putil/factory.I +++ b/panda/src/putil/factory.I @@ -70,6 +70,6 @@ make_instance_more_general(const string &type_name, */ template INLINE void Factory:: -register_factory(TypeHandle handle, CreateFunc *func) { - FactoryBase::register_factory(handle, (BaseCreateFunc *)func); +register_factory(TypeHandle handle, CreateFunc *func, void *user_data) { + FactoryBase::register_factory(handle, (BaseCreateFunc *)func, user_data); } diff --git a/panda/src/putil/factory.h b/panda/src/putil/factory.h index f45f1ffce3..4520153911 100644 --- a/panda/src/putil/factory.h +++ b/panda/src/putil/factory.h @@ -49,7 +49,8 @@ public: make_instance_more_general(const string &type_name, const FactoryParams ¶ms = FactoryParams()); - INLINE void register_factory(TypeHandle handle, CreateFunc *func); + INLINE void register_factory(TypeHandle handle, CreateFunc *func, + void *user_data = NULL); }; #include "factory.I" diff --git a/panda/src/putil/factoryBase.cxx b/panda/src/putil/factoryBase.cxx index 935ad7bb33..52704e92cd 100644 --- a/panda/src/putil/factoryBase.cxx +++ b/panda/src/putil/factoryBase.cxx @@ -128,12 +128,18 @@ find_registered_type(TypeHandle handle) { /** * Registers a new kind of thing the Factory will be able to create. + * + * @param user_data an optional pointer to be passed along to the function. */ void FactoryBase:: -register_factory(TypeHandle handle, BaseCreateFunc *func) { +register_factory(TypeHandle handle, BaseCreateFunc *func, void *user_data) { nassertv(handle != TypeHandle::none()); nassertv(func != (BaseCreateFunc *)NULL); - _creators[handle] = func; + + Creator creator; + creator._func = func; + creator._user_data = user_data; + _creators[handle] = creator; } /** @@ -234,15 +240,16 @@ operator = (const FactoryBase &) { * not be created. */ TypedObject *FactoryBase:: -make_instance_exact(TypeHandle handle, const FactoryParams ¶ms) { +make_instance_exact(TypeHandle handle, FactoryParams params) { Creators::const_iterator ci = _creators.find(handle); if (ci == _creators.end()) { return NULL; } - BaseCreateFunc *func = (BaseCreateFunc *)((*ci).second); - nassertr(func != (BaseCreateFunc *)NULL, NULL); - return (*func)(params); + Creator creator = (*ci).second; + nassertr(creator._func != (BaseCreateFunc *)NULL, NULL); + params._user_data = creator._user_data; + return (*creator._func)(params); } /** @@ -251,7 +258,7 @@ make_instance_exact(TypeHandle handle, const FactoryParams ¶ms) { * instance could not be created. */ TypedObject *FactoryBase:: -make_instance_more_specific(TypeHandle handle, const FactoryParams ¶ms) { +make_instance_more_specific(TypeHandle handle, FactoryParams params) { // First, walk through the established preferred list. Maybe one of these // qualifies. @@ -272,9 +279,10 @@ make_instance_more_specific(TypeHandle handle, const FactoryParams ¶ms) { for (ci = _creators.begin(); ci != _creators.end(); ++ci) { TypeHandle ctype = (*ci).first; if (ctype.is_derived_from(handle)) { - BaseCreateFunc *func = (BaseCreateFunc *)((*ci).second); - nassertr(func != (BaseCreateFunc *)NULL, NULL); - TypedObject *object = (*func)(params); + Creator creator = (*ci).second; + nassertr(creator._func != (BaseCreateFunc *)NULL, NULL); + params._user_data = creator._user_data; + TypedObject *object = (*creator._func)(params); if (object != (TypedObject *)NULL) { return object; } diff --git a/panda/src/putil/factoryBase.h b/panda/src/putil/factoryBase.h index 13ea0c8eaa..6fcfc2f54f 100644 --- a/panda/src/putil/factoryBase.h +++ b/panda/src/putil/factoryBase.h @@ -56,7 +56,7 @@ public: TypeHandle find_registered_type(TypeHandle handle); - void register_factory(TypeHandle handle, BaseCreateFunc *func); + void register_factory(TypeHandle handle, BaseCreateFunc *func, void *user_data = NULL); int get_num_types() const; TypeHandle get_type(int n) const; @@ -74,22 +74,18 @@ private: void operator = (const FactoryBase ©); // internal utility functions - TypedObject *make_instance_exact(TypeHandle handle, - const FactoryParams ¶ms); + TypedObject *make_instance_exact(TypeHandle handle, FactoryParams params); TypedObject *make_instance_more_specific(TypeHandle handle, - const FactoryParams ¶ms); + FactoryParams params); private: // internal mechanics and bookkeeping + struct Creator { + BaseCreateFunc *_func; + void *_user_data; + }; -#if (defined(WIN32_VC) || defined(WIN64_VC)) && !defined(__ICL) //__ICL is Intel C++ - // Visual C++ seems to have a problem with building a map based on - // BaseCreateFunc. We'll have to typecast it on the way out. - typedef pmap Creators; -#else - typedef pmap Creators; -#endif - + typedef pmap Creators; Creators _creators; typedef pvector Preferred; diff --git a/panda/src/putil/factoryParams.I b/panda/src/putil/factoryParams.I index 3183ae718e..0c6fdd09e7 100644 --- a/panda/src/putil/factoryParams.I +++ b/panda/src/putil/factoryParams.I @@ -13,6 +13,54 @@ #include "pnotify.h" +/** + * + */ +INLINE FactoryParams:: +FactoryParams() : _user_data(NULL) { +} + +/** + * + */ +INLINE FactoryParams:: +FactoryParams(const FactoryParams ©) : + _params(copy._params), + _user_data(copy._user_data) {} + +/** + * + */ +INLINE FactoryParams:: +~FactoryParams() { +} + +#ifdef USE_MOVE_SEMANTICS +/** + * + */ +INLINE FactoryParams:: +FactoryParams(FactoryParams &&from) NOEXCEPT : + _params(move(from._params)), + _user_data(from._user_data) {} + +/** + * + */ +INLINE void FactoryParams:: +operator = (FactoryParams &&from) NOEXCEPT { + _params = move(from._params); + _user_data = from._user_data; +} +#endif + +/** + * Returns the custom pointer that was associated with the factory function. + */ +INLINE void *FactoryParams:: +get_user_data() const { + return _user_data; +} /** * A handy convenience template function that extracts a parameter of the diff --git a/panda/src/putil/factoryParams.cxx b/panda/src/putil/factoryParams.cxx index 47e41ebcf3..6224f8b94e 100644 --- a/panda/src/putil/factoryParams.cxx +++ b/panda/src/putil/factoryParams.cxx @@ -13,20 +13,6 @@ #include "factoryParams.h" -/** - * - */ -FactoryParams:: -FactoryParams() { -} - -/** - * - */ -FactoryParams:: -~FactoryParams() { -} - /** * */ diff --git a/panda/src/putil/factoryParams.h b/panda/src/putil/factoryParams.h index 428399dd85..5c45a6e2ee 100644 --- a/panda/src/putil/factoryParams.h +++ b/panda/src/putil/factoryParams.h @@ -35,8 +35,14 @@ */ class EXPCL_PANDA_PUTIL FactoryParams { public: - FactoryParams(); - ~FactoryParams(); + INLINE FactoryParams(); + INLINE FactoryParams(const FactoryParams ©); + INLINE ~FactoryParams(); + +#ifdef USE_MOVE_SEMANTICS + INLINE FactoryParams(FactoryParams &&from) NOEXCEPT; + INLINE void operator = (FactoryParams &&from) NOEXCEPT; +#endif void add_param(FactoryParam *param); void clear(); @@ -46,10 +52,15 @@ public: FactoryParam *get_param_of_type(TypeHandle type) const; + INLINE void *get_user_data() const; + private: typedef pvector< PT(TypedReferenceCount) > Params; Params _params; + void *_user_data; + + friend class FactoryBase; }; template diff --git a/panda/src/putil/modifierButtons.h b/panda/src/putil/modifierButtons.h index d409b30f35..c95791b2a0 100644 --- a/panda/src/putil/modifierButtons.h +++ b/panda/src/putil/modifierButtons.h @@ -51,6 +51,7 @@ PUBLISHED: INLINE int get_num_buttons() const; INLINE ButtonHandle get_button(int index) const; MAKE_SEQ(get_buttons, get_num_buttons, get_button); + MAKE_SEQ_PROPERTY(buttons, get_num_buttons, get_button); bool button_down(ButtonHandle button); bool button_up(ButtonHandle button); diff --git a/panda/src/putil/p3putil_ext_composite.cxx b/panda/src/putil/p3putil_ext_composite.cxx new file mode 100644 index 0000000000..4bedeea559 --- /dev/null +++ b/panda/src/putil/p3putil_ext_composite.cxx @@ -0,0 +1,3 @@ +#include "bamReader_ext.cxx" +#include "pythonCallbackObject.cxx" +#include "typedWritable_ext.cxx" diff --git a/panda/src/putil/pbitops.I b/panda/src/putil/pbitops.I index f746b8ba77..3d830306f4 100644 --- a/panda/src/putil/pbitops.I +++ b/panda/src/putil/pbitops.I @@ -15,7 +15,7 @@ * Returns the number of 1 bits in the indicated word. */ INLINE int -count_bits_in_word(PN_uint16 x) { +count_bits_in_word(uint16_t x) { return (int)num_bits_on[x]; } @@ -23,7 +23,7 @@ count_bits_in_word(PN_uint16 x) { * Returns the number of 1 bits in the indicated word. */ INLINE int -count_bits_in_word(PN_uint32 x) { +count_bits_in_word(uint32_t x) { #if defined(__GNUC__) && defined(__POPCNT__) return __builtin_popcount((unsigned int) x); #else @@ -35,19 +35,19 @@ count_bits_in_word(PN_uint32 x) { * Returns the number of 1 bits in the indicated word. */ INLINE int -count_bits_in_word(PN_uint64 x) { +count_bits_in_word(uint64_t x) { #if defined(__GNUC__) && defined(__POPCNT__) return __builtin_popcountll((unsigned long long) x); #else - return count_bits_in_word((PN_uint32)x) + count_bits_in_word((PN_uint32)(x >> 32)); + return count_bits_in_word((uint32_t)x) + count_bits_in_word((uint32_t)(x >> 32)); #endif } /** * Returns a value such that every bit at or below the highest bit in x is 1. */ -INLINE PN_uint16 -flood_bits_down(PN_uint16 x) { +INLINE uint16_t +flood_bits_down(uint16_t x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); @@ -58,8 +58,8 @@ flood_bits_down(PN_uint16 x) { /** * Returns a value such that every bit at or below the highest bit in x is 1. */ -INLINE PN_uint32 -flood_bits_down(PN_uint32 x) { +INLINE uint32_t +flood_bits_down(uint32_t x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); @@ -71,8 +71,8 @@ flood_bits_down(PN_uint32 x) { /** * Returns a value such that every bit at or below the highest bit in x is 1. */ -INLINE PN_uint64 -flood_bits_down(PN_uint64 x) { +INLINE uint64_t +flood_bits_down(uint64_t x) { x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); @@ -85,8 +85,8 @@ flood_bits_down(PN_uint64 x) { /** * Returns a value such that every bit at or above the highest bit in x is 1. */ -INLINE PN_uint16 -flood_bits_up(PN_uint16 x) { +INLINE uint16_t +flood_bits_up(uint16_t x) { x |= (x << 1); x |= (x << 2); x |= (x << 4); @@ -97,8 +97,8 @@ flood_bits_up(PN_uint16 x) { /** * Returns a value such that every bit at or above the highest bit in x is 1. */ -INLINE PN_uint32 -flood_bits_up(PN_uint32 x) { +INLINE uint32_t +flood_bits_up(uint32_t x) { x |= (x << 1); x |= (x << 2); x |= (x << 4); @@ -110,8 +110,8 @@ flood_bits_up(PN_uint32 x) { /** * Returns a value such that every bit at or above the highest bit in x is 1. */ -INLINE PN_uint64 -flood_bits_up(PN_uint64 x) { +INLINE uint64_t +flood_bits_up(uint64_t x) { x |= (x << 1); x |= (x << 2); x |= (x << 4); @@ -126,7 +126,7 @@ flood_bits_up(PN_uint64 x) { * no 1 bits. */ INLINE int -get_lowest_on_bit(PN_uint16 x) { +get_lowest_on_bit(uint16_t x) { #if defined(_MSC_VER) unsigned long result; return (_BitScanForward(&result, (unsigned long) x) == 0) ? -1 : result; @@ -137,7 +137,7 @@ get_lowest_on_bit(PN_uint16 x) { return -1; } - PN_uint16 w = (x & (~x + 1)); + uint16_t w = (x & (~x + 1)); return (int)num_bits_on[w - 1]; #endif } @@ -147,7 +147,7 @@ get_lowest_on_bit(PN_uint16 x) { * no 1 bits. */ INLINE int -get_lowest_on_bit(PN_uint32 x) { +get_lowest_on_bit(uint32_t x) { #if defined(_MSC_VER) unsigned long result; return (_BitScanForward(&result, (unsigned long) x) == 0) ? -1 : result; @@ -158,7 +158,7 @@ get_lowest_on_bit(PN_uint32 x) { return -1; } - PN_uint32 w = (x & (~x + 1)); + uint32_t w = (x & (~x + 1)); return count_bits_in_word(w - 1); #endif } @@ -168,7 +168,7 @@ get_lowest_on_bit(PN_uint32 x) { * no 1 bits. */ INLINE int -get_lowest_on_bit(PN_uint64 x) { +get_lowest_on_bit(uint64_t x) { #if defined(_MSC_VER) && defined(_M_X64) unsigned long result; return (_BitScanForward64(&result, (unsigned __int64) x) == 0) ? -1 : result; @@ -179,7 +179,7 @@ get_lowest_on_bit(PN_uint64 x) { return -1; } - PN_uint64 w = (x & (~x + 1)); + uint64_t w = (x & (~x + 1)); return count_bits_in_word(w - 1); #endif } @@ -189,14 +189,14 @@ get_lowest_on_bit(PN_uint64 x) { * are no 1 bits. */ INLINE int -get_highest_on_bit(PN_uint16 x) { +get_highest_on_bit(uint16_t x) { #if defined(_MSC_VER) unsigned long result; return (_BitScanReverse(&result, (unsigned long) x) == 0) ? -1 : result; #elif defined(__GNUC__) return (x == 0) ? -1 : 31 - __builtin_clz((unsigned int) x); #else - PN_uint16 w = flood_bits_down(x); + uint16_t w = flood_bits_down(x); return count_bits_in_word(w) - 1; #endif } @@ -206,14 +206,14 @@ get_highest_on_bit(PN_uint16 x) { * are no 1 bits. */ INLINE int -get_highest_on_bit(PN_uint32 x) { +get_highest_on_bit(uint32_t x) { #if defined(_MSC_VER) unsigned long result; return (_BitScanReverse(&result, (unsigned long) x) == 0) ? -1 : result; #elif defined(__GNUC__) return (x == 0) ? -1 : 31 - __builtin_clz((unsigned int) x); #else - PN_uint32 w = flood_bits_down(x); + uint32_t w = flood_bits_down(x); return count_bits_in_word(w) - 1; #endif } @@ -223,14 +223,14 @@ get_highest_on_bit(PN_uint32 x) { * are no 1 bits. */ INLINE int -get_highest_on_bit(PN_uint64 x) { +get_highest_on_bit(uint64_t x) { #if defined(_MSC_VER) && defined(_M_X64) unsigned long result; return (_BitScanReverse64(&result, (unsigned __int64) x) == 0) ? -1 : result; #elif defined(__GNUC__) return (x == 0) ? -1 : 63 - __builtin_clzll((unsigned long long) x); #else - PN_uint64 w = flood_bits_down(x); + uint64_t w = flood_bits_down(x); return count_bits_in_word(w) - 1; #endif } @@ -241,7 +241,7 @@ get_highest_on_bit(PN_uint64 x) { * Returns the smallest number n such that (1 << n) is larger than x. */ INLINE int -get_next_higher_bit(PN_uint16 x) { +get_next_higher_bit(uint16_t x) { return get_highest_on_bit(x) + 1; } @@ -251,7 +251,7 @@ get_next_higher_bit(PN_uint16 x) { * Returns the smallest number n such that (1 << n) is larger than x. */ INLINE int -get_next_higher_bit(PN_uint32 x) { +get_next_higher_bit(uint32_t x) { return get_highest_on_bit(x) + 1; } @@ -261,6 +261,6 @@ get_next_higher_bit(PN_uint32 x) { * Returns the smallest number n such that (1 << n) is larger than x. */ INLINE int -get_next_higher_bit(PN_uint64 x) { +get_next_higher_bit(uint64_t x) { return get_highest_on_bit(x) + 1; } diff --git a/panda/src/putil/pbitops.h b/panda/src/putil/pbitops.h index 545cce9dba..5b4a10b601 100644 --- a/panda/src/putil/pbitops.h +++ b/panda/src/putil/pbitops.h @@ -24,27 +24,27 @@ // This file defines a few low-level bit-operation routines, optimized all to // heck. -INLINE int count_bits_in_word(PN_uint16 x); -INLINE int count_bits_in_word(PN_uint32 x); -INLINE int count_bits_in_word(PN_uint64 x); +INLINE int count_bits_in_word(uint16_t x); +INLINE int count_bits_in_word(uint32_t x); +INLINE int count_bits_in_word(uint64_t x); -INLINE PN_uint16 flood_bits_down(PN_uint16 x); -INLINE PN_uint32 flood_bits_down(PN_uint32 x); -INLINE PN_uint64 flood_bits_down(PN_uint64 x); -INLINE PN_uint16 flood_bits_up(PN_uint16 x); -INLINE PN_uint32 flood_bits_up(PN_uint32 x); -INLINE PN_uint64 flood_bits_up(PN_uint64 x); +INLINE uint16_t flood_bits_down(uint16_t x); +INLINE uint32_t flood_bits_down(uint32_t x); +INLINE uint64_t flood_bits_down(uint64_t x); +INLINE uint16_t flood_bits_up(uint16_t x); +INLINE uint32_t flood_bits_up(uint32_t x); +INLINE uint64_t flood_bits_up(uint64_t x); -INLINE int get_lowest_on_bit(PN_uint16 x); -INLINE int get_lowest_on_bit(PN_uint32 x); -INLINE int get_lowest_on_bit(PN_uint64 x); -INLINE int get_highest_on_bit(PN_uint16 x); -INLINE int get_highest_on_bit(PN_uint32 x); -INLINE int get_highest_on_bit(PN_uint64 x); +INLINE int get_lowest_on_bit(uint16_t x); +INLINE int get_lowest_on_bit(uint32_t x); +INLINE int get_lowest_on_bit(uint64_t x); +INLINE int get_highest_on_bit(uint16_t x); +INLINE int get_highest_on_bit(uint32_t x); +INLINE int get_highest_on_bit(uint64_t x); -INLINE int get_next_higher_bit(PN_uint16 x); -INLINE int get_next_higher_bit(PN_uint32 x); -INLINE int get_next_higher_bit(PN_uint64 x); +INLINE int get_next_higher_bit(uint16_t x); +INLINE int get_next_higher_bit(uint32_t x); +INLINE int get_next_higher_bit(uint64_t x); // This table precomputes the number of on bits in each 16-bit word. extern EXPCL_PANDA_PUTIL const unsigned char num_bits_on[65536]; diff --git a/panda/src/putil/pythonCallbackObject.cxx b/panda/src/putil/pythonCallbackObject.cxx index f78121630f..0679a4c473 100644 --- a/panda/src/putil/pythonCallbackObject.cxx +++ b/panda/src/putil/pythonCallbackObject.cxx @@ -126,8 +126,10 @@ do_python_callback(CallbackData *cbdata) { Py_DECREF(args); if (result == (PyObject *)NULL) { - util_cat.error() - << "Exception occurred in " << *this << "\n"; + if (PyErr_Occurred() != PyExc_SystemExit) { + util_cat.error() + << "Exception occurred in " << *this << "\n"; + } } else { Py_DECREF(result); } diff --git a/panda/src/putil/pythonCallbackObject.h b/panda/src/putil/pythonCallbackObject.h index a34b1ceecb..d7757813db 100644 --- a/panda/src/putil/pythonCallbackObject.h +++ b/panda/src/putil/pythonCallbackObject.h @@ -34,6 +34,8 @@ PUBLISHED: void set_function(PyObject *function); PyObject *get_function(); + MAKE_PROPERTY(function, get_function, set_function); + public: virtual void do_callback(CallbackData *cbdata); diff --git a/panda/src/putil/typedWritable.h b/panda/src/putil/typedWritable.h index 20d7a7cb67..8278efba95 100644 --- a/panda/src/putil/typedWritable.h +++ b/panda/src/putil/typedWritable.h @@ -47,7 +47,10 @@ public: virtual int complete_pointers(TypedWritable **p_list, BamReader *manager); virtual bool require_fully_complete() const; +PUBLISHED: virtual void fillin(DatagramIterator &scan, BamReader *manager); + +public: virtual void finalize(BamReader *manager); virtual ReferenceCount *as_reference_count(); diff --git a/panda/src/putil/typedWritable_ext.cxx b/panda/src/putil/typedWritable_ext.cxx index afa7f986c8..224686ed3e 100644 --- a/panda/src/putil/typedWritable_ext.cxx +++ b/panda/src/putil/typedWritable_ext.cxx @@ -110,7 +110,11 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const { } } +#if PY_MAJOR_VERSION >= 3 + PyObject *result = Py_BuildValue("(O(Oy#))", func, this_class, bam_stream.data(), (Py_ssize_t) bam_stream.size()); +#else PyObject *result = Py_BuildValue("(O(Os#))", func, this_class, bam_stream.data(), (Py_ssize_t) bam_stream.size()); +#endif Py_DECREF(func); Py_DECREF(this_class); return result; @@ -212,10 +216,18 @@ py_decode_TypedWritable_from_bam_stream_persist(PyObject *pickler, PyObject *thi PyObject *result; if (py_reader != NULL){ +#if PY_MAJOR_VERSION >= 3 + result = PyObject_CallFunction(func, (char *)"(y#O)", data.data(), (Py_ssize_t) data.size(), py_reader); +#else result = PyObject_CallFunction(func, (char *)"(s#O)", data.data(), (Py_ssize_t) data.size(), py_reader); +#endif Py_DECREF(py_reader); } else { +#if PY_MAJOR_VERSION >= 3 + result = PyObject_CallFunction(func, (char *)"(y#)", data.data(), (Py_ssize_t) data.size()); +#else result = PyObject_CallFunction(func, (char *)"(s#)", data.data(), (Py_ssize_t) data.size()); +#endif } if (result == NULL) { diff --git a/panda/src/putil/uniqueIdAllocator.cxx b/panda/src/putil/uniqueIdAllocator.cxx index 3bca1d1ea6..0b3307a2af 100644 --- a/panda/src/putil/uniqueIdAllocator.cxx +++ b/panda/src/putil/uniqueIdAllocator.cxx @@ -20,8 +20,8 @@ NotifyCategoryDecl(uniqueIdAllocator, EXPCL_PANDA_PUTIL, EXPTP_PANDA_PUTIL); NotifyCategoryDef(uniqueIdAllocator, ""); -const PN_uint32 UniqueIdAllocator::IndexEnd = (PN_uint32)-1; -const PN_uint32 UniqueIdAllocator::IndexAllocated = (PN_uint32)-2; +const uint32_t UniqueIdAllocator::IndexEnd = (uint32_t)-1; +const uint32_t UniqueIdAllocator::IndexAllocated = (uint32_t)-2; #ifndef NDEBUG //[ // Non-release build: @@ -50,7 +50,7 @@ const PN_uint32 UniqueIdAllocator::IndexAllocated = (PN_uint32)-2; * Create a free id pool in the range [min:max]. */ UniqueIdAllocator:: -UniqueIdAllocator(PN_uint32 min, PN_uint32 max) +UniqueIdAllocator(uint32_t min, uint32_t max) : _min(min), _max(max) { uniqueIdAllocator_debug("UniqueIdAllocator("< 0. - _table = (PN_uint32 *)PANDA_MALLOC_ARRAY(_size * sizeof(PN_uint32)); + _table = (uint32_t *)PANDA_MALLOC_ARRAY(_size * sizeof(uint32_t)); nassertv(_table); // This should be redundant if new throws an exception. - for (PN_uint32 i = 0; i < _size; ++i) { + for (uint32_t i = 0; i < _size; ++i) { _table[i] = i + 1; } _table[_size - 1] = IndexEnd; @@ -84,14 +84,14 @@ UniqueIdAllocator:: * Returns an id between _min and _max (that were passed to the constructor). * IndexEnd is returned if no ids are available. */ -PN_uint32 UniqueIdAllocator:: +uint32_t UniqueIdAllocator:: allocate() { if (_next_free == IndexEnd) { // ...all ids allocated. uniqueIdAllocator_warning("allocate Error: no more free ids."); return IndexEnd; } - PN_uint32 index = _next_free; + uint32_t index = _next_free; nassertr(_table[index] != IndexAllocated, IndexEnd); _next_free = _table[_next_free]; @@ -99,7 +99,7 @@ allocate() { --_free; - PN_uint32 id = index + _min; + uint32_t id = index + _min; uniqueIdAllocator_debug("allocate() returning " << id); return id; } @@ -116,9 +116,9 @@ allocate() { * reserved at any time. */ void UniqueIdAllocator:: -initial_reserve_id(PN_uint32 id) { +initial_reserve_id(uint32_t id) { nassertv(id >= _min && id <= _max); // Attempt to reserve out-of-range id. - PN_uint32 index = id - _min; // Convert to _table index. + uint32_t index = id - _min; // Convert to _table index. nassertv(_table[index] != IndexAllocated); @@ -143,7 +143,7 @@ initial_reserve_id(PN_uint32 id) { * slot right before it, or if not, it usually won't be far before it. */ - PN_uint32 prev_index = index; + uint32_t prev_index = index; while (prev_index > 0 && _table[prev_index - 1] != index) { --prev_index; } @@ -177,11 +177,11 @@ initial_reserve_id(PN_uint32 id) { * passed to the constructor). */ void UniqueIdAllocator:: -free(PN_uint32 id) { +free(uint32_t id) { uniqueIdAllocator_debug("free("<= _min && id <= _max); // Attempt to free out-of-range id. - PN_uint32 index = id - _min; // Convert to _table index. + uint32_t index = id - _min; // Convert to _table index. nassertv(_table[index] == IndexAllocated); // Attempt to free non-allocated id. if (_next_free != IndexEnd) { nassertv(_table[_last_free] == IndexEnd); @@ -223,8 +223,8 @@ output(ostream &out) const { void UniqueIdAllocator:: write(ostream &out) const { out << "_min: " << _min << "; _max: " << _max - << ";\n_next_free: " << PN_int32(_next_free) - << "; _last_free: " << PN_int32(_last_free) + << ";\n_next_free: " << int32_t(_next_free) + << "; _last_free: " << int32_t(_last_free) << "; _size: " << _size << "; _free: " << _free << "; used: " << _size - _free @@ -232,13 +232,13 @@ write(ostream &out) const { << ";\n"; out << "Table:"; - for (PN_uint32 i = 0; i < _size; ++i) { - out << " " << PN_int32(_table[i]); + for (uint32_t i = 0; i < _size; ++i) { + out << " " << int32_t(_table[i]); } out << "\n"; out << "Free chain:"; - PN_uint32 index = _next_free; + uint32_t index = _next_free; while (index != IndexEnd) { out << " " << index + _min; index = _table[index]; diff --git a/panda/src/putil/uniqueIdAllocator.h b/panda/src/putil/uniqueIdAllocator.h index 7dd42ace04..90efcaee69 100644 --- a/panda/src/putil/uniqueIdAllocator.h +++ b/panda/src/putil/uniqueIdAllocator.h @@ -37,21 +37,21 @@ */ class EXPCL_PANDA_PUTIL UniqueIdAllocator { PUBLISHED: - UniqueIdAllocator(PN_uint32 min=0, PN_uint32 max=20); + UniqueIdAllocator(uint32_t min=0, uint32_t max=20); ~UniqueIdAllocator(); - PN_uint32 allocate(); - void initial_reserve_id(PN_uint32 id); + uint32_t allocate(); + void initial_reserve_id(uint32_t id); - void free(PN_uint32 index); + void free(uint32_t index); PN_stdfloat fraction_used() const; void output(ostream &out) const; void write(ostream &out) const; public: - static const PN_uint32 IndexEnd; - static const PN_uint32 IndexAllocated; + static const uint32_t IndexEnd; + static const uint32_t IndexAllocated; protected: // _table stores an array of _size words, corresponding to each allocatable @@ -63,27 +63,27 @@ protected: // For an allocated id, the table entry at the corresponding index contains // IndexAllocated. - PN_uint32 *_table; + uint32_t *_table; // The minimum and maximum as passed to the constructor. - PN_uint32 _min; - PN_uint32 _max; + uint32_t _min; + uint32_t _max; // This is the head of the free chain: as elements are allocated, they are // taken from _table[_next_free]. If the free chain is empty, _next_free == // IndexEnd. - PN_uint32 _next_free; + uint32_t _next_free; // This is the tail of the free chain: as elements are freed, they are // stored in _table[_last_free]. Normally, _table[_last_free] is the end of // the free chain, unless the free chain is empty. - PN_uint32 _last_free; + uint32_t _last_free; // The total number of elements in _table. - PN_uint32 _size; + uint32_t _size; // The number of free elements in _table. - PN_uint32 _free; + uint32_t _free; }; #endif //] diff --git a/panda/src/recorder/mouseRecorder.h b/panda/src/recorder/mouseRecorder.h index b26b9e76a6..b97df0b7ed 100644 --- a/panda/src/recorder/mouseRecorder.h +++ b/panda/src/recorder/mouseRecorder.h @@ -77,6 +77,7 @@ public: virtual void write_datagram(BamWriter *manager, Datagram &dg); virtual void write_recorder(BamWriter *manager, Datagram &dg); + INLINE virtual int get_ref_count() const FINAL { return ReferenceCount::get_ref_count(); }; INLINE virtual void ref() const FINAL { ReferenceCount::ref(); }; INLINE virtual bool unref() const FINAL { return ReferenceCount::unref(); }; diff --git a/panda/src/recorder/recorderBase.h b/panda/src/recorder/recorderBase.h index 816f74030d..65044424d5 100644 --- a/panda/src/recorder/recorderBase.h +++ b/panda/src/recorder/recorderBase.h @@ -61,6 +61,7 @@ public: // We can't let RecorderBase inherit from ReferenceCount, so we define these // so we can still manage the reference count. + virtual int get_ref_count() const=0; virtual void ref() const=0; virtual bool unref() const=0; diff --git a/panda/src/recorder/socketStreamRecorder.h b/panda/src/recorder/socketStreamRecorder.h index 09513a0c54..26f39047c4 100644 --- a/panda/src/recorder/socketStreamRecorder.h +++ b/panda/src/recorder/socketStreamRecorder.h @@ -74,6 +74,7 @@ public: static void register_with_read_factory(); virtual void write_recorder(BamWriter *manager, Datagram &dg); + INLINE virtual int get_ref_count() const FINAL { return ReferenceCount::get_ref_count(); }; INLINE virtual void ref() const FINAL { ReferenceCount::ref(); }; INLINE virtual bool unref() const FINAL { return ReferenceCount::unref(); }; diff --git a/panda/src/rocket/rocketRegion_ext.cxx b/panda/src/rocket/rocketRegion_ext.cxx index adc73a219e..cb79f467a1 100644 --- a/panda/src/rocket/rocketRegion_ext.cxx +++ b/panda/src/rocket/rocketRegion_ext.cxx @@ -40,7 +40,8 @@ get_context() const { context->AddReference(); return py_context.ptr(); - } catch (const python::error_already_set& e) { + } catch (const python::error_already_set &e) { + (void)e; // Return NULL, which will trigger the exception in Python } return NULL; diff --git a/panda/src/speedtree/loaderFileTypeSrt.cxx b/panda/src/speedtree/loaderFileTypeSrt.cxx index 594267ec26..6589e28c10 100644 --- a/panda/src/speedtree/loaderFileTypeSrt.cxx +++ b/panda/src/speedtree/loaderFileTypeSrt.cxx @@ -42,7 +42,7 @@ get_extension() const { /** * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. + * (with a .pz or .gz extension), false otherwise. */ bool LoaderFileTypeSrt:: supports_compressed() const { diff --git a/panda/src/speedtree/loaderFileTypeStf.cxx b/panda/src/speedtree/loaderFileTypeStf.cxx index 7a8f71631d..8e1e15a2e8 100644 --- a/panda/src/speedtree/loaderFileTypeStf.cxx +++ b/panda/src/speedtree/loaderFileTypeStf.cxx @@ -41,7 +41,7 @@ get_extension() const { /** * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. + * (with a .pz or .gz extension), false otherwise. */ bool LoaderFileTypeStf:: supports_compressed() const { diff --git a/panda/src/text/dynamicTextFont.h b/panda/src/text/dynamicTextFont.h index 773f3a7467..c418ea34c3 100644 --- a/panda/src/text/dynamicTextFont.h +++ b/panda/src/text/dynamicTextFont.h @@ -114,6 +114,7 @@ PUBLISHED: int get_num_pages() const; DynamicTextPage *get_page(int n) const; MAKE_SEQ(get_pages, get_num_pages, get_page); + MAKE_SEQ_PROPERTY(pages, get_num_pages, get_page); int garbage_collect(); void clear(); diff --git a/panda/src/text/dynamicTextPage.cxx b/panda/src/text/dynamicTextPage.cxx index 093f6fda2d..fbe1b93486 100644 --- a/panda/src/text/dynamicTextPage.cxx +++ b/panda/src/text/dynamicTextPage.cxx @@ -110,15 +110,15 @@ fill_region(int x, int y, int x_size, int y_size, const LColor &color) { union { unsigned char p[2]; - PN_uint16 v; + uint16_t v; } v; v.p[0] = (unsigned char)(color[0] * 255.0f); v.p[1] = (unsigned char)(color[3] * 255.0f); - PN_uint16 *image = (PN_uint16 *)modify_ram_image().p(); + uint16_t *image = (uint16_t *)modify_ram_image().p(); for (int yi = y; yi < y + y_size; yi++) { - PN_uint16 *row = image + yi * _size[0] ; + uint16_t *row = image + yi * _size[0] ; for (int xi = x; xi < x + x_size; xi++) { row[xi] = v.v; } @@ -145,7 +145,7 @@ fill_region(int x, int y, int x_size, int y_size, const LColor &color) { // RGBA. union { unsigned char p[4]; - PN_uint32 v; + uint32_t v; } v; v.p[0] = (unsigned char)(color[2] * 255.0f); @@ -153,9 +153,9 @@ fill_region(int x, int y, int x_size, int y_size, const LColor &color) { v.p[2] = (unsigned char)(color[0] * 255.0f); v.p[3] = (unsigned char)(color[3] * 255.0f); - PN_uint32 *image = (PN_uint32 *)modify_ram_image().p(); + uint32_t *image = (uint32_t *)modify_ram_image().p(); for (int yi = y; yi < y + y_size; yi++) { - PN_uint32 *row = image + yi * _size[0]; + uint32_t *row = image + yi * _size[0]; for (int xi = x; xi < x + x_size; xi++) { row[xi] = v.v; } diff --git a/panda/src/text/textAssembler.cxx b/panda/src/text/textAssembler.cxx index c2092fec6b..996713a85a 100644 --- a/panda/src/text/textAssembler.cxx +++ b/panda/src/text/textAssembler.cxx @@ -1163,7 +1163,7 @@ generate_quads(GeomNode *geom_node, const QuadMap &quad_map) { // 32-bit index case. PT(GeomVertexArrayDataHandle) idx_handle = indices->modify_handle(); idx_handle->unclean_set_num_rows(quads.size() * 6); - PN_uint32 *idx_ptr = (PN_uint32 *)idx_handle->get_write_pointer(); + uint32_t *idx_ptr = (uint32_t *)idx_handle->get_write_pointer(); QuadDefs::const_iterator qi; for (qi = quads.begin(); qi != quads.end(); ++qi) { @@ -1219,7 +1219,7 @@ generate_quads(GeomNode *geom_node, const QuadMap &quad_map) { // 16-bit index case. PT(GeomVertexArrayDataHandle) idx_handle = indices->modify_handle(); idx_handle->unclean_set_num_rows(quads.size() * 6); - PN_uint16 *idx_ptr = (PN_uint16 *)idx_handle->get_write_pointer(); + uint16_t *idx_ptr = (uint16_t *)idx_handle->get_write_pointer(); QuadDefs::const_iterator qi; for (qi = quads.begin(); qi != quads.end(); ++qi) { diff --git a/panda/src/tform/buttonThrower.h b/panda/src/tform/buttonThrower.h index a772326fd6..009055fe3b 100644 --- a/panda/src/tform/buttonThrower.h +++ b/panda/src/tform/buttonThrower.h @@ -77,6 +77,7 @@ PUBLISHED: int get_num_parameters() const; EventParameter get_parameter(int n) const; MAKE_SEQ(get_parameters, get_num_parameters, get_parameter); + MAKE_SEQ_PROPERTY(parameters, get_num_parameters, get_parameter); INLINE const ModifierButtons &get_modifier_buttons() const; INLINE void set_modifier_buttons(const ModifierButtons &mods); diff --git a/panda/src/tform/mouseWatcherBase.h b/panda/src/tform/mouseWatcherBase.h index 962adc53b5..8836f57023 100644 --- a/panda/src/tform/mouseWatcherBase.h +++ b/panda/src/tform/mouseWatcherBase.h @@ -42,10 +42,12 @@ PUBLISHED: void sort_regions(); bool is_sorted() const; + MAKE_PROPERTY(sorted, is_sorted); int get_num_regions() const; MouseWatcherRegion *get_region(int n) const; MAKE_SEQ(get_regions, get_num_regions, get_region); + MAKE_SEQ_PROPERTY(regions, get_num_regions, get_region); void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx index dacb90c88e..9e37c67037 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx @@ -960,7 +960,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) { switch (reader->get_index_type()) { case Geom::NT_uint8: { - PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force); + uint8_t *index = (uint8_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } @@ -975,7 +975,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) { case Geom::NT_uint16: { - PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force); + uint16_t *index = (uint16_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } @@ -990,7 +990,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) { case Geom::NT_uint32: { - PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force); + uint32_t *index = (uint32_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } @@ -1051,7 +1051,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) { switch (reader->get_index_type()) { case Geom::NT_uint8: { - PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force); + uint8_t *index = (uint8_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } @@ -1076,7 +1076,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) { case Geom::NT_uint16: { - PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force); + uint16_t *index = (uint16_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } @@ -1101,7 +1101,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) { case Geom::NT_uint32: { - PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force); + uint32_t *index = (uint32_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } @@ -1182,7 +1182,7 @@ draw_lines(const GeomPrimitivePipelineReader *reader, bool force) { switch (reader->get_index_type()) { case Geom::NT_uint8: { - PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force); + uint8_t *index = (uint8_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } @@ -1196,7 +1196,7 @@ draw_lines(const GeomPrimitivePipelineReader *reader, bool force) { case Geom::NT_uint16: { - PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force); + uint16_t *index = (uint16_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } @@ -1210,7 +1210,7 @@ draw_lines(const GeomPrimitivePipelineReader *reader, bool force) { case Geom::NT_uint32: { - PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force); + uint32_t *index = (uint32_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } @@ -1259,7 +1259,7 @@ draw_points(const GeomPrimitivePipelineReader *reader, bool force) { switch (reader->get_index_type()) { case Geom::NT_uint8: { - PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force); + uint8_t *index = (uint8_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } @@ -1272,7 +1272,7 @@ draw_points(const GeomPrimitivePipelineReader *reader, bool force) { case Geom::NT_uint16: { - PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force); + uint16_t *index = (uint16_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } @@ -1285,7 +1285,7 @@ draw_points(const GeomPrimitivePipelineReader *reader, bool force) { case Geom::NT_uint32: { - PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force); + uint32_t *index = (uint32_t *)reader->get_read_pointer(force); if (index == NULL) { return false; } diff --git a/panda/src/vrpn/vrpn_interface.h b/panda/src/vrpn/vrpn_interface.h index 99349922ec..e3626e9055 100644 --- a/panda/src/vrpn/vrpn_interface.h +++ b/panda/src/vrpn/vrpn_interface.h @@ -27,6 +27,14 @@ #endif #endif +// VPRN misses an include to this in vrpn_Shared.h. +#include + +// Prevent VRPN from defining this function, which we don't need, +// and cause compilation errors in MSVC 2015. +#include "vrpn_Configure.h" +#undef VRPN_EXPORT_GETTIMEOFDAY + #include "vrpn_Connection.h" #include "vrpn_Tracker.h" #include "vrpn_Analog.h" diff --git a/panda/src/wgldisplay/wglGraphicsBuffer.cxx b/panda/src/wgldisplay/wglGraphicsBuffer.cxx index c0b897a3a1..309533df4b 100644 --- a/panda/src/wgldisplay/wglGraphicsBuffer.cxx +++ b/panda/src/wgldisplay/wglGraphicsBuffer.cxx @@ -74,10 +74,12 @@ begin_frame(FrameMode mode, Thread *current_thread) { return false; } - if (_fb_properties.is_single_buffered()) { - wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB); - } else { - wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB); + if (_pbuffer_bound) { + if (_fb_properties.is_single_buffered()) { + wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB); + } else { + wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB); + } } if (!rebuild_bitplanes()) { @@ -146,7 +148,7 @@ bind_texture_to_pbuffer() { for (size_t i = 0; i != cdata->_textures.size(); ++i) { const RenderTexture &rt = cdata->_textures[i]; RenderTexturePlane plane = rt._plane; - if (plane == RTP_color) { + if (plane == RTP_color && rt._rtm_mode == RTM_bind_or_copy) { tex_index = i; break; } diff --git a/panda/src/windisplay/winDetectDx.h b/panda/src/windisplay/winDetectDx.h index b57c6575a0..8a3a9c340e 100644 --- a/panda/src/windisplay/winDetectDx.h +++ b/panda/src/windisplay/winDetectDx.h @@ -133,8 +133,8 @@ static int get_display_information (DisplaySearchParameters &display_search_para int total_display_modes; DisplayMode *display_mode_array; - PN_uint64 physical_memory; - PN_uint64 available_physical_memory; + uint64_t physical_memory; + uint64_t available_physical_memory; int vendor_id; int device_id; diff --git a/panda/src/windisplay/winGraphicsPipe.cxx b/panda/src/windisplay/winGraphicsPipe.cxx index 64623d6bfe..01d9ab4068 100644 --- a/panda/src/windisplay/winGraphicsPipe.cxx +++ b/panda/src/windisplay/winGraphicsPipe.cxx @@ -123,11 +123,11 @@ void get_memory_information (DisplayInformation *display_information) { } typedef union { - PN_uint64 long_integer; + uint64_t long_integer; } LONG_INTEGER; -PN_uint64 cpu_time_function (void) { +uint64_t cpu_time_function (void) { #ifdef _WIN64 return __rdtsc(); #else @@ -594,7 +594,7 @@ int update_cpu_frequency_function(int processor_number, DisplayInformation *disp processor_power_information = processor_power_information_array; for (i = 0; i < MAXIMUM_PROCESSORS; i++) { if (processor_power_information->Number == processor_number) { - PN_uint64 value; + uint64_t value; value = processor_power_information->MaxMhz; display_information->_maximum_cpu_frequency = value * 1000000; @@ -662,7 +662,7 @@ count_number_of_cpus(DisplayInformation *display_information) { num_cpu_cores++; // A hyperthreaded core supplies more than one logical processor. - num_logical_cpus += count_bits_in_word((PN_uint64)(ptr->ProcessorMask)); + num_logical_cpus += count_bits_in_word((uint64_t)(ptr->ProcessorMask)); } ++ptr; } @@ -810,8 +810,8 @@ lookup_cpu_data() { _display_information->_cpu_time_function = cpu_time_function; // determine CPU frequency - PN_uint64 time; - PN_uint64 end_time; + uint64_t time; + uint64_t end_time; LARGE_INTEGER counter; LARGE_INTEGER end; LARGE_INTEGER frequency; diff --git a/panda/src/x11display/x11GraphicsWindow.cxx b/panda/src/x11display/x11GraphicsWindow.cxx index 5eab765bf0..e62923e662 100644 --- a/panda/src/x11display/x11GraphicsWindow.cxx +++ b/panda/src/x11display/x11GraphicsWindow.cxx @@ -1060,11 +1060,11 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) { // to set certain properties as a "type"; the other one as a "state". We'll // try to honor both. static const int max_type_data = 32; - PN_int32 type_data[max_type_data]; + int32_t type_data[max_type_data]; int next_type_data = 0; static const int max_state_data = 32; - PN_int32 state_data[max_state_data]; + int32_t state_data[max_state_data]; int next_state_data = 0; static const int max_set_data = 32; @@ -1154,7 +1154,7 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) { nassertv(next_set_data < max_set_data); // Add the process ID as a convenience for other applications. - PN_int32 pid = getpid(); + int32_t pid = getpid(); XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_pid, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&pid, 1); diff --git a/pandatool/src/assimp/loaderFileTypeAssimp.cxx b/pandatool/src/assimp/loaderFileTypeAssimp.cxx index cdfc9a8a22..b4a667d5fe 100644 --- a/pandatool/src/assimp/loaderFileTypeAssimp.cxx +++ b/pandatool/src/assimp/loaderFileTypeAssimp.cxx @@ -63,7 +63,7 @@ get_additional_extensions() const { /** * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. + * (with a .pz or .gz extension), false otherwise. */ bool LoaderFileTypeAssimp:: supports_compressed() const { diff --git a/pandatool/src/lwo/iffId.h b/pandatool/src/lwo/iffId.h index ff48a7e443..2d20b9b99c 100644 --- a/pandatool/src/lwo/iffId.h +++ b/pandatool/src/lwo/iffId.h @@ -40,7 +40,7 @@ public: private: union { - PN_uint32 _n; + uint32_t _n; char _c[4]; } _id; }; diff --git a/pandatool/src/lwo/iffInputFile.cxx b/pandatool/src/lwo/iffInputFile.cxx index 0707d78044..17f4225625 100644 --- a/pandatool/src/lwo/iffInputFile.cxx +++ b/pandatool/src/lwo/iffInputFile.cxx @@ -83,7 +83,7 @@ set_input(istream *input, bool owns_istream) { /** * Extracts a signed 8-bit integer. */ -PN_int8 IffInputFile:: +int8_t IffInputFile:: get_int8() { Datagram dg; if (!read_bytes(dg, 1)) { @@ -96,7 +96,7 @@ get_int8() { /** * Extracts an unsigned 8-bit integer. */ -PN_uint8 IffInputFile:: +uint8_t IffInputFile:: get_uint8() { Datagram dg; if (!read_bytes(dg, 1)) { @@ -109,7 +109,7 @@ get_uint8() { /** * Extracts a signed 16-bit big-endian integer. */ -PN_int16 IffInputFile:: +int16_t IffInputFile:: get_be_int16() { Datagram dg; if (!read_bytes(dg, 2)) { @@ -122,7 +122,7 @@ get_be_int16() { /** * Extracts a signed 32-bit big-endian integer. */ -PN_int32 IffInputFile:: +int32_t IffInputFile:: get_be_int32() { Datagram dg; if (!read_bytes(dg, 4)) { @@ -135,7 +135,7 @@ get_be_int32() { /** * Extracts an unsigned 16-bit big-endian integer. */ -PN_uint16 IffInputFile:: +uint16_t IffInputFile:: get_be_uint16() { Datagram dg; if (!read_bytes(dg, 2)) { @@ -148,7 +148,7 @@ get_be_uint16() { /** * Extracts an unsigned 32-bit big-endian integer. */ -PN_uint32 IffInputFile:: +uint32_t IffInputFile:: get_be_uint32() { Datagram dg; if (!read_bytes(dg, 4)) { @@ -215,7 +215,7 @@ get_chunk() { } IffId id = get_id(); - PN_uint32 length = get_be_uint32(); + uint32_t length = get_be_uint32(); if (!is_eof()) { PT(IffChunk) chunk = make_new_chunk(id); @@ -265,7 +265,7 @@ get_subchunk(IffChunk *context) { } IffId id = get_id(); - PN_uint16 length = get_be_uint16(); + uint16_t length = get_be_uint16(); if (!is_eof()) { PT(IffChunk) chunk = context->make_new_chunk(this, id); diff --git a/pandatool/src/lwo/iffInputFile.h b/pandatool/src/lwo/iffInputFile.h index 3afe12bae8..2b788f07a0 100644 --- a/pandatool/src/lwo/iffInputFile.h +++ b/pandatool/src/lwo/iffInputFile.h @@ -43,13 +43,13 @@ public: INLINE void align(); - PN_int8 get_int8(); - PN_uint8 get_uint8(); + int8_t get_int8(); + uint8_t get_uint8(); - PN_int16 get_be_int16(); - PN_int32 get_be_int32(); - PN_uint16 get_be_uint16(); - PN_uint32 get_be_uint32(); + int16_t get_be_int16(); + int32_t get_be_int32(); + uint16_t get_be_uint16(); + uint32_t get_be_uint32(); PN_stdfloat get_be_float32(); string get_string(); diff --git a/pandatool/src/lwo/lwoInputFile.cxx b/pandatool/src/lwo/lwoInputFile.cxx index 63f3b51731..78e7dfa10c 100644 --- a/pandatool/src/lwo/lwoInputFile.cxx +++ b/pandatool/src/lwo/lwoInputFile.cxx @@ -46,10 +46,10 @@ LwoInputFile:: */ int LwoInputFile:: get_vx() { - PN_uint16 top = get_be_uint16(); + uint16_t top = get_be_uint16(); if ((top & 0xff00) == 0xff00) { // The first byte is 0xff, which indicates we have a 4-byte integer. - PN_uint16 bottom = get_be_uint16(); + uint16_t bottom = get_be_uint16(); return ((int)(top & 0xff) << 16) | bottom; } diff --git a/pandatool/src/mayaegg/mayaNodeDesc.cxx b/pandatool/src/mayaegg/mayaNodeDesc.cxx index 72c8854976..efef4879a8 100644 --- a/pandatool/src/mayaegg/mayaNodeDesc.cxx +++ b/pandatool/src/mayaegg/mayaNodeDesc.cxx @@ -333,9 +333,9 @@ mark_joint_parent() { */ void MayaNodeDesc:: check_pseudo_joints(bool joint_above) { - static PN_uint32 space_count = 0; + static uint32_t space_count = 0; string space; - for (PN_uint32 idx=0; idx= 0) { set_drag_mode(DM_guide_bar); - PN_int16 x = LOWORD(lparam); + int16_t x = LOWORD(lparam); _drag_start_x = x; SetCapture(_graph_window); return 0; @@ -231,8 +231,8 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { case WM_MOUSEMOVE: if (_drag_mode == DM_none && _potential_drag_mode == DM_none) { // When the mouse is over a color bar, highlight it. - PN_int16 x = LOWORD(lparam); - PN_int16 y = HIWORD(lparam); + int16_t x = LOWORD(lparam); + int16_t y = HIWORD(lparam); _label_stack.highlight_label(get_collector_under_pixel(x, y)); // Now we want to get a WM_MOUSELEAVE when the mouse leaves the graph @@ -251,7 +251,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } if (_drag_mode == DM_scale) { - PN_int16 x = LOWORD(lparam); + int16_t x = LOWORD(lparam); double ratio = (double)x / (double)get_xsize(); if (ratio > 0.0f) { set_horizontal_scale(_drag_scale_start / ratio); @@ -261,7 +261,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } else if (_drag_mode == DM_new_guide_bar) { // We haven't created the new guide bar yet; we won't until the mouse // comes within the graph's region. - PN_int16 x = LOWORD(lparam); + int16_t x = LOWORD(lparam); if (x >= 0 && x < get_xsize()) { set_drag_mode(DM_guide_bar); _drag_guide_bar = add_user_guide_bar(pixel_to_height(x)); @@ -269,7 +269,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } } else if (_drag_mode == DM_guide_bar) { - PN_int16 x = LOWORD(lparam); + int16_t x = LOWORD(lparam); move_user_guide_bar(_drag_guide_bar, pixel_to_height(x)); return 0; } @@ -287,7 +287,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { return 0; } else if (_drag_mode == DM_guide_bar) { - PN_int16 x = LOWORD(lparam); + int16_t x = LOWORD(lparam); if (x < 0 || x >= get_xsize()) { remove_user_guide_bar(_drag_guide_bar); } else { @@ -303,8 +303,8 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { { // Double-clicking on a color bar in the graph is the same as double- // clicking on the corresponding label. - PN_int16 x = LOWORD(lparam); - PN_int16 y = HIWORD(lparam); + int16_t x = LOWORD(lparam); + int16_t y = HIWORD(lparam); clicked_label(get_collector_under_pixel(x, y)); return 0; } diff --git a/pandatool/src/win-stats/winStatsStripChart.cxx b/pandatool/src/win-stats/winStatsStripChart.cxx index 2e1d346f3b..066673aecd 100644 --- a/pandatool/src/win-stats/winStatsStripChart.cxx +++ b/pandatool/src/win-stats/winStatsStripChart.cxx @@ -370,14 +370,14 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { case WM_LBUTTONDOWN: if (_potential_drag_mode == DM_none) { set_drag_mode(DM_scale); - PN_int16 y = HIWORD(lparam); + int16_t y = HIWORD(lparam); _drag_scale_start = pixel_to_height(y); SetCapture(_graph_window); return 0; } else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) { set_drag_mode(DM_guide_bar); - PN_int16 y = HIWORD(lparam); + int16_t y = HIWORD(lparam); _drag_start_y = y; SetCapture(_graph_window); return 0; @@ -387,8 +387,8 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { case WM_MOUSEMOVE: if (_drag_mode == DM_none && _potential_drag_mode == DM_none) { // When the mouse is over a color bar, highlight it. - PN_int16 x = LOWORD(lparam); - PN_int16 y = HIWORD(lparam); + int16_t x = LOWORD(lparam); + int16_t y = HIWORD(lparam); _label_stack.highlight_label(get_collector_under_pixel(x, y)); // Now we want to get a WM_MOUSELEAVE when the mouse leaves the graph @@ -407,7 +407,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } if (_drag_mode == DM_scale) { - PN_int16 y = HIWORD(lparam); + int16_t y = HIWORD(lparam); double ratio = 1.0f - ((double)y / (double)get_ysize()); if (ratio > 0.0f) { set_vertical_scale(_drag_scale_start / ratio); @@ -417,7 +417,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } else if (_drag_mode == DM_new_guide_bar) { // We haven't created the new guide bar yet; we won't until the mouse // comes within the graph's region. - PN_int16 y = HIWORD(lparam); + int16_t y = HIWORD(lparam); if (y >= 0 && y < get_ysize()) { set_drag_mode(DM_guide_bar); _drag_guide_bar = add_user_guide_bar(pixel_to_height(y)); @@ -425,7 +425,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } } else if (_drag_mode == DM_guide_bar) { - PN_int16 y = HIWORD(lparam); + int16_t y = HIWORD(lparam); move_user_guide_bar(_drag_guide_bar, pixel_to_height(y)); return 0; } @@ -443,7 +443,7 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { return 0; } else if (_drag_mode == DM_guide_bar) { - PN_int16 y = HIWORD(lparam); + int16_t y = HIWORD(lparam); if (y < 0 || y >= get_ysize()) { remove_user_guide_bar(_drag_guide_bar); } else { @@ -459,8 +459,8 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { { // Double-clicking on a color bar in the graph is the same as double- // clicking on the corresponding label. - PN_int16 x = LOWORD(lparam); - PN_int16 y = HIWORD(lparam); + int16_t x = LOWORD(lparam); + int16_t y = HIWORD(lparam); clicked_label(get_collector_under_pixel(x, y)); return 0; } diff --git a/samples/particles/particle_panel.py b/samples/particles/particle_panel.py index d74e42155c..b449bc474f 100755 --- a/samples/particles/particle_panel.py +++ b/samples/particles/particle_panel.py @@ -17,13 +17,14 @@ try: except: sys.exit("Please install Python megawidgets") +# Makes sure that Panda is configured to play nice with Tkinter +from panda3d.core import * +loadPrcFileData("", "want-tk true") + # Open the Panda window from direct.showbase.ShowBase import ShowBase base = ShowBase() -# Makes sure that Panda is configured to play nice with Tkinter -base.startTk() - from direct.tkpanels.ParticlePanel import ParticlePanel pp = ParticlePanel() # Create the panel diff --git a/samples/shader-terrain/heightfield.png b/samples/shader-terrain/heightfield.png new file mode 100644 index 0000000000..2d72c0445f Binary files /dev/null and b/samples/shader-terrain/heightfield.png differ diff --git a/samples/shader-terrain/main.py b/samples/shader-terrain/main.py new file mode 100644 index 0000000000..92ff61467a --- /dev/null +++ b/samples/shader-terrain/main.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python + +# Author: tobspr +# +# Last Updated: 2016-04-30 +# +# This tutorial provides an example of using the ShaderTerrainMesh class + +from direct.showbase.ShowBase import ShowBase +from panda3d.core import ShaderTerrainMesh, Shader, load_prc_file_data +from panda3d.core import SamplerState + + +class ShaderTerrainDemo(ShowBase): + def __init__(self): + + # Load some configuration variables, its important for this to happen + # before the ShowBase is initialized + load_prc_file_data("", """ + textures-power-2 none + gl-coordinate-system default + window-title Panda3D ShaderTerrainMesh Demo + """) + + # Initialize the showbase + ShowBase.__init__(self) + + # Increase camera FOV as well as the far plane + self.camLens.set_fov(90) + self.camLens.set_near_far(0.1, 50000) + + # Construct the terrain + self.terrain_node = ShaderTerrainMesh() + + # Set a heightfield, the heightfield should be a 16-bit png and + # have a quadratic size of a power of two. + self.terrain_node.heightfield = self.loader.loadTexture("heightfield.png") + + # Set the target triangle width. For a value of 10.0 for example, + # the terrain will attempt to make every triangle 10 pixels wide on screen. + self.terrain_node.target_triangle_width = 10.0 + + # Generate the terrain + self.terrain_node.generate() + + # Attach the terrain to the main scene and set its scale. With no scale + # set, the terrain ranges from (0, 0, 0) to (1, 1, 1) + self.terrain = self.render.attach_new_node(self.terrain_node) + self.terrain.set_scale(1024, 1024, 100) + self.terrain.set_pos(-512, -512, -70.0) + + # Set a shader on the terrain. The ShaderTerrainMesh only works with + # an applied shader. You can use the shaders used here in your own application + terrain_shader = Shader.load(Shader.SL_GLSL, "terrain.vert.glsl", "terrain.frag.glsl") + self.terrain.set_shader(terrain_shader) + self.terrain.set_shader_input("camera", self.camera) + + # Shortcut to view the wireframe mesh + self.accept("f3", self.toggleWireframe) + + # Set some texture on the terrain + grass_tex = self.loader.loadTexture("textures/grass.png") + grass_tex.set_minfilter(SamplerState.FT_linear_mipmap_linear) + grass_tex.set_anisotropic_degree(16) + self.terrain.set_texture(grass_tex) + + # Load a skybox - you can safely ignore this code + skybox = self.loader.loadModel("models/skybox.bam") + skybox.reparent_to(self.render) + skybox.set_scale(20000) + + skybox_texture = self.loader.loadTexture("textures/skybox.jpg") + skybox_texture.set_minfilter(SamplerState.FT_linear) + skybox_texture.set_magfilter(SamplerState.FT_linear) + skybox_texture.set_wrap_u(SamplerState.WM_repeat) + skybox_texture.set_wrap_v(SamplerState.WM_mirror) + skybox_texture.set_anisotropic_degree(16) + skybox.set_texture(skybox_texture) + + skybox_shader = Shader.load(Shader.SL_GLSL, "skybox.vert.glsl", "skybox.frag.glsl") + skybox.set_shader(skybox_shader) + +ShaderTerrainDemo().run() diff --git a/samples/shader-terrain/models/skybox.bam b/samples/shader-terrain/models/skybox.bam new file mode 100644 index 0000000000..d39bf69577 Binary files /dev/null and b/samples/shader-terrain/models/skybox.bam differ diff --git a/samples/shader-terrain/skybox.frag.glsl b/samples/shader-terrain/skybox.frag.glsl new file mode 100644 index 0000000000..1703cfd425 --- /dev/null +++ b/samples/shader-terrain/skybox.frag.glsl @@ -0,0 +1,21 @@ +#version 150 + +in vec3 skybox_pos; +out vec4 color; + +uniform sampler2D p3d_Texture0; + +void main() { + + vec3 view_dir = normalize(skybox_pos); + vec2 skybox_uv; + + // Convert spherical coordinates + const float pi = 3.14159265359; + skybox_uv.x = (atan(view_dir.y, view_dir.x) + (0.5 * pi)) / (2 * pi); + skybox_uv.y = clamp(view_dir.z * 0.72 + 0.35, 0.0, 1.0); + + vec3 skybox_color = textureLod(p3d_Texture0, skybox_uv, 0).xyz; + + color = vec4(skybox_color, 1); +} diff --git a/samples/shader-terrain/skybox.vert.glsl b/samples/shader-terrain/skybox.vert.glsl new file mode 100644 index 0000000000..464d9d2a94 --- /dev/null +++ b/samples/shader-terrain/skybox.vert.glsl @@ -0,0 +1,13 @@ +#version 150 + +// This is just a simple vertex shader transforming the skybox + +in vec4 p3d_Vertex; +uniform mat4 p3d_ModelViewProjectionMatrix; + +out vec3 skybox_pos; + +void main() { + skybox_pos = p3d_Vertex.xyz; + gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex; +} diff --git a/samples/shader-terrain/terrain.frag.glsl b/samples/shader-terrain/terrain.frag.glsl new file mode 100644 index 0000000000..0f447842c3 --- /dev/null +++ b/samples/shader-terrain/terrain.frag.glsl @@ -0,0 +1,56 @@ +#version 150 + +// This is the terrain fragment shader. There is a lot of code in here +// which is not necessary to render the terrain, but included for convenience - +// Like generating normals from the heightmap or a simple fog effect. + +// Most of the time you want to adjust this shader to get your terrain the look +// you want. The vertex shader most likely will stay the same. + +in vec2 terrain_uv; +in vec3 vtx_pos; +out vec4 color; + +uniform struct { + sampler2D data_texture; + sampler2D heightfield; + int view_index; + int terrain_size; + int chunk_size; +} ShaderTerrainMesh; + +uniform sampler2D p3d_Texture0; +uniform vec3 wspos_camera; + +// Compute normal from the heightmap, this assumes the terrain is facing z-up +vec3 get_terrain_normal() { + const float terrain_height = 50.0; + vec3 pixel_size = vec3(1.0, -1.0, 0) / textureSize(ShaderTerrainMesh.heightfield, 0).xxx; + float u0 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.yz).x * terrain_height; + float u1 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.xz).x * terrain_height; + float v0 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.zy).x * terrain_height; + float v1 = texture(ShaderTerrainMesh.heightfield, terrain_uv + pixel_size.zx).x * terrain_height; + vec3 tangent = normalize(vec3(1.0, 0, u1 - u0)); + vec3 binormal = normalize(vec3(0, 1.0, v1 - v0)); + return normalize(cross(tangent, binormal)); +} + + + +void main() { + vec3 diffuse = texture(p3d_Texture0, terrain_uv * 16.0).xyz; + vec3 normal = get_terrain_normal(); + + // Add some fake lighting - you usually want to use your own lighting code here + vec3 fake_sun = normalize(vec3(0.7, 0.2, 0.6)); + vec3 shading = max(0.0, dot(normal, fake_sun)) * diffuse; + shading += vec3(0.07, 0.07, 0.1); + + + // Fake fog + float dist = distance(vtx_pos, wspos_camera); + float fog_factor = smoothstep(0, 1, dist / 1000.0); + shading = mix(shading, vec3(0.7, 0.7, 0.8), fog_factor); + + color = vec4(shading, 1.0); +} diff --git a/samples/shader-terrain/terrain.vert.glsl b/samples/shader-terrain/terrain.vert.glsl new file mode 100644 index 0000000000..d693451c89 --- /dev/null +++ b/samples/shader-terrain/terrain.vert.glsl @@ -0,0 +1,56 @@ +#version 150 + +// This is the default terrain vertex shader. Most of the time you can just copy +// this and reuse it, and just modify the fragment shader. + +in vec4 p3d_Vertex; +uniform mat4 p3d_ModelViewProjectionMatrix; +uniform mat4 p3d_ModelMatrix; + +uniform struct { + sampler2D data_texture; + sampler2D heightfield; + int view_index; + int terrain_size; + int chunk_size; +} ShaderTerrainMesh; + +out vec2 terrain_uv; +out vec3 vtx_pos; + +void main() { + + // Terrain data has the layout: + // x: x-pos, y: y-pos, z: size, w: clod + vec4 terrain_data = texelFetch(ShaderTerrainMesh.data_texture, + ivec2(gl_InstanceID, ShaderTerrainMesh.view_index), 0); + + // Get initial chunk position in the (0, 0, 0), (1, 1, 0) range + vec3 chunk_position = p3d_Vertex.xyz; + + // CLOD implementation + float clod_factor = smoothstep(0, 1, terrain_data.w); + chunk_position.xy -= clod_factor * fract(chunk_position.xy * ShaderTerrainMesh.chunk_size / 2.0) + * 2.0 / ShaderTerrainMesh.chunk_size; + + // Scale the chunk + chunk_position *= terrain_data.z * float(ShaderTerrainMesh.chunk_size) + / float(ShaderTerrainMesh.terrain_size); + chunk_position.z *= ShaderTerrainMesh.chunk_size; + + // Offset the chunk, it is important that this happens after the scale + chunk_position.xy += terrain_data.xy / float(ShaderTerrainMesh.terrain_size); + + // Compute the terrain UV coordinates + terrain_uv = chunk_position.xy; + + // Sample the heightfield and offset the terrain - we do not need to multiply + // the height with anything since the terrain transform is included in the + // model view projection matrix. + chunk_position.z += texture(ShaderTerrainMesh.heightfield, terrain_uv).x; + gl_Position = p3d_ModelViewProjectionMatrix * vec4(chunk_position, 1); + + // Output the vertex world space position - in this case we use this to render + // the fog. + vtx_pos = (p3d_ModelMatrix * vec4(chunk_position, 1)).xyz; +} diff --git a/samples/shader-terrain/textures/LICENSE.txt b/samples/shader-terrain/textures/LICENSE.txt new file mode 100644 index 0000000000..e59b601333 --- /dev/null +++ b/samples/shader-terrain/textures/LICENSE.txt @@ -0,0 +1,5 @@ +Grass texture from (cc by 3.0) +http://opengameart.org/content/grass-texture + +Skybox by rdb +http://rdb.name/PANO_20140818_112419.jpg diff --git a/samples/shader-terrain/textures/grass.png b/samples/shader-terrain/textures/grass.png new file mode 100644 index 0000000000..79e09bb135 Binary files /dev/null and b/samples/shader-terrain/textures/grass.png differ diff --git a/samples/shader-terrain/textures/skybox.jpg b/samples/shader-terrain/textures/skybox.jpg new file mode 100644 index 0000000000..1092bc6aae Binary files /dev/null and b/samples/shader-terrain/textures/skybox.jpg differ