mirror of
https://github.com/php/php-src.git
synced 2026-04-23 07:58:20 +02:00
Merge branch 'PHP-5.6' of https://git.php.net/push/php-src into PHP-5.6
This commit is contained in:
@@ -106,7 +106,7 @@ define dump_bt
|
||||
printf "%ld", $zvalue->value.lval
|
||||
end
|
||||
if $type == 2
|
||||
printf "%lf", $zvalue->value.dval
|
||||
printf "%f", $zvalue->value.dval
|
||||
end
|
||||
if $type == 3
|
||||
if $zvalue->value.lval
|
||||
@@ -185,7 +185,7 @@ define ____printzv_contents
|
||||
printf "long: %ld", $zvalue->value.lval
|
||||
end
|
||||
if $type == 2
|
||||
printf "double: %lf", $zvalue->value.dval
|
||||
printf "double: %f", $zvalue->value.dval
|
||||
end
|
||||
if $type == 3
|
||||
printf "bool: "
|
||||
|
||||
+4
-1
@@ -259,7 +259,10 @@ The file labelled 'EXPERIMENTAL' should include the following
|
||||
information::
|
||||
|
||||
Any authoring information (known bugs, future directions of the module).
|
||||
Ongoing status notes which may not be appropriate for SVN comments.
|
||||
Ongoing status notes which may not be appropriate for Git comments.
|
||||
|
||||
In general new features should go to PECL or experimental branches until
|
||||
there are specific reasons for directly adding it to the core distribution.
|
||||
|
||||
Aliases & Legacy Documentation
|
||||
-----------------------------------
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@ clean:
|
||||
distclean: clean
|
||||
rm -f Makefile config.cache config.log config.status Makefile.objects Makefile.fragments libtool main/php_config.h main/internal_functions_cli.c main/internal_functions.c stamp-h sapi/apache/libphp$(PHP_MAJOR_VERSION).module sapi/apache_hooks/libphp$(PHP_MAJOR_VERSION).module buildmk.stamp Zend/zend_dtrace_gen.h Zend/zend_dtrace_gen.h.bak Zend/zend_config.h TSRM/tsrm_config.h
|
||||
rm -f php5.spec main/build-defs.h scripts/phpize
|
||||
rm -f ext/date/lib/timelib_config.h ext/mbstring/oniguruma/config.h ext/mbstring/libmbfl/config.h ext/mysqlnd/php_mysqlnd_config.h
|
||||
rm -f ext/date/lib/timelib_config.h ext/mbstring/oniguruma/config.h ext/mbstring/libmbfl/config.h ext/oci8/oci8_dtrace_gen.h ext/oci8/oci8_dtrace_gen.h.bak
|
||||
rm -f scripts/man1/phpize.1 scripts/php-config scripts/man1/php-config.1 sapi/cli/php.1 sapi/cgi/php-cgi.1 ext/phar/phar.1 ext/phar/phar.phar.1
|
||||
rm -f sapi/fpm/php-fpm.conf sapi/fpm/init.d.php-fpm sapi/fpm/php-fpm.service sapi/fpm/php-fpm.8 sapi/fpm/status.html
|
||||
rm -f ext/iconv/php_have_bsd_iconv.h ext/iconv/php_have_glibc_iconv.h ext/iconv/php_have_ibm_iconv.h ext/iconv/php_have_iconv.h ext/iconv/php_have_libiconv.h ext/iconv/php_iconv_aliased_libiconv.h ext/iconv/php_iconv_supports_errno.h ext/iconv/php_php_iconv_h_path.h ext/iconv/php_php_iconv_impl.h
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
Between PHP 4.0.6 and 4.1.0, the Zend module struct changed in a way
|
||||
that broke both source and binary compatibility. If you are
|
||||
maintaining a third party extension, here's how to update it:
|
||||
|
||||
If this was your old module entry:
|
||||
|
||||
zend_module_entry foo_module_entry = {
|
||||
"foo", /* extension name */
|
||||
foo_functions, /* extension function list */
|
||||
NULL, /* extension-wide startup function */
|
||||
NULL, /* extension-wide shutdown function */
|
||||
PHP_RINIT(foo), /* per-request startup function */
|
||||
PHP_RSHUTDOWN(foo), /* per-request shutdown function */
|
||||
PHP_MINFO(foo), /* information function */
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
Here's how it should look if you want your code to build with PHP
|
||||
4.1.0 and up:
|
||||
|
||||
zend_module_entry foo_module_entry = {
|
||||
#if ZEND_MODULE_API_NO >= 20010901
|
||||
STANDARD_MODULE_HEADER,
|
||||
#endif
|
||||
"foo", /* extension name */
|
||||
foo_functions, /* extension function list */
|
||||
NULL, /* extension-wide startup function */
|
||||
NULL, /* extension-wide shutdown function */
|
||||
PHP_RINIT(foo), /* per-request startup function */
|
||||
PHP_RSHUTDOWN(foo), /* per-request shutdown function */
|
||||
PHP_MINFO(foo), /* information function */
|
||||
#if ZEND_MODULE_API_NO >= 20010901
|
||||
PHP_FOO_VERSION, /* extension version number (string) */
|
||||
#endif
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
If you don't care about source compatibility with earlier PHP releases
|
||||
than 4.1.0, you can drop the #if/#endif lines.
|
||||
@@ -1,155 +0,0 @@
|
||||
1. strrpos() and strripos() now use the entire string as a needle. Be aware
|
||||
that the existing scripts may no longer work as you expect.
|
||||
|
||||
EX :
|
||||
<?php
|
||||
var_dump(strrpos("ABCDEF","DEF"));
|
||||
var_dump(strrpos("ABCDEF","DAF"));
|
||||
?>
|
||||
|
||||
Will give you different results. The former returns 3 while the latter
|
||||
returns false rather than the position of the last occurrence of 'D'.
|
||||
The same applies to strripos().
|
||||
|
||||
2. Illegal use of string offsets causes E_ERROR instead of E_WARNING.
|
||||
|
||||
EX :
|
||||
<?php
|
||||
$a = "foo";
|
||||
unset($a[0][1][2]);
|
||||
?>
|
||||
|
||||
Fatal error: Cannot use string offset as an array in ... on line 1
|
||||
|
||||
3. array_merge() was changed to accept only arrays. If a non-array variable is
|
||||
passed, a E_WARNING will be thrown for every such parameter. Be careful
|
||||
because your code may start emitting E_WARNING out of the blue.
|
||||
|
||||
4. Be careful when porting from ext/mysql to ext/mysqli. The following
|
||||
functions return NULL when no more data is available in the result set
|
||||
(ext/mysql's functions return FALSE).
|
||||
|
||||
- mysqli_fetch_row()
|
||||
- mysqli_fetch_array()
|
||||
- mysqli_fetch_assoc()
|
||||
|
||||
5. PATH_TRANSLATED server variable is no longer set implicitly under
|
||||
Apache2 SAPI in contrast to the situation in PHP 4, where it is set to the
|
||||
same value as the SCRIPT_FILENAME server variable when it is not populated
|
||||
by Apache. This change was made to comply with the CGI specification.
|
||||
Please refer to bug #23610 for further information.
|
||||
|
||||
6. Starting PHP 5.0.0 the T_ML_CONSTANT constant is no longer defined by the
|
||||
ext/tokenizer extension. If error_reporting is set to E_ALL notices will
|
||||
be produced. Instead of T_ML_CONSTANT for /* */ the T_COMMENT constant
|
||||
is used, thus both // and /* */ are resolved as the T_COMMENT constant.
|
||||
However the PHPDoc style comments /** */ ,which starting PHP 5 are parsed
|
||||
by PHP, are recongnized as T_DOC_COMMENT.
|
||||
|
||||
7. $_SERVER should be populated with argc and argv if variables_order
|
||||
includes "S". If you have specifically configured your system to not
|
||||
create $_SERVER, then of course it shouldn't be there. The change was to
|
||||
always make argc and argv available in the CLI version regardless of the
|
||||
variables_order setting. As in, the CLI version will now always populate
|
||||
the global $argc and $argv variables.
|
||||
|
||||
8. In some cases classes must be declared before used. It only happens only
|
||||
if some of the new features of PHP 5 are used. Otherwise the behaviour is
|
||||
the old.
|
||||
Example 1 (works with no errors):
|
||||
<?php
|
||||
$a = new a();
|
||||
class a {
|
||||
}
|
||||
?>
|
||||
|
||||
Example 2 (throws an error):
|
||||
<?php
|
||||
$a = new a();
|
||||
interface b{
|
||||
}
|
||||
class a implements b {
|
||||
}
|
||||
?>
|
||||
|
||||
Output (example 2) :
|
||||
Fatal error: Class 'a' not found in /tmp/cl.php on line 2
|
||||
|
||||
9. get_class() starting PHP 5 returns the name of the class as it was
|
||||
declared which may lead to problems in older scripts that rely on
|
||||
the previous behaviour - the class name is lowercased. Expect the
|
||||
same behaviour from get_parent_class() when applicable.
|
||||
Example :
|
||||
<?php
|
||||
class FooBar {
|
||||
}
|
||||
class ExtFooBar extends FooBar{}
|
||||
$a = new FooBar();
|
||||
var_dump(get_class($a), get_parent_class($a));
|
||||
?>
|
||||
|
||||
Output (PHP 4):
|
||||
string(6) "foobar"
|
||||
string(9) "extfoobar"
|
||||
|
||||
Output (PHP 5):
|
||||
string(6) "FooBar"
|
||||
string(9) "ExtFooBar"
|
||||
----------------------------------------------------------------------
|
||||
Example code that will break :
|
||||
//....
|
||||
function someMethod($p) {
|
||||
if (get_class($p) != 'helpingclass') {
|
||||
return FALSE;
|
||||
}
|
||||
//...
|
||||
}
|
||||
//...
|
||||
Possible solution is to search for get_class() and get_parent_class() in
|
||||
all your scripts and use strtolower().
|
||||
|
||||
10. get_class_methods() returns the names of the methods of a class as they
|
||||
declared. In PHP4 the names are all lowercased.
|
||||
Example code :
|
||||
<?php
|
||||
class Foo{
|
||||
function doFoo(){}
|
||||
function hasFoo(){}
|
||||
}
|
||||
var_dump(get_class_methods("Foo"));
|
||||
?>
|
||||
Output (PHP4):
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(5) "dofoo"
|
||||
[1]=>
|
||||
string(6) "hasfoo"
|
||||
}
|
||||
Output (PHP5):
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(5) "doFoo"
|
||||
[1]=>
|
||||
string(6) "hasFoo"
|
||||
}
|
||||
|
||||
11. Assignment $this is impossible. Starting PHP 5.0.0 $this has special
|
||||
meaning in class methods and is recognized by the PHP parser. The latter
|
||||
will generate a parse error when assignment to $this is found
|
||||
Example code :
|
||||
<?php
|
||||
class Foo {
|
||||
function assignNew($obj) {
|
||||
$this = $obj;
|
||||
}
|
||||
}
|
||||
$a = new Foo();
|
||||
$b = new Foo();
|
||||
$a->assignNew($b);
|
||||
echo "I was executed\n";
|
||||
?>
|
||||
Output (PHP 4):
|
||||
I was executed
|
||||
Output (PHP 5):
|
||||
PHP Fatal error: Cannot re-assign $this in /tmp/this_ex.php on line 4
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ Opening Streams
|
||||
===============
|
||||
In most cases, you should use this API:
|
||||
|
||||
PHPAPI php_stream *php_stream_open_wrapper(char *path, char *mode,
|
||||
PHPAPI php_stream *php_stream_open_wrapper(const char *path, const char *mode,
|
||||
int options, char **opened_path TSRMLS_DC);
|
||||
|
||||
Where:
|
||||
|
||||
+14
-14
@@ -5,7 +5,7 @@ This document describes how to submit an enhancement or patch for PHP.
|
||||
It's easy!
|
||||
|
||||
You don't need any login accounts or special access to download,
|
||||
build, debug and begin submitting PHP, PECL or PEAR code, tests or
|
||||
build, debug and begin submitting PHP or PECL code, tests or
|
||||
documentation. Once you've followed this README and had several
|
||||
patches accepted, commit privileges are often quickly granted.
|
||||
|
||||
@@ -16,8 +16,8 @@ http://phpadvent.org/2008/less-whining-more-coding-by-elizabeth-smith
|
||||
Online Forums
|
||||
-------------
|
||||
There are several IRC channels where PHP developers are often
|
||||
available to discuss questions. They include #php.pecl, #php.doc and
|
||||
#pear on the EFNet network and #php-dev-win on FreeNode.
|
||||
available to discuss questions. They include #php.pecl and #php.doc
|
||||
on the EFNet network and #php-dev-win on FreeNode.
|
||||
|
||||
|
||||
PHP Patches
|
||||
@@ -78,7 +78,7 @@ of type 'text/*' are accepted.
|
||||
PECL Extension Patches: http://pecl.php.net/
|
||||
--------------------------------------------
|
||||
If you are fixing broken functionality in a PECL extension then create
|
||||
a bug or identify an existing bug at http://pecl.php.net/bugs/. A bug
|
||||
a bug or identify an existing bug at http://bugs.php.net/. A bug
|
||||
can be used to track the patch progress and prevent your changes
|
||||
getting lost in the PHP mail archives.
|
||||
|
||||
@@ -114,15 +114,15 @@ http://pear.php.net/manual/en/guide-developers.php
|
||||
|
||||
How to create your PHP, PHP Documentation or PECL patch
|
||||
-------------------------------------------------------
|
||||
PHP and PECL use Subversion (SVN) for revision control. Read
|
||||
http://www.php.net/svn.php for help on using SVN to get and build PHP
|
||||
source code. We recommend using a Sparse Directory checkout described
|
||||
in http://wiki.php.net/vcs/svnfaq. If you are new to SVN, read
|
||||
http://svnbook.red-bean.com.
|
||||
PHP and most PECL packages use Git for revision control. Some PECL
|
||||
packages use Subversion (SVN) Read http://www.php.net/git.php for help
|
||||
on using Git to get and build PHP source code. We recommend to look
|
||||
at our workflow on https://wiki.php.net/vcs/gitworkflow and our FAQ
|
||||
https://wiki.php.net/vcs/gitfaq.
|
||||
|
||||
Generally we ask that bug fix patches work on the current stable PHP
|
||||
development branches and on "trunk". New PHP features only need to
|
||||
work on "trunk".
|
||||
development branches and on "master". New PHP features only need to
|
||||
work on "master".
|
||||
|
||||
Read CODING_STANDARDS before you start working.
|
||||
|
||||
@@ -134,7 +134,7 @@ comprehensive.
|
||||
|
||||
After testing is finished, create a patch file using the command:
|
||||
|
||||
svn diff > your_patch.txt
|
||||
git diff > your_patch.txt
|
||||
|
||||
For ease of review and later troubleshooting, submit individual
|
||||
patches for each bug or feature.
|
||||
@@ -142,7 +142,7 @@ patches for each bug or feature.
|
||||
|
||||
Checklist for submitting your PHP or PECL code patch
|
||||
----------------------------------------------------
|
||||
- Update SVN source just before running your final 'diff' and
|
||||
- Update git source just before running your final 'diff' and
|
||||
before testing.
|
||||
- Add in-line comments and/or have external documentation ready.
|
||||
Use only "/* */" style comments, not "//".
|
||||
@@ -175,7 +175,7 @@ about these questions:
|
||||
|
||||
What happens when your PHP or PECL patch is applied
|
||||
---------------------------------------------------
|
||||
Your name will likely be included in the SVN commit log. If your
|
||||
Your name will likely be included in the Git commit log. If your
|
||||
patch affects end users, a brief description and your name might be
|
||||
added to the NEWS file.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
## process this file with automake to produce Makefile.am
|
||||
AUTOMAKE_OPTIONS=foreign
|
||||
noinst_LTLIBRARIES=libtsrm.la
|
||||
libtsrm_la_SOURCES = TSRM.c tsrm_strtok_r.c tsrm_virtual_cwd.c
|
||||
libtsrm_la_SOURCES = TSRM.c tsrm_strtok_r.c
|
||||
|
||||
depend:
|
||||
|
||||
@@ -143,10 +143,6 @@ SOURCE=.\tsrm_strtok_r.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tsrm_virtual_cwd.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tsrm_win32.c
|
||||
# End Source File
|
||||
# End Group
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// vim:ft=javascript
|
||||
// $Id$
|
||||
|
||||
ADD_SOURCES("TSRM", "TSRM.c tsrm_strtok_r.c tsrm_virtual_cwd.c tsrm_win32.c");
|
||||
ADD_SOURCES("TSRM", "TSRM.c tsrm_strtok_r.c tsrm_win32.c");
|
||||
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@
|
||||
#ifdef TSRM_WIN32
|
||||
#include <Sddl.h>
|
||||
#include "tsrm_win32.h"
|
||||
#include "tsrm_virtual_cwd.h"
|
||||
#include "zend_virtual_cwd.h"
|
||||
|
||||
#ifdef ZTS
|
||||
static ts_rsrc_id win32_globals_id;
|
||||
|
||||
@@ -1,486 +1,163 @@
|
||||
$Id$
|
||||
|
||||
PHP 5.5 UPGRADE NOTES
|
||||
PHP X.Y UPGRADE NOTES
|
||||
|
||||
1. Backward Incompatible Changes
|
||||
2. New Features
|
||||
2. Changes in SAPI modules
|
||||
3. Deprecated Functionality
|
||||
4. Changed Functions
|
||||
5. New Functions
|
||||
6. New Classes and Interfaces
|
||||
7. Removed Extensions
|
||||
8. Other Changes to Extensions
|
||||
9. New Global Constants
|
||||
1. Backward Incompatible Changes
|
||||
2. New Features
|
||||
2. Changes in SAPI modules
|
||||
3. Deprecated Functionality
|
||||
4. Changed Functions
|
||||
5. New Functions
|
||||
6. New Classes and Interfaces
|
||||
7. Removed Extensions
|
||||
8. Other Changes to Extensions
|
||||
9. New Global Constants
|
||||
10. Changes to INI File Handling
|
||||
11. Windows Support
|
||||
12. Other Changes
|
||||
11. Other Changes
|
||||
|
||||
|
||||
========================================
|
||||
1. Backward Incompatible Changes
|
||||
========================================
|
||||
|
||||
- Dropped Windows XP and 2003 support. (Pierre)
|
||||
- Core:
|
||||
Removed $HTTP_RAW_POST_DATA global variable. Restore backwards compatibility
|
||||
by:
|
||||
<?php
|
||||
global $HTTP_RAW_POST_DATA;
|
||||
if (!isset($HTTP_RAW_POST_DATA)) {
|
||||
$HTTP_RAW_POST_DATA = file_get_contents("php://input");
|
||||
}
|
||||
?>
|
||||
|
||||
- All internal case insensitivity handling for class, function and constant
|
||||
names is done according to ASCII rules. Current locale settings are ignored.
|
||||
|
||||
- self, parent & static keywords now are always case-insensitive (see bug
|
||||
#60833).
|
||||
|
||||
- Removed Logo GUIDs: php_logo_guid(), php_egg_logo_guid(),
|
||||
php_real_logo_guid() and zend_logo_guid()
|
||||
- JSON:
|
||||
json_decode() no longer accepts non-lowercase variants of lone JSON true,
|
||||
false or null values. For example, True or FALSE will now cause json_decode to
|
||||
return NULL and set an error value you can fetch with json_last_error().
|
||||
This affects JSON texts consisting solely of true, false or null. Text
|
||||
containing non-lowercase values inside JSON arrays or objects has never been
|
||||
accepted.
|
||||
|
||||
========================================
|
||||
2. New Features
|
||||
========================================
|
||||
|
||||
- Support list in foreach. (Laruence)
|
||||
(http://php.net/foreach#control-structures.foreach.list,
|
||||
http://wiki.php.net/rfc/foreachlist)
|
||||
- Added constant scalar expressions syntax
|
||||
(https://wiki.php.net/rfc/const_scalar_exprs)
|
||||
|
||||
- Support "finally" keyword. (Laruence)
|
||||
(http://php.net/exceptions, http://wiki.php.net/rfc/finally)
|
||||
- Added dedicated syntax for variadic functions.
|
||||
(https://wiki.php.net/rfc/variadics)
|
||||
|
||||
- Support constant array/string dereferencing. (Laruence)
|
||||
(http://php.net/manual/en/language.types.array.php,
|
||||
https://wiki.php.net/rfc/constdereference)
|
||||
- The php://input stream is now re-usable and can be used concurrently with
|
||||
enable_post_data_reading=0.
|
||||
|
||||
- Add support for using empty() on the result of function calls and
|
||||
other expressions. Thus it is now possible to write empty(getArray()),
|
||||
for example. (http://php.net/manual/en/function.empty.php,
|
||||
https://wiki.php.net/rfc/empty_isset_exprs)
|
||||
- Added gost-crypto (CryptoPro S-box) hash algo.
|
||||
|
||||
- Added generators.
|
||||
(http://php.net/generators, https://wiki.php.net/rfc/generators)
|
||||
- Added openssl certificate fingerprint support (inclusive stream context
|
||||
option).
|
||||
|
||||
- ClassName::class syntax returning full class name for a class as a
|
||||
string constant. (http://php.net/oop5.basic,
|
||||
https://wiki.php.net/rfc/class_name_scalars)
|
||||
|
||||
- Added support for non-scalar Iterator keys in foreach.
|
||||
(http://php.net/manual/en/control-structures.foreach.php,
|
||||
https://wiki.php.net/rfc/foreach-non-scalar-keys).
|
||||
|
||||
- Bundled Zend OPcache extension to improve performance
|
||||
(http://php.net/manual/en/book.opcache.php,
|
||||
https://wiki.php.net/rfc/optimizerplus)
|
||||
|
||||
- Added a simplified password hashing API
|
||||
(http://php.net/password, https://wiki.php.net/rfc/password_hash)
|
||||
- Added openssl crypto method stream context option.
|
||||
|
||||
========================================
|
||||
2. Changes in SAPI modules
|
||||
========================================
|
||||
|
||||
- Support for changing the process's title in CLI/CLI-Server
|
||||
SAPIs. (Keyur)
|
||||
(http://php.net/manual/en/function.cli-set-process-title.php,
|
||||
http://php.net/manual/en/function.cli-get-process-title.php,
|
||||
https://wiki.php.net/rfc/cli_process_title)
|
||||
|
||||
- Support for systemd in php-fpm: Add --with-fpm-systemd option to
|
||||
report health to systemd, and add systemd_interval option to
|
||||
configure this. The service can now use Type=notify in the systemd
|
||||
unit file. (Remi)
|
||||
|
||||
========================================
|
||||
3. Deprecated Functionality
|
||||
========================================
|
||||
|
||||
- The original MySQL extension is now deprecated and will generate
|
||||
deprecation warnings when connecting to a database through
|
||||
mysql_connect(), mysql_pconnect() or by establishing an implicit
|
||||
connection. Use MySQLi or PDO instead.
|
||||
|
||||
- The preg_replace /e modifier is now deprecated. Use
|
||||
preg_replace_callback instead.
|
||||
(https://wiki.php.net/rfc/remove_preg_replace_eval_modifier)
|
||||
|
||||
- IntlDateFormatter::setTimeZoneID() and datefmt_set_timezone_id() are
|
||||
deprecated. Use IntlDateFormatter::setTimeZone() or
|
||||
datefmt_set_timezone() instead.
|
||||
|
||||
- mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() and mcrypt_ofb() now throw
|
||||
E_DEPRECATED. Their use was already previously discouraged in the
|
||||
documentation, but that predated the existence of E_DEPRECATED.
|
||||
- Incompatible context calls:
|
||||
Instance calls from an incompatible context are now deprecated and issue
|
||||
E_DEPRECATED instead of E_STRICT. See https://wiki.php.net/rfc/incompat_ctx
|
||||
|
||||
========================================
|
||||
4. Changed Functions
|
||||
========================================
|
||||
|
||||
- pack()/unpack() had the following changes, which bring it more in
|
||||
line with Perl's behavior: - Implemented format character "Z": NULL
|
||||
padded string, with trailing NULL bytes removed. - Changed format
|
||||
character "a": this no longer removes trailing NULL bytes. -
|
||||
Changed format character "A": all trailing ASCII whitespace is now
|
||||
removed (defined as spaces, tabs, \r, \n and NULL).
|
||||
- cURL:
|
||||
CURLOPT_SAFE_UPLOAD is now turned on by default and uploads with @file
|
||||
do not work unless it is explicitly set to false.
|
||||
|
||||
- MessageFormatter::format() and related functions now accepted named
|
||||
arguments and mixed numeric/named arguments in ICU 4.8+.
|
||||
- Crypt:
|
||||
crypt() will now raise an E_NOTICE error if the salt parameter is omitted.
|
||||
See: https://wiki.php.net/rfc/crypt_function_salt
|
||||
|
||||
- MessageFormatter::format() and related functions now don't error out
|
||||
when an insufficient argument count is provided. Instead, the
|
||||
placeholders will remain unsubstituted.
|
||||
|
||||
- MessageFormatter::parse() and MessageFormat::format() (and their
|
||||
static equivalents) now don't throw away better than second
|
||||
precision in the arguments.
|
||||
|
||||
- IntlDateFormatter::__construct and datefmt_create() now accept for
|
||||
the $timezone argument time zone identifiers, IntlTimeZone objects,
|
||||
DateTimeZone objects and NULL. It used to accept only time zone
|
||||
identifiers and NULL. Invalid time zone identifiers are no longer
|
||||
accepted. Empty strings are no longer accepted.
|
||||
|
||||
- The default time zone used in IntlDateFormatter::__construct and
|
||||
datefmt_create() (when the corresponding argument is not passed or
|
||||
NULL is passed) is now the one given by date_default_timezone_get(),
|
||||
not the default ICU time zone.
|
||||
|
||||
- The time zone passed to the IntlDateFormatter is ignored if it is
|
||||
NULL and if the calendar passed is an IntlCalendar object -- in this
|
||||
case, the IntlCalendar's time zone will be used instead. Otherwise,
|
||||
the time zone specified in the $timezone argument is used
|
||||
instead. This does not affect old code, as IntlCalendar was
|
||||
introduced in this version.
|
||||
|
||||
- IntlDateFormatter::__construct and datefmt_create() now accept for
|
||||
the $calendar argument also IntlCalendar objects.
|
||||
|
||||
- IntlDateFormatter::getCalendar() and datefmt_get_calendar() return
|
||||
false if the IntlDateFormatter was set up with an IntlCalendar
|
||||
instead of the constants
|
||||
IntlDateFormatter::GREGORIAN/TRADITIONAL. IntlCalendar did not exist
|
||||
before this version.
|
||||
|
||||
- IntlDateFormatter::setCalendar() and datefmt_set_calendar() now also
|
||||
accept an IntlCalendar object, in which case its time zone is
|
||||
taken. Passing a constant is still allowed, and still keeps the time
|
||||
zone.
|
||||
|
||||
- IntlDateFormatter::format() and datefmt_format() now also accept an
|
||||
IntlCalendar object for formatting.
|
||||
|
||||
- set_error_handler(NULL) can now be used to reset the error handler.
|
||||
Furthermore both set_error_handler(NULL) and
|
||||
set_exception_handler(NULL) will now return the previously defined
|
||||
error/exception handler. Previously bool(true) was returned.
|
||||
|
||||
- setcookie(), setrawcookie() and ext/session now send Max-Age headers
|
||||
alongside Expires headers. (see
|
||||
https://wiki.php.net/rfc/cookie_max-age)
|
||||
|
||||
- curl_setopt now accepts new option CURLOPT_SAFE_UPLOAD and CURLFile
|
||||
object for safer file uploads (see
|
||||
https://wiki.php.net/rfc/curl-file-upload)
|
||||
|
||||
- Functions in the socket extension now do not emit warnings when the
|
||||
errno is EAGAIN, EWOULDBLOCK or EINPROGRESS.
|
||||
|
||||
- Since 5.5.2, spl_autoload_functions() returns different names for
|
||||
different lambda functions registered via spl_autoload_register().
|
||||
|
||||
- Since 5.5.3, DOMDocument::schemaValidateSource() and
|
||||
DOMDocument::schemaValidate() accept flag parameter. Only flag
|
||||
available now is LIBXML_SCHEMA_CREATE. Default is 0.
|
||||
|
||||
- Since 5.5.4, fputcsv() has fifth parameter escape_char, allowing to
|
||||
specify escape char.
|
||||
- XMLReader:
|
||||
XMLReader::getAttributeNs and XMLReader::getAttributeNo now return NULL if
|
||||
the attribute could not be found, just like XMLReader::getAttribute.
|
||||
|
||||
========================================
|
||||
5. New Functions
|
||||
========================================
|
||||
|
||||
- Core:
|
||||
- array_column()
|
||||
- boolval()
|
||||
- password_get_info()
|
||||
- password_hash()
|
||||
- password_needs_rehash()
|
||||
- password_verify()
|
||||
- GMP:
|
||||
Added gmp_root($a, $nth) and gmp_rootrem($a, $nth) for calculating nth roots.
|
||||
|
||||
- cURL:
|
||||
- curl_file_create
|
||||
- Openssl:
|
||||
Added string openssl_x509_fingerprint($x509, $type, $binary).
|
||||
|
||||
- GD
|
||||
- imageflip
|
||||
- imagecrop
|
||||
- imagecropauto
|
||||
- imagesetinterpolation
|
||||
- imageaffine
|
||||
- imageaffinematrixget
|
||||
- imageaffinematrixconcat
|
||||
- imagescale
|
||||
- LDAP:
|
||||
Added ldap_escape($value, $ignore = "", $flags = 0).
|
||||
|
||||
- Hash:
|
||||
- hash_pbkdf2()
|
||||
|
||||
- Intl:
|
||||
- datefmt_format_object()
|
||||
- datefmt_get_calendar_object()
|
||||
- datefmt_get_timezone()
|
||||
- datefmt_set_timezone()
|
||||
- datefmt_get_calendar_object()
|
||||
- intlcal_create_instance()
|
||||
- intlcal_get_keyword_values_for_locale()
|
||||
- intlcal_get_now()
|
||||
- intlcal_get_available_locales()
|
||||
- intlcal_get()
|
||||
- intlcal_get_time()
|
||||
- intlcal_set_time()
|
||||
- intlcal_add()
|
||||
- intlcal_set_time_zone()
|
||||
- intlcal_after()
|
||||
- intlcal_before()
|
||||
- intlcal_set()
|
||||
- intlcal_roll()
|
||||
- intlcal_clear()
|
||||
- intlcal_field_difference()
|
||||
- intlcal_get_actual_maximum()
|
||||
- intlcal_get_actual_minimum()
|
||||
- intlcal_get_day_of_week_type()
|
||||
- intlcal_get_first_day_of_week()
|
||||
- intlcal_get_greatest_minimum()
|
||||
- intlcal_get_least_maximum()
|
||||
- intlcal_get_locale()
|
||||
- intlcal_get_maximum()
|
||||
- intlcal_get_minimal_days_in_first_week()
|
||||
- intlcal_get_minimum()
|
||||
- intlcal_get_time_zone()
|
||||
- intlcal_get_type()
|
||||
- intlcal_get_weekend_transition()
|
||||
- intlcal_in_daylight_time()
|
||||
- intlcal_is_equivalent_to()
|
||||
- intlcal_is_lenient()
|
||||
- intlcal_is_set()
|
||||
- intlcal_is_weekend()
|
||||
- intlcal_set_first_day_of_week()
|
||||
- intlcal_set_lenient()
|
||||
- intlcal_equals()
|
||||
- intlcal_get_repeated_wall_time_option()
|
||||
- intlcal_get_skipped_wall_time_option()
|
||||
- intlcal_set_repeated_wall_time_option()
|
||||
- intlcal_set_skipped_wall_time_option()
|
||||
- intlcal_from_date_time()
|
||||
- intlcal_to_date_time()
|
||||
- intlcal_get_error_code()
|
||||
- intlcal_get_error_message()
|
||||
- intlgregcal_create_instance()
|
||||
- intlgregcal_set_gregorian_change()
|
||||
- intlgregcal_get_gregorian_change()
|
||||
- intlgregcal_is_leap_year()
|
||||
- intltz_create_time_zone()
|
||||
- intltz_create_default()
|
||||
- intltz_get_id()
|
||||
- intltz_get_gmt()
|
||||
- intltz_get_unknown()
|
||||
- intltz_create_enumeration()
|
||||
- intltz_count_equivalent_ids()
|
||||
- intltz_create_time_zone_id_enumeration()
|
||||
- intltz_get_canonical_id()
|
||||
- intltz_get_region()
|
||||
- intltz_get_tz_data_version()
|
||||
- intltz_get_equivalent_id()
|
||||
- intltz_use_daylight_time()
|
||||
- intltz_get_offset()
|
||||
- intltz_get_raw_offset()
|
||||
- intltz_has_same_rules()
|
||||
- intltz_get_display_name()
|
||||
- intltz_get_dst_savings()
|
||||
- intltz_from_date_time_zone()
|
||||
- intltz_to_date_time_zone()
|
||||
- intltz_get_error_code()
|
||||
- intltz_get_error_message()
|
||||
|
||||
- IntlDateFormatter::formatObject()
|
||||
- IntlDateFormatter::getCalendarObject()
|
||||
- IntlDateFormatter::getTimeZone()
|
||||
- IntlDateFormatter::setTimeZone()
|
||||
|
||||
- Sockets:
|
||||
- socket_sendmsg()
|
||||
- socket_recvmsg()
|
||||
- socket_cmsg_space()
|
||||
|
||||
- SPL:
|
||||
- SplFixedArray::__wakeup()
|
||||
- SplDoublyLinkedList::add()
|
||||
- RecursiveTreeIterator::getPostfix() (5.5.2)
|
||||
- RecursiveTreeIterator::setPostfix() (5.5.2)
|
||||
|
||||
- Zend OPcache:
|
||||
- opcache_get_configuration()
|
||||
- opcache_get_status()
|
||||
- opcache_reset()
|
||||
- Zip:
|
||||
Added ZipArchive::setPassword($password)
|
||||
|
||||
========================================
|
||||
6. New Classes and Interfaces
|
||||
========================================
|
||||
|
||||
- Intl:
|
||||
- IntlCalendar
|
||||
- IntlGregorianCalendar
|
||||
- IntlTimeZone
|
||||
- IntlBreakIterator
|
||||
- IntlRuleBasedBreakIterator
|
||||
- IntlCodePointBreakIterator
|
||||
- UConverter
|
||||
|
||||
- cURL:
|
||||
- CURLFile
|
||||
|
||||
========================================
|
||||
7. Removed Extensions
|
||||
========================================
|
||||
|
||||
None
|
||||
|
||||
========================================
|
||||
8. Other Changes to Extensions
|
||||
========================================
|
||||
|
||||
- Intl:
|
||||
- This extension now requires ICU 4.0+.
|
||||
- Phar:
|
||||
- Added ability of resolving alias created by Phar::map
|
||||
- GMP:
|
||||
The GMP extension now uses objects as the underlying data structure, rather
|
||||
than resources. GMP instances now support dumping, serialization, cloning,
|
||||
casts to primitive types and have overloaded operators.
|
||||
(RFC: https://wiki.php.net/rfc/operator_overloading_gmp)
|
||||
|
||||
- OCI8:
|
||||
- Added Implicit Result Set support for Oracle Database 12c with a
|
||||
new oci_get_implicit_resultset() function.
|
||||
- Using 'oci_execute($s, OCI_NO_AUTO_COMMIT)' for a SELECT no longer
|
||||
unnecessarily initiates an internal ROLLBACK during connection
|
||||
close.
|
||||
- Added DTrace probes enabled with PHP's generic --enable-dtrace
|
||||
- The oci_internal_debug() function is now a no-op.
|
||||
- The phpinfo() output format for OCI8 has changed.
|
||||
|
||||
========================================
|
||||
9. New Global Constants
|
||||
========================================
|
||||
|
||||
- mysqli:
|
||||
- Added MYSQLI_SERVER_PUBLIC_KEY constant to be used with mysqli_options()
|
||||
|
||||
- cURL:
|
||||
- Added CURLOPT_SAFE_UPLOAD to be used with curl_setopt().
|
||||
- Added CURL_WRAPPERS_ENABLED to reflect --with-curlwrappers.
|
||||
|
||||
- GD
|
||||
- Added constants for imageflip:
|
||||
. IMG_FLIP_HORIZONTAL
|
||||
. IMG_FLIP_VERTICAL
|
||||
. IMG_FLIP_BOTH
|
||||
- Added constants for imagecrop
|
||||
. IMG_CROP_DEFAULT
|
||||
. IMG_CROP_TRANSPARENT
|
||||
. IMG_CROP_BLACK
|
||||
. IMG_CROP_WHITE
|
||||
. IMG_CROP_SIDES
|
||||
. IMG_CROP_THRESHOLD
|
||||
- Added constants for imagesetinterpolation, used by imagescale
|
||||
imagerotate and imageaffine:
|
||||
. IMG_BELL
|
||||
. IMG_BESSEL
|
||||
. IMG_BILINEAR_FIXED
|
||||
. IMG_BICUBIC
|
||||
. IMG_BICUBIC_FIXED
|
||||
. IMG_BLACKMAN
|
||||
. IMG_BOX
|
||||
. IMG_BSPLINE
|
||||
. IMG_CATMULLROM
|
||||
. IMG_GAUSSIAN
|
||||
. IMG_GENERALIZED_CUBIC
|
||||
. IMG_HERMITE
|
||||
. IMG_HAMMING
|
||||
. IMG_HANNING
|
||||
. IMG_MITCHELL
|
||||
. IMG_POWER
|
||||
. IMG_QUADRATIC
|
||||
. IMG_SINC
|
||||
. IMG_NEAREST_NEIGHBOUR
|
||||
. IMG_WEIGHTED4
|
||||
. IMG_TRIANGLE
|
||||
- Added constants for imageaffinematrixget
|
||||
. IMG_AFFINE_TRANSLATE
|
||||
. IMG_AFFINE_SCALE
|
||||
. IMG_AFFINE_ROTATE
|
||||
. IMG_AFFINE_SHEAR_HORIZONTAL
|
||||
. IMG_AFFINE_SHEAR_VERTICAL
|
||||
- LDAP:
|
||||
LDAP_ESCAPE_FILTER int(1)
|
||||
LDAP_ESCAPE_DN int(2)
|
||||
|
||||
========================================
|
||||
10. Changes to INI File Handling
|
||||
========================================
|
||||
|
||||
- Core:
|
||||
- Added sys_temp_dir INI directive, for specifying temporary
|
||||
directory.
|
||||
|
||||
- Intl:
|
||||
- Added intl.use_exceptions INI directive, which controls what
|
||||
happens when global errors are set together with intl.error_level.
|
||||
|
||||
- MSSQL:
|
||||
- mssql.compatability_mode renamed to mssql.compatibility_mode in 5.5.2,
|
||||
old directive still supported for BC reasons.
|
||||
|
||||
- mysqlnd:
|
||||
- Added mysqlnd.sha256_server_public_key INI PERDIR setting that
|
||||
affects all APIs which use(are built) for mysqlnd. This allows
|
||||
ext/mysqli to be used with the new auth protocol, although at
|
||||
coarser level.
|
||||
|
||||
- Sessions:
|
||||
- Added session.use_strict_mode in 5.5.3, which prevents session
|
||||
fixation attacks and session collisions.
|
||||
See also https://wiki.php.net/rfc/strict_sessions
|
||||
|
||||
- Zend OPcache (See http://php.net/manual/en/book.opcache.php)
|
||||
- Added the following directives:
|
||||
- opcache.enable (default "1")
|
||||
- opcache.memory_consumption (default "64")
|
||||
- opcache.interned_strings_buffer (default "4")
|
||||
- opcache.max_accelerated_files (default "2000")
|
||||
- opcache.max_wasted_percentage (default "5")
|
||||
- opcache.use_cwd (default "1")
|
||||
- opcache.validate_timestamps (default "1")
|
||||
- opcache.revalidate_freq (default "2")
|
||||
- opcache.revalidate_path (default "0")
|
||||
- opcache.save_comments (default "1")
|
||||
- opcache.load_comments (default "1")
|
||||
- opcache.fast_shutdown (default "0")
|
||||
- opcache.enable_file_override (default "0")
|
||||
- opcache.optimization_level (default "0xffffffff")
|
||||
- opcache.inherited_hack (default "1")
|
||||
- opcache.blacklist_filename (default "")
|
||||
- opcache.max_file_size (default "0")
|
||||
- opcache.consistency_checks (default "0")
|
||||
- opcache.force_restart_timeout (default "180")
|
||||
- opcache.error_log (default "" which means stderr)
|
||||
- opcache.log_verbosity_level (default "1")
|
||||
- opcache.preferred_memory_model (default "")
|
||||
- opcache.protect_memory (default "0")
|
||||
- opcache.mmap_base (Windows-only)
|
||||
Removed always_populate_raw_post_data.
|
||||
|
||||
========================================
|
||||
11. Windows Support
|
||||
11. Other Changes
|
||||
========================================
|
||||
|
||||
- The Apache 2.4 handler is supported as of PHP 5.5.0
|
||||
- File upload:
|
||||
Uploads equal or greater than 2GB in size are now accepted.
|
||||
|
||||
- OPcache: Errors like 'unable to reattach to base address' could
|
||||
happen in many common setups. It is due to some technical and
|
||||
design restriction in the engine and could not be fixed easily
|
||||
before 5.5.0 was released.
|
||||
- HTTP stream wrapper:
|
||||
HTTP 1.1 requests now include a Connection: close header unless explicitly
|
||||
overridden by setting a Connection header via the header context option.
|
||||
|
||||
A possible fix is to tweak the opcache.mmap_base INI setting by
|
||||
forcing the first address to be tried.
|
||||
|
||||
For x86 version, the following addreses can be tried:
|
||||
. 0x20000000, 0x21000000, 0x30000000, 0x31000000, 0x50000000
|
||||
and for x64 (still experimental):
|
||||
. 0x0000100000000000, 0x0000200000000000, 0x0000300000000000, 0x0000700000000000
|
||||
|
||||
========================================
|
||||
12. Other Changes
|
||||
========================================
|
||||
|
||||
- If the APC or WinCache user cache APIs were used before, consider
|
||||
these alternatives for PHP 5.5:
|
||||
|
||||
- APCu
|
||||
- all supported OSes: http://pecl.php.net/package/APCu
|
||||
- Windows: http://windows.php.net/downloads/pecl/releases/apcu/
|
||||
|
||||
- WinCache, Windows only: http://pecl.php.net/package/WinCache
|
||||
- Zip:
|
||||
New --with-libzip option allow to use system libzip. Version > 0.11 required.
|
||||
|
||||
+82
-78
@@ -3,11 +3,10 @@ $Id$
|
||||
UPGRADE NOTES - PHP X.Y
|
||||
|
||||
1. Internal API changes
|
||||
a. Executor changes
|
||||
b. Streams pooling API
|
||||
c. Lowercasing and locales
|
||||
d. zend_qsort_r
|
||||
e. get_current_key
|
||||
a. Addition of do_operation and compare object handlers
|
||||
b. return_value_ptr now always available, RETVAL_ZVAL_FAST macros
|
||||
c. POST data handling
|
||||
d. Arginfo changes
|
||||
|
||||
2. Build system changes
|
||||
a. Unix build system changes
|
||||
@@ -18,103 +17,108 @@ UPGRADE NOTES - PHP X.Y
|
||||
1. Internal API changes
|
||||
========================
|
||||
|
||||
a. Executor changes
|
||||
a. Addition of do_operation and compare object handlers
|
||||
|
||||
* extensions can't override zend_execute() any more, they should override
|
||||
zend_execute_ex() instead. The EG(current_execute_data) is already
|
||||
initialized in zend_execute_ex(), so for compatibility extensions
|
||||
may need to use EG(current_execute_data)->prev_execute_data instead.
|
||||
* removed EG(arg_types_stack), EX(fbc), EX(called_scope), EX(current_object)
|
||||
* added op_array->nested_calls. It's calculated at compile time.
|
||||
* added EX(call_slots). It is an array to store information about syntaticaly
|
||||
nested calls (e.g. foo(bar())). It's preallocated together with execute_data.
|
||||
* added EX(call) - pointer to a current calling function. Actually an
|
||||
element of EX(call_slots)
|
||||
* opcodes INIT_METHOD_CALL, ZEND_INIT_STATIC_METHOD_CALL,
|
||||
ZEND_INIT_FCALL_BY_NAME, ZEND_INIT_NS_FCALL_BY_NAME use result.num as
|
||||
an index in EX(call_slots)
|
||||
* opcode ZEND_NEW uses extended_vallue as an index in EX(call_slots)
|
||||
* opcoes ZEND_DO_FCALL and ZEND_DO_FCALL_BY_NAME use op2.num as
|
||||
an index in EX(call_slots)
|
||||
* added op_array->used_stack. It's calculated at compile time and the
|
||||
corresponding stack space is preallocated together with execute_data.
|
||||
ZEND_SEND* and ZEND_DO_FCALL* don't need to check for stack overflow
|
||||
anymore.
|
||||
* Removed execute_data->Ts field. The VM temporary variables always allocated
|
||||
immediately before execute_data structure. Now they are accessed by offset
|
||||
from the execute_data base pointer (instead of execute_data->Ts). Compiler
|
||||
stores new offsets in op_array->opcodes[*].op?.num. You can use macros
|
||||
EX_TMP_VAR() and EX_TMP_VAR_NUM() to access temp_variable by offset or
|
||||
number. You can convert number to offset using EX_TMP_VAR_NUM(0, num) or
|
||||
offset to number (EX_TMP_VAR_NUM(0,0)-EX_TMP_VAR(0,offset)).
|
||||
* Removed execute_data->CVs field. The VM compiled variables always allocated
|
||||
immediately after execute_data structure. Now they are accessed by offset
|
||||
from the execute_data base pointer (instead of execute_data->CVs). You can
|
||||
use macros EX_CV_NUM() to access compiled variables by number.
|
||||
Two new object handlers have been added:
|
||||
|
||||
b. Streams pooling API
|
||||
do_operation:
|
||||
typedef int (*zend_object_do_operation_t)(
|
||||
zend_uchar opcode, zval *result, zval *op1, zval *op2 TSRMLS_DC
|
||||
);
|
||||
|
||||
The streams pooling API has been removed. The following functions no longer
|
||||
exist:
|
||||
compare:
|
||||
typedef int (*zend_object_compare_zvals_t)(
|
||||
zval *result, zval *op1, zval *op2 TSRMLS_DC
|
||||
);
|
||||
|
||||
PHPAPI int php_stream_context_get_link(php_stream_context *context,
|
||||
const char *hostent, php_stream **stream);
|
||||
PHPAPI int php_stream_context_set_link(php_stream_context *context,
|
||||
const char *hostent, php_stream *stream);
|
||||
PHPAPI int php_stream_context_del_link(php_stream_context *context,
|
||||
php_stream *stream);
|
||||
The first handler is used to overload arithmetic operations. The first
|
||||
argument specifies the opcode of the operator, result is the target zval,
|
||||
op1 the first operand and op2 the second operand. For unary operations
|
||||
op2 is NULL. If the handler returns FAILURE PHP falls back to the default
|
||||
behavior for the operation.
|
||||
|
||||
c. Lowercasing and locales
|
||||
The second handler is used to perform comparison operations with
|
||||
non-objects. The value written into result must be an IS_LONG with value
|
||||
-1 (smaller), 0 (equal) or 1 (greater). The return value is a SUCCESS/FAILURE
|
||||
return code. The difference between this handler and compare_objects is
|
||||
that it will be triggered for comparisons with non-objects and objects of
|
||||
different types. It takes precedence over compare_objects.
|
||||
|
||||
The lowercasing functions in zend_operators.c were split into those that do
|
||||
lowercasing according to locale rules and those that do ASCII lowercasing.
|
||||
ASCII:
|
||||
Further docs in the RFC: https://wiki.php.net/rfc/operator_overloading_gmp
|
||||
|
||||
zend_str_tolower_copy
|
||||
zend_str_tolower_dup
|
||||
zend_str_tolower
|
||||
zend_binary_strcasecmp
|
||||
zend_binary_strncasecmp
|
||||
b. return_value_ptr now always available, RETVAL_ZVAL_FAST macros
|
||||
|
||||
Locale-based:
|
||||
zend_binary_strncasecmp_l
|
||||
zend_binary_strcasecmp_l
|
||||
zend_binary_zval_strcasecmp
|
||||
zend_binary_zval_strncasecmp
|
||||
string_compare_function_ex
|
||||
string_case_compare_function
|
||||
The return_value_ptr argument to internal functions is now always set.
|
||||
Previously it was only available for functions returning by-reference.
|
||||
return_value_ptr can now be used to return zvals without copying them.
|
||||
For this purpose two new macros are provided:
|
||||
|
||||
Internal engine lowercasing will be using ASCII-only rules. User-facing functions,
|
||||
such as strcasecmp, will be using locale rules.
|
||||
RETVAL_ZVAL_FAST(zv); /* analog to RETVAL_ZVAL(zv, 1, 0) */
|
||||
RETURN_ZVAL_FAST(zv); /* analog to RETURN_ZVAL(zv, 1, 0) */
|
||||
|
||||
Two new functions - zend_binary_strncasecmp_l and zend_binary_strcasecmp_l - added as
|
||||
locale-based counterparts to zend_binary_strcasecmp and zend_binary_strncasecmp.
|
||||
The macros behave similarly to the non-FAST variants with copy=1 and
|
||||
dtor=0, but will try to return the zval without making a copy by utilizing
|
||||
return_value_ptr.
|
||||
|
||||
c. POST data handling
|
||||
|
||||
The sapi_request_info's members post_data, post_data_len and raw_post_data as
|
||||
well as raw_post_data_len have been replaced with a temp PHP stream
|
||||
request_body.
|
||||
|
||||
The recommended way to access raw POST data is to open and use a php://input
|
||||
stream wrapper. It is safe to be used concurrently and more than once.
|
||||
|
||||
d. zend_qsort_r
|
||||
d. Arginfo changes
|
||||
|
||||
Added the function zend_qsort_r():
|
||||
The pass_rest_by_reference argument of the ZEND_BEGIN_ARG_INFO and
|
||||
ZEND_BEGIN_ARG_INFO_EX() is no longer used. The value passed to it is ignored.
|
||||
|
||||
typedef int (*compare_r_func_t)(const void *, const void * TSRMLS_DC, void *);
|
||||
void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_t compare, void *arg TSRMLS_DC);
|
||||
Instead a variadic argument is created using ZEND_ARG_VARIADIC_INFO():
|
||||
|
||||
The extra argument it has (relatively to zend_qsort()) is passed to the
|
||||
comparison function.
|
||||
ZEND_ARG_VARIADIC_INFO(0, name) /* pass rest by value */
|
||||
ZEND_ARG_VARIADIC_INFO(1, name) /* pass rest by reference */
|
||||
ZEND_ARG_VARIADIC_INFO(ZEND_SEND_PREFER_REF, name)
|
||||
/* pass rest by prefer-ref */
|
||||
|
||||
e. get_current_key
|
||||
ZEND_ARG_VARIADIC_INFO() should only be used for the last argument.
|
||||
|
||||
The signature of the get_current_key iteration handler has been changed to:
|
||||
The following changes were applied to the zend_arg_info struct:
|
||||
|
||||
void (*get_current_key)(zend_object_iterator *iter, zval *key TSRMLS_DC);
|
||||
typedef struct _zend_arg_info {
|
||||
const char *class_name;
|
||||
zend_uint class_name_len;
|
||||
zend_uchar type_hint;
|
||||
+ zend_uchar pass_by_reference;
|
||||
zend_bool allow_null;
|
||||
- zend_bool pass_by_reference;
|
||||
+ zend_bool is_variadic;
|
||||
} zend_arg_info;
|
||||
|
||||
The key should be written into the zval* using the ZVAL_* macros.
|
||||
The following changes were applied to the zend_internal_function_info struct:
|
||||
|
||||
typedef struct _zend_internal_function_info {
|
||||
zend_uint required_num_args;
|
||||
zend_uchar _type_hint;
|
||||
zend_bool return_reference;
|
||||
- zend_bool pass_rest_by_reference;
|
||||
+ zend_bool _allow_null;
|
||||
+ zend_bool _is_variadic;
|
||||
} zend_internal_function_info;
|
||||
|
||||
The CHECK_ARG_SEND_TYPE(), ARG_MUST_BE_SENT_BY_REF(),
|
||||
ARG_SHOULD_BE_SENT_BY_REF() and ARG_MAY_BE_SENT_BY_REF() macros now assume
|
||||
that the argument passed to them is a zend_function* and that it is non-NULL.
|
||||
|
||||
========================
|
||||
2. Build system changes
|
||||
========================
|
||||
|
||||
a. Unix build system changes
|
||||
-
|
||||
- The bison version check is now a blacklist instead of a whitelist.
|
||||
- The bison binary can be specified through the YACC environment/configure
|
||||
variable. Previously `bison` was assumed to be in $PATH.
|
||||
|
||||
b. Windows build system changes
|
||||
- Drop Windows XP and 2003 support.
|
||||
-
|
||||
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ libZend_la_SOURCES=\
|
||||
zend_default_classes.c \
|
||||
zend_iterators.c zend_interfaces.c zend_exceptions.c \
|
||||
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \
|
||||
zend_generators.c
|
||||
zend_generators.c zend_virtual_cwd.c zend_ast.c
|
||||
|
||||
libZend_la_LDFLAGS =
|
||||
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
|
||||
|
||||
+3
-3
@@ -9,11 +9,11 @@ Modified: 2001-09-17
|
||||
1. Background/Need
|
||||
==================
|
||||
|
||||
Many internal function of PHP will reject parameters because of their
|
||||
Many internal functions of PHP will reject parameters because of their
|
||||
type (the array and variable function come to mind). For userland
|
||||
this is not an easy task as there is no uniform way to do it. An
|
||||
addition to the engine for requiring loose types would allow
|
||||
delevopers to know that the data passed to their functions is of the
|
||||
developers to know that the data passed to their functions are of the
|
||||
correct type and reduce the need for duplicating the same code in
|
||||
every function to check for the type of data.
|
||||
|
||||
@@ -57,7 +57,7 @@ function foo (array $var){
|
||||
===========
|
||||
|
||||
Mis-matches in type should be reported as fatal errors and should halt
|
||||
the execution of a script as that function can not be run and code
|
||||
the execution of a script as that function cannot be run and code
|
||||
following could not reliably run.
|
||||
|
||||
|
||||
|
||||
@@ -119,6 +119,10 @@ SOURCE=.\zend_API.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zend_ast.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zend_builtin_functions.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -429,6 +433,10 @@ SOURCE=.\zend_ts_hash.h
|
||||
|
||||
SOURCE=.\zend_variables.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zend_virtual_cwd.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Parsers"
|
||||
|
||||
|
||||
@@ -140,6 +140,10 @@ SOURCE=.\zend_alloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zend_ast.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zend_API.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
+18
-9
@@ -3,8 +3,13 @@ dnl
|
||||
dnl This file contains local autoconf functions.
|
||||
|
||||
AC_DEFUN([LIBZEND_BISON_CHECK],[
|
||||
# we only support certain bison versions
|
||||
bison_version_list="2.4 2.4.1 2.4.2 2.4.3 2.5 2.5.1 2.6 2.6.1 2.6.2 2.6.3 2.6.4 2.6.5 2.7"
|
||||
# we only support certain bison versions;
|
||||
# min: 2.4 (i.e. 204, major * 100 + minor for easier comparison)
|
||||
bison_version_min="204"
|
||||
# non-working versions, e.g. "3.0 3.2";
|
||||
# remove "none" when introducing the first incompatible bison version an
|
||||
# separate any following additions by spaces
|
||||
bison_version_exclude="3.0"
|
||||
|
||||
# for standalone build of Zend Engine
|
||||
test -z "$SED" && SED=sed
|
||||
@@ -17,18 +22,22 @@ AC_DEFUN([LIBZEND_BISON_CHECK],[
|
||||
if test -n "$bison_version_vars"; then
|
||||
set $bison_version_vars
|
||||
bison_version="${1}.${2}"
|
||||
for bison_check_version in $bison_version_list; do
|
||||
if test "$bison_version" = "$bison_check_version"; then
|
||||
php_cv_bison_version="$bison_check_version (ok)"
|
||||
break
|
||||
fi
|
||||
done
|
||||
bison_version_num="`expr ${1} \* 100 + ${2}`"
|
||||
if test $bison_version_num -ge $bison_version_min; then
|
||||
php_cv_bison_version="$bison_version (ok)"
|
||||
for bison_check_version in $bison_version_exclude; do
|
||||
if test "$bison_version" = "$bison_check_version"; then
|
||||
php_cv_bison_version=invalid
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
])
|
||||
fi
|
||||
case $php_cv_bison_version in
|
||||
""|invalid[)]
|
||||
bison_msg="bison versions supported for regeneration of the Zend/PHP parsers: $bison_version_list (found: $bison_version)."
|
||||
bison_msg="This bison version is not supported for regeneration of the Zend/PHP parsers (found: $bison_version, min: $bison_version_min, excluded: $bison_version_exclude)."
|
||||
AC_MSG_WARN([$bison_msg])
|
||||
YACC="exit 0;"
|
||||
;;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Bug #30820 (static member conflict with $this->member silently ignored)
|
||||
--INI--
|
||||
error_reporting=4095
|
||||
opcache.optimization_level=0
|
||||
--FILE--
|
||||
<?php
|
||||
class Blah {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
--TEST--
|
||||
Fixed Bug #65784 (Segfault with finally)
|
||||
--XFAIL--
|
||||
This bug is not fixed in 5.5 due to ABI BC
|
||||
--FILE--
|
||||
<?php
|
||||
function foo1() {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
Bug #66252 (Problems in AST evaluation invalidating valid parent:: reference)
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
const HW = "this is A";
|
||||
}
|
||||
class B extends A {
|
||||
const BHW = parent::HW . " extended by B";
|
||||
}
|
||||
const C = B::BHW;
|
||||
echo C, "\n";
|
||||
--EXPECT--
|
||||
this is A extended by B
|
||||
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
Class Property Expressions
|
||||
--FILE--
|
||||
<?php
|
||||
class Foo {
|
||||
const BAR = 1 << 0;
|
||||
const BAZ = 1 << 1;
|
||||
public $bar = self::BAR | self::BAZ;
|
||||
}
|
||||
echo (new Foo)->bar;
|
||||
?>
|
||||
--EXPECTF--
|
||||
3
|
||||
@@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
Static Class Property Expressions
|
||||
--FILE--
|
||||
<?php
|
||||
class Foo {
|
||||
public $b1 = 1 + 1;
|
||||
public $b2 = 1 << 2;
|
||||
public $b3 = "foo " . " bar " . " baz";
|
||||
}
|
||||
$f = new Foo;
|
||||
var_dump(
|
||||
$f->b1,
|
||||
$f->b2,
|
||||
$f->b3
|
||||
);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
int(4)
|
||||
string(13) "foo bar baz"
|
||||
@@ -21,8 +21,11 @@ var_dump($x = $test->test($y));
|
||||
var_dump($y, $x);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
Notice: Only variable references should be returned by reference in %sclosure_018.php on line 7
|
||||
int(4)
|
||||
|
||||
Notice: Only variable references should be returned by reference in %sclosure_018.php on line 7
|
||||
int(16)
|
||||
int(16)
|
||||
int(16)
|
||||
|
||||
@@ -20,7 +20,10 @@ test();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Notice: Only variable references should be returned by reference in %sclosure_019.php on line 4
|
||||
int(9)
|
||||
|
||||
Notice: Only variable references should be returned by reference in %sclosure_019.php on line 4
|
||||
int(81)
|
||||
|
||||
Fatal error: Cannot pass parameter 1 by reference in %s on line %d
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
--TEST--
|
||||
Constant Expressions
|
||||
--FILE--
|
||||
<?php
|
||||
const T_1 = 1 << 1;
|
||||
const T_2 = 1 / 2;
|
||||
const T_3 = 1.5 + 1.5;
|
||||
const T_4 = "foo" . "bar";
|
||||
const T_5 = (1.5 + 1.5) * 2;
|
||||
const T_6 = "foo" . 2 . 3 . 4.0;
|
||||
const T_7 = __LINE__;
|
||||
const T_8 = <<<ENDOFSTRING
|
||||
This is a test string
|
||||
ENDOFSTRING;
|
||||
const T_9 = ~-1;
|
||||
const T_10 = (-1?:1) + (0?2:3);
|
||||
const T_11 = 1 && 0;
|
||||
const T_12 = 1 and 1;
|
||||
const T_13 = 0 || 0;
|
||||
const T_14 = 1 or 0;
|
||||
const T_15 = 1 xor 1;
|
||||
const T_16 = 1 xor 0;
|
||||
const T_17 = 1 < 0;
|
||||
const T_18 = 0 <= 0;
|
||||
const T_19 = 1 > 0;
|
||||
const T_20 = 1 >= 0;
|
||||
const T_21 = 1 === 1;
|
||||
const T_22 = 1 !== 1;
|
||||
const T_23 = 0 != "0";
|
||||
const T_24 = 1 == "1";
|
||||
|
||||
// Test order of operations
|
||||
const T_25 = 1 + 2 * 3;
|
||||
|
||||
// Test for memory leaks
|
||||
const T_26 = "1" + 2 + "3";
|
||||
|
||||
var_dump(T_1);
|
||||
var_dump(T_2);
|
||||
var_dump(T_3);
|
||||
var_dump(T_4);
|
||||
var_dump(T_5);
|
||||
var_dump(T_6);
|
||||
var_dump(T_7);
|
||||
var_dump(T_8);
|
||||
var_dump(T_9);
|
||||
var_dump(T_10);
|
||||
var_dump(T_11);
|
||||
var_dump(T_12);
|
||||
var_dump(T_13);
|
||||
var_dump(T_14);
|
||||
var_dump(T_15);
|
||||
var_dump(T_16);
|
||||
var_dump(T_17);
|
||||
var_dump(T_18);
|
||||
var_dump(T_19);
|
||||
var_dump(T_20);
|
||||
var_dump(T_21);
|
||||
var_dump(T_22);
|
||||
var_dump(T_23);
|
||||
var_dump(T_24);
|
||||
var_dump(T_25);
|
||||
var_dump(T_26);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
float(0.5)
|
||||
float(3)
|
||||
string(6) "foobar"
|
||||
float(6)
|
||||
string(6) "foo234"
|
||||
int(8)
|
||||
string(21) "This is a test string"
|
||||
int(0)
|
||||
int(2)
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(true)
|
||||
int(7)
|
||||
int(6)
|
||||
@@ -0,0 +1,43 @@
|
||||
--TEST--
|
||||
Constant scalar expressions with autoloading and classes
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.optimization_level=-1
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded('Zend OPcache') || php_sapi_name() != "cli") die("skip CLI only"); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
# This test validates that autoloading works for common const expression (AST) use cases
|
||||
$classlist = [
|
||||
'A'=> 'class A { const HW = "this is A"; }',
|
||||
'B'=> 'class B extends A { const HW = parent::HW." extended by B"; }',
|
||||
'space1\C' => 'namespace space1; class C { const HW = "this is space1\C"; }',
|
||||
'D' => 'class D { const HW = \space1\C::HW." extented by D"; }',
|
||||
'trE' => 'trait trE { public static function getHW() { return parent::HW; } }',
|
||||
'E' => 'class E extends B { use trE; }',
|
||||
'F' => 'class F { const XX = "this is F"; }',
|
||||
'G' => 'class G extends F { const XX = parent::XX." extended by G"; public static function get_me($x = "got ".self::XX) { return $x; } }',
|
||||
];
|
||||
|
||||
spl_autoload_register(function ($class) use ($classlist) {
|
||||
if (isset($classlist[$class])) {
|
||||
eval($classlist[$class]);
|
||||
} else {
|
||||
die("Cannot autoload $class\n");
|
||||
}
|
||||
});
|
||||
|
||||
printf("B::HW = %s\n", B::HW);
|
||||
printf("D::HW = %s\n", D::HW);
|
||||
|
||||
printf("E::getHW() = %s\n", E::getHW());
|
||||
printf("G::get_me() = %s\n", G::get_me());
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
B::HW = this is A extended by B
|
||||
D::HW = this is space1\C extented by D
|
||||
E::getHW() = this is A extended by B
|
||||
G::get_me() = got this is F extended by G
|
||||
@@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
Dynamic Constant Expressions
|
||||
--FILE--
|
||||
<?php
|
||||
const FOO = 1;
|
||||
const BAR = FOO | 2;
|
||||
|
||||
echo BAR;
|
||||
?>
|
||||
--EXPECTF--
|
||||
3
|
||||
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
jmp into a finally block 01
|
||||
--FILE--
|
||||
<?php
|
||||
function foo() {
|
||||
goto test;
|
||||
try {
|
||||
} finally {
|
||||
test:
|
||||
}
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: jump into a finally block is disallowed in %sfinally_goto_001.php on line %d
|
||||
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
jmp into a finally block 02
|
||||
--FILE--
|
||||
<?php
|
||||
function foo() {
|
||||
try {
|
||||
goto test;
|
||||
} finally {
|
||||
test:
|
||||
}
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: jump into a finally block is disallowed in %sfinally_goto_002.php on line %d
|
||||
@@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
jmp into a finally block 03
|
||||
--FILE--
|
||||
<?php
|
||||
function foo() {
|
||||
try {
|
||||
} finally {
|
||||
goto test;
|
||||
test:
|
||||
}
|
||||
}
|
||||
echo "okey";
|
||||
?>
|
||||
--EXPECTF--
|
||||
okey
|
||||
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
jmp into a finally block 03
|
||||
--FILE--
|
||||
<?php
|
||||
function foo() {
|
||||
try {
|
||||
} finally {
|
||||
test:
|
||||
}
|
||||
goto test;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: jump into a finally block is disallowed in %sfinally_goto_004.php on line %d
|
||||
@@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
Function Argument Parsing #003
|
||||
--FILE--
|
||||
<?php
|
||||
const a = 10;
|
||||
|
||||
function t1($a = 1 + 1, $b = 1 << 2, $c = "foo" . "bar", $d = a * 10) {
|
||||
var_dump($a, $b, $c, $d);
|
||||
}
|
||||
|
||||
t1();
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
int(4)
|
||||
string(6) "foobar"
|
||||
int(100)
|
||||
@@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
Incompatible context call (non-internal function)
|
||||
--INI--
|
||||
error_reporting=E_ALL
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
function foo() { var_dump(get_class($this)); }
|
||||
}
|
||||
class B {
|
||||
function bar() { A::foo(); }
|
||||
}
|
||||
$b = new B;
|
||||
$b->bar();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Deprecated: Non-static method A::foo() should not be called statically, assuming $this from incompatible context in %s on line %d
|
||||
string(1) "B"
|
||||
@@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
Static Variable Expressions
|
||||
--FILE--
|
||||
<?php
|
||||
const bar = 2, baz = bar + 1;
|
||||
|
||||
function foo() {
|
||||
static $a = 1 + 1;
|
||||
static $b = [bar => 1 + 1, baz * 2 => 1 << 2];
|
||||
static $c = [1 => bar, 3 => baz];
|
||||
var_dump($a, $b, $c);
|
||||
}
|
||||
|
||||
foo();
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
array(2) {
|
||||
[2]=>
|
||||
int(2)
|
||||
[6]=>
|
||||
int(4)
|
||||
}
|
||||
array(2) {
|
||||
[1]=>
|
||||
int(2)
|
||||
[3]=>
|
||||
int(3)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
aliasing imported constants to resolve naming conflicts
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace foo {
|
||||
const baz = 42;
|
||||
}
|
||||
|
||||
namespace bar {
|
||||
const baz = 43;
|
||||
}
|
||||
|
||||
namespace {
|
||||
use const foo\baz as foo_baz,
|
||||
bar\baz as bar_baz;
|
||||
var_dump(foo_baz);
|
||||
var_dump(bar_baz);
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(42)
|
||||
int(43)
|
||||
Done
|
||||
@@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
import namespaced constant
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace foo\bar {
|
||||
const baz = 42;
|
||||
const qux = 43;
|
||||
}
|
||||
|
||||
namespace {
|
||||
use const foo\bar\baz, foo\bar\qux;
|
||||
var_dump(baz);
|
||||
var_dump(qux);
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(42)
|
||||
int(43)
|
||||
Done
|
||||
@@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
importing const with same name but different case
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
use const foo\bar;
|
||||
use const foo\BAR;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
@@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
use const statements with conflicting names
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace foo {
|
||||
const baz = 42;
|
||||
}
|
||||
|
||||
namespace bar {
|
||||
const baz = 42;
|
||||
}
|
||||
|
||||
namespace {
|
||||
use const foo\baz, bar\baz;
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot use const bar\baz as baz because the name is already in use in %s on line %d
|
||||
@@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
use and use const with the same alias
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
const foo = 'foo';
|
||||
}
|
||||
|
||||
namespace x {
|
||||
use foo as bar;
|
||||
use const foo as bar;
|
||||
var_dump(bar);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(3) "foo"
|
||||
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
defining const with same name as imported should fail
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
use const foo\bar;
|
||||
|
||||
const bar = 42;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot declare const bar because the name is already in use in %s on line %d
|
||||
@@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
using const with same name as defined should fail
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
const bar = 42;
|
||||
|
||||
use const foo\bar;
|
||||
}
|
||||
|
||||
namespace {
|
||||
echo "Done";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot use const foo\bar as bar because the name is already in use in %s on line %d
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace foo;
|
||||
|
||||
const bar = 'local bar';
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace foo;
|
||||
|
||||
const PHP_VERSION = 42;
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
const bar = 'global bar';
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
const baz = NULL;
|
||||
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
non-existent imported constants should not be looked up in the global table
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require 'includes/global_baz.php';
|
||||
|
||||
use const foo\bar\baz;
|
||||
var_dump(baz);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Notice: Use of undefined constant baz - assumed 'baz' in %s on line %d
|
||||
string(3) "baz"
|
||||
@@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
Allow self and parent in use const statement
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
use const self as foo;
|
||||
use const parent as bar;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
shadowing a global core constant with a local version
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require 'includes/foo_php_version.php';
|
||||
|
||||
use const foo\PHP_VERSION;
|
||||
|
||||
var_dump(PHP_VERSION);
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
int(42)
|
||||
Done
|
||||
@@ -0,0 +1,25 @@
|
||||
--TEST--
|
||||
shadowing a global constant with a local version
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
require 'includes/global_bar.php';
|
||||
require 'includes/foo_bar.php';
|
||||
}
|
||||
|
||||
namespace {
|
||||
var_dump(bar);
|
||||
}
|
||||
|
||||
namespace {
|
||||
use const foo\bar;
|
||||
var_dump(bar);
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(10) "global bar"
|
||||
string(9) "local bar"
|
||||
Done
|
||||
@@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
aliasing imported functions to resolve naming conflicts
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace foo {
|
||||
function baz() {
|
||||
return 'foo.baz';
|
||||
}
|
||||
}
|
||||
|
||||
namespace bar {
|
||||
function baz() {
|
||||
return 'bar.baz';
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
use function foo\baz as foo_baz,
|
||||
bar\baz as bar_baz;
|
||||
var_dump(foo_baz());
|
||||
var_dump(bar_baz());
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(7) "foo.baz"
|
||||
string(7) "bar.baz"
|
||||
Done
|
||||
@@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
import namespaced function
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace foo\bar {
|
||||
function baz() {
|
||||
return 'foo.bar.baz';
|
||||
}
|
||||
function qux() {
|
||||
return baz();
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
use function foo\bar\baz, foo\bar\qux;
|
||||
var_dump(baz());
|
||||
var_dump(qux());
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(11) "foo.bar.baz"
|
||||
string(11) "foo.bar.baz"
|
||||
Done
|
||||
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
importing function with same name but different case should fail
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
use function foo\bar;
|
||||
use function foo\BAR;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot use function foo\BAR as BAR because the name is already in use in %s on line %d
|
||||
@@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
function that is conditionally defined at runtime should not cause compiler error
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
if (0) {
|
||||
function foo() {
|
||||
}
|
||||
}
|
||||
|
||||
use function bar\foo;
|
||||
|
||||
echo "Done";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
||||
@@ -0,0 +1,25 @@
|
||||
--TEST--
|
||||
use function statements with conflicting names
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace foo {
|
||||
function baz() {
|
||||
return 'foo.baz';
|
||||
}
|
||||
}
|
||||
|
||||
namespace bar {
|
||||
function baz() {
|
||||
return 'bar.baz';
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
use function foo\baz, bar\baz;
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot use function bar\baz as baz because the name is already in use in %s on line %d
|
||||
@@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
use and use function with the same alias
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
function foo() {
|
||||
return 'foo';
|
||||
}
|
||||
}
|
||||
|
||||
namespace x {
|
||||
use foo as bar;
|
||||
use function foo as bar;
|
||||
var_dump(bar());
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(3) "foo"
|
||||
@@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
use const and use function with the same alias
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
const foo = 'foo.const';
|
||||
function foo() {
|
||||
return 'foo.function';
|
||||
}
|
||||
}
|
||||
|
||||
namespace x {
|
||||
use const foo as bar;
|
||||
use function foo as bar;
|
||||
var_dump(bar);
|
||||
var_dump(bar());
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(9) "foo.const"
|
||||
string(12) "foo.function"
|
||||
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
defining function with same name as imported should fail
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
use function foo\bar;
|
||||
|
||||
function bar() {}
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot declare function bar because the name is already in use in %s on line %d
|
||||
@@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
using function with same name as defined should fail
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
function bar() {}
|
||||
|
||||
use function foo\bar;
|
||||
}
|
||||
|
||||
namespace {
|
||||
echo "Done";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot use function foo\bar as bar because the name is already in use in %s on line %d
|
||||
@@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
use function should ignore namespaced constants
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace foo {
|
||||
const bar = 42;
|
||||
}
|
||||
|
||||
namespace {
|
||||
const bar = 43;
|
||||
}
|
||||
|
||||
namespace {
|
||||
use function foo\bar;
|
||||
var_dump(bar);
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(43)
|
||||
Done
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace foo;
|
||||
|
||||
function bar() {
|
||||
return 'local bar';
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace foo;
|
||||
|
||||
function strlen($str) {
|
||||
return 4;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
function bar() {
|
||||
return 'global bar';
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
|
||||
function baz() {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
non-existent imported functions should not be looked up in the global table
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require 'includes/global_baz.php';
|
||||
|
||||
use function foo\bar\baz;
|
||||
var_dump(baz());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Call to undefined function foo\bar\baz() in %s on line %d
|
||||
@@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
non-existent imported functions should not be looked up in the global table
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
function test() {
|
||||
echo "NO!";
|
||||
}
|
||||
}
|
||||
namespace foo {
|
||||
use function bar\test;
|
||||
test();
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Call to undefined function bar\test() in %s on line %d
|
||||
@@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
Allow self and parent in use function statement
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
use function self as foo;
|
||||
use function parent as bar;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
shadowing a global core function with a local version
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require 'includes/foo_strlen.php';
|
||||
|
||||
use function foo\strlen;
|
||||
|
||||
var_dump(strlen('foo bar baz'));
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(4)
|
||||
Done
|
||||
@@ -0,0 +1,25 @@
|
||||
--TEST--
|
||||
shadowing a global function with a local version
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
require 'includes/global_bar.php';
|
||||
require 'includes/foo_bar.php';
|
||||
}
|
||||
|
||||
namespace {
|
||||
var_dump(bar());
|
||||
}
|
||||
|
||||
namespace {
|
||||
use function foo\bar;
|
||||
var_dump(bar());
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(10) "global bar"
|
||||
string(9) "local bar"
|
||||
Done
|
||||
@@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
It's possible to add additional optional arguments with matching signature
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface DB {
|
||||
public function query($query, string ...$params);
|
||||
}
|
||||
|
||||
class MySQL implements DB {
|
||||
public function query($query, string $extraParam = null, string ...$params) { }
|
||||
}
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECT--
|
||||
===DONE===
|
||||
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Additional optional parameters must have a matching prototype
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface DB {
|
||||
public function query($query, string ...$params);
|
||||
}
|
||||
|
||||
class MySQL implements DB {
|
||||
public function query($query, int $extraParam = null, string ...$params) { }
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Declaration of MySQL::query() must be compatible with DB::query($query, string ...$params) in %s on line %d
|
||||
@@ -0,0 +1,57 @@
|
||||
--TEST--
|
||||
Basic variadic function
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test1(... $args) {
|
||||
var_dump($args);
|
||||
}
|
||||
|
||||
test1();
|
||||
test1(1);
|
||||
test1(1, 2, 3);
|
||||
|
||||
function test2($arg1, $arg2, ...$args) {
|
||||
var_dump($arg1, $arg2, $args);
|
||||
}
|
||||
|
||||
test2(1, 2);
|
||||
test2(1, 2, 3);
|
||||
test2(1, 2, 3, 4, 5);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(0) {
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(1)
|
||||
}
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
int(1)
|
||||
int(2)
|
||||
array(0) {
|
||||
}
|
||||
int(1)
|
||||
int(2)
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(3)
|
||||
}
|
||||
int(1)
|
||||
int(2)
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(3)
|
||||
[1]=>
|
||||
int(4)
|
||||
[2]=>
|
||||
int(5)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
Variadic arguments with by-reference passing
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(&... $args) {
|
||||
$i = 0;
|
||||
foreach ($args as &$arg) {
|
||||
$arg = $i++;
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
||||
test($a);
|
||||
var_dump($a);
|
||||
test($b, $c, $d);
|
||||
var_dump($b, $c, $d);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(0)
|
||||
int(0)
|
||||
int(1)
|
||||
int(2)
|
||||
@@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
By-ref variadics enforce the reference
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(&... $args) { }
|
||||
|
||||
test(1);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Only variables can be passed by reference in %s on line %d
|
||||
@@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Variadic argument cannot have a default value
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(...$args = 123) {}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Variadic parameter cannot have a default value in %s on line %d
|
||||
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
It's not possible to turn a variadic function into a non-variadic one
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface DB {
|
||||
public function query($query, ...$params);
|
||||
}
|
||||
|
||||
class MySQL implements DB {
|
||||
public function query($query, $params) { }
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Declaration of MySQL::query() must be compatible with DB::query($query, ...$params) in %s on line %d
|
||||
@@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Only the last argument can be variadic
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test($foo, ...$bar, $baz) {}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Only the last parameter can be variadic in %s on line %d
|
||||
@@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
Optional parameter before variadic parameter
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function fn($reqParam, $optParam = null, ...$params) {
|
||||
var_dump($reqParam, $optParam, $params);
|
||||
}
|
||||
|
||||
fn(1);
|
||||
fn(1, 2);
|
||||
fn(1, 2, 3);
|
||||
fn(1, 2, 3, 4);
|
||||
fn(1, 2, 3, 4, 5);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(1)
|
||||
NULL
|
||||
array(0) {
|
||||
}
|
||||
int(1)
|
||||
int(2)
|
||||
array(0) {
|
||||
}
|
||||
int(1)
|
||||
int(2)
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(3)
|
||||
}
|
||||
int(1)
|
||||
int(2)
|
||||
array(2) {
|
||||
[0]=>
|
||||
int(3)
|
||||
[1]=>
|
||||
int(4)
|
||||
}
|
||||
int(1)
|
||||
int(2)
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(3)
|
||||
[1]=>
|
||||
int(4)
|
||||
[2]=>
|
||||
int(5)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
It's not possible to remove required parameter before a variadic parameter
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/* Theoretically this should be valid because it weakens the constraint, but
|
||||
* PHP does not allow this (for non-variadics), so I'm not allowing it here, too,
|
||||
* to stay consistent. */
|
||||
|
||||
interface DB {
|
||||
public function query($query, ...$params);
|
||||
}
|
||||
|
||||
class MySQL implements DB {
|
||||
public function query(...$params) { }
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Declaration of MySQL::query() must be compatible with DB::query($query, ...$params) in %s on line %d
|
||||
@@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
Variadic arguments enforce typehints
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(array... $args) {
|
||||
var_dump($args);
|
||||
}
|
||||
|
||||
test();
|
||||
test([0], [1], [2]);
|
||||
test([0], [1], 2);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(0) {
|
||||
}
|
||||
array(3) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(0)
|
||||
}
|
||||
[1]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(1)
|
||||
}
|
||||
[2]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(2)
|
||||
}
|
||||
}
|
||||
|
||||
Catchable fatal error: Argument 3 passed to test() must be of the type array, integer given, called in %s on line %d
|
||||
@@ -0,0 +1,33 @@
|
||||
--TEST--
|
||||
Error suppression for typehints on variadic arguments works
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(array... $args) {
|
||||
var_dump($args);
|
||||
}
|
||||
|
||||
set_error_handler(function($errno, $errstr) {
|
||||
var_dump($errstr);
|
||||
return true;
|
||||
});
|
||||
|
||||
test([0], [1], 2);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(%d) "Argument 3 passed to test() must be of the type array, integer given, called in %s on line %d and defined"
|
||||
array(3) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(0)
|
||||
}
|
||||
[1]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(1)
|
||||
}
|
||||
[2]=>
|
||||
int(2)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Variadic arguments must have compatible passing modes
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface DB {
|
||||
public function query($query, &...$params);
|
||||
}
|
||||
|
||||
class MySQL implements DB {
|
||||
public function query($query, ...$params) { }
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Declaration of MySQL::query() must be compatible with DB::query($query, &...$params) in %s on line %d
|
||||
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Typehints for variadic arguments have to be compatible
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface DB {
|
||||
public function query($query, string ...$params);
|
||||
}
|
||||
|
||||
class MySQL implements DB {
|
||||
public function query($query, int ...$params) { }
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Declaration of MySQL::query() must be compatible with DB::query($query, string ...$params) in %s on line %d
|
||||
@@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
A non-variadic function can be turned into a variadic one
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface DB {
|
||||
public function query($query);
|
||||
}
|
||||
|
||||
class MySQL implements DB {
|
||||
public function query($query, ...$params) { }
|
||||
}
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECT--
|
||||
===DONE===
|
||||
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
Zend signed multiply 32-bit
|
||||
--SKIPIF--
|
||||
<?php if ((1 << 31) > 0) print "skip Running on 64-bit target"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(0x8000 * -0xffff);
|
||||
var_dump(0x8001 * 0xfffe);
|
||||
var_dump(0x8001 * -0xffff);
|
||||
?>
|
||||
--EXPECTF--
|
||||
int(-2147450880)
|
||||
int(2147483646)
|
||||
float(-2147516415)
|
||||
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
Zend signed multiply 64-bit
|
||||
--SKIPIF--
|
||||
<?php if ((1 << 31) < 0) print "skip Running on 32-bit target"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(0x80000000 * -0xffffffff);
|
||||
var_dump(0x80000001 * 0xfffffffe);
|
||||
var_dump(0x80000001 * -0xffffffff);
|
||||
?>
|
||||
--EXPECTF--
|
||||
int(-9223372034707292160)
|
||||
int(9223372036854775806)
|
||||
float(-9.2233720390023E+18)
|
||||
+16
-2
@@ -30,6 +30,7 @@
|
||||
#include "zend_ini.h"
|
||||
#include "zend_vm.h"
|
||||
#include "zend_dtrace.h"
|
||||
#include "zend_virtual_cwd.h"
|
||||
|
||||
#ifdef ZTS
|
||||
# define GLOBAL_FUNCTION_TABLE global_function_table
|
||||
@@ -652,6 +653,8 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
|
||||
|
||||
start_memory_manager(TSRMLS_C);
|
||||
|
||||
virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
/* FreeBSD and DragonFly floating point precision fix */
|
||||
fpsetmask(0);
|
||||
@@ -802,9 +805,14 @@ void zend_post_startup(TSRMLS_D) /* {{{ */
|
||||
compiler_globals_ctor(compiler_globals, tsrm_ls);
|
||||
}
|
||||
free(EG(zend_constants));
|
||||
|
||||
virtual_cwd_deactivate(TSRMLS_C);
|
||||
|
||||
executor_globals_ctor(executor_globals, tsrm_ls);
|
||||
global_persistent_list = &EG(persistent_list);
|
||||
zend_copy_ini_directives(TSRMLS_C);
|
||||
#else
|
||||
virtual_cwd_deactivate(TSRMLS_C);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
@@ -820,6 +828,9 @@ void zend_shutdown(TSRMLS_D) /* {{{ */
|
||||
zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
|
||||
zend_destroy_modules();
|
||||
|
||||
virtual_cwd_deactivate(TSRMLS_C);
|
||||
virtual_cwd_shutdown();
|
||||
|
||||
zend_hash_destroy(GLOBAL_FUNCTION_TABLE);
|
||||
zend_hash_destroy(GLOBAL_CLASS_TABLE);
|
||||
|
||||
@@ -908,8 +919,11 @@ ZEND_API char *get_zend_version(void) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_activate(TSRMLS_D) /* {{{ */
|
||||
ZEND_API void zend_activate(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
#ifdef ZTS
|
||||
virtual_cwd_activate(TSRMLS_C);
|
||||
#endif
|
||||
gc_reset(TSRMLS_C);
|
||||
init_compiler(TSRMLS_C);
|
||||
init_executor(TSRMLS_C);
|
||||
@@ -925,7 +939,7 @@ void zend_call_destructors(TSRMLS_D) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_deactivate(TSRMLS_D) /* {{{ */
|
||||
ZEND_API void zend_deactivate(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
/* we're no longer executing anything */
|
||||
EG(opline_ptr) = NULL;
|
||||
|
||||
+19
-12
@@ -22,7 +22,7 @@
|
||||
#ifndef ZEND_H
|
||||
#define ZEND_H
|
||||
|
||||
#define ZEND_VERSION "2.5.0"
|
||||
#define ZEND_VERSION "2.6.0-dev"
|
||||
|
||||
#define ZEND_ENGINE_2
|
||||
|
||||
@@ -193,7 +193,7 @@ char *alloca ();
|
||||
#endif
|
||||
#define restrict __restrict__
|
||||
|
||||
#if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2)) && !(defined(ZTS) && defined(ZEND_WIN32)) && !(defined(ZTS) && defined(NETWARE)) && !(defined(ZTS) && defined(HPUX)) && !defined(DARWIN)
|
||||
#if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2)) && !(defined(ZTS) && defined(NETWARE)) && !(defined(ZTS) && defined(HPUX)) && !defined(DARWIN)
|
||||
# define ZEND_ALLOCA_MAX_SIZE (32 * 1024)
|
||||
# define ALLOCA_FLAG(name) \
|
||||
zend_bool name;
|
||||
@@ -317,6 +317,7 @@ typedef struct _zend_object {
|
||||
} zend_object;
|
||||
|
||||
#include "zend_object_handlers.h"
|
||||
#include "zend_ast.h"
|
||||
|
||||
typedef union _zvalue_value {
|
||||
long lval; /* long value */
|
||||
@@ -327,6 +328,7 @@ typedef union _zvalue_value {
|
||||
} str;
|
||||
HashTable *ht; /* hash table value */
|
||||
zend_object_value obj;
|
||||
zend_ast *ast;
|
||||
} zvalue_value;
|
||||
|
||||
struct _zval_struct {
|
||||
@@ -587,7 +589,8 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
|
||||
#define IS_RESOURCE 7
|
||||
#define IS_CONSTANT 8
|
||||
#define IS_CONSTANT_ARRAY 9
|
||||
#define IS_CALLABLE 10
|
||||
#define IS_CONSTANT_AST 10
|
||||
#define IS_CALLABLE 11
|
||||
|
||||
/* Ugly hack to support constants as static array indices */
|
||||
#define IS_CONSTANT_TYPE_MASK 0x00f
|
||||
@@ -597,6 +600,8 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
|
||||
#define IS_LEXICAL_REF 0x040
|
||||
#define IS_CONSTANT_IN_NAMESPACE 0x100
|
||||
|
||||
#define IS_CONSTANT_TYPE(type) (((type) & IS_CONSTANT_TYPE_MASK) >= IS_CONSTANT && ((type) & IS_CONSTANT_TYPE_MASK) <= IS_CONSTANT_AST)
|
||||
|
||||
/* overloaded elements data types */
|
||||
#define OE_IS_ARRAY (1<<0)
|
||||
#define OE_IS_OBJECT (1<<1)
|
||||
@@ -651,12 +656,14 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int
|
||||
ZEND_API void zend_output_debug_string(zend_bool trigger_break, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
|
||||
END_EXTERN_C()
|
||||
|
||||
void zend_activate(TSRMLS_D);
|
||||
void zend_deactivate(TSRMLS_D);
|
||||
void zend_call_destructors(TSRMLS_D);
|
||||
void zend_activate_modules(TSRMLS_D);
|
||||
void zend_deactivate_modules(TSRMLS_D);
|
||||
void zend_post_deactivate_modules(TSRMLS_D);
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API void zend_activate(TSRMLS_D);
|
||||
ZEND_API void zend_deactivate(TSRMLS_D);
|
||||
ZEND_API void zend_call_destructors(TSRMLS_D);
|
||||
ZEND_API void zend_activate_modules(TSRMLS_D);
|
||||
ZEND_API void zend_deactivate_modules(TSRMLS_D);
|
||||
ZEND_API void zend_post_deactivate_modules(TSRMLS_D);
|
||||
END_EXTERN_C()
|
||||
|
||||
#if ZEND_DEBUG
|
||||
#define Z_DBG(expr) (expr)
|
||||
@@ -670,8 +677,8 @@ END_EXTERN_C()
|
||||
|
||||
/* FIXME: Check if we can save if (ptr) too */
|
||||
|
||||
#define STR_FREE(ptr) if (ptr && !IS_INTERNED(ptr)) { efree(ptr); }
|
||||
#define STR_FREE_REL(ptr) if (ptr && !IS_INTERNED(ptr)) { efree_rel(ptr); }
|
||||
#define STR_FREE(ptr) if (ptr) { str_efree(ptr); }
|
||||
#define STR_FREE_REL(ptr) if (ptr) { str_efree_rel(ptr); }
|
||||
|
||||
#define STR_EMPTY_ALLOC() estrndup("", sizeof("")-1)
|
||||
|
||||
@@ -683,7 +690,7 @@ END_EXTERN_C()
|
||||
#define ZEND_WRITE_EX(str, str_len) write_func((str), (str_len))
|
||||
#define ZEND_PUTS(str) zend_write((str), strlen((str)))
|
||||
#define ZEND_PUTS_EX(str) write_func((str), strlen((str)))
|
||||
#define ZEND_PUTC(c) zend_write(&(c), 1), (c)
|
||||
#define ZEND_PUTC(c) zend_write(&(c), 1)
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
extern ZEND_API int (*zend_printf)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
|
||||
|
||||
+29
-26
@@ -1010,7 +1010,7 @@ ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) /* {{{ */
|
||||
{
|
||||
ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg));
|
||||
|
||||
_zend_hash_init(Z_ARRVAL_P(arg), size, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
|
||||
_zend_hash_init(Z_ARRVAL_P(arg), size, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
|
||||
Z_TYPE_P(arg) = IS_ARRAY;
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -1053,8 +1053,7 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro
|
||||
|
||||
static int zval_update_class_constant(zval **pp, int is_static, int offset TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if ((Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
|
||||
(Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT_ARRAY) {
|
||||
if (IS_CONSTANT_TYPE(Z_TYPE_PP(pp))) {
|
||||
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
|
||||
|
||||
if ((*scope)->parent) {
|
||||
@@ -1078,7 +1077,7 @@ static int zval_update_class_constant(zval **pp, int is_static, int offset TSRML
|
||||
}
|
||||
ce = ce->parent;
|
||||
} while (ce);
|
||||
|
||||
|
||||
}
|
||||
return zval_update_constant(pp, (void*)1 TSRMLS_CC);
|
||||
}
|
||||
@@ -2029,7 +2028,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
|
||||
const zend_function_entry *ptr = functions;
|
||||
zend_function function, *reg_function;
|
||||
zend_internal_function *internal_function = (zend_internal_function *)&function;
|
||||
int count=0, unload=0, result=0;
|
||||
int count=0, unload=0;
|
||||
HashTable *target_function_table = function_table;
|
||||
int error_type;
|
||||
zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL;
|
||||
@@ -2037,6 +2036,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
|
||||
int fname_len;
|
||||
const char *lc_class_name = NULL;
|
||||
int class_name_len = 0;
|
||||
zend_ulong hash;
|
||||
|
||||
if (type==MODULE_PERSISTENT) {
|
||||
error_type = E_CORE_WARNING;
|
||||
@@ -2089,16 +2089,12 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
|
||||
} else {
|
||||
internal_function->required_num_args = info->required_num_args;
|
||||
}
|
||||
if (info->pass_rest_by_reference) {
|
||||
if (info->pass_rest_by_reference == ZEND_SEND_PREFER_REF) {
|
||||
internal_function->fn_flags |= ZEND_ACC_PASS_REST_PREFER_REF;
|
||||
} else {
|
||||
internal_function->fn_flags |= ZEND_ACC_PASS_REST_BY_REFERENCE;
|
||||
}
|
||||
}
|
||||
if (info->return_reference) {
|
||||
internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
|
||||
}
|
||||
if (ptr->arg_info[ptr->num_args].is_variadic) {
|
||||
internal_function->fn_flags |= ZEND_ACC_VARIADIC;
|
||||
}
|
||||
} else {
|
||||
internal_function->arg_info = NULL;
|
||||
internal_function->num_args = 0;
|
||||
@@ -2135,16 +2131,25 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
|
||||
}
|
||||
fname_len = strlen(ptr->fname);
|
||||
lowercase_name = zend_new_interned_string(zend_str_tolower_dup(ptr->fname, fname_len), fname_len + 1, 1 TSRMLS_CC);
|
||||
if (IS_INTERNED(lowercase_name)) {
|
||||
result = zend_hash_quick_add(target_function_table, lowercase_name, fname_len+1, INTERNED_HASH(lowercase_name), &function, sizeof(zend_function), (void**)®_function);
|
||||
} else {
|
||||
result = zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)®_function);
|
||||
}
|
||||
if (result == FAILURE) {
|
||||
hash = str_hash(lowercase_name, fname_len);
|
||||
if (zend_hash_quick_add(target_function_table, lowercase_name, fname_len+1, hash, &function, sizeof(zend_function), (void**)®_function) == FAILURE) {
|
||||
unload=1;
|
||||
str_efree(lowercase_name);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If types of arguments have to be checked */
|
||||
if (reg_function->common.arg_info && reg_function->common.num_args) {
|
||||
int i;
|
||||
for (i = 0; i < reg_function->common.num_args; i++) {
|
||||
if (reg_function->common.arg_info[i].class_name ||
|
||||
reg_function->common.arg_info[i].type_hint) {
|
||||
reg_function->common.fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scope) {
|
||||
/* Look for ctor, dtor, clone
|
||||
* If it's an old-style constructor, store it only if we don't have
|
||||
@@ -2388,7 +2393,7 @@ void module_destructor(zend_module_entry *module) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_activate_modules(TSRMLS_D) /* {{{ */
|
||||
ZEND_API void zend_activate_modules(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
zend_module_entry **p = module_request_startup_handlers;
|
||||
|
||||
@@ -2417,7 +2422,7 @@ int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_deactivate_modules(TSRMLS_D) /* {{{ */
|
||||
ZEND_API void zend_deactivate_modules(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
EG(opline_ptr) = NULL; /* we're no longer executing anything */
|
||||
|
||||
@@ -2464,7 +2469,7 @@ static int exec_done_cb(zend_module_entry *module TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_post_deactivate_modules(TSRMLS_D) /* {{{ */
|
||||
ZEND_API void zend_post_deactivate_modules(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
if (EG(full_tables_cleanup)) {
|
||||
zend_hash_apply(&module_registry, (apply_func_t) exec_done_cb TSRMLS_CC);
|
||||
@@ -2493,6 +2498,7 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class
|
||||
{
|
||||
zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
|
||||
char *lowercase_name = emalloc(orig_class_entry->name_length + 1);
|
||||
zend_ulong hash;
|
||||
*class_entry = *orig_class_entry;
|
||||
|
||||
class_entry->type = ZEND_INTERNAL_CLASS;
|
||||
@@ -2506,11 +2512,8 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class
|
||||
|
||||
zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
|
||||
lowercase_name = (char*)zend_new_interned_string(lowercase_name, class_entry->name_length + 1, 1 TSRMLS_CC);
|
||||
if (IS_INTERNED(lowercase_name)) {
|
||||
zend_hash_quick_update(CG(class_table), lowercase_name, class_entry->name_length+1, INTERNED_HASH(lowercase_name), &class_entry, sizeof(zend_class_entry *), NULL);
|
||||
} else {
|
||||
zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL);
|
||||
}
|
||||
hash = str_hash(lowercase_name, class_entry->name_length);
|
||||
zend_hash_quick_update(CG(class_table), lowercase_name, class_entry->name_length+1, hash, &class_entry, sizeof(zend_class_entry *), NULL);
|
||||
str_efree(lowercase_name);
|
||||
return class_entry;
|
||||
}
|
||||
|
||||
+31
-19
@@ -98,16 +98,18 @@ typedef struct _zend_fcall_info_cache {
|
||||
|
||||
#define ZEND_FE_END { NULL, NULL, NULL, 0, 0 }
|
||||
|
||||
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref},
|
||||
#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, NULL, 0, 0, 0, pass_by_ref},
|
||||
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, IS_OBJECT, allow_null, pass_by_ref},
|
||||
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, IS_ARRAY, allow_null, pass_by_ref},
|
||||
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, sizeof(#name)-1, NULL, 0, type_hint, allow_null, pass_by_ref},
|
||||
#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \
|
||||
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, pass_by_ref, 0, 0 },
|
||||
#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, NULL, 0, 0, pass_by_ref, 0, 0 },
|
||||
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, IS_OBJECT, pass_by_ref, allow_null, 0 },
|
||||
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, IS_ARRAY, pass_by_ref, allow_null, 0 },
|
||||
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, sizeof(#name)-1, NULL, 0, type_hint, pass_by_ref, allow_null, 0 },
|
||||
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, pass_by_ref, 0, 1 },
|
||||
|
||||
#define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \
|
||||
static const zend_arg_info name[] = { \
|
||||
{ NULL, 0, NULL, required_num_args, 0, return_reference, pass_rest_by_reference},
|
||||
#define ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference) \
|
||||
ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, ZEND_RETURN_VALUE, -1)
|
||||
{ NULL, 0, NULL, required_num_args, 0, return_reference, 0, 0 },
|
||||
#define ZEND_BEGIN_ARG_INFO(name, _unused) \
|
||||
ZEND_BEGIN_ARG_INFO_EX(name, 0, ZEND_RETURN_VALUE, -1)
|
||||
#define ZEND_END_ARG_INFO() };
|
||||
|
||||
/* Name macros */
|
||||
@@ -594,22 +596,20 @@ END_EXTERN_C()
|
||||
Z_TYPE_P(__z) = IS_STRING; \
|
||||
} while (0)
|
||||
|
||||
#define ZVAL_ZVAL(z, zv, copy, dtor) { \
|
||||
zend_uchar is_ref = Z_ISREF_P(z); \
|
||||
zend_uint refcount = Z_REFCOUNT_P(z); \
|
||||
ZVAL_COPY_VALUE(z, zv); \
|
||||
#define ZVAL_ZVAL(z, zv, copy, dtor) do { \
|
||||
zval *__z = (z); \
|
||||
zval *__zv = (zv); \
|
||||
ZVAL_COPY_VALUE(__z, __zv); \
|
||||
if (copy) { \
|
||||
zval_copy_ctor(z); \
|
||||
zval_copy_ctor(__z); \
|
||||
} \
|
||||
if (dtor) { \
|
||||
if (!copy) { \
|
||||
ZVAL_NULL(zv); \
|
||||
ZVAL_NULL(__zv); \
|
||||
} \
|
||||
zval_ptr_dtor(&zv); \
|
||||
zval_ptr_dtor(&__zv); \
|
||||
} \
|
||||
Z_SET_ISREF_TO_P(z, is_ref); \
|
||||
Z_SET_REFCOUNT_P(z, refcount); \
|
||||
}
|
||||
} while (0)
|
||||
|
||||
#define ZVAL_FALSE(z) ZVAL_BOOL(z, 0)
|
||||
#define ZVAL_TRUE(z) ZVAL_BOOL(z, 1)
|
||||
@@ -638,6 +638,18 @@ END_EXTERN_C()
|
||||
#define RETURN_FALSE { RETVAL_FALSE; return; }
|
||||
#define RETURN_TRUE { RETVAL_TRUE; return; }
|
||||
|
||||
#define RETVAL_ZVAL_FAST(z) do { \
|
||||
zval *_z = (z); \
|
||||
if (Z_ISREF_P(_z)) { \
|
||||
RETVAL_ZVAL(_z, 1, 0); \
|
||||
} else { \
|
||||
zval_ptr_dtor(&return_value); \
|
||||
Z_ADDREF_P(_z); \
|
||||
*return_value_ptr = _z; \
|
||||
} \
|
||||
} while (0)
|
||||
#define RETURN_ZVAL_FAST(z) { RETVAL_ZVAL_FAST(z); return; }
|
||||
|
||||
#define SET_VAR_STRING(n, v) { \
|
||||
{ \
|
||||
zval *var; \
|
||||
|
||||
+329
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.00 of the Zend license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.zend.com/license/2_00.txt. |
|
||||
| If you did not receive a copy of the Zend license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@zend.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Bob Weinand <bwoebi@php.net> |
|
||||
| Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "zend_ast.h"
|
||||
#include "zend_API.h"
|
||||
#include "zend_operators.h"
|
||||
|
||||
ZEND_API zend_ast *zend_ast_create_constant(zval *zv)
|
||||
{
|
||||
zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zval));
|
||||
ast->kind = ZEND_CONST;
|
||||
ast->children = 0;
|
||||
ast->u.val = (zval*)(ast + 1);
|
||||
INIT_PZVAL_COPY(ast->u.val, zv);
|
||||
return ast;
|
||||
}
|
||||
|
||||
ZEND_API zend_ast* zend_ast_create_unary(uint kind, zend_ast *op0)
|
||||
{
|
||||
zend_ast *ast = emalloc(sizeof(zend_ast));
|
||||
ast->kind = kind;
|
||||
ast->children = 1;
|
||||
(&ast->u.child)[0] = op0;
|
||||
return ast;
|
||||
}
|
||||
|
||||
ZEND_API zend_ast* zend_ast_create_binary(uint kind, zend_ast *op0, zend_ast *op1)
|
||||
{
|
||||
zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*));
|
||||
ast->kind = kind;
|
||||
ast->children = 2;
|
||||
(&ast->u.child)[0] = op0;
|
||||
(&ast->u.child)[1] = op1;
|
||||
return ast;
|
||||
}
|
||||
|
||||
ZEND_API zend_ast* zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2)
|
||||
{
|
||||
zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 2);
|
||||
ast->kind = kind;
|
||||
ast->children = 3;
|
||||
(&ast->u.child)[0] = op0;
|
||||
(&ast->u.child)[1] = op1;
|
||||
(&ast->u.child)[2] = op2;
|
||||
return ast;
|
||||
}
|
||||
|
||||
ZEND_API int zend_ast_is_ct_constant(zend_ast *ast)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ast->kind == ZEND_CONST) {
|
||||
return !IS_CONSTANT_TYPE(Z_TYPE_P(ast->u.val));
|
||||
} else {
|
||||
for (i = 0; i < ast->children; i++) {
|
||||
if ((&ast->u.child)[i]) {
|
||||
if (!zend_ast_is_ct_constant((&ast->u.child)[i])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope TSRMLS_DC)
|
||||
{
|
||||
zval op1, op2;
|
||||
|
||||
switch (ast->kind) {
|
||||
case ZEND_ADD:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
add_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_SUB:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
sub_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_MUL:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
mul_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_DIV:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
div_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_MOD:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
mod_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_SL:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
shift_left_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_SR:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
shift_right_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_CONCAT:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
concat_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_BW_OR:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
bitwise_or_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_BW_AND:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
bitwise_and_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_BW_XOR:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
bitwise_xor_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_BW_NOT:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
bitwise_not_function(result, &op1 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
break;
|
||||
case ZEND_BOOL_NOT:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
boolean_not_function(result, &op1 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
break;
|
||||
case ZEND_BOOL_XOR:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
boolean_xor_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_IS_IDENTICAL:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
is_identical_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_IS_NOT_IDENTICAL:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
is_not_identical_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_IS_EQUAL:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
is_equal_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_IS_NOT_EQUAL:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
is_not_equal_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_IS_SMALLER:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
is_smaller_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_IS_SMALLER_OR_EQUAL:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
is_smaller_or_equal_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_CONST:
|
||||
*result = *ast->u.val;
|
||||
zval_copy_ctor(result);
|
||||
if (IS_CONSTANT_TYPE(Z_TYPE_P(result))) {
|
||||
zval_update_constant_ex(&result, (void *) 1, scope TSRMLS_CC);
|
||||
}
|
||||
break;
|
||||
case ZEND_BOOL_AND:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
if (zend_is_true(&op1)) {
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
ZVAL_BOOL(result, zend_is_true(&op2));
|
||||
zval_dtor(&op2);
|
||||
} else {
|
||||
ZVAL_BOOL(result, 0);
|
||||
}
|
||||
zval_dtor(&op1);
|
||||
break;
|
||||
case ZEND_BOOL_OR:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
if (zend_is_true(&op1)) {
|
||||
ZVAL_BOOL(result, 1);
|
||||
} else {
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
ZVAL_BOOL(result, zend_is_true(&op2));
|
||||
zval_dtor(&op2);
|
||||
}
|
||||
zval_dtor(&op1);
|
||||
break;
|
||||
case ZEND_SELECT:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
if (zend_is_true(&op1)) {
|
||||
if (!(&ast->u.child)[1]) {
|
||||
*result = op1;
|
||||
} else {
|
||||
zend_ast_evaluate(result, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
}
|
||||
} else {
|
||||
zend_ast_evaluate(result, (&ast->u.child)[2], scope TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
}
|
||||
break;
|
||||
case ZEND_UNARY_PLUS:
|
||||
ZVAL_LONG(&op1, 0);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
add_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
case ZEND_UNARY_MINUS:
|
||||
ZVAL_LONG(&op1, 0);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
sub_function(result, &op1, &op2 TSRMLS_CC);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
default:
|
||||
zend_error(E_ERROR, "Unsupported constant expression");
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
|
||||
{
|
||||
if (ast == NULL) {
|
||||
return NULL;
|
||||
} else if (ast->kind == ZEND_CONST) {
|
||||
zend_ast *copy = zend_ast_create_constant(ast->u.val);
|
||||
zval_copy_ctor(copy->u.val);
|
||||
return copy;
|
||||
} else {
|
||||
switch (ast->children) {
|
||||
case 1:
|
||||
return zend_ast_create_unary(
|
||||
ast->kind,
|
||||
zend_ast_copy((&ast->u.child)[0]));
|
||||
case 2:
|
||||
return zend_ast_create_binary(
|
||||
ast->kind,
|
||||
zend_ast_copy((&ast->u.child)[0]),
|
||||
zend_ast_copy((&ast->u.child)[1]));
|
||||
case 3:
|
||||
return zend_ast_create_ternary(
|
||||
ast->kind,
|
||||
zend_ast_copy((&ast->u.child)[0]),
|
||||
zend_ast_copy((&ast->u.child)[1]),
|
||||
zend_ast_copy((&ast->u.child)[2]));
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZEND_API void zend_ast_destroy(zend_ast *ast)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ast->kind == ZEND_CONST) {
|
||||
zval_dtor(ast->u.val);
|
||||
} else {
|
||||
for (i = 0; i < ast->children; i++) {
|
||||
if ((&ast->u.child)[i]) {
|
||||
zend_ast_destroy((&ast->u.child)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
efree(ast);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.00 of the Zend license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.zend.com/license/2_00.txt. |
|
||||
| If you did not receive a copy of the Zend license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@zend.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Bob Weinand <bwoebi@php.net> |
|
||||
| Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef ZEND_AST_H
|
||||
#define ZEND_AST_H
|
||||
|
||||
typedef struct _zend_ast zend_ast;
|
||||
|
||||
#include "zend.h"
|
||||
|
||||
typedef enum _zend_ast_kind {
|
||||
/* first 256 kinds are reserved for opcodes */
|
||||
ZEND_CONST = 256,
|
||||
ZEND_BOOL_AND,
|
||||
ZEND_BOOL_OR,
|
||||
ZEND_SELECT,
|
||||
ZEND_UNARY_PLUS,
|
||||
ZEND_UNARY_MINUS,
|
||||
} zend_ast_kind;
|
||||
|
||||
struct _zend_ast {
|
||||
unsigned short kind;
|
||||
unsigned short children;
|
||||
union {
|
||||
zval *val;
|
||||
zend_ast *child;
|
||||
} u;
|
||||
};
|
||||
|
||||
ZEND_API zend_ast *zend_ast_create_constant(zval *zv);
|
||||
|
||||
ZEND_API zend_ast *zend_ast_create_unary(uint kind, zend_ast *op0);
|
||||
ZEND_API zend_ast *zend_ast_create_binary(uint kind, zend_ast *op0, zend_ast *op1);
|
||||
ZEND_API zend_ast *zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2);
|
||||
|
||||
ZEND_API int zend_ast_is_ct_constant(zend_ast *ast);
|
||||
|
||||
ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope TSRMLS_DC);
|
||||
|
||||
ZEND_API zend_ast *zend_ast_copy(zend_ast *ast);
|
||||
ZEND_API void zend_ast_destroy(zend_ast *ast);
|
||||
|
||||
#endif
|
||||
@@ -435,9 +435,7 @@ ZEND_FUNCTION(func_get_arg)
|
||||
}
|
||||
|
||||
arg = *(p-(arg_count-requested_offset));
|
||||
*return_value = *arg;
|
||||
zval_copy_ctor(return_value);
|
||||
INIT_PZVAL(return_value);
|
||||
RETURN_ZVAL_FAST(arg);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -461,12 +459,17 @@ ZEND_FUNCTION(func_get_args)
|
||||
|
||||
array_init_size(return_value, arg_count);
|
||||
for (i=0; i<arg_count; i++) {
|
||||
zval *element;
|
||||
zval *element, *arg;
|
||||
|
||||
ALLOC_ZVAL(element);
|
||||
*element = **((zval **) (p-(arg_count-i)));
|
||||
zval_copy_ctor(element);
|
||||
INIT_PZVAL(element);
|
||||
arg = *((zval **) (p-(arg_count-i)));
|
||||
if (!Z_ISREF_P(arg)) {
|
||||
element = arg;
|
||||
Z_ADDREF_P(element);
|
||||
} else {
|
||||
ALLOC_ZVAL(element);
|
||||
INIT_PZVAL_COPY(element, arg);
|
||||
zval_copy_ctor(element);
|
||||
}
|
||||
zend_hash_next_index_insert(return_value->value.ht, &element, sizeof(zval *), NULL);
|
||||
}
|
||||
}
|
||||
@@ -606,9 +609,9 @@ ZEND_FUNCTION(each)
|
||||
Z_ADDREF_P(entry);
|
||||
|
||||
/* add the key elements */
|
||||
switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 1, NULL)) {
|
||||
switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_key_len, &num_key, 0, NULL)) {
|
||||
case HASH_KEY_IS_STRING:
|
||||
add_get_index_stringl(return_value, 0, string_key, string_key_len-1, (void **) &inserted_pointer, 0);
|
||||
add_get_index_stringl(return_value, 0, string_key, string_key_len-1, (void **) &inserted_pointer, !IS_INTERNED(string_key));
|
||||
break;
|
||||
case HASH_KEY_IS_LONG:
|
||||
add_get_index_long(return_value, 0, num_key, (void **) &inserted_pointer);
|
||||
@@ -706,7 +709,7 @@ repeat:
|
||||
zval_ptr_dtor(&val_free);
|
||||
}
|
||||
c.flags = case_sensitive; /* non persistent */
|
||||
c.name = IS_INTERNED(name) ? name : zend_strndup(name, name_len);
|
||||
c.name = str_strndup(name, name_len);
|
||||
if(c.name == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -943,11 +946,11 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
|
||||
|
||||
/* this is necessary to make it able to work with default array
|
||||
* properties, returned to user */
|
||||
if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
|
||||
if (IS_CONSTANT_TYPE(Z_TYPE_P(prop_copy))) {
|
||||
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
|
||||
}
|
||||
|
||||
add_assoc_zval(return_value, key, prop_copy);
|
||||
zend_hash_update(Z_ARRVAL_P(return_value), key, key_len, &prop_copy, sizeof(zval*), NULL);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1017,7 +1020,14 @@ ZEND_FUNCTION(get_object_vars)
|
||||
zend_unmangle_property_name_ex(key, key_len - 1, &class_name, &prop_name, (int*) &prop_len);
|
||||
/* Not separating references */
|
||||
Z_ADDREF_PP(value);
|
||||
add_assoc_zval_ex(return_value, prop_name, prop_len + 1, *value);
|
||||
if (IS_INTERNED(key) && prop_name != key) {
|
||||
/* we can't use substring of interned string as a new key */
|
||||
char *tmp = estrndup(prop_name, prop_len);
|
||||
add_assoc_zval_ex(return_value, tmp, prop_len + 1, *value);
|
||||
efree(tmp);
|
||||
} else {
|
||||
add_assoc_zval_ex(return_value, prop_name, prop_len + 1, *value);
|
||||
}
|
||||
}
|
||||
}
|
||||
zend_hash_move_forward_ex(properties, &pos);
|
||||
@@ -1388,12 +1398,11 @@ ZEND_FUNCTION(function_exists)
|
||||
Creates an alias for user defined class */
|
||||
ZEND_FUNCTION(class_alias)
|
||||
{
|
||||
char *class_name, *lc_name, *alias_name;
|
||||
char *class_name, *alias_name;
|
||||
zend_class_entry **ce;
|
||||
int class_name_len, alias_name_len;
|
||||
int found;
|
||||
zend_bool autoload = 1;
|
||||
ALLOCA_FLAG(use_heap)
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &class_name, &class_name_len, &alias_name, &alias_name_len, &autoload) == FAILURE) {
|
||||
return;
|
||||
@@ -1474,6 +1483,7 @@ ZEND_FUNCTION(crash)
|
||||
ZEND_FUNCTION(get_included_files)
|
||||
{
|
||||
char *entry;
|
||||
uint entry_len;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
@@ -1481,8 +1491,8 @@ ZEND_FUNCTION(get_included_files)
|
||||
|
||||
array_init(return_value);
|
||||
zend_hash_internal_pointer_reset(&EG(included_files));
|
||||
while (zend_hash_get_current_key(&EG(included_files), &entry, NULL, 1) == HASH_KEY_IS_STRING) {
|
||||
add_next_index_string(return_value, entry, 0);
|
||||
while (zend_hash_get_current_key_ex(&EG(included_files), &entry, &entry_len, NULL, 0, NULL) == HASH_KEY_IS_STRING) {
|
||||
add_next_index_stringl(return_value, entry, entry_len-1, !IS_INTERNED(entry));
|
||||
zend_hash_move_forward(&EG(included_files));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,14 +59,8 @@ ZEND_METHOD(Closure, __invoke) /* {{{ */
|
||||
} else if (call_user_function_ex(CG(function_table), NULL, this_ptr, &closure_result_ptr, ZEND_NUM_ARGS(), arguments, 1, NULL TSRMLS_CC) == FAILURE) {
|
||||
RETVAL_FALSE;
|
||||
} else if (closure_result_ptr) {
|
||||
if (Z_ISREF_P(closure_result_ptr) && return_value_ptr) {
|
||||
if (return_value) {
|
||||
zval_ptr_dtor(&return_value);
|
||||
}
|
||||
*return_value_ptr = closure_result_ptr;
|
||||
} else {
|
||||
RETVAL_ZVAL(closure_result_ptr, 1, 1);
|
||||
}
|
||||
zval_ptr_dtor(&return_value);
|
||||
*return_value_ptr = closure_result_ptr;
|
||||
}
|
||||
efree(arguments);
|
||||
|
||||
|
||||
+546
-319
File diff suppressed because it is too large
Load Diff
+37
-23
@@ -23,6 +23,7 @@
|
||||
#define ZEND_COMPILE_H
|
||||
|
||||
#include "zend.h"
|
||||
#include "zend_ast.h"
|
||||
|
||||
#ifdef HAVE_STDARG_H
|
||||
# include <stdarg.h>
|
||||
@@ -74,7 +75,7 @@ typedef struct _zend_literal {
|
||||
#define Z_HASH_P(zv) \
|
||||
(((zend_literal*)(zv))->hash_value)
|
||||
|
||||
typedef union _znode_op {
|
||||
typedef union _znode_op {
|
||||
zend_uint constant;
|
||||
zend_uint var;
|
||||
zend_uint num;
|
||||
@@ -86,12 +87,13 @@ typedef union _znode_op {
|
||||
void *ptr; /* Used for passing pointers from the compile to execution phase, currently used for traits */
|
||||
} znode_op;
|
||||
|
||||
typedef struct _znode { /* used only during compilation */
|
||||
typedef struct _znode { /* used only during compilation */
|
||||
int op_type;
|
||||
union {
|
||||
znode_op op;
|
||||
zval constant; /* replaced by literal/zv */
|
||||
zend_op_array *op_array;
|
||||
zend_ast *ast;
|
||||
} u;
|
||||
zend_uint EA; /* extended attributes */
|
||||
} znode;
|
||||
@@ -207,12 +209,14 @@ typedef struct _zend_try_catch_element {
|
||||
/* disable inline caching */
|
||||
#define ZEND_ACC_NEVER_CACHE 0x400000
|
||||
|
||||
#define ZEND_ACC_PASS_REST_BY_REFERENCE 0x1000000
|
||||
#define ZEND_ACC_PASS_REST_PREFER_REF 0x2000000
|
||||
#define ZEND_ACC_VARIADIC 0x1000000
|
||||
|
||||
#define ZEND_ACC_RETURN_REFERENCE 0x4000000
|
||||
#define ZEND_ACC_DONE_PASS_TWO 0x8000000
|
||||
|
||||
/* function has arguments with type hinting */
|
||||
#define ZEND_ACC_HAS_TYPE_HINTS 0x10000000
|
||||
|
||||
char *zend_visibility_string(zend_uint fn_flags);
|
||||
|
||||
|
||||
@@ -234,12 +238,13 @@ typedef struct _zend_arg_info {
|
||||
const char *class_name;
|
||||
zend_uint class_name_len;
|
||||
zend_uchar type_hint;
|
||||
zend_uchar pass_by_reference;
|
||||
zend_bool allow_null;
|
||||
zend_bool pass_by_reference;
|
||||
zend_bool is_variadic;
|
||||
} zend_arg_info;
|
||||
|
||||
/* the following structure repeats the layout of zend_arg_info,
|
||||
* but its fields have different meaning. It's used as the first element of
|
||||
* but its fields have different meaning. It's used as the first element of
|
||||
* arg_info array to define properties of internal functions.
|
||||
*/
|
||||
typedef struct _zend_internal_function_info {
|
||||
@@ -249,7 +254,8 @@ typedef struct _zend_internal_function_info {
|
||||
zend_uint required_num_args;
|
||||
zend_uchar _type_hint;
|
||||
zend_bool return_reference;
|
||||
zend_bool pass_rest_by_reference;
|
||||
zend_bool _allow_null;
|
||||
zend_bool _is_variadic;
|
||||
} zend_internal_function_info;
|
||||
|
||||
typedef struct _zend_compiled_variable {
|
||||
@@ -261,7 +267,7 @@ typedef struct _zend_compiled_variable {
|
||||
struct _zend_op_array {
|
||||
/* Common elements */
|
||||
zend_uchar type;
|
||||
const char *function_name;
|
||||
const char *function_name;
|
||||
zend_class_entry *scope;
|
||||
zend_uint fn_flags;
|
||||
union _zend_function *prototype;
|
||||
@@ -395,6 +401,7 @@ struct _zend_execute_data {
|
||||
zend_class_entry *current_called_scope;
|
||||
zval *current_this;
|
||||
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
|
||||
zval *delayed_exception;
|
||||
call_slot *call_slots;
|
||||
call_slot *call;
|
||||
};
|
||||
@@ -437,8 +444,10 @@ ZEND_API char *zend_get_compiled_filename(TSRMLS_D);
|
||||
ZEND_API int zend_get_compiled_lineno(TSRMLS_D);
|
||||
ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D);
|
||||
|
||||
void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace TSRMLS_DC);
|
||||
void zend_resolve_class_name(znode *class_name, ulong fetch_type, int check_ns_name TSRMLS_DC);
|
||||
void zend_resolve_non_class_name(znode *element_name, zend_bool *check_namespace, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC);
|
||||
void zend_resolve_function_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC);
|
||||
void zend_resolve_const_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC);
|
||||
void zend_resolve_class_name(znode *class_name TSRMLS_DC);
|
||||
ZEND_API const char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len);
|
||||
|
||||
#ifdef ZTS
|
||||
@@ -500,7 +509,7 @@ void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRM
|
||||
int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier);
|
||||
void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC);
|
||||
void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC);
|
||||
void zend_do_receive_arg(zend_uchar op, znode *varname, const znode *offset, const znode *initialization, znode *class_type, zend_bool pass_by_reference TSRMLS_DC);
|
||||
void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initialization, znode *class_type, zend_bool pass_by_reference, zend_bool is_variadic TSRMLS_DC);
|
||||
int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC);
|
||||
void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC);
|
||||
void zend_do_clone(znode *result, const znode *expr TSRMLS_DC);
|
||||
@@ -636,7 +645,11 @@ void zend_do_begin_namespace(const znode *name, zend_bool with_brackets TSRMLS_D
|
||||
void zend_do_end_namespace(TSRMLS_D);
|
||||
void zend_verify_namespace(TSRMLS_D);
|
||||
void zend_do_use(znode *name, znode *new_name, int is_global TSRMLS_DC);
|
||||
void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, int is_function, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC);
|
||||
void zend_do_use_function(znode *name, znode *new_name, int is_global TSRMLS_DC);
|
||||
void zend_do_use_const(znode *name, znode *new_name, int is_global TSRMLS_DC);
|
||||
void zend_do_end_compilation(TSRMLS_D);
|
||||
void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC);
|
||||
|
||||
void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC);
|
||||
|
||||
@@ -674,7 +687,7 @@ void zend_class_add_ref(zend_class_entry **ce);
|
||||
|
||||
ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal);
|
||||
#define zend_unmangle_property_name(mangled_property, mangled_property_len, class_name, prop_name) \
|
||||
zend_unmangle_property_name_ex(mangled_property, mangled_property_len, class_name, prop_name, NULL)
|
||||
zend_unmangle_property_name_ex(mangled_property, mangled_property_len, class_name, prop_name, NULL)
|
||||
ZEND_API int zend_unmangle_property_name_ex(const char *mangled_property, int mangled_property_len, const char **class_name, const char **prop_name, int *prop_len);
|
||||
|
||||
#define ZEND_FUNCTION_DTOR (void (*)(void *)) zend_function_dtor
|
||||
@@ -726,8 +739,8 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
|
||||
#define ZEND_FETCH_CLASS_DEFAULT 0
|
||||
#define ZEND_FETCH_CLASS_SELF 1
|
||||
#define ZEND_FETCH_CLASS_PARENT 2
|
||||
#define ZEND_FETCH_CLASS_MAIN 3
|
||||
#define ZEND_FETCH_CLASS_GLOBAL 4
|
||||
#define ZEND_FETCH_CLASS_MAIN 3 /* unused */
|
||||
#define ZEND_FETCH_CLASS_GLOBAL 4 /* unused */
|
||||
#define ZEND_FETCH_CLASS_AUTO 5
|
||||
#define ZEND_FETCH_CLASS_INTERFACE 6
|
||||
#define ZEND_FETCH_CLASS_STATIC 7
|
||||
@@ -817,21 +830,21 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
|
||||
#define ZEND_SEND_BY_REF 1
|
||||
#define ZEND_SEND_PREFER_REF 2
|
||||
|
||||
#define CHECK_ARG_SEND_TYPE(zf, arg_num, m1, m2) \
|
||||
((zf) && \
|
||||
((((zend_function*)(zf))->common.arg_info && \
|
||||
arg_num <= ((zend_function*)(zf))->common.num_args) ? \
|
||||
(((zend_function *)(zf))->common.arg_info[arg_num-1].pass_by_reference & (m1)) : \
|
||||
(((zend_function *)(zf))->common.fn_flags & (m2))))
|
||||
#define CHECK_ARG_SEND_TYPE(zf, arg_num, m) \
|
||||
((zf)->common.arg_info && \
|
||||
(arg_num <= (zf)->common.num_args \
|
||||
? ((zf)->common.arg_info[arg_num-1].pass_by_reference & (m)) \
|
||||
: ((zf)->common.fn_flags & ZEND_ACC_VARIADIC) \
|
||||
? ((zf)->common.arg_info[(zf)->common.num_args-1].pass_by_reference & (m)) : 0))
|
||||
|
||||
#define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \
|
||||
CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF, ZEND_ACC_PASS_REST_BY_REFERENCE)
|
||||
CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF)
|
||||
|
||||
#define ARG_SHOULD_BE_SENT_BY_REF(zf, arg_num) \
|
||||
CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF, ZEND_ACC_PASS_REST_BY_REFERENCE|ZEND_ACC_PASS_REST_PREFER_REF)
|
||||
CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF)
|
||||
|
||||
#define ARG_MAY_BE_SENT_BY_REF(zf, arg_num) \
|
||||
CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_PREFER_REF, ZEND_ACC_PASS_REST_PREFER_REF)
|
||||
CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_PREFER_REF)
|
||||
|
||||
#define ZEND_RETURN_VAL 0
|
||||
#define ZEND_RETURN_REF 1
|
||||
@@ -839,6 +852,7 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
|
||||
|
||||
#define ZEND_RETURNS_FUNCTION 1<<0
|
||||
#define ZEND_RETURNS_NEW 1<<1
|
||||
#define ZEND_RETURNS_VALUE 1<<2
|
||||
|
||||
#define ZEND_FAST_RET_TO_CATCH 1
|
||||
#define ZEND_FAST_RET_TO_FINALLY 2
|
||||
|
||||
+38
-56
@@ -25,7 +25,7 @@
|
||||
#include "zend_variables.h"
|
||||
#include "zend_operators.h"
|
||||
#include "zend_globals.h"
|
||||
|
||||
#include "zend_API.h"
|
||||
|
||||
void free_zend_constant(zend_constant *c)
|
||||
{
|
||||
@@ -38,9 +38,7 @@ void free_zend_constant(zend_constant *c)
|
||||
|
||||
void copy_zend_constant(zend_constant *c)
|
||||
{
|
||||
if (!IS_INTERNED(c->name)) {
|
||||
c->name = zend_strndup(c->name, c->name_len - 1);
|
||||
}
|
||||
c->name = str_strndup(c->name, c->name_len - 1);
|
||||
if (!(c->flags & CONST_PERSISTENT)) {
|
||||
zval_copy_ctor(&c->value);
|
||||
}
|
||||
@@ -119,42 +117,12 @@ void zend_register_standard_constants(TSRMLS_D)
|
||||
REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS);
|
||||
/* true/false constants */
|
||||
{
|
||||
zend_constant c;
|
||||
|
||||
c.flags = CONST_PERSISTENT | CONST_CT_SUBST;
|
||||
c.module_number = 0;
|
||||
|
||||
c.name = zend_strndup(ZEND_STRL("TRUE"));
|
||||
c.name_len = sizeof("TRUE");
|
||||
c.value.value.lval = 1;
|
||||
c.value.type = IS_BOOL;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
|
||||
c.name = zend_strndup(ZEND_STRL("FALSE"));
|
||||
c.name_len = sizeof("FALSE");
|
||||
c.value.value.lval = 0;
|
||||
c.value.type = IS_BOOL;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
|
||||
c.name = zend_strndup(ZEND_STRL("NULL"));
|
||||
c.name_len = sizeof("NULL");
|
||||
c.value.type = IS_NULL;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
|
||||
c.flags = CONST_PERSISTENT | CONST_CS;
|
||||
|
||||
c.name = zend_strndup(ZEND_STRL("ZEND_THREAD_SAFE"));
|
||||
c.name_len = sizeof("ZEND_THREAD_SAFE");
|
||||
c.value.value.lval = ZTS_V;
|
||||
c.value.type = IS_BOOL;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
|
||||
c.name = zend_strndup(ZEND_STRL("ZEND_DEBUG_BUILD"));
|
||||
c.name_len = sizeof("ZEND_DEBUG_BUILD");
|
||||
c.value.value.lval = ZEND_DEBUG;
|
||||
c.value.type = IS_BOOL;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
REGISTER_MAIN_BOOL_CONSTANT("TRUE", 1, CONST_PERSISTENT | CONST_CT_SUBST);
|
||||
REGISTER_MAIN_BOOL_CONSTANT("FALSE", 0, CONST_PERSISTENT | CONST_CT_SUBST);
|
||||
REGISTER_MAIN_BOOL_CONSTANT("ZEND_THREAD_SAFE", ZTS_V, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_MAIN_BOOL_CONSTANT("ZEND_DEBUG_BUILD", ZEND_DEBUG, CONST_PERSISTENT | CONST_CS);
|
||||
}
|
||||
REGISTER_MAIN_NULL_CONSTANT("NULL", CONST_PERSISTENT | CONST_CT_SUBST);
|
||||
}
|
||||
|
||||
|
||||
@@ -175,13 +143,35 @@ void clean_non_persistent_constants(TSRMLS_D)
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_register_null_constant(const char *name, uint name_len, int flags, int module_number TSRMLS_DC)
|
||||
{
|
||||
zend_constant c;
|
||||
|
||||
ZVAL_NULL(&c.value);
|
||||
c.flags = flags;
|
||||
c.name = zend_strndup(name, name_len-1);
|
||||
c.name_len = name_len;
|
||||
c.module_number = module_number;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
}
|
||||
|
||||
ZEND_API void zend_register_bool_constant(const char *name, uint name_len, zend_bool bval, int flags, int module_number TSRMLS_DC)
|
||||
{
|
||||
zend_constant c;
|
||||
|
||||
ZVAL_BOOL(&c.value, bval);
|
||||
c.flags = flags;
|
||||
c.name = zend_strndup(name, name_len-1);
|
||||
c.name_len = name_len;
|
||||
c.module_number = module_number;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
}
|
||||
|
||||
ZEND_API void zend_register_long_constant(const char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC)
|
||||
{
|
||||
zend_constant c;
|
||||
|
||||
c.value.type = IS_LONG;
|
||||
c.value.value.lval = lval;
|
||||
ZVAL_LONG(&c.value, lval);
|
||||
c.flags = flags;
|
||||
c.name = zend_strndup(name, name_len-1);
|
||||
c.name_len = name_len;
|
||||
@@ -194,8 +184,7 @@ ZEND_API void zend_register_double_constant(const char *name, uint name_len, dou
|
||||
{
|
||||
zend_constant c;
|
||||
|
||||
c.value.type = IS_DOUBLE;
|
||||
c.value.value.dval = dval;
|
||||
ZVAL_DOUBLE(&c.value, dval);
|
||||
c.flags = flags;
|
||||
c.name = zend_strndup(name, name_len-1);
|
||||
c.name_len = name_len;
|
||||
@@ -208,9 +197,7 @@ ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, ch
|
||||
{
|
||||
zend_constant c;
|
||||
|
||||
c.value.type = IS_STRING;
|
||||
c.value.value.str.val = strval;
|
||||
c.value.value.str.len = strlen;
|
||||
ZVAL_STRINGL(&c.value, strval, strlen, 0);
|
||||
c.flags = flags;
|
||||
c.name = zend_strndup(name, name_len-1);
|
||||
c.name_len = name_len;
|
||||
@@ -485,7 +472,7 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
|
||||
char *lowercase_name = NULL;
|
||||
char *name;
|
||||
int ret = SUCCESS;
|
||||
ulong chash = 0;
|
||||
ulong chash;
|
||||
|
||||
#if 0
|
||||
printf("Registering constant for module %d\n", c->module_number);
|
||||
@@ -497,23 +484,18 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
|
||||
zend_str_tolower(lowercase_name, c->name_len-1);
|
||||
lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
|
||||
name = lowercase_name;
|
||||
chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0;
|
||||
} else {
|
||||
char *slash = strrchr(c->name, '\\');
|
||||
if(slash) {
|
||||
if (slash) {
|
||||
lowercase_name = estrndup(c->name, c->name_len-1);
|
||||
zend_str_tolower(lowercase_name, slash-c->name);
|
||||
lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
|
||||
name = lowercase_name;
|
||||
|
||||
chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0;
|
||||
} else {
|
||||
name = c->name;
|
||||
}
|
||||
}
|
||||
if (chash == 0) {
|
||||
chash = zend_hash_func(name, c->name_len);
|
||||
}
|
||||
chash = str_hash(name, c->name_len-1);
|
||||
|
||||
/* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */
|
||||
if ((c->name_len == sizeof("__COMPILER_HALT_OFFSET__")
|
||||
@@ -532,8 +514,8 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
|
||||
}
|
||||
ret = FAILURE;
|
||||
}
|
||||
if (lowercase_name && !IS_INTERNED(lowercase_name)) {
|
||||
efree(lowercase_name);
|
||||
if (lowercase_name) {
|
||||
str_efree(lowercase_name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -38,16 +38,22 @@ typedef struct _zend_constant {
|
||||
int module_number;
|
||||
} zend_constant;
|
||||
|
||||
#define REGISTER_NULL_CONSTANT(name, flags) zend_register_null_constant((name), sizeof(name), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_BOOL_CONSTANT(name, bval, flags) zend_register_bool_constant((name), sizeof(name), (bval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_LONG_CONSTANT(name, lval, flags) zend_register_long_constant((name), sizeof(name), (lval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_DOUBLE_CONSTANT(name, dval, flags) zend_register_double_constant((name), sizeof(name), (dval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_STRING_CONSTANT(name, str, flags) zend_register_string_constant((name), sizeof(name), (str), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_STRINGL_CONSTANT(name, str, len, flags) zend_register_stringl_constant((name), sizeof(name), (str), (len), (flags), module_number TSRMLS_CC)
|
||||
|
||||
#define REGISTER_NS_NULL_CONSTANT(ns, name, flags) zend_register_null_constant(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name)), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_NS_BOOL_CONSTANT(ns, name, bval, flags) zend_register_bool_constant(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name)), (bval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_NS_LONG_CONSTANT(ns, name, lval, flags) zend_register_long_constant(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name)), (lval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_NS_DOUBLE_CONSTANT(ns, name, dval, flags) zend_register_double_constant(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name)), (dval), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_NS_STRING_CONSTANT(ns, name, str, flags) zend_register_string_constant(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name)), (str), (flags), module_number TSRMLS_CC)
|
||||
#define REGISTER_NS_STRINGL_CONSTANT(ns, name, str, len, flags) zend_register_stringl_constant(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name)), (str), (len), (flags), module_number TSRMLS_CC)
|
||||
|
||||
#define REGISTER_MAIN_NULL_CONSTANT(name, flags) zend_register_null_constant((name), sizeof(name), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_BOOL_CONSTANT(name, bval, flags) zend_register_bool_constant((name), sizeof(name), (bval), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_LONG_CONSTANT(name, lval, flags) zend_register_long_constant((name), sizeof(name), (lval), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_DOUBLE_CONSTANT(name, dval, flags) zend_register_double_constant((name), sizeof(name), (dval), (flags), 0 TSRMLS_CC)
|
||||
#define REGISTER_MAIN_STRING_CONSTANT(name, str, flags) zend_register_string_constant((name), sizeof(name), (str), (flags), 0 TSRMLS_CC)
|
||||
@@ -62,6 +68,8 @@ void zend_register_standard_constants(TSRMLS_D);
|
||||
void clean_non_persistent_constants(TSRMLS_D);
|
||||
ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC);
|
||||
ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC);
|
||||
ZEND_API void zend_register_bool_constant(const char *name, uint name_len, zend_bool bval, int flags, int module_number TSRMLS_DC);
|
||||
ZEND_API void zend_register_null_constant(const char *name, uint name_len, int flags, int module_number TSRMLS_DC);
|
||||
ZEND_API void zend_register_long_constant(const char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC);
|
||||
ZEND_API void zend_register_double_constant(const char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC);
|
||||
ZEND_API void zend_register_string_constant(const char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC);
|
||||
|
||||
+86
-82
@@ -40,7 +40,7 @@
|
||||
#include "zend_dtrace.h"
|
||||
|
||||
/* Virtual current working directory support */
|
||||
#include "tsrm_virtual_cwd.h"
|
||||
#include "zend_virtual_cwd.h"
|
||||
|
||||
#define _CONST_CODE 0
|
||||
#define _TMP_CODE 1
|
||||
@@ -79,7 +79,6 @@ static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *sho
|
||||
if (unref && Z_ISREF_P(z) && Z_REFCOUNT_P(z) == 1) {
|
||||
Z_UNSET_ISREF_P(z);
|
||||
}
|
||||
GC_ZVAL_CHECK_POSSIBLE_ROOT(z);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +93,8 @@ static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
|
||||
}
|
||||
|
||||
#undef zval_ptr_dtor
|
||||
#define zval_ptr_dtor(pzv) i_zval_ptr_dtor(*(pzv) ZEND_FILE_LINE_CC)
|
||||
#define zval_ptr_dtor(pzv) i_zval_ptr_dtor(*(pzv) ZEND_FILE_LINE_CC TSRMLS_CC)
|
||||
#define zval_ptr_dtor_nogc(pzv) i_zval_ptr_dtor_nogc(*(pzv) ZEND_FILE_LINE_CC TSRMLS_CC)
|
||||
|
||||
#define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f, 1 TSRMLS_CC)
|
||||
#define PZVAL_UNLOCK_EX(z, f, u) zend_pzval_unlock_func(z, f, u TSRMLS_CC)
|
||||
@@ -102,16 +102,14 @@ static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
|
||||
#define PZVAL_LOCK(z) Z_ADDREF_P((z))
|
||||
#define SELECTIVE_PZVAL_LOCK(pzv, opline) if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(pzv); }
|
||||
|
||||
#define EXTRACT_ZVAL_PTR(t) do { \
|
||||
temp_variable *__t = (t); \
|
||||
if (__t->var.ptr_ptr) { \
|
||||
__t->var.ptr = *__t->var.ptr_ptr; \
|
||||
__t->var.ptr_ptr = &__t->var.ptr; \
|
||||
if (!PZVAL_IS_REF(__t->var.ptr) && \
|
||||
Z_REFCOUNT_P(__t->var.ptr) > 2) { \
|
||||
SEPARATE_ZVAL(__t->var.ptr_ptr); \
|
||||
} \
|
||||
} \
|
||||
#define EXTRACT_ZVAL_PTR(t) do { \
|
||||
temp_variable *__t = (t); \
|
||||
__t->var.ptr = *__t->var.ptr_ptr; \
|
||||
__t->var.ptr_ptr = &__t->var.ptr; \
|
||||
if (!PZVAL_IS_REF(__t->var.ptr) && \
|
||||
Z_REFCOUNT_P(__t->var.ptr) > 2) { \
|
||||
SEPARATE_ZVAL(__t->var.ptr_ptr); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define AI_SET_PTR(t, val) do { \
|
||||
@@ -125,18 +123,18 @@ static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
|
||||
if ((zend_uintptr_t)should_free.var & 1L) { \
|
||||
zval_dtor((zval*)((zend_uintptr_t)should_free.var & ~1L)); \
|
||||
} else { \
|
||||
zval_ptr_dtor(&should_free.var); \
|
||||
zval_ptr_dtor_nogc(&should_free.var); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FREE_OP_IF_VAR(should_free) \
|
||||
if (should_free.var != NULL && (((zend_uintptr_t)should_free.var & 1L) == 0)) { \
|
||||
zval_ptr_dtor(&should_free.var); \
|
||||
zval_ptr_dtor_nogc(&should_free.var); \
|
||||
}
|
||||
|
||||
#define FREE_OP_VAR_PTR(should_free) \
|
||||
if (should_free.var) { \
|
||||
zval_ptr_dtor(&should_free.var); \
|
||||
zval_ptr_dtor_nogc(&should_free.var); \
|
||||
}
|
||||
|
||||
#define TMP_FREE(z) (zval*)(((zend_uintptr_t)(z)) | 1L)
|
||||
@@ -183,8 +181,7 @@ static zend_always_inline zval *_get_zval_ptr_var(zend_uint var, const zend_exec
|
||||
{
|
||||
zval *ptr = EX_T(var).var.ptr;
|
||||
|
||||
PZVAL_UNLOCK(ptr, should_free);
|
||||
return ptr;
|
||||
return should_free->var = ptr;
|
||||
}
|
||||
|
||||
static zend_never_inline zval **_get_zval_cv_lookup(zval ***ptr, zend_uint var, int type TSRMLS_DC)
|
||||
@@ -386,6 +383,19 @@ static zend_always_inline zval **_get_zval_ptr_ptr_var(zend_uint var, const zend
|
||||
return ptr_ptr;
|
||||
}
|
||||
|
||||
static zend_always_inline zval **_get_zval_ptr_ptr_var_fast(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
|
||||
{
|
||||
zval** ptr_ptr = EX_T(var).var.ptr_ptr;
|
||||
|
||||
if (EXPECTED(ptr_ptr != NULL)) {
|
||||
should_free->var = *ptr_ptr;
|
||||
} else {
|
||||
/* string offset */
|
||||
should_free->var = EX_T(var).str_offset.str;
|
||||
}
|
||||
return ptr_ptr;
|
||||
}
|
||||
|
||||
static zend_always_inline zval **_get_zval_ptr_ptr_cv(zend_uint var, int type TSRMLS_DC)
|
||||
{
|
||||
zval ***ptr = EX_CV_NUM(EG(current_execute_data), var);
|
||||
@@ -604,12 +614,17 @@ static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zva
|
||||
char *need_msg;
|
||||
zend_class_entry *ce;
|
||||
|
||||
if (!zf->common.arg_info
|
||||
|| arg_num>zf->common.num_args) {
|
||||
if (!zf->common.arg_info) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
cur_arg_info = &zf->common.arg_info[arg_num-1];
|
||||
if (arg_num <= zf->common.num_args) {
|
||||
cur_arg_info = &zf->common.arg_info[arg_num-1];
|
||||
} else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
|
||||
cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (cur_arg_info->class_name) {
|
||||
const char *class_name;
|
||||
@@ -755,32 +770,21 @@ static inline void zend_assign_to_object(zval **retval, zval **object_ptr, zval
|
||||
|
||||
static inline int zend_assign_to_string_offset(const temp_variable *T, const zval *value, int value_type TSRMLS_DC)
|
||||
{
|
||||
if (Z_TYPE_P(T->str_offset.str) == IS_STRING) {
|
||||
|
||||
if (((int)T->str_offset.offset < 0)) {
|
||||
zend_error(E_WARNING, "Illegal string offset: %d", T->str_offset.offset);
|
||||
zval *str = T->str_offset.str;
|
||||
zend_uint offset = T->str_offset.offset;
|
||||
if (Z_TYPE_P(str) == IS_STRING) {
|
||||
if ((int)offset < 0) {
|
||||
zend_error(E_WARNING, "Illegal string offset: %d", offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (T->str_offset.offset >= Z_STRLEN_P(T->str_offset.str)) {
|
||||
if (IS_INTERNED(Z_STRVAL_P(T->str_offset.str))) {
|
||||
char *tmp = (char *) emalloc(T->str_offset.offset+1+1);
|
||||
|
||||
memcpy(tmp, Z_STRVAL_P(T->str_offset.str), Z_STRLEN_P(T->str_offset.str)+1);
|
||||
Z_STRVAL_P(T->str_offset.str) = tmp;
|
||||
} else {
|
||||
Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1);
|
||||
}
|
||||
memset(Z_STRVAL_P(T->str_offset.str) + Z_STRLEN_P(T->str_offset.str),
|
||||
' ',
|
||||
T->str_offset.offset - Z_STRLEN_P(T->str_offset.str));
|
||||
Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset+1] = 0;
|
||||
Z_STRLEN_P(T->str_offset.str) = T->str_offset.offset+1;
|
||||
} else if (IS_INTERNED(Z_STRVAL_P(T->str_offset.str))) {
|
||||
char *tmp = (char *) emalloc(Z_STRLEN_P(T->str_offset.str) + 1);
|
||||
|
||||
memcpy(tmp, Z_STRVAL_P(T->str_offset.str), Z_STRLEN_P(T->str_offset.str) + 1);
|
||||
Z_STRVAL_P(T->str_offset.str) = tmp;
|
||||
if (offset >= Z_STRLEN_P(str)) {
|
||||
Z_STRVAL_P(str) = str_erealloc(Z_STRVAL_P(str), offset+1+1);
|
||||
memset(Z_STRVAL_P(str) + Z_STRLEN_P(str), ' ', offset - Z_STRLEN_P(str));
|
||||
Z_STRVAL_P(str)[offset+1] = 0;
|
||||
Z_STRLEN_P(str) = offset+1;
|
||||
} else if (IS_INTERNED(Z_STRVAL_P(str))) {
|
||||
Z_STRVAL_P(str) = estrndup(Z_STRVAL_P(str), Z_STRLEN_P(str));
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(value) != IS_STRING) {
|
||||
@@ -791,15 +795,15 @@ static inline int zend_assign_to_string_offset(const temp_variable *T, const zva
|
||||
zval_copy_ctor(&tmp);
|
||||
}
|
||||
convert_to_string(&tmp);
|
||||
Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL(tmp)[0];
|
||||
STR_FREE(Z_STRVAL(tmp));
|
||||
Z_STRVAL_P(str)[offset] = Z_STRVAL(tmp)[0];
|
||||
str_efree(Z_STRVAL(tmp));
|
||||
} else {
|
||||
Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL_P(value)[0];
|
||||
Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
|
||||
if (value_type == IS_TMP_VAR) {
|
||||
/* we can safely free final_value here
|
||||
* because separation is done only
|
||||
* in case value_type == IS_VAR */
|
||||
STR_FREE(Z_STRVAL_P(value));
|
||||
str_efree(Z_STRVAL_P(value));
|
||||
}
|
||||
}
|
||||
/*
|
||||
@@ -909,7 +913,7 @@ static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value
|
||||
} else { /* we need to split */
|
||||
Z_DELREF_P(variable_ptr);
|
||||
GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
|
||||
if (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) {
|
||||
if (PZVAL_IS_REF(value)) {
|
||||
ALLOC_ZVAL(variable_ptr);
|
||||
*variable_ptr_ptr = variable_ptr;
|
||||
INIT_PZVAL_COPY(variable_ptr, value);
|
||||
@@ -918,7 +922,6 @@ static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value
|
||||
} else {
|
||||
*variable_ptr_ptr = value;
|
||||
Z_ADDREF_P(value);
|
||||
Z_UNSET_ISREF_P(value);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1013,11 +1016,7 @@ static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const zva
|
||||
hval = Z_HASH_P(dim);
|
||||
} else {
|
||||
ZEND_HANDLE_NUMERIC_EX(offset_key, offset_key_length+1, hval, goto num_index);
|
||||
if (IS_INTERNED(offset_key)) {
|
||||
hval = INTERNED_HASH(offset_key);
|
||||
} else {
|
||||
hval = zend_hash_func(offset_key, offset_key_length+1);
|
||||
}
|
||||
hval = str_hash(offset_key, offset_key_length);
|
||||
}
|
||||
fetch_string_dim:
|
||||
if (zend_hash_quick_find(ht, offset_key, offset_key_length+1, hval, (void **) &retval) == FAILURE) {
|
||||
@@ -1214,12 +1213,12 @@ convert_to_array:
|
||||
zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name);
|
||||
}
|
||||
}
|
||||
retval = &overloaded_result;
|
||||
AI_SET_PTR(result, overloaded_result);
|
||||
PZVAL_LOCK(overloaded_result);
|
||||
} else {
|
||||
retval = &EG(error_zval_ptr);
|
||||
result->var.ptr_ptr = &EG(error_zval_ptr);
|
||||
PZVAL_LOCK(EG(error_zval_ptr));
|
||||
}
|
||||
AI_SET_PTR(result, *retval);
|
||||
PZVAL_LOCK(*retval);
|
||||
if (dim_type == IS_TMP_VAR) {
|
||||
zval_ptr_dtor(&dim);
|
||||
}
|
||||
@@ -1236,8 +1235,8 @@ convert_to_array:
|
||||
default:
|
||||
if (type == BP_VAR_UNSET) {
|
||||
zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
|
||||
AI_SET_PTR(result, &EG(uninitialized_zval));
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
result->var.ptr_ptr = &EG(uninitialized_zval_ptr);
|
||||
PZVAL_LOCK(EG(uninitialized_zval_ptr));
|
||||
} else {
|
||||
zend_error(E_WARNING, "Cannot use a scalar value as an array");
|
||||
result->var.ptr_ptr = &EG(error_zval_ptr);
|
||||
@@ -1255,12 +1254,12 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval *conta
|
||||
|
||||
case IS_ARRAY:
|
||||
retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
|
||||
AI_SET_PTR(result, *retval);
|
||||
result->var.ptr = *retval;
|
||||
PZVAL_LOCK(*retval);
|
||||
return;
|
||||
|
||||
case IS_NULL:
|
||||
AI_SET_PTR(result, &EG(uninitialized_zval));
|
||||
result->var.ptr = &EG(uninitialized_zval);
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
return;
|
||||
|
||||
@@ -1313,7 +1312,7 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval *conta
|
||||
Z_STRVAL_P(ptr)[1] = 0;
|
||||
Z_STRLEN_P(ptr) = 1;
|
||||
}
|
||||
AI_SET_PTR(result, ptr);
|
||||
result->var.ptr = ptr;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -1331,12 +1330,14 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval *conta
|
||||
}
|
||||
overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
|
||||
|
||||
if (overloaded_result) {
|
||||
AI_SET_PTR(result, overloaded_result);
|
||||
PZVAL_LOCK(overloaded_result);
|
||||
} else if (result) {
|
||||
AI_SET_PTR(result, &EG(uninitialized_zval));
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
if (result) {
|
||||
if (overloaded_result) {
|
||||
result->var.ptr = overloaded_result;
|
||||
PZVAL_LOCK(overloaded_result);
|
||||
} else {
|
||||
result->var.ptr = &EG(uninitialized_zval);
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
}
|
||||
}
|
||||
if (dim_type == IS_TMP_VAR) {
|
||||
zval_ptr_dtor(&dim);
|
||||
@@ -1345,7 +1346,7 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval *conta
|
||||
return;
|
||||
|
||||
default:
|
||||
AI_SET_PTR(result, &EG(uninitialized_zval));
|
||||
result->var.ptr = &EG(uninitialized_zval);
|
||||
PZVAL_LOCK(&EG(uninitialized_zval));
|
||||
return;
|
||||
}
|
||||
@@ -1475,15 +1476,17 @@ ZEND_API opcode_handler_t *zend_opcode_handlers;
|
||||
|
||||
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC)
|
||||
{
|
||||
if(fci != NULL) {
|
||||
((zend_internal_function *) execute_data_ptr->function_state.function)->handler(fci->param_count,
|
||||
*fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
|
||||
|
||||
if (fci != NULL) {
|
||||
execute_data_ptr->function_state.function->internal_function.handler(
|
||||
fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr,
|
||||
fci->object_ptr, 1 TSRMLS_CC
|
||||
);
|
||||
} else {
|
||||
zval **return_value_ptr = &EX_TMP_VAR(execute_data_ptr, execute_data_ptr->opline->result.var)->var.ptr;
|
||||
((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr,
|
||||
(execute_data_ptr->function_state.function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL,
|
||||
execute_data_ptr->object, return_value_used TSRMLS_CC);
|
||||
execute_data_ptr->function_state.function->internal_function.handler(
|
||||
execute_data_ptr->opline->extended_value, *return_value_ptr, return_value_ptr,
|
||||
execute_data_ptr->object, return_value_used TSRMLS_CC
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1501,7 +1504,7 @@ void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC) /* {{{
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
|
||||
static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval ***cv = EX_CV_NUM(execute_data, 0);
|
||||
zval ***end = cv + EX(op_array)->last_var;
|
||||
@@ -1514,9 +1517,9 @@ static zend_always_inline void i_free_compiled_variables(zend_execute_data *exec
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
|
||||
void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
i_free_compiled_variables(execute_data);
|
||||
i_free_compiled_variables(execute_data TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -1647,6 +1650,7 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
|
||||
EX(call) = NULL;
|
||||
EG(current_execute_data) = execute_data;
|
||||
EX(nested) = nested;
|
||||
EX(delayed_exception) = NULL;
|
||||
|
||||
if (!op_array->run_time_cache && op_array->last_cache_slot) {
|
||||
op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
|
||||
@@ -1674,7 +1678,7 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */
|
||||
ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return i_create_execute_data_from_op_array(op_array, nested TSRMLS_CC);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user