1
0
mirror of https://github.com/php/php-src.git synced 2026-04-27 18:23:26 +02:00

Merge branch 'PHP-5.5' of https://git.php.net/push/php-src into PHP-5.5

* 'PHP-5.5' of https://git.php.net/push/php-src: (266 commits)
  Fix "passing NULL to non-pointer argument" warnings in intl
  Remove support for cloning generators
  Removed deprecated check
  Fix whitespace issue in the SOAP test
  Fix SOAP test
  Forgot to fix the test on 5.4
  Exclude Travis build for 5.3 and 5.4
  Fix tests after addition of ^ (xor) operator to ini
  Fix Bug #64545:	PHP Error in ef93a93ee2
  Attempt to fix SKIP
  This will PHP 5.3.25
  Typo fix (greater then => greater than)
  don't optimize script if it's not going to be cached
  Reimplemented OPcache restart trigger. Now, if memory or hash are full the restart is scheduled only in case the amount of wasted memory is above opcache.max_wasted_percentage. Otherwise OPcahce continue serving the following requests using already cached files, but doesn't try to add new files (the cache is full anyway).
  With pkgconfig < 0.28 output is a single space With pkgconfig = 0.28 output is an empty string, This breaks the test on the 2 vars
  Fixed issue #78 (incorrect file path validation)
  Fix test on Mac (\D shows up)
  Add test for #64529
  will be 5.4.15
  fix NEWS
  ...
This commit is contained in:
Keyur Govande
2013-03-29 14:35:45 +00:00
213 changed files with 20372 additions and 2352 deletions
+2
View File
@@ -23,6 +23,8 @@ sapi/continuity/capi.c ident
Zend/RFCs/002.txt ident
Zend/RFCs/003.txt ident
NEWS merge=NEWS
UPGRADING merge=NEWS
UPGRADING.INTERNALS merge=NEWS
/ext/bz2/tests/with_strings.phpt -crlf
/ext/dom/tests/bug40836.phpt -crlf
/ext/dom/tests/domelement.phpt -crlf
+2 -2
View File
@@ -8,7 +8,7 @@ notifications:
email: false
env:
- REPORT_EXIT_STATUS=1 TEST_PHP_EXECUTABLE=./sapi/cli/php
- REPORT_EXIT_STATUS=1
before_script:
# Compile PHP
@@ -21,4 +21,4 @@ before_script:
- . ./travis/ext/pdo_pgsql/setup.sh
# Run PHPs run-tests.php
script: ./sapi/cli/php run-tests.php -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP"
script: ./sapi/cli/php run-tests.php -p `pwd`/sapi/cli/php -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP" --show-diff
+45 -1
View File
@@ -1,14 +1,54 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 20??, PHP 5.5.0 Beta 1
?? ??? 20??, PHP 5.5.0 Beta 3
28 Mar 2013, PHP 5.5.0 Beta 2
- Core:
. Fixed bug #64515 (Memoryleak when using the same variablename 2times in
function declaration). (Laruence)
. Fixed bug #64503 (Compilation fails with error: conflicting types for
'zendparse'). (Laruence)
. Fixed bug #64239 (Debug backtrace changed behavior since 5.4.10 or 5.4.11).
(Dmitry, Laruence)
. Fixed bug #64523, allow XOR in php.ini. (Dejan Marjanovic, Lars)
- Opcache:
. Fixed bug # 64490 (struct flock undefined on FreeBSD). (Joe Watkins)
21 Mar 2013, PHP 5.5.0 Beta 1
- Core:
. Added Zend Opcache extension and enable building it by default.
More details here: https://wiki.php.net/rfc/optimizerplus. (Dmitry)
. Added array_column function which returns a column in a multidimensional
array. https://wiki.php.net/rfc/array_column. (Ben Ramsey)
. Fixed bug #64354 (Unserialize array of objects whose class can't
be autoloaded fail). (Laruence)
. Added support for changing the process's title in CLI/CLI-Server SAPIs.
The implementation is more robust that the proctitle PECL module. More
details here: https://wiki.php.net/rfc/cli_process_title. (Keyur)
. Fixed bug #64370 (microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT']).
(Anatol)
. Added support for non-scalar Iterator keys in foreach
(https://wiki.php.net/rfc/foreach-non-scalar-keys). (Nikita Popov)
- mysqlnd
. Fixed bug #63530 (mysqlnd_stmt::bind_one_parameter crashes, uses wrong alloc
for stmt->param_bind). (Andrey)
- DateTime
. Fixed bug #53437 (Crash when using unserialized DatePeriod instance).
(Gustavo, Derick, Anatol)
. Fixed bug #62852 (Unserialize Invalid Date causes crash). (Anatol)
- SPL:
. Implement FR #48358 (Add SplDoublyLinkedList::add() to insert an element
at a given offset). (Mark Baker, David Soria Parra)
- Zip:
. Bug #64452 (Zip crash intermittently). (Anatol)
07 Mar 2013, PHP 5.5.0 Alpha 6
@@ -27,6 +67,10 @@ PHP NEWS
- DateTime:
. Fixed bug #64359 (strftime crash with VS2012). (Anatol)
- SNMP:
. Fixed bug #61981 (OO API, walk: $suffix_as_key is not working correctly).
(Boris Lytochkin)
21 Feb 2013, PHP 5.5.0 Alpha 5
- Core:
+11 -2
View File
@@ -64,7 +64,8 @@ Do not use abbreviations for alpha and beta.
``git push --tags origin HEAD``
8. run: ``./makedist 5.4.2RC2``, this will export the tree, create configure
and build three tarballs (gz,bz2 and xz).
and build three tarballs (gz,bz2 and xz). Make sure you use the same GNU Bison
version as snaps. Recent bison version are known to break ZTS.
9. Copy those three tarballs to www.php.net, in your homedir there should be a
directory "downloads/". Copy them into there, so that the system can generate
@@ -154,7 +155,15 @@ origin <branch>``".
11. run: ``./makedist php 5.4.1``, this will export the tree, create configure
and build two tarballs (one gz and one bz2).
12. Commit those two tarballs to Git (php-distributions.git)
12. Commit those two tarballs to web/php-distributions.git, then update the git
submodule reference in web/php.git:
git submodule init;
git submodule update;
cd distributions;
git pull origin master;
cd ..;
git commit distributions;
git push;
13. Once the release has been tagged, contact the PHP Windows development team
(internals-win@lists.php.net) so that Windows binaries can be created. Once
+75 -35
View File
@@ -30,38 +30,6 @@ PHP 5.5 UPGRADE NOTES
zend_logo_guid() have been removed
- Removal of Logo GUIDs
- 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.
========================================
2. New Features
========================================
@@ -79,13 +47,17 @@ PHP 5.5 UPGRADE NOTES
(https://wiki.php.net/rfc/generators)
- ClassName::class syntax returning full class name for a class as
a string constant. (https://wiki.php.net/rfc/class_name_scalars)
- Support for changing the process's title in CLI/CLI-Server SAPIs. (Keyur)
(https://wiki.php.net/rfc/cli_process_title)
- Added support for non-scalar Iterator keys in foreach.
(https://wiki.php.net/rfc/foreach-non-scalar-keys).
- Bundled Zend OPcache extension
(https://wiki.php.net/rfc/optimizerplus)
========================================
2. Changes in SAPI modules
========================================
- Support for changing the process's title in CLI/CLI-Server SAPIs. (Keyur)
(https://wiki.php.net/rfc/cli_process_title)
========================================
3. Deprecated Functionality
@@ -167,6 +139,7 @@ PHP 5.5 UPGRADE NOTES
========================================
- Core:
- array_column()
- boolval()
- password_get_info()
- password_hash()
@@ -180,6 +153,11 @@ PHP 5.5 UPGRADE NOTES
- imageflip
- imagecrop
- imagecropauto
- imagesetinterpolation
- imageaffine
- imageaffinematrixget
- imageaffinematrixconcat
- imagescale
- Hash:
- hash_pbkdf2()
@@ -273,6 +251,12 @@ PHP 5.5 UPGRADE NOTES
- SPL:
- SplFixedArray::__wakeup()
- SplDoublyLinkedList::add()
- Zend OPcache
- opcache_get_configuration()
- opcache_get_status()
- opcache_reset()
========================================
6. New Classes and Interfaces
@@ -324,13 +308,42 @@ PHP 5.5 UPGRADE NOTES
. 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
========================================
10. Changes to INI File Handling
========================================
- Core:
- Added sys_temp_dir INI directive, for specifying temp firectory.
- Added sys_temp_dir INI directive, for specifying temp directory.
- Intl:
- Added intl.use_exceptions INI directive, which controls what happens when
@@ -341,6 +354,33 @@ PHP 5.5 UPGRADE NOTES
APIs which use(are built) for mysqlnd. This allows ext/mysqli to be used
with the new auth protocol, although at coarser level.
- Zend OPcache (See ext/opcache/README for more details)
- 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)
========================================
11. Windows Support
========================================
+50 -6
View File
@@ -3,9 +3,11 @@ $Id$
UPGRADE NOTES - PHP X.Y
1. Internal API changes
a. Streams pooling API
b. Lowercasing and locales
c. zend_qsort_r
a. Executor changes
b. Streams pooling API
c. Lowercasing and locales
d. zend_qsort_r
e. get_current_key
2. Build system changes
a. Unix build system changes
@@ -16,7 +18,41 @@ UPGRADE NOTES - PHP X.Y
1. Internal API changes
========================
a. Streams pooling API
a. Executor changes
* 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.
b. Streams pooling API
The streams pooling API has been removed. The following functions no longer
exist:
@@ -28,7 +64,7 @@ PHPAPI int php_stream_context_set_link(php_stream_context *context,
PHPAPI int php_stream_context_del_link(php_stream_context *context,
php_stream *stream);
b. Lowercasing and locales
c. Lowercasing and locales
The lowercasing functions in zend_operators.c were split into those that do
lowercasing according to locale rules and those that do ASCII lowercasing.
@@ -54,7 +90,7 @@ such as strcasecmp, will be using locale rules.
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.
c. zend_qsort_r
d. zend_qsort_r
Added the function zend_qsort_r():
@@ -64,6 +100,14 @@ void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_t compare
The extra argument it has (relatively to zend_qsort()) is passed to the
comparison function.
e. get_current_key
The signature of the get_current_key iteration handler has been changed to:
void (*get_current_key)(zend_object_iterator *iter, zval *key TSRMLS_DC);
The key should be written into the zval* using the ZVAL_* macros.
========================
2. Build system changes
========================
+3
View File
@@ -1,5 +1,8 @@
--TEST--
Bug #55156 (ReflectionClass::getDocComment() returns comment even though the class has none)
--INI--
opcache.save_comments=1
opcache.load_comments=1
--FILE--
<?php
+13
View File
@@ -0,0 +1,13 @@
--TEST--
Bug #62343 (Show class_alias In get_declared_classes())
--FILE--
<?php
class a { }
class_alias("a", "b");
$c = get_declared_classes();
var_dump(end($c));
var_dump(prev($c));
?>
--EXPECT--
string(1) "b"
string(1) "a"
+20
View File
@@ -0,0 +1,20 @@
--TEST--
Bug #63976 (Parent class incorrectly using child constant in class property)
--FILE--
<?php
if (1) {
class Foo {
const TABLE = "foo";
public $table = self::TABLE;
}
}
if (1) {
class Bar extends Foo {
const TABLE = "bar";
}
}
$bar = new Bar();
var_dump($bar->table);
?>
--EXPECT--
string(3) "foo"
+28
View File
@@ -0,0 +1,28 @@
--TEST--
Bug #64239 (get_class_methods() changed behavior)
--FILE--
<?php
class A {
use T2 { t2method as Bmethod; }
}
class B extends A {
}
trait T2 {
public function t2method() {
}
}
print_r(get_class_methods("A"));
print_r(get_class_methods("B"));
--EXPECT--
Array
(
[0] => Bmethod
[1] => t2method
)
Array
(
[0] => Bmethod
[1] => t2method
)
+58
View File
@@ -0,0 +1,58 @@
--TEST--
Bug #64239 (debug_backtrace() changed behavior)
--FILE--
<?php
class A {
use T1;
public function test() { $this->backtrace(); }
}
class B {
use T2 { t2method as Bmethod; }
}
class C extends A {
}
trait T1 {
protected function backtrace() {
$b = new B();
$b->Bmethod();
}
}
trait T2 {
public function t2method() {
print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1));
}
}
$a = new A();
$a->test();
$c = new C();
$c->test();
?>
--EXPECTF--
Array
(
[0] => Array
(
[file] => %sbug64239_2.php
[line] => %d
[function] => Bmethod
[class] => B
[type] => ->
)
)
Array
(
[0] => Array
(
[file] => %sbug64239_2.php
[line] => %d
[function] => Bmethod
[class] => B
[type] => ->
)
)
+33
View File
@@ -0,0 +1,33 @@
--TEST--
Bug #64239 (debug_print_backtrace() changed behavior)
--FILE--
<?php
class A {
use T2 { t2method as Bmethod; }
}
class C extends A {
public function Bmethod() {
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
}
}
trait T2 {
public function t2method() {
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
}
}
$a = new A();
$a->Bmethod();
$a->t2method();
$c = new C();
$c->Bmethod();
$c->t2method();
?>
--EXPECTF--
#0 A->Bmethod() called at [%sbug64239_3.php:%d]
#0 A->t2method() called at [%sbug64239_3.php:%d]
#0 C->Bmethod() called at [%sbug64239_3.php:%d]
#0 A->t2method() called at [%sbug64239_3.php:%d]
+31
View File
@@ -0,0 +1,31 @@
--TEST--
Bug #64239 (debug_print_backtrace() changed behavior)
--FILE--
<?php
class A {
use T2 { t2method as Bmethod; }
}
class C extends A {
public static function Bmethod() {
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
}
}
trait T2 {
public static function t2method() {
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
}
}
A::Bmethod();
A::t2method();
C::Bmethod();
C::t2method();
?>
--EXPECTF--
#0 A::Bmethod() called at [%sbug64239_4.php:%d]
#0 A::t2method() called at [%sbug64239_4.php:%d]
#0 C::Bmethod() called at [%sbug64239_4.php:%d]
#0 A::t2method() called at [%sbug64239_4.php:%d]
+39
View File
@@ -0,0 +1,39 @@
--TEST--
Bug #64417 (BC break: ArrayAccess::&offsetGet() in a trait causes fatal error)
--FILE--
<?php
trait aa {
private $container = array();
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function &offsetGet($offset) {
$result = null;
if (isset($this->container[$offset])) {
$result = &$this->container[$offset];
}
return $result;
}
}
class obj implements ArrayAccess {
use aa;
}
$o = new obj;
$o['x'] = 1;
++$o['x'];
echo $o['x'], "\n";
--EXPECT--
2
+12
View File
@@ -0,0 +1,12 @@
--TEST--
Bug #64515 (Memoryleak when using the same variablename 2times in function declaration)
--FILE--
<?php
function foo($unused = null, $unused = null, $arg = array()) {
return 1;
}
foo();
echo "okey";
?>
--EXPECT--
okey
+7 -24
View File
@@ -1,32 +1,15 @@
--TEST--
Generators can be cloned
Generators cannot be cloned
--FILE--
<?php
function firstN($end) {
for ($i = 0; $i < $end; ++$i) {
yield $i;
}
function gen() {
yield;
}
$g1 = firstN(5);
var_dump($g1->current());
$g1->next();
$g2 = clone $g1;
var_dump($g2->current());
$g2->next();
var_dump($g2->current());
var_dump($g1->current());
$g1->next();
var_dump($g1->current());
$gen = gen();
clone $gen;
?>
--EXPECT--
int(0)
int(1)
int(2)
int(1)
int(2)
--EXPECTF--
Fatal error: Trying to clone an uncloneable object of class Generator in %s on line %d
@@ -1,20 +0,0 @@
--TEST--
Cloning a generator after an object method was called
--FILE--
<?php
class A { public function b() { } }
function gen() {
$a = new A;
$a->b();
yield;
}
$g1 = gen();
$g1->rewind();
$g2 = clone $g1;
echo "Done";
--EXPECT--
Done
@@ -1,33 +0,0 @@
--TEST--
Cloning a generator with a foreach loop properly adds a ref for the loop var
--FILE--
<?php
function gen() {
foreach ([1, 2, 3] as $i) {
yield $i;
}
}
$g1 = gen();
var_dump($g1->current());
$g2 = clone $g1;
var_dump($g2->current());
$g1->next();
$g2->next();
var_dump($g1->current());
var_dump($g2->current());
unset($g1);
$g2->next();
var_dump($g2->current());
?>
--EXPECT--
int(1)
int(1)
int(2)
int(2)
int(3)
@@ -1,18 +0,0 @@
--TEST--
Tests cloning a generator with properties
--FILE--
<?php
function gen() { yield; }
$g1 = gen();
$g1->prop = 'val';
$g2 = clone $g1;
unset($g1);
var_dump($g2->prop);
?>
--EXPECT--
string(3) "val"
@@ -1,18 +0,0 @@
--TEST--
A generator with an active stack can be cloned
--FILE--
<?php
function gen() {
var_dump(str_repeat("x", yield));
}
$g1 = gen();
$g1->rewind();
$g2 = clone $g1;
unset($g1);
$g2->send(10);
?>
--EXPECT--
string(10) "xxxxxxxxxx"
@@ -1,27 +0,0 @@
--TEST--
A generator using a symbol table can be cloned
--FILE--
<?php
function gen() {
// force compiled variable for $foo
$foo = 'foo';
// force symbol table
extract(['foo' => 'bar']);
// interrupt
yield;
var_dump($foo);
}
$g1 = gen();
$g1->rewind();
$g2 = clone $g1;
unset($g1);
$g2->next();
?>
--EXPECT--
string(3) "bar"
@@ -1,24 +0,0 @@
--TEST--
Cloning a generator method (with $this)
--FILE--
<?php
class Test {
protected $foo;
public function gen() {
$this->foo = 'bar';
yield; // interrupt
var_dump($this->foo);
}
}
$g1 = (new Test)->gen();
$g1->rewind(); // goto yield
$g2 = clone $g1;
unset($g1);
$g2->next();
?>
--EXPECT--
string(3) "bar"
@@ -0,0 +1,52 @@
--TEST--
Generators can return non-scalar keys
--FILE--
<?php
function gen() {
yield [1, 2, 3] => [4, 5, 6];
yield (object) ['a' => 'b'] => (object) ['b' => 'a'];
yield 3.14 => 2.73;
yield false => true;
yield true => false;
yield null => null;
}
foreach (gen() as $k => $v) {
var_dump($k, $v);
}
?>
--EXPECT--
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
array(3) {
[0]=>
int(4)
[1]=>
int(5)
[2]=>
int(6)
}
object(stdClass)#3 (1) {
["a"]=>
string(1) "b"
}
object(stdClass)#4 (1) {
["b"]=>
string(1) "a"
}
float(3.14)
float(2.73)
bool(false)
bool(true)
bool(true)
bool(false)
NULL
NULL
@@ -26,10 +26,7 @@ $g2 = gen(new B);
$g2->current();
$g1->next();
$g3 = clone $g2;
unset($g2);
$g3->next();
$g2->next();
?>
--EXPECT--
@@ -22,14 +22,6 @@ $gen = gen();
$gen->rewind();
unset($gen);
// test cloning
$g1 = gen();
$g1->rewind();
$g2 = clone $g1;
unset($g1);
$g2->send('bar');
?>
--EXPECT--
foo
bar
+2
View File
@@ -1,5 +1,7 @@
--TEST--
026: Name ambiguity (class name & namespace name)
--INI--
opcache.optimization_level=0
--FILE--
<?php
namespace Foo;
+5 -2
View File
@@ -299,7 +299,6 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore
/*
* zval
*/
typedef struct _zval_struct zval;
typedef struct _zend_class_entry zend_class_entry;
typedef struct _zend_guard {
@@ -365,6 +364,10 @@ struct _zval_struct {
#define Z_UNSET_ISREF(z) Z_UNSET_ISREF_P(&(z))
#define Z_SET_ISREF_TO(z, isref) Z_SET_ISREF_TO_P(&(z), isref)
#if ZEND_DEBUG
#define zend_always_inline inline
#define zend_never_inline
#else
#if defined(__GNUC__)
#if __GNUC__ >= 3
#define zend_always_inline inline __attribute__((always_inline))
@@ -373,7 +376,6 @@ struct _zval_struct {
#define zend_always_inline inline
#define zend_never_inline
#endif
#elif defined(_MSC_VER)
#define zend_always_inline __forceinline
#define zend_never_inline
@@ -381,6 +383,7 @@ struct _zval_struct {
#define zend_always_inline inline
#define zend_never_inline
#endif
#endif /* ZEND_DEBUG */
#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
# define EXPECTED(condition) __builtin_expect(condition, 1)
+127 -2
View File
@@ -1051,6 +1051,41 @@ 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) {
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
if ((*scope)->parent) {
zend_class_entry *ce = *scope;
HashPosition pos;
zend_property_info *prop_info;
do {
for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS;
zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) &&
offset == prop_info->offset) {
int ret;
zend_class_entry *old_scope = *scope;
*scope = prop_info->ce;
ret = zval_update_constant(pp, (void*)1 TSRMLS_CC);
*scope = old_scope;
return ret;
}
}
ce = ce->parent;
} while (ce);
}
return zval_update_constant(pp, (void*)1 TSRMLS_CC);
}
return 0;
}
/* }}} */
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0 || (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count)) {
@@ -1063,7 +1098,7 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
for (i = 0; i < class_type->default_properties_count; i++) {
if (class_type->default_properties_table[i]) {
zval_update_constant(&class_type->default_properties_table[i], (void**)1 TSRMLS_CC);
zval_update_class_constant(&class_type->default_properties_table[i], 0, i TSRMLS_CC);
}
}
@@ -1104,7 +1139,7 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
}
for (i = 0; i < class_type->default_static_members_count; i++) {
zval_update_constant(&CE_STATIC_MEMBERS(class_type)[i], (void**)1 TSRMLS_CC);
zval_update_class_constant(&CE_STATIC_MEMBERS(class_type)[i], 1, i TSRMLS_CC);
}
*scope = old_scope;
@@ -1502,6 +1537,40 @@ ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint
}
/* }}} */
ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
{
int result;
switch (Z_TYPE_P(key)) {
case IS_STRING:
result = zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
break;
case IS_NULL:
result = zend_symtable_update(ht, "", 1, &value, sizeof(zval *), NULL);
break;
case IS_RESOURCE:
zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(key), Z_LVAL_P(key));
/* break missing intentionally */
case IS_BOOL:
case IS_LONG:
result = zend_hash_index_update(ht, Z_LVAL_P(key), &value, sizeof(zval *), NULL);
break;
case IS_DOUBLE:
result = zend_hash_index_update(ht, zend_dval_to_lval(Z_DVAL_P(key)), &value, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
result = FAILURE;
}
if (result == SUCCESS) {
Z_ADDREF_P(value);
}
return result;
}
/* }}} */
ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3907,6 +3976,62 @@ ZEND_API void zend_restore_error_handling(zend_error_handling *saved TSRMLS_DC)
}
/* }}} */
ZEND_API const char* zend_find_alias_name(zend_class_entry *ce, const char *name, zend_uint len) /* {{{ */
{
zend_trait_alias *alias, **alias_ptr;
alias_ptr = ce->trait_aliases;
alias = *alias_ptr;
while (alias) {
if (alias->alias_len == len &&
!strncasecmp(name, alias->alias, alias->alias_len)) {
return alias->alias;
}
alias_ptr++;
alias = *alias_ptr;
}
return name;
}
/* }}} */
ZEND_API const char* zend_resolve_method_name(zend_class_entry *ce, zend_function *f) /* {{{ */
{
zend_function *func;
HashPosition iterator;
HashTable *function_table;
if (f->common.type != ZEND_USER_FUNCTION ||
*(f->op_array.refcount) < 2 ||
!f->common.scope ||
!f->common.scope->trait_aliases) {
return f->common.function_name;
}
function_table = &ce->function_table;
zend_hash_internal_pointer_reset_ex(function_table, &iterator);
while (zend_hash_get_current_data_ex(function_table, (void **)&func, &iterator) == SUCCESS) {
if (func == f) {
char *name;
uint len;
ulong idx;
if (zend_hash_get_current_key_ex(function_table, &name, &len, &idx, 0, &iterator) != HASH_KEY_IS_STRING) {
return f->common.function_name;
}
--len;
if (len == strlen(f->common.function_name) &&
!strncasecmp(name, f->common.function_name, len)) {
return f->common.function_name;
}
return zend_find_alias_name(f->common.scope, name, len);
}
zend_hash_move_forward_ex(function_table, &iterator);
}
return f->common.function_name;
}
/* }}} */
/*
* Local variables:
* tab-width: 4
+5
View File
@@ -426,6 +426,8 @@ ZEND_API int add_get_index_double(zval *arg, ulong idx, double d, void **dest);
ZEND_API int add_get_index_string(zval *arg, ulong idx, const char *str, void **dest, int duplicate);
ZEND_API int add_get_index_stringl(zval *arg, ulong idx, const char *str, uint length, void **dest, int duplicate);
ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value);
ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long l TSRMLS_DC);
ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC);
ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC);
@@ -519,6 +521,9 @@ ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC);
ZEND_API void zend_rebuild_symbol_table(TSRMLS_D);
ZEND_API const char* zend_find_alias_name(zend_class_entry *ce, const char *name, zend_uint len);
ZEND_API const char* zend_resolve_method_name(zend_class_entry *ce, zend_function *f);
#define add_method(arg, key, method) add_assoc_function((arg), (key), (method))
ZEND_API ZEND_FUNCTION(display_disabled_function);
+47 -9
View File
@@ -1025,6 +1025,13 @@ ZEND_FUNCTION(get_object_vars)
}
/* }}} */
static int same_name(const char *key, const char *name, zend_uint name_len)
{
char *lcname = zend_str_tolower_dup(name, name_len);
int ret = memcmp(lcname, key, name_len) == 0;
efree(lcname);
return ret;
}
/* {{{ proto array get_class_methods(mixed class)
Returns an array of method names for class or class instance. */
@@ -1072,14 +1079,26 @@ ZEND_FUNCTION(get_class_methods)
uint len = strlen(mptr->common.function_name);
/* Do not display old-style inherited constructors */
if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 ||
mptr->common.scope == ce ||
zend_hash_get_current_key_ex(&ce->function_table, &key, &key_len, &num_index, 0, &pos) != HASH_KEY_IS_STRING ||
zend_binary_strcasecmp(key, key_len-1, mptr->common.function_name, len) == 0) {
if (zend_hash_get_current_key_ex(&ce->function_table, &key, &key_len, &num_index, 0, &pos) != HASH_KEY_IS_STRING) {
MAKE_STD_ZVAL(method_name);
ZVAL_STRINGL(method_name, mptr->common.function_name, len, 1);
zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL);
} else if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 ||
mptr->common.scope == ce ||
zend_binary_strcasecmp(key, key_len-1, mptr->common.function_name, len) == 0) {
if (mptr->type == ZEND_USER_FUNCTION &&
*mptr->op_array.refcount > 1 &&
(len != key_len - 1 ||
!same_name(key, mptr->common.function_name, len))) {
MAKE_STD_ZVAL(method_name);
ZVAL_STRINGL(method_name, zend_find_alias_name(mptr->common.scope, key, key_len - 1), key_len - 1, 1);
zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL);
} else {
MAKE_STD_ZVAL(method_name);
ZVAL_STRINGL(method_name, mptr->common.function_name, len, 1);
zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL);
}
}
}
zend_hash_move_forward_ex(&ce->function_table, &pos);
@@ -1625,7 +1644,6 @@ ZEND_FUNCTION(restore_exception_handler)
}
/* }}} */
static int copy_class_or_interface_name(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
{
zval *array = va_arg(args, zval *);
@@ -1636,7 +1654,13 @@ static int copy_class_or_interface_name(zend_class_entry **pce TSRMLS_DC, int nu
if ((hash_key->nKeyLength==0 || hash_key->arKey[0]!=0)
&& (comply_mask == (ce->ce_flags & mask))) {
add_next_index_stringl(array, ce->name, ce->name_length, 1);
if (ce->refcount > 1 &&
(ce->name_length != hash_key->nKeyLength - 1 ||
!same_name(hash_key->arKey, ce->name, ce->name_length))) {
add_next_index_stringl(array, hash_key->arKey, hash_key->nKeyLength - 1, 1);
} else {
add_next_index_stringl(array, ce->name, ce->name_length, 1);
}
}
return ZEND_HASH_APPLY_KEEP;
}
@@ -2079,7 +2103,14 @@ ZEND_FUNCTION(debug_print_backtrace)
lineno = 0;
}
function_name = ptr->function_state.function->common.function_name;
function_name = (ptr->function_state.function->common.scope &&
ptr->function_state.function->common.scope->trait_aliases) ?
zend_resolve_method_name(
ptr->object ?
Z_OBJCE_P(ptr->object) :
ptr->function_state.function->common.scope,
ptr->function_state.function) :
ptr->function_state.function->common.function_name;
if (function_name) {
if (ptr->object) {
@@ -2260,7 +2291,14 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
filename = NULL;
}
function_name = ptr->function_state.function->common.function_name;
function_name = (ptr->function_state.function->common.scope &&
ptr->function_state.function->common.scope->trait_aliases) ?
zend_resolve_method_name(
ptr->object ?
Z_OBJCE_P(ptr->object) :
ptr->function_state.function->common.scope,
ptr->function_state.function) :
ptr->function_state.function->common.function_name;
if (function_name) {
add_assoc_string_ex(stack_frame, "function", sizeof("function"), (char*)function_name, 1);
+5 -4
View File
@@ -1809,7 +1809,7 @@ void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC) /*
zend_do_return(NULL, 0 TSRMLS_CC);
pass_two(CG(active_op_array) TSRMLS_CC);
zend_release_labels(TSRMLS_C);
zend_release_labels(0 TSRMLS_CC);
if (CG(active_class_entry)) {
zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC);
@@ -2391,13 +2391,14 @@ void zend_do_goto(const znode *label TSRMLS_DC) /* {{{ */
}
/* }}} */
void zend_release_labels(TSRMLS_D) /* {{{ */
void zend_release_labels(int temporary TSRMLS_DC) /* {{{ */
{
if (CG(context).labels) {
zend_hash_destroy(CG(context).labels);
FREE_HASHTABLE(CG(context).labels);
CG(context).labels = NULL;
}
if (!zend_stack_is_empty(&CG(context_stack))) {
if (!temporary && !zend_stack_is_empty(&CG(context_stack))) {
zend_compiler_context *ctx;
zend_stack_top(&CG(context_stack), (void**)&ctx);
@@ -3831,7 +3832,7 @@ static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_
zend_uint other_flags = other_fn->common.scope->ce_flags;
return zend_do_perform_implementation_check(fn, other_fn TSRMLS_CC)
&& zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC)
&& ((other_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) || zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC))
&& ((fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC)) ==
(other_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC))); /* equal final and static qualifier */
}
+1 -1
View File
@@ -643,7 +643,7 @@ void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static
void zend_do_label(znode *label TSRMLS_DC);
void zend_do_goto(const znode *label TSRMLS_DC);
void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC);
void zend_release_labels(TSRMLS_D);
void zend_release_labels(int temporary TSRMLS_DC);
ZEND_API void function_add_ref(zend_function *function);
+4 -7
View File
@@ -898,13 +898,10 @@ static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value
} else if (EXPECTED(!PZVAL_IS_REF(value))) {
Z_ADDREF_P(value);
*variable_ptr_ptr = value;
if (EXPECTED(variable_ptr != &EG(uninitialized_zval))) {
GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr);
zval_dtor(variable_ptr);
efree(variable_ptr);
} else {
Z_DELREF_P(variable_ptr);
}
ZEND_ASSERT(variable_ptr != &EG(uninitialized_zval));
GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr);
zval_dtor(variable_ptr);
efree(variable_ptr);
return value;
} else {
goto copy_value;
+1 -1
View File
@@ -1295,7 +1295,7 @@ void execute_new_code(TSRMLS_D) /* {{{ */
opline++;
}
zend_release_labels(TSRMLS_C);
zend_release_labels(1 TSRMLS_CC);
EG(return_value_ptr_ptr) = NULL;
EG(active_op_array) = CG(active_op_array);
+6 -189
View File
@@ -196,175 +196,6 @@ static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /*
}
/* }}} */
static zend_object_value zend_generator_clone(zval *object TSRMLS_DC) /* {{{ */
{
zend_generator *orig = zend_object_store_get_object(object TSRMLS_CC);
zend_object_value clone_val = zend_generator_create(Z_OBJCE_P(object) TSRMLS_CC);
zend_generator *clone = zend_object_store_get_object_by_handle(clone_val.handle TSRMLS_CC);
zend_objects_clone_members(
&clone->std, clone_val, &orig->std, Z_OBJ_HANDLE_P(object) TSRMLS_CC
);
clone->execute_data = orig->execute_data;
clone->largest_used_integer_key = orig->largest_used_integer_key;
clone->flags = orig->flags;
if (orig->execute_data) {
/* Create a few shorter aliases to the old execution data */
zend_execute_data *execute_data = orig->execute_data;
zend_op_array *op_array = execute_data->op_array;
HashTable *symbol_table = execute_data->symbol_table;
zend_execute_data *current_execute_data;
zend_op **opline_ptr;
HashTable *current_symbol_table;
zend_vm_stack current_stack;
zval *current_this;
void **stack_frame, **orig_stack_frame;
/* Create new execution context. We have to back up and restore
* EG(current_execute_data), EG(opline_ptr), EG(active_symbol_table)
* and EG(This) here because the function modifies or uses them */
current_execute_data = EG(current_execute_data);
EG(current_execute_data) = execute_data->prev_execute_data;
opline_ptr = EG(opline_ptr);
current_symbol_table = EG(active_symbol_table);
EG(active_symbol_table) = execute_data->symbol_table;
current_this = EG(This);
EG(This) = NULL;
current_stack = EG(argument_stack);
clone->execute_data = zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC);
clone->stack = EG(argument_stack);
EG(argument_stack) = current_stack;
EG(This) = current_this;
EG(active_symbol_table) = current_symbol_table;
EG(current_execute_data) = current_execute_data;
EG(opline_ptr) = opline_ptr;
/* copy */
clone->execute_data->opline = execute_data->opline;
clone->execute_data->function_state = execute_data->function_state;
clone->execute_data->object = execute_data->object;
clone->execute_data->current_scope = execute_data->current_scope;
clone->execute_data->current_called_scope = execute_data->current_called_scope;
clone->execute_data->fast_ret = execute_data->fast_ret;
if (!symbol_table) {
int i;
/* Copy compiled variables */
for (i = 0; i < op_array->last_var; i++) {
if (*EX_CV_NUM(execute_data, i)) {
*EX_CV_NUM(clone->execute_data, i) = (zval **) EX_CV_NUM(clone->execute_data, op_array->last_var + i);
**EX_CV_NUM(clone->execute_data, i) = *(zval **) EX_CV_NUM(execute_data, op_array->last_var + i);
Z_ADDREF_PP(*EX_CV_NUM(clone->execute_data, i));
}
}
} else {
/* Copy symbol table */
ALLOC_HASHTABLE(clone->execute_data->symbol_table);
zend_hash_init(clone->execute_data->symbol_table, zend_hash_num_elements(symbol_table), NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(clone->execute_data->symbol_table, symbol_table, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
/* Update zval** pointers for compiled variables */
{
int i;
for (i = 0; i < op_array->last_var; i++) {
if (zend_hash_quick_find(clone->execute_data->symbol_table, op_array->vars[i].name, op_array->vars[i].name_len + 1, op_array->vars[i].hash_value, (void **) EX_CV_NUM(clone->execute_data, i)) == FAILURE) {
*EX_CV_NUM(clone->execute_data, i) = NULL;
}
}
}
}
/* Copy nested-calls stack */
if (execute_data->call) {
clone->execute_data->call = clone->execute_data->call_slots +
(execute_data->call - execute_data->call_slots);
} else {
clone->execute_data->call = NULL;
}
memcpy(clone->execute_data->call_slots, execute_data->call_slots, ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls);
if (clone->execute_data->call >= clone->execute_data->call_slots) {
call_slot *call = clone->execute_data->call;
while (call >= clone->execute_data->call_slots) {
if (call->object) {
Z_ADDREF_P(call->object);
}
call--;
}
}
/* Copy the temporary variables */
memcpy(EX_TMP_VAR_NUM(clone->execute_data, op_array->T-1), EX_TMP_VAR_NUM(execute_data, op_array->T-1), ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T);
/* Copy arguments passed on stack */
stack_frame = zend_vm_stack_frame_base(clone->execute_data);
orig_stack_frame = zend_vm_stack_frame_base(execute_data);
clone->stack->top = stack_frame + (orig->stack->top - orig_stack_frame);
if (clone->stack->top != stack_frame) {
memcpy(stack_frame, orig_stack_frame, ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (orig->stack->top - orig_stack_frame));
while (clone->stack->top != stack_frame) {
Z_ADDREF_PP((zval**)stack_frame);
stack_frame++;
}
}
/* Add references to loop variables */
{
zend_uint op_num = execute_data->opline - op_array->opcodes;
int i;
for (i = 0; i < op_array->last_brk_cont; ++i) {
zend_brk_cont_element *brk_cont = op_array->brk_cont_array + i;
if (brk_cont->start < 0) {
continue;
} else if (brk_cont->start > op_num) {
break;
} else if (brk_cont->brk > op_num) {
zend_op *brk_opline = op_array->opcodes + brk_cont->brk;
if (brk_opline->opcode == ZEND_SWITCH_FREE) {
temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var);
Z_ADDREF_P(var->var.ptr);
}
}
}
}
/* Update the send_target to use the temporary variable with the same
* offset as the original generator, but in our temporary variable
* memory segment. */
if (orig->send_target) {
size_t offset = (char *) orig->send_target - (char *)execute_data;
clone->send_target = EX_TMP_VAR(clone->execute_data, offset);
zval_copy_ctor(&clone->send_target->tmp_var);
}
if (execute_data->current_this) {
clone->execute_data->current_this = execute_data->current_this;
Z_ADDREF_P(execute_data->current_this);
}
}
/* The value and key are known not to be references, so simply add refs */
if (orig->value) {
clone->value = orig->value;
Z_ADDREF_P(orig->value);
}
if (orig->key) {
clone->key = orig->key;
Z_ADDREF_P(orig->key);
}
return clone_val;
}
/* }}} */
static zend_object_value zend_generator_create(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
zend_generator *generator;
@@ -755,31 +586,17 @@ static void zend_generator_iterator_get_data(zend_object_iterator *iterator, zva
}
/* }}} */
static int zend_generator_iterator_get_key(zend_object_iterator *iterator, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
static void zend_generator_iterator_get_key(zend_object_iterator *iterator, zval *key TSRMLS_DC) /* {{{ */
{
zend_generator *generator = (zend_generator *) iterator->data;
zend_generator_ensure_initialized(generator TSRMLS_CC);
if (!generator->key) {
return HASH_KEY_NON_EXISTANT;
if (generator->key) {
ZVAL_ZVAL(key, generator->key, 1, 0);
} else {
ZVAL_NULL(key);
}
if (Z_TYPE_P(generator->key) == IS_LONG) {
*int_key = Z_LVAL_P(generator->key);
return HASH_KEY_IS_LONG;
}
if (Z_TYPE_P(generator->key) == IS_STRING) {
*str_key = estrndup(Z_STRVAL_P(generator->key), Z_STRLEN_P(generator->key));
*str_key_len = Z_STRLEN_P(generator->key) + 1;
return HASH_KEY_IS_STRING;
}
/* Waiting for Etienne's patch to allow arbitrary zval keys. Until then
* error out on non-int and non-string keys. */
zend_error_noreturn(E_ERROR, "Currently only int and string keys can be yielded");
return HASH_KEY_NON_EXISTANT; /* Nerver reached */
}
/* }}} */
@@ -881,7 +698,7 @@ void zend_register_generator_ce(TSRMLS_D) /* {{{ */
memcpy(&zend_generator_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
zend_generator_handlers.get_constructor = zend_generator_get_constructor;
zend_generator_handlers.clone_obj = zend_generator_clone;
zend_generator_handlers.clone_obj = NULL;
}
/* }}} */
+18
View File
@@ -1171,6 +1171,24 @@ ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, char **str_index,
return HASH_KEY_NON_EXISTANT;
}
ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) {
Bucket *p;
IS_CONSISTENT(ht);
p = pos ? (*pos) : ht->pInternalPointer;
if (!p) {
Z_TYPE_P(key) = IS_NULL;
} else if (p->nKeyLength) {
Z_TYPE_P(key) = IS_STRING;
Z_STRVAL_P(key) = IS_INTERNED(p->arKey) ? (char *) p->arKey : estrndup(p->arKey, p->nKeyLength - 1);
Z_STRLEN_P(key) = p->nKeyLength - 1;
} else {
Z_TYPE_P(key) = IS_LONG;
Z_LVAL_P(key) = p->h;
}
}
ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
{
+3 -1
View File
@@ -170,13 +170,13 @@ ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint
ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h);
ZEND_API ulong zend_hash_next_free_element(const HashTable *ht);
/* traversing */
#define zend_hash_has_more_elements_ex(ht, pos) \
(zend_hash_get_current_key_type_ex(ht, pos) == HASH_KEY_NON_EXISTANT ? FAILURE : SUCCESS)
ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos);
ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos);
ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, char **str_index, uint *str_length, ulong *num_index, zend_bool duplicate, HashPosition *pos);
ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos);
ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos);
ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos);
ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos);
@@ -199,6 +199,8 @@ ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr);
zend_hash_move_backwards_ex(ht, NULL)
#define zend_hash_get_current_key(ht, str_index, num_index, duplicate) \
zend_hash_get_current_key_ex(ht, str_index, NULL, num_index, duplicate, NULL)
#define zend_hash_get_current_key_zval(ht, key) \
zend_hash_get_current_key_zval_ex(ht, key, NULL)
#define zend_hash_get_current_key_type(ht) \
zend_hash_get_current_key_type_ex(ht, NULL)
#define zend_hash_get_current_data(ht, pData) \
+5 -1
View File
@@ -67,6 +67,9 @@ static void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
case '&':
i_result = i_op1 & i_op2;
break;
case '^':
i_result = i_op1 ^ i_op2;
break;
case '~':
i_result = ~i_op1;
break;
@@ -264,7 +267,7 @@ ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, int s
%token BOOL_FALSE
%token END_OF_LINE
%token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@' '{' '}'
%left '|' '&'
%left '|' '&' '^'
%right '~' '!'
%%
@@ -348,6 +351,7 @@ expr:
var_string_list { $$ = $1; }
| expr '|' expr { zend_ini_do_op('|', &$$, &$1, &$3); }
| expr '&' expr { zend_ini_do_op('&', &$$, &$1, &$3); }
| expr '^' expr { zend_ini_do_op('^', &$$, &$1, &$3); }
| '~' expr { zend_ini_do_op('~', &$$, &$2, NULL); }
| '!' expr { zend_ini_do_op('!', &$$, &$2, NULL); }
| '(' expr ')' { $$ = $2; }
+405 -358
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -340,9 +340,9 @@ NEWLINE ("\r"|"\n"|"\r\n")
TABS_AND_SPACES [ \t]
WHITESPACE [ \t]+
CONSTANT [a-zA-Z_][a-zA-Z0-9_]*
LABEL [^=\n\r\t;|&$~(){}!"\[]+
TOKENS [:,.\[\]"'()|^&+-/*=%$!~<>?@{}]
OPERATORS [&|~()!]
LABEL [^=\n\r\t;&|^$~(){}!"\[]+
TOKENS [:,.\[\]"'()&|^+-/*=%$!~<>?@{}]
OPERATORS [&|^~()!]
DOLLAR_CURLY "${"
SECTION_RAW_CHARS [^\]\n\r]
@@ -350,7 +350,7 @@ SINGLE_QUOTED_CHARS [^']
RAW_VALUE_CHARS [^\n\r;\000]
LITERAL_DOLLAR ("$"([^{\000]|("\\"{ANY_CHAR})))
VALUE_CHARS ([^$= \t\n\r;&|~()!"'\000]|{LITERAL_DOLLAR})
VALUE_CHARS ([^$= \t\n\r;&|^~()!"'\000]|{LITERAL_DOLLAR})
SECTION_VALUE_CHARS ([^$\n\r;"'\]\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
<!*> := yyleng = YYCURSOR - SCNG(yy_text);
+6 -32
View File
@@ -195,7 +195,7 @@ static int zend_user_it_get_current_key_default(zend_object_iterator *_iter, cha
/* }}} */
/* {{{ zend_user_it_get_current_key */
ZEND_API int zend_user_it_get_current_key(zend_object_iterator *_iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *key TSRMLS_DC)
{
zend_user_iterator *iter = (zend_user_iterator*)_iter;
zval *object = (zval*)iter->it.data;
@@ -203,42 +203,16 @@ ZEND_API int zend_user_it_get_current_key(zend_object_iterator *_iter, char **st
zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_key, "key", &retval);
if (!retval) {
*int_key = 0;
if (!EG(exception))
{
if (retval) {
ZVAL_ZVAL(key, retval, 1, 1);
} else {
if (!EG(exception)) {
zend_error(E_WARNING, "Nothing returned from %s::key()", iter->ce->name);
}
return HASH_KEY_IS_LONG;
}
switch (Z_TYPE_P(retval)) {
default:
zend_error(E_WARNING, "Illegal type returned from %s::key()", iter->ce->name);
case IS_NULL:
*int_key = 0;
zval_ptr_dtor(&retval);
return HASH_KEY_IS_LONG;
case IS_STRING:
*str_key = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
*str_key_len = Z_STRLEN_P(retval)+1;
zval_ptr_dtor(&retval);
return HASH_KEY_IS_STRING;
case IS_DOUBLE:
*int_key = (long)Z_DVAL_P(retval);
zval_ptr_dtor(&retval);
return HASH_KEY_IS_LONG;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
*int_key = (long)Z_LVAL_P(retval);
zval_ptr_dtor(&retval);
return HASH_KEY_IS_LONG;
ZVAL_LONG(key, 0);
}
}
/* }}} */
/* {{{ zend_user_it_move_forward */
ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC)
+1 -1
View File
@@ -51,7 +51,7 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter TSRMLS_DC);
ZEND_API int zend_user_it_valid(zend_object_iterator *_iter TSRMLS_DC);
ZEND_API int zend_user_it_get_current_key(zend_object_iterator *_iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC);
ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *key TSRMLS_DC);
ZEND_API void zend_user_it_get_current_data(zend_object_iterator *_iter, zval ***data TSRMLS_DC);
ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC);
ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter TSRMLS_DC);
+5 -2
View File
@@ -38,8 +38,11 @@ typedef struct _zend_object_iterator_funcs {
/* fetch the item data for the current element */
void (*get_current_data)(zend_object_iterator *iter, zval ***data TSRMLS_DC);
/* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */
int (*get_current_key)(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC);
/* fetch the key for the current element (optional, may be NULL). The key
* should be written into the provided zval* using the ZVAL_* macros. If
* this handler is not provided auto-incrementing integer keys will be
* used. */
void (*get_current_key)(zend_object_iterator *iter, zval *key TSRMLS_DC);
/* step forwards to next element */
void (*move_forward)(zend_object_iterator *iter TSRMLS_DC);
+7 -5
View File
@@ -41,17 +41,19 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
#define YYERROR_VERBOSE
#define YYSTYPE znode
#ifdef ZTS
# define YYPARSE_PARAM tsrm_ls
# define YYLEX_PARAM tsrm_ls
#endif
%}
%pure_parser
%expect 3
%code requires {
#ifdef ZTS
# define YYPARSE_PARAM tsrm_ls
# define YYLEX_PARAM tsrm_ls
#endif
}
%token END 0 "end of file"
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
%token T_INCLUDE "include (T_INCLUDE)"
+2 -2
View File
@@ -597,7 +597,7 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
CG(active_op_array) = original_active_op_array;
if (compilation_successful) {
pass_two(op_array TSRMLS_CC);
zend_release_labels(TSRMLS_C);
zend_release_labels(0 TSRMLS_CC);
} else {
efree(op_array);
retval = NULL;
@@ -772,7 +772,7 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
zend_do_return(NULL, 0 TSRMLS_CC);
CG(active_op_array) = original_active_op_array;
pass_two(op_array TSRMLS_CC);
zend_release_labels(TSRMLS_C);
zend_release_labels(0 TSRMLS_CC);
retval = op_array;
}
}
+2 -2
View File
@@ -595,7 +595,7 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
CG(active_op_array) = original_active_op_array;
if (compilation_successful) {
pass_two(op_array TSRMLS_CC);
zend_release_labels(TSRMLS_C);
zend_release_labels(0 TSRMLS_CC);
} else {
efree(op_array);
retval = NULL;
@@ -770,7 +770,7 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
zend_do_return(NULL, 0 TSRMLS_CC);
CG(active_op_array) = original_active_op_array;
pass_two(op_array TSRMLS_CC);
zend_release_labels(TSRMLS_C);
zend_release_labels(0 TSRMLS_CC);
retval = op_array;
}
}
+1
View File
@@ -52,6 +52,7 @@ typedef unsigned long zend_uintptr_t;
typedef unsigned int zend_object_handle;
typedef struct _zend_object_handlers zend_object_handlers;
typedef struct _zval_struct zval;
typedef struct _zend_object_value {
zend_object_handle handle;
+54 -76
View File
@@ -1967,13 +1967,6 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
LOAD_OPLINE();
if (fbc->type == ZEND_INTERNAL_FUNCTION) {
temp_variable *ret = &EX_T(opline->result.var);
MAKE_STD_ZVAL(ret->var.ptr);
ZVAL_NULL(ret->var.ptr);
ret->var.ptr_ptr = &ret->var.ptr;
ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
if (fbc->common.arg_info) {
zend_uint i=0;
zval **p = (zval**)EX(function_state).arguments;
@@ -1985,15 +1978,24 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
}
}
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
}
if (EXPECTED(EG(exception) == NULL)) {
temp_variable *ret = &EX_T(opline->result.var);
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(&ret->var.ptr);
MAKE_STD_ZVAL(ret->var.ptr);
ZVAL_NULL(ret->var.ptr);
ret->var.ptr_ptr = &ret->var.ptr;
ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
}
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(&ret->var.ptr);
}
}
} else if (fbc->type == ZEND_USER_FUNCTION) {
EX(original_return_value) = EG(return_value_ptr_ptr);
@@ -2839,17 +2841,17 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
if (OP1_TYPE == IS_TMP_VAR) {
FREE_OP1();
}
} else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */
if (*EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
} else {
if (OP1_TYPE == IS_CONST ||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
OP1_TYPE == IS_TMP_VAR ||
PZVAL_IS_REF(retval_ptr)) {
zval *ret;
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
zval_copy_ctor(ret);
if (OP1_TYPE != IS_TMP_VAR) {
zval_copy_ctor(ret);
}
*EG(return_value_ptr_ptr) = ret;
} else if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) &&
retval_ptr == &EG(uninitialized_zval)) {
@@ -2861,16 +2863,6 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
*EG(return_value_ptr_ptr) = retval_ptr;
Z_ADDREF_P(retval_ptr);
}
} else {
zval *ret;
if (*EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
*EG(return_value_ptr_ptr) = ret;
}
FREE_OP1_IF_VAR();
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
@@ -2886,10 +2878,6 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
SAVE_OPLINE();
do {
if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
/* Not supposed to happen, but we'll allow it */
zend_error(E_NOTICE, "Only variable references should be returned by reference");
@@ -3274,7 +3262,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC);
var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
Z_DELREF_PP(var_ptr);
zval_ptr_dtor(var_ptr);
*var_ptr = assignment_value;
CHECK_EXCEPTION();
@@ -4245,13 +4233,13 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
zend_free_op free_op1;
zval *array = EX_T(opline->op1.var).fe.ptr;
zval **value;
char *str_key;
uint str_key_len;
ulong int_key;
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
int key_type = 0;
zend_bool use_key = (zend_bool)(opline->extended_value & ZEND_FE_FETCH_WITH_KEY);
zval *key = NULL;
if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
key = &EX_T((opline+1)->result.var).tmp_var;
}
SAVE_OPLINE();
@@ -4262,8 +4250,11 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
case ZEND_ITER_PLAIN_OBJECT: {
const char *class_name, *prop_name;
zend_object *zobj = zend_objects_get_address(array TSRMLS_CC);
int key_type;
char *str_key;
zend_uint str_key_len;
zend_ulong int_key;
fe_ht = Z_OBJPROP_P(array);
zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
@@ -4275,15 +4266,23 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
zend_hash_move_forward(fe_ht);
} while (key_type == HASH_KEY_NON_EXISTANT ||
(key_type != HASH_KEY_IS_LONG &&
zend_check_property_access(zobj, str_key, str_key_len-1 TSRMLS_CC) != SUCCESS));
zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
if (use_key && key_type != HASH_KEY_IS_LONG) {
zend_unmangle_property_name_ex(str_key, str_key_len-1, &class_name, &prop_name, &str_key_len);
str_key = estrndup(prop_name, str_key_len);
str_key_len++;
} while (key_type != HASH_KEY_IS_LONG &&
zend_check_property_access(zobj, str_key, str_key_len - 1 TSRMLS_CC) != SUCCESS);
if (key) {
if (key_type == HASH_KEY_IS_LONG) {
ZVAL_LONG(key, int_key);
} else {
const char *class_name, *prop_name;
int prop_name_len;
zend_unmangle_property_name_ex(
str_key, str_key_len - 1, &class_name, &prop_name, &prop_name_len
);
ZVAL_STRINGL(key, prop_name, prop_name_len, 1);
}
}
zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
break;
}
@@ -4294,8 +4293,8 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
/* reached end of iteration */
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
if (use_key) {
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL);
if (key) {
zend_hash_get_current_key_zval(fe_ht, key);
}
zend_hash_move_forward(fe_ht);
zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
@@ -4330,16 +4329,15 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
/* failure in get_current_data */
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
if (use_key) {
if (key) {
if (iter->funcs->get_current_key) {
key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
iter->funcs->get_current_key(iter, key TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
HANDLE_EXCEPTION();
}
} else {
key_type = HASH_KEY_IS_LONG;
int_key = iter->index;
ZVAL_LONG(key, iter->index);
}
}
break;
@@ -4355,26 +4353,6 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
AI_SET_PTR(&EX_T(opline->result.var), *value);
}
if (use_key) {
zval *key = &EX_T((opline+1)->result.var).tmp_var;
switch (key_type) {
case HASH_KEY_IS_STRING:
Z_STRVAL_P(key) = (char*)str_key;
Z_STRLEN_P(key) = str_key_len-1;
Z_TYPE_P(key) = IS_STRING;
break;
case HASH_KEY_IS_LONG:
Z_LVAL_P(key) = int_key;
Z_TYPE_P(key) = IS_LONG;
break;
default:
case HASH_KEY_NON_EXISTANT:
ZVAL_NULL(key);
break;
}
}
CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
+72 -136
View File
@@ -519,13 +519,6 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
LOAD_OPLINE();
if (fbc->type == ZEND_INTERNAL_FUNCTION) {
temp_variable *ret = &EX_T(opline->result.var);
MAKE_STD_ZVAL(ret->var.ptr);
ZVAL_NULL(ret->var.ptr);
ret->var.ptr_ptr = &ret->var.ptr;
ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
if (fbc->common.arg_info) {
zend_uint i=0;
zval **p = (zval**)EX(function_state).arguments;
@@ -537,15 +530,24 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
}
}
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
}
if (EXPECTED(EG(exception) == NULL)) {
temp_variable *ret = &EX_T(opline->result.var);
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(&ret->var.ptr);
MAKE_STD_ZVAL(ret->var.ptr);
ZVAL_NULL(ret->var.ptr);
ret->var.ptr_ptr = &ret->var.ptr;
ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
}
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(&ret->var.ptr);
}
}
} else if (fbc->type == ZEND_USER_FUNCTION) {
EX(original_return_value) = EG(return_value_ptr_ptr);
@@ -1404,7 +1406,7 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC);
var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
Z_DELREF_PP(var_ptr);
zval_ptr_dtor(var_ptr);
*var_ptr = assignment_value;
CHECK_EXCEPTION();
@@ -2333,17 +2335,17 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
if (IS_CONST == IS_TMP_VAR) {
}
} else if (!0) { /* Not a temp var */
if (*EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
} else {
if (IS_CONST == IS_CONST ||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
IS_CONST == IS_TMP_VAR ||
PZVAL_IS_REF(retval_ptr)) {
zval *ret;
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
zval_copy_ctor(ret);
if (IS_CONST != IS_TMP_VAR) {
zval_copy_ctor(ret);
}
*EG(return_value_ptr_ptr) = ret;
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) &&
retval_ptr == &EG(uninitialized_zval)) {
@@ -2355,16 +2357,6 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
*EG(return_value_ptr_ptr) = retval_ptr;
Z_ADDREF_P(retval_ptr);
}
} else {
zval *ret;
if (*EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
*EG(return_value_ptr_ptr) = ret;
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -2380,10 +2372,6 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
SAVE_OPLINE();
do {
if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
/* Not supposed to happen, but we'll allow it */
zend_error(E_NOTICE, "Only variable references should be returned by reference");
@@ -7654,17 +7642,17 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (IS_TMP_VAR == IS_TMP_VAR) {
zval_dtor(free_op1.var);
}
} else if (!1) { /* Not a temp var */
if (*EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
} else {
if (IS_TMP_VAR == IS_CONST ||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
IS_TMP_VAR == IS_TMP_VAR ||
PZVAL_IS_REF(retval_ptr)) {
zval *ret;
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
zval_copy_ctor(ret);
if (IS_TMP_VAR != IS_TMP_VAR) {
zval_copy_ctor(ret);
}
*EG(return_value_ptr_ptr) = ret;
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) &&
retval_ptr == &EG(uninitialized_zval)) {
@@ -7676,16 +7664,6 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
*EG(return_value_ptr_ptr) = retval_ptr;
Z_ADDREF_P(retval_ptr);
}
} else {
zval *ret;
if (*EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
*EG(return_value_ptr_ptr) = ret;
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -7701,10 +7679,6 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
SAVE_OPLINE();
do {
if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
/* Not supposed to happen, but we'll allow it */
zend_error(E_NOTICE, "Only variable references should be returned by reference");
@@ -12888,17 +12862,17 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (IS_VAR == IS_TMP_VAR) {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
}
} else if (!0) { /* Not a temp var */
if (*EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
} else {
if (IS_VAR == IS_CONST ||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
IS_VAR == IS_TMP_VAR ||
PZVAL_IS_REF(retval_ptr)) {
zval *ret;
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
zval_copy_ctor(ret);
if (IS_VAR != IS_TMP_VAR) {
zval_copy_ctor(ret);
}
*EG(return_value_ptr_ptr) = ret;
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) &&
retval_ptr == &EG(uninitialized_zval)) {
@@ -12910,16 +12884,6 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
*EG(return_value_ptr_ptr) = retval_ptr;
Z_ADDREF_P(retval_ptr);
}
} else {
zval *ret;
if (*EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
*EG(return_value_ptr_ptr) = ret;
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -12935,10 +12899,6 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
SAVE_OPLINE();
do {
if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
/* Not supposed to happen, but we'll allow it */
zend_error(E_NOTICE, "Only variable references should be returned by reference");
@@ -13588,13 +13548,13 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
zval *array = EX_T(opline->op1.var).fe.ptr;
zval **value;
char *str_key;
uint str_key_len;
ulong int_key;
HashTable *fe_ht;
zend_object_iterator *iter = NULL;
int key_type = 0;
zend_bool use_key = (zend_bool)(opline->extended_value & ZEND_FE_FETCH_WITH_KEY);
zval *key = NULL;
if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
key = &EX_T((opline+1)->result.var).tmp_var;
}
SAVE_OPLINE();
@@ -13605,8 +13565,11 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
case ZEND_ITER_PLAIN_OBJECT: {
const char *class_name, *prop_name;
zend_object *zobj = zend_objects_get_address(array TSRMLS_CC);
int key_type;
char *str_key;
zend_uint str_key_len;
zend_ulong int_key;
fe_ht = Z_OBJPROP_P(array);
zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
@@ -13618,15 +13581,23 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
zend_hash_move_forward(fe_ht);
} while (key_type == HASH_KEY_NON_EXISTANT ||
(key_type != HASH_KEY_IS_LONG &&
zend_check_property_access(zobj, str_key, str_key_len-1 TSRMLS_CC) != SUCCESS));
zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
if (use_key && key_type != HASH_KEY_IS_LONG) {
zend_unmangle_property_name_ex(str_key, str_key_len-1, &class_name, &prop_name, &str_key_len);
str_key = estrndup(prop_name, str_key_len);
str_key_len++;
} while (key_type != HASH_KEY_IS_LONG &&
zend_check_property_access(zobj, str_key, str_key_len - 1 TSRMLS_CC) != SUCCESS);
if (key) {
if (key_type == HASH_KEY_IS_LONG) {
ZVAL_LONG(key, int_key);
} else {
const char *class_name, *prop_name;
int prop_name_len;
zend_unmangle_property_name_ex(
str_key, str_key_len - 1, &class_name, &prop_name, &prop_name_len
);
ZVAL_STRINGL(key, prop_name, prop_name_len, 1);
}
}
zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
break;
}
@@ -13637,8 +13608,8 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* reached end of iteration */
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
if (use_key) {
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL);
if (key) {
zend_hash_get_current_key_zval(fe_ht, key);
}
zend_hash_move_forward(fe_ht);
zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
@@ -13673,16 +13644,15 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* failure in get_current_data */
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
if (use_key) {
if (key) {
if (iter->funcs->get_current_key) {
key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
iter->funcs->get_current_key(iter, key TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
HANDLE_EXCEPTION();
}
} else {
key_type = HASH_KEY_IS_LONG;
int_key = iter->index;
ZVAL_LONG(key, iter->index);
}
}
break;
@@ -13698,26 +13668,6 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
AI_SET_PTR(&EX_T(opline->result.var), *value);
}
if (use_key) {
zval *key = &EX_T((opline+1)->result.var).tmp_var;
switch (key_type) {
case HASH_KEY_IS_STRING:
Z_STRVAL_P(key) = (char*)str_key;
Z_STRLEN_P(key) = str_key_len-1;
Z_TYPE_P(key) = IS_STRING;
break;
case HASH_KEY_IS_LONG:
Z_LVAL_P(key) = int_key;
Z_TYPE_P(key) = IS_LONG;
break;
default:
case HASH_KEY_NON_EXISTANT:
ZVAL_NULL(key);
break;
}
}
CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
@@ -30534,17 +30484,17 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (IS_CV == IS_TMP_VAR) {
}
} else if (!0) { /* Not a temp var */
if (*EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
} else {
if (IS_CV == IS_CONST ||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
IS_CV == IS_TMP_VAR ||
PZVAL_IS_REF(retval_ptr)) {
zval *ret;
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
zval_copy_ctor(ret);
if (IS_CV != IS_TMP_VAR) {
zval_copy_ctor(ret);
}
*EG(return_value_ptr_ptr) = ret;
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) &&
retval_ptr == &EG(uninitialized_zval)) {
@@ -30556,16 +30506,6 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
*EG(return_value_ptr_ptr) = retval_ptr;
Z_ADDREF_P(retval_ptr);
}
} else {
zval *ret;
if (*EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
*EG(return_value_ptr_ptr) = ret;
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -30581,10 +30521,6 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
SAVE_OPLINE();
do {
if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
zval_ptr_dtor(EG(return_value_ptr_ptr));
}
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
/* Not supposed to happen, but we'll allow it */
zend_error(E_NOTICE, "Only variable references should be returned by reference");
+3 -1
View File
@@ -2342,8 +2342,10 @@ AC_DEFUN([PHP_SETUP_OPENSSL],[
AC_MSG_ERROR([OpenSSL version 0.9.6 or greater required.])
fi
if test -n "$OPENSSL_LIBS" && test -n "$OPENSSL_INCS"; then
if test -n "$OPENSSL_LIBS"; then
PHP_EVAL_LIBLINE($OPENSSL_LIBS, $1)
fi
if test -n "$OPENSSL_INCS"; then
PHP_EVAL_INCLINE($OPENSSL_INCS)
fi
fi
+4 -5
View File
@@ -74,16 +74,15 @@ static void com_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC
*data = &I->zdata;
}
static int com_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len,
ulong *int_key TSRMLS_DC)
static void com_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
if (I->key == (ulong)-1) {
return HASH_KEY_NON_EXISTANT;
ZVAL_NULL(key);
} else {
ZVAL_LONG(key, I->key);
}
*int_key = I->key;
return HASH_KEY_IS_LONG;
}
static int com_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
+4 -5
View File
@@ -519,16 +519,15 @@ static void saproxy_iter_get_data(zend_object_iterator *iter, zval ***data TSRML
*data = ptr_ptr;
}
static int saproxy_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len,
ulong *int_key TSRMLS_DC)
static void saproxy_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
if (I->key == -1) {
return HASH_KEY_NON_EXISTANT;
ZVAL_NULL(key);
} else {
ZVAL_LONG(key, I->key);
}
*int_key = (ulong)I->key;
return HASH_KEY_IS_LONG;
}
static int saproxy_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
+616 -595
View File
File diff suppressed because it is too large Load Diff
+325 -34
View File
@@ -39,6 +39,20 @@ static __inline __int64_t php_date_llabs( __int64_t i ) { return i >= 0 ? i : -i
static inline long long php_date_llabs( long long i ) { return i >= 0 ? i : -i; }
#endif
#ifdef PHP_WIN32
#define DATE_I64_BUF_LEN 65
# define DATE_I64A(i, s, len) _i64toa_s(i, s, len, 10)
# define DATE_A64I(i, s) i = _atoi64(s)
#else
#define DATE_I64_BUF_LEN 65
# define DATE_I64A(i, s, len) \
do { \
int st = snprintf(s, len, "%lld", i); \
s[st] = '\0'; \
} while (0);
# define DATE_A64I(i, s) i = atoll(s)
#endif
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_date, 0, 0, 1)
ZEND_ARG_INFO(0, format)
@@ -488,6 +502,8 @@ const zend_function_entry date_funcs_interval[] = {
const zend_function_entry date_funcs_period[] = {
PHP_ME(DatePeriod, __construct, arginfo_date_period_construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
PHP_ME(DatePeriod, __wakeup, NULL, ZEND_ACC_PUBLIC)
PHP_ME(DatePeriod, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_FE_END
};
@@ -594,9 +610,13 @@ static HashTable *date_object_get_gc(zval *object, zval ***table, int *n TSRMLS_
static HashTable *date_object_get_properties(zval *object TSRMLS_DC);
static HashTable *date_object_get_gc_interval(zval *object, zval ***table, int *n TSRMLS_DC);
static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC);
static HashTable *date_object_get_gc_period(zval *object, zval ***table, int *n TSRMLS_DC);
static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC);
zval *date_interval_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC);
void date_interval_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC);
static zval *date_period_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC);
static void date_period_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC);
/* {{{ Module struct */
zend_module_entry date_module_entry = {
@@ -1867,11 +1887,10 @@ static void date_period_it_current_data(zend_object_iterator *iter, zval ***data
/* {{{ date_period_it_current_key */
static int date_period_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
static void date_period_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
date_period_it *iterator = (date_period_it *)iter;
*int_key = iterator->current_index;
return HASH_KEY_IS_LONG;
date_period_it *iterator = (date_period_it *)iter;
ZVAL_LONG(key, iterator->current_index);
}
/* }}} */
@@ -2013,6 +2032,11 @@ static void date_register_classes(TSRMLS_D)
zend_class_implements(date_ce_period TSRMLS_CC, 1, zend_ce_traversable);
memcpy(&date_object_handlers_period, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
date_object_handlers_period.clone_obj = date_object_clone_period;
date_object_handlers_period.get_properties = date_object_get_properties_period;
date_object_handlers_period.get_property_ptr_ptr = NULL;
date_object_handlers_period.get_gc = date_object_get_gc_period;
date_object_handlers_period.read_property = date_period_read_property;
date_object_handlers_period.write_property = date_period_write_property;
#define REGISTER_PERIOD_CLASS_CONST_STRING(const_name, value) \
zend_declare_class_constant_long(date_ce_period, const_name, sizeof(const_name)-1, value TSRMLS_CC);
@@ -2125,7 +2149,7 @@ static HashTable *date_object_get_properties(zval *object TSRMLS_DC)
props = zend_std_get_properties(object TSRMLS_CC);
if (!dateobj->time) {
if (!dateobj->time || GC_G(gc_active)) {
return props;
}
@@ -2273,7 +2297,6 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC)
zval *zv;
php_interval_obj *intervalobj;
intervalobj = (php_interval_obj *) zend_object_store_get_object(object TSRMLS_CC);
props = zend_std_get_properties(object TSRMLS_CC);
@@ -2282,6 +2305,15 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC)
return props;
}
#define PHP_DATE_INTERVAL_ADD_PROPERTY_I64(n, f) \
do { \
char i64_buf[DATE_I64_BUF_LEN]; \
MAKE_STD_ZVAL(zv); \
DATE_I64A(intervalobj->diff->f, i64_buf, DATE_I64_BUF_LEN); \
ZVAL_STRING(zv, i64_buf, 1); \
zend_hash_update(props, n, strlen(n) + 1, &zv, sizeof(zval), NULL); \
} while(0);
#define PHP_DATE_INTERVAL_ADD_PROPERTY(n,f) \
MAKE_STD_ZVAL(zv); \
ZVAL_LONG(zv, intervalobj->diff->f); \
@@ -2293,14 +2325,21 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC)
PHP_DATE_INTERVAL_ADD_PROPERTY("h", h);
PHP_DATE_INTERVAL_ADD_PROPERTY("i", i);
PHP_DATE_INTERVAL_ADD_PROPERTY("s", s);
PHP_DATE_INTERVAL_ADD_PROPERTY("weekday", weekday);
PHP_DATE_INTERVAL_ADD_PROPERTY("weekday_behavior", weekday_behavior);
PHP_DATE_INTERVAL_ADD_PROPERTY("first_last_day_of", first_last_day_of);
PHP_DATE_INTERVAL_ADD_PROPERTY("invert", invert);
if (intervalobj->diff->days != -99999) {
PHP_DATE_INTERVAL_ADD_PROPERTY("days", days);
PHP_DATE_INTERVAL_ADD_PROPERTY_I64("days", days);
} else {
MAKE_STD_ZVAL(zv);
ZVAL_FALSE(zv);
zend_hash_update(props, "days", 5, &zv, sizeof(zval), NULL);
}
PHP_DATE_INTERVAL_ADD_PROPERTY("special_type", special.type);
PHP_DATE_INTERVAL_ADD_PROPERTY_I64("special_amount", special.amount);
PHP_DATE_INTERVAL_ADD_PROPERTY("have_weekday_relative", have_weekday_relative);
PHP_DATE_INTERVAL_ADD_PROPERTY("have_special_relative", have_special_relative);
return props;
}
@@ -2402,6 +2441,7 @@ PHPAPI zval *php_date_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC)
object_init_ex(object, pce);
Z_SET_REFCOUNT_P(object, 1);
Z_UNSET_ISREF_P(object);
return object;
}
@@ -2634,13 +2674,15 @@ static int php_date_initialize_from_hash(zval **return_value, php_date_obj **dat
case TIMELIB_ZONETYPE_OFFSET:
case TIMELIB_ZONETYPE_ABBR: {
char *tmp = emalloc(Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 2);
int ret;
snprintf(tmp, Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 2, "%s %s", Z_STRVAL_PP(z_date), Z_STRVAL_PP(z_timezone));
php_date_initialize(*dateobj, tmp, Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 1, NULL, NULL, 0 TSRMLS_CC);
ret = php_date_initialize(*dateobj, tmp, Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 1, NULL, NULL, 0 TSRMLS_CC);
efree(tmp);
return 1;
return 1 == ret;
}
case TIMELIB_ZONETYPE_ID:
case TIMELIB_ZONETYPE_ID: {
int ret;
convert_to_string(*z_timezone);
tzi = php_date_parse_tzfile(Z_STRVAL_PP(z_timezone), DATE_TIMEZONEDB TSRMLS_CC);
@@ -2651,9 +2693,10 @@ static int php_date_initialize_from_hash(zval **return_value, php_date_obj **dat
tzobj->tzi.tz = tzi;
tzobj->initialized = 1;
php_date_initialize(*dateobj, Z_STRVAL_PP(z_date), Z_STRLEN_PP(z_date), NULL, tmp_obj, 0 TSRMLS_CC);
ret = php_date_initialize(*dateobj, Z_STRVAL_PP(z_date), Z_STRLEN_PP(z_date), NULL, tmp_obj, 0 TSRMLS_CC);
zval_ptr_dtor(&tmp_obj);
return 1;
return 1 == ret;
}
}
}
}
@@ -2677,7 +2720,9 @@ PHP_METHOD(DateTime, __set_state)
php_date_instantiate(date_ce_date, return_value TSRMLS_CC);
dateobj = (php_date_obj *) zend_object_store_get_object(return_value TSRMLS_CC);
php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC);
if (!php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC)) {
php_error(E_ERROR, "Invalid serialization data for DateTime object");
}
}
/* }}} */
@@ -2697,7 +2742,9 @@ PHP_METHOD(DateTimeImmutable, __set_state)
php_date_instantiate(date_ce_immutable, return_value TSRMLS_CC);
dateobj = (php_date_obj *) zend_object_store_get_object(return_value TSRMLS_CC);
php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC);
if (!php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC)) {
php_error(E_ERROR, "Invalid serialization data for DateTimeImmutable object");
}
}
/* }}} */
@@ -2713,7 +2760,9 @@ PHP_METHOD(DateTime, __wakeup)
myht = Z_OBJPROP_P(object);
php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC);
if (!php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC)) {
php_error(E_ERROR, "Invalid serialization data for DateTime object");
}
}
/* }}} */
@@ -3952,30 +4001,48 @@ PHP_METHOD(DateInterval, __construct)
}
/* }}} */
static long php_date_long_from_hash_element(HashTable *myht, char *element, size_t size)
{
zval **z_arg = NULL;
if (zend_hash_find(myht, element, size + 1, (void**) &z_arg) == SUCCESS) {
convert_to_long(*z_arg);
return Z_LVAL_PP(z_arg);
} else {
return -1;
}
}
static int php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, HashTable *myht TSRMLS_DC)
{
(*intobj)->diff = timelib_rel_time_ctor();
(*intobj)->diff->y = php_date_long_from_hash_element(myht, "y", 1);
(*intobj)->diff->m = php_date_long_from_hash_element(myht, "m", 1);
(*intobj)->diff->d = php_date_long_from_hash_element(myht, "d", 1);
(*intobj)->diff->h = php_date_long_from_hash_element(myht, "h", 1);
(*intobj)->diff->i = php_date_long_from_hash_element(myht, "i", 1);
(*intobj)->diff->s = php_date_long_from_hash_element(myht, "s", 1);
(*intobj)->diff->invert = php_date_long_from_hash_element(myht, "invert", 6);
(*intobj)->diff->days = php_date_long_from_hash_element(myht, "days", 4);
#define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype, def) \
do { \
zval **z_arg = NULL; \
if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \
convert_to_long(*z_arg); \
(*intobj)->diff->member = (itype)Z_LVAL_PP(z_arg); \
} else { \
(*intobj)->diff->member = (itype)def; \
} \
} while (0);
#define PHP_DATE_INTERVAL_READ_PROPERTY_I64(element, member) \
do { \
zval **z_arg = NULL; \
if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \
convert_to_string(*z_arg); \
DATE_A64I((*intobj)->diff->member, Z_STRVAL_PP(z_arg)); \
} else { \
(*intobj)->diff->member = -1LL; \
} \
} while (0);
PHP_DATE_INTERVAL_READ_PROPERTY("y", y, timelib_sll, -1)
PHP_DATE_INTERVAL_READ_PROPERTY("m", m, timelib_sll, -1)
PHP_DATE_INTERVAL_READ_PROPERTY("d", d, timelib_sll, -1)
PHP_DATE_INTERVAL_READ_PROPERTY("h", h, timelib_sll, -1)
PHP_DATE_INTERVAL_READ_PROPERTY("i", i, timelib_sll, -1)
PHP_DATE_INTERVAL_READ_PROPERTY("s", s, timelib_sll, -1)
PHP_DATE_INTERVAL_READ_PROPERTY("weekday", weekday, int, -1)
PHP_DATE_INTERVAL_READ_PROPERTY("weekday_behavior", weekday_behavior, int, -1)
PHP_DATE_INTERVAL_READ_PROPERTY("first_last_day_of", first_last_day_of, int, -1)
PHP_DATE_INTERVAL_READ_PROPERTY("invert", invert, int, 0);
PHP_DATE_INTERVAL_READ_PROPERTY_I64("days", days);
PHP_DATE_INTERVAL_READ_PROPERTY("special_type", special.type, unsigned int, 0);
PHP_DATE_INTERVAL_READ_PROPERTY_I64("special_amount", special.amount);
PHP_DATE_INTERVAL_READ_PROPERTY("have_weekday_relative", have_weekday_relative, unsigned int, 0);
PHP_DATE_INTERVAL_READ_PROPERTY("have_special_relative", have_special_relative, unsigned int, 0);
(*intobj)->initialized = 1;
return 0;
@@ -4581,6 +4648,230 @@ PHP_FUNCTION(date_sun_info)
timelib_time_dtor(t2);
}
/* }}} */
static HashTable *date_object_get_gc_period(zval *object, zval ***table, int *n TSRMLS_DC)
{
*table = NULL;
*n = 0;
return zend_std_get_properties(object TSRMLS_CC);
}
static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC)
{
HashTable *props;
zval *zv;
php_period_obj *period_obj;
period_obj = zend_object_store_get_object(object TSRMLS_CC);
props = zend_std_get_properties(object TSRMLS_CC);
if (!period_obj->start || GC_G(gc_active)) {
return props;
}
MAKE_STD_ZVAL(zv);
if (period_obj->start) {
php_date_obj *date_obj;
object_init_ex(zv, date_ce_date);
date_obj = zend_object_store_get_object(zv TSRMLS_CC);
date_obj->time = timelib_time_clone(period_obj->start);
} else {
ZVAL_NULL(zv);
}
zend_hash_update(props, "start", sizeof("start"), &zv, sizeof(zv), NULL);
MAKE_STD_ZVAL(zv);
if (period_obj->current) {
php_date_obj *date_obj;
object_init_ex(zv, date_ce_date);
date_obj = zend_object_store_get_object(zv TSRMLS_CC);
date_obj->time = timelib_time_clone(period_obj->current);
} else {
ZVAL_NULL(zv);
}
zend_hash_update(props, "current", sizeof("current"), &zv, sizeof(zv), NULL);
MAKE_STD_ZVAL(zv);
if (period_obj->end) {
php_date_obj *date_obj;
object_init_ex(zv, date_ce_date);
date_obj = zend_object_store_get_object(zv TSRMLS_CC);
date_obj->time = timelib_time_clone(period_obj->end);
} else {
ZVAL_NULL(zv);
}
zend_hash_update(props, "end", sizeof("end"), &zv, sizeof(zv), NULL);
MAKE_STD_ZVAL(zv);
if (period_obj->interval) {
php_interval_obj *interval_obj;
object_init_ex(zv, date_ce_interval);
interval_obj = zend_object_store_get_object(zv TSRMLS_CC);
interval_obj->diff = timelib_rel_time_clone(period_obj->interval);
interval_obj->initialized = 1;
} else {
ZVAL_NULL(zv);
}
zend_hash_update(props, "interval", sizeof("interval"), &zv, sizeof(zv), NULL);
/* converted to larger type (int->long); must check when unserializing */
MAKE_STD_ZVAL(zv);
ZVAL_LONG(zv, (long) period_obj->recurrences);
zend_hash_update(props, "recurrences", sizeof("recurrences"), &zv, sizeof(zv), NULL);
MAKE_STD_ZVAL(zv);
ZVAL_BOOL(zv, period_obj->include_start_date);
zend_hash_update(props, "include_start_date", sizeof("include_start_date"), &zv, sizeof(zv), NULL);
return props;
}
static int php_date_period_initialize_from_hash(php_period_obj *period_obj, HashTable *myht TSRMLS_DC)
{
zval **ht_entry;
/* this function does no rollback on error */
if (zend_hash_find(myht, "start", sizeof("start"), (void**) &ht_entry) == SUCCESS) {
if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) {
php_date_obj *date_obj;
date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC);
period_obj->start = timelib_time_clone(date_obj->time);
period_obj->start_ce = Z_OBJCE_PP(ht_entry);
} else if (Z_TYPE_PP(ht_entry) != IS_NULL) {
return 0;
}
} else {
return 0;
}
if (zend_hash_find(myht, "end", sizeof("end"), (void**) &ht_entry) == SUCCESS) {
if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) {
php_date_obj *date_obj;
date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC);
period_obj->end = timelib_time_clone(date_obj->time);
} else if (Z_TYPE_PP(ht_entry) != IS_NULL) {
return 0;
}
} else {
return 0;
}
if (zend_hash_find(myht, "current", sizeof("current"), (void**) &ht_entry) == SUCCESS) {
if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) {
php_date_obj *date_obj;
date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC);
period_obj->current = timelib_time_clone(date_obj->time);
} else if (Z_TYPE_PP(ht_entry) != IS_NULL) {
return 0;
}
} else {
return 0;
}
if (zend_hash_find(myht, "interval", sizeof("interval"), (void**) &ht_entry) == SUCCESS) {
if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_interval) {
php_interval_obj *interval_obj;
interval_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC);
period_obj->interval = timelib_rel_time_clone(interval_obj->diff);
} else { /* interval is required */
return 0;
}
} else {
return 0;
}
if (zend_hash_find(myht, "recurrences", sizeof("recurrences"), (void**) &ht_entry) == SUCCESS &&
Z_TYPE_PP(ht_entry) == IS_LONG && Z_LVAL_PP(ht_entry) >= 0 && Z_LVAL_PP(ht_entry) <= INT_MAX) {
period_obj->recurrences = Z_LVAL_PP(ht_entry);
} else {
return 0;
}
if (zend_hash_find(myht, "include_start_date", sizeof("include_start_date"), (void**) &ht_entry) == SUCCESS &&
Z_TYPE_PP(ht_entry) == IS_BOOL) {
period_obj->include_start_date = Z_BVAL_PP(ht_entry);
} else {
return 0;
}
period_obj->initialized = 1;
return 1;
}
/* {{{ proto DatePeriod::__set_state()
*/
PHP_METHOD(DatePeriod, __set_state)
{
php_period_obj *period_obj;
zval *array;
HashTable *myht;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) {
RETURN_FALSE;
}
myht = Z_ARRVAL_P(array);
object_init_ex(return_value, date_ce_period);
period_obj = zend_object_store_get_object(return_value TSRMLS_CC);
if (!php_date_period_initialize_from_hash(period_obj, myht TSRMLS_CC)) {
php_error(E_ERROR, "Invalid serialization data for DatePeriod object");
}
}
/* }}} */
/* {{{ proto DatePeriod::__wakeup()
*/
PHP_METHOD(DatePeriod, __wakeup)
{
zval *object = getThis();
php_period_obj *period_obj;
HashTable *myht;
period_obj = zend_object_store_get_object(object TSRMLS_CC);
myht = Z_OBJPROP_P(object);
if (!php_date_period_initialize_from_hash(period_obj, myht TSRMLS_CC)) {
php_error(E_ERROR, "Invalid serialization data for DatePeriod object");
}
}
/* }}} */
/* {{{ date_period_read_property */
static zval *date_period_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
{
zval *zv;
if (type != BP_VAR_IS && type != BP_VAR_R) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Retrieval of DatePeriod properties for modification is unsupported");
}
Z_OBJPROP_P(object); /* build properties hash table */
zv = std_object_handlers.read_property(object, member, type, key TSRMLS_CC);
if (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJ_HANDLER_P(zv, clone_obj)) {
/* defensive copy */
zend_object_value zov = Z_OBJ_HANDLER_P(zv, clone_obj)(zv TSRMLS_CC);
MAKE_STD_ZVAL(zv);
Z_TYPE_P(zv) = IS_OBJECT;
Z_OBJVAL_P(zv) = zov;
}
return zv;
}
/* }}} */
/* {{{ date_period_write_property */
static void date_period_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Writing to DatePeriod properties is unsupported");
}
/* }}} */
/*
* Local variables:
* tab-width: 4
+2
View File
@@ -101,6 +101,8 @@ PHP_FUNCTION(date_interval_format);
PHP_FUNCTION(date_interval_create_from_date_string);
PHP_METHOD(DatePeriod, __construct);
PHP_METHOD(DatePeriod, __wakeup);
PHP_METHOD(DatePeriod, __set_state);
/* Options and Configuration */
PHP_FUNCTION(date_default_timezone_set);
+17 -3
View File
@@ -11,8 +11,8 @@ $other = new DateTime("31-July-2008");
$diff = date_diff($date, $other);
var_dump($diff);
--EXPECT--
object(DateInterval)#3 (8) {
--EXPECTF--
object(DateInterval)#%d (15) {
["y"]=>
int(0)
["m"]=>
@@ -25,8 +25,22 @@ object(DateInterval)#3 (8) {
int(0)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
int(3)
string(1) "3"
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
+16 -2
View File
@@ -15,8 +15,15 @@ DateInterval Object
[h] => 12
[i] => 30
[s] => 5
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] =>%s
[days] =>
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
DateInterval Object
(
@@ -26,6 +33,13 @@ DateInterval Object
[h] => 12
[i] => 30
[s] => 5
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] =>%s
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
+7
View File
@@ -17,6 +17,13 @@ DateInterval Object
[h] => 4
[i] => 0
[s] => 0
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 30
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
+15 -1
View File
@@ -8,7 +8,7 @@ echo $i->format("%d"), "\n";
echo $i->format("%a"), "\n";
?>
--EXPECT--
object(DateInterval)#1 (8) {
object(DateInterval)#1 (15) {
["y"]=>
int(0)
["m"]=>
@@ -21,10 +21,24 @@ object(DateInterval)#1 (8) {
int(0)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
bool(false)
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
7
(unknown)
+157 -8
View File
@@ -32,7 +32,7 @@ var_dump($unser, $p);
?>
--EXPECT--
object(DateInterval)#3 (8) {
object(DateInterval)#3 (15) {
["y"]=>
int(0)
["m"]=>
@@ -45,12 +45,26 @@ object(DateInterval)#3 (8) {
int(0)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
string(1) "0"
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
string(128) "O:12:"DateInterval":8:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:4;s:1:"i";i:0;s:1:"s";i:0;s:6:"invert";i:0;s:4:"days";i:0;}"
string(328) "O:12:"DateInterval":15:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:4;s:1:"i";i:0;s:1:"s";i:0;s:7:"weekday";i:0;s:16:"weekday_behavior";i:0;s:17:"first_last_day_of";i:0;s:6:"invert";i:0;s:4:"days";s:1:"0";s:12:"special_type";i:0;s:14:"special_amount";s:1:"0";s:21:"have_weekday_relative";i:0;s:21:"have_special_relative";i:0;}"
DateInterval::__set_state(array(
'y' => 0,
'm' => 0,
@@ -58,9 +72,16 @@ DateInterval::__set_state(array(
'h' => 4,
'i' => 0,
's' => 0,
'weekday' => 0,
'weekday_behavior' => 0,
'first_last_day_of' => 0,
'invert' => 0,
'days' => 0,
))object(DateInterval)#5 (8) {
'days' => '0',
'special_type' => 0,
'special_amount' => '0',
'have_weekday_relative' => 0,
'have_special_relative' => 0,
))object(DateInterval)#5 (15) {
["y"]=>
int(0)
["m"]=>
@@ -73,14 +94,78 @@ DateInterval::__set_state(array(
int(0)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
string(1) "0"
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
object(DatePeriod)#6 (0) {
object(DatePeriod)#6 (6) {
["start"]=>
object(DateTime)#4 (3) {
["date"]=>
string(19) "2003-01-02 08:00:00"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
["current"]=>
NULL
["end"]=>
NULL
["interval"]=>
object(DateInterval)#7 (15) {
["y"]=>
int(0)
["m"]=>
int(0)
["d"]=>
int(0)
["h"]=>
int(4)
["i"]=>
int(0)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
string(1) "0"
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
["recurrences"]=>
int(3)
["include_start_date"]=>
bool(true)
}
object(DateInterval)#4 (8) {
object(DateInterval)#8 (15) {
["y"]=>
int(7)
["m"]=>
@@ -93,10 +178,74 @@ object(DateInterval)#4 (8) {
int(3)
["s"]=>
int(2)
["weekday"]=>
int(-1)
["weekday_behavior"]=>
int(-1)
["first_last_day_of"]=>
int(-1)
["invert"]=>
int(1)
["days"]=>
int(2400)
string(4) "2400"
["special_type"]=>
int(0)
["special_amount"]=>
string(2) "-1"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
object(DatePeriod)#7 (0) {
object(DatePeriod)#9 (6) {
["start"]=>
object(DateTime)#6 (3) {
["date"]=>
string(19) "2003-01-02 08:00:00"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
["current"]=>
NULL
["end"]=>
NULL
["interval"]=>
object(DateInterval)#7 (15) {
["y"]=>
int(0)
["m"]=>
int(0)
["d"]=>
int(0)
["h"]=>
int(4)
["i"]=>
int(0)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
string(1) "0"
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
["recurrences"]=>
int(3)
["include_start_date"]=>
bool(true)
}
+7
View File
@@ -27,6 +27,13 @@ di Object
[h] => 0
[i] => 0
[s] => 0
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] =>
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
+48 -6
View File
@@ -25,7 +25,7 @@ foreach($intervals as $iv) {
echo "==DONE==\n";
?>
--EXPECTF--
object(DateInterval)#%d (8) {
object(DateInterval)#%d (15) {
["y"]=>
int(1)
["m"]=>
@@ -38,12 +38,26 @@ object(DateInterval)#%d (8) {
int(30)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(1)
["days"]=>
int(437)
string(3) "437"
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
object(DateInterval)#%d (8) {
object(DateInterval)#%d (15) {
["y"]=>
int(0)
["m"]=>
@@ -56,12 +70,26 @@ object(DateInterval)#%d (8) {
int(30)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
int(294)
string(3) "294"
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
object(DateInterval)#%d (8) {
object(DateInterval)#%d (15) {
["y"]=>
int(0)
["m"]=>
@@ -74,10 +102,24 @@ object(DateInterval)#%d (8) {
int(30)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
int(294)
string(3) "294"
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
DateInterval::__construct(): Failed to parse interval (2007-05-11T15:30:00Z/)
DateInterval::__construct(): Failed to parse interval (2007-05-11T15:30:00Z)
+130 -4
View File
@@ -1,7 +1,5 @@
--TEST--
Bug #53437 (Crash when using unserialized DatePeriod instance)
--XFAIL--
Bug #53437 Not fixed yet
Bug #53437 (Crash when using unserialized DatePeriod instance), variation 1
--FILE--
<?php
$dp = new DatePeriod(new DateTime('2010-01-01 UTC'), new DateInterval('P1D'), 2);
@@ -20,9 +18,137 @@ $dpu = unserialize($ser); // $dpu has invalid values???
var_dump($dpu);
echo "Unserialized:\r\n";
// ???which leads to CRASH:
foreach($dpu as $dt) {
echo $dt->format('Y-m-d H:i:s')."\r\n";
}
?>
==DONE==
--EXPECT--
Original:
2010-01-01 00:00:00
2010-01-02 00:00:00
2010-01-03 00:00:00
object(DatePeriod)#1 (6) {
["start"]=>
object(DateTime)#2 (3) {
["date"]=>
string(19) "2010-01-01 00:00:00"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
["current"]=>
object(DateTime)#4 (3) {
["date"]=>
string(19) "2010-01-04 00:00:00"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
["end"]=>
NULL
["interval"]=>
object(DateInterval)#5 (15) {
["y"]=>
int(0)
["m"]=>
int(0)
["d"]=>
int(1)
["h"]=>
int(0)
["i"]=>
int(0)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
bool(false)
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
["recurrences"]=>
int(3)
["include_start_date"]=>
bool(true)
}
object(DatePeriod)#5 (6) {
["start"]=>
object(DateTime)#10 (3) {
["date"]=>
string(19) "2010-01-01 00:00:00"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
["current"]=>
object(DateTime)#7 (3) {
["date"]=>
string(19) "2010-01-04 00:00:00"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
["end"]=>
NULL
["interval"]=>
object(DateInterval)#8 (15) {
["y"]=>
int(0)
["m"]=>
int(0)
["d"]=>
int(1)
["h"]=>
int(0)
["i"]=>
int(0)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
string(1) "0"
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
["recurrences"]=>
int(3)
["include_start_date"]=>
bool(true)
}
Unserialized:
2010-01-01 00:00:00
2010-01-02 00:00:00
2010-01-03 00:00:00
==DONE==
+13
View File
@@ -0,0 +1,13 @@
--TEST--
Bug #53437 (Crash when using unserialized DatePeriod instance), variation 2
--FILE--
<?php
$s = 'O:10:"DatePeriod":0:{}';
$dp = unserialize($s);
var_dump($dp);
?>
==DONE==
--EXPECTF--
Fatal error: Invalid serialization data for DatePeriod object in %sbug53437_var1.php on line %d
+80
View File
@@ -0,0 +1,80 @@
--TEST--
Bug #53437 DateInterval basic serialization
--FILE--
<?php
$di0 = new DateInterval('P2Y4DT6H8M');
$s = serialize($di0);
$di1 = unserialize($s);
var_dump($di0, $di1);
?>
==DONE==
--EXPECT--
object(DateInterval)#1 (15) {
["y"]=>
int(2)
["m"]=>
int(0)
["d"]=>
int(4)
["h"]=>
int(6)
["i"]=>
int(8)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
bool(false)
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
object(DateInterval)#2 (15) {
["y"]=>
int(2)
["m"]=>
int(0)
["d"]=>
int(4)
["h"]=>
int(6)
["i"]=>
int(8)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
string(1) "0"
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
==DONE==
+45
View File
@@ -0,0 +1,45 @@
--TEST--
Bug #53437 DateInterval unserialize bad data
--FILE--
<?php
$s = 'O:12:"DateInterval":15:{s:1:"y";s:1:"2";s:1:"m";s:1:"0";s:1:"d";s:3:"bla";s:1:"h";s:1:"6";s:1:"i";s:1:"8";s:1:"s";s:1:"0";s:7:"weekday";i:10;s:16:"weekday_behavior";i:10;s:17:"first_last_day_of";i:0;s:6:"invert";i:0;s:4:"days";s:4:"aoeu";s:12:"special_type";i:0;s:14:"special_amount";s:21:"234523452345234532455";s:21:"have_weekday_relative";i:21474836489;s:21:"have_special_relative";s:3:"bla";}';
$di = unserialize($s);
var_dump($di);
?>
==DONE==
--EXPECT--
object(DateInterval)#1 (15) {
["y"]=>
int(2)
["m"]=>
int(0)
["d"]=>
int(0)
["h"]=>
int(6)
["i"]=>
int(8)
["s"]=>
int(0)
["weekday"]=>
int(10)
["weekday_behavior"]=>
int(10)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
string(1) "0"
["special_type"]=>
int(0)
["special_amount"]=>
string(19) "9223372036854775807"
["have_weekday_relative"]=>
int(9)
["have_special_relative"]=>
int(0)
}
==DONE==
+1 -2
View File
@@ -7,5 +7,4 @@ date_default_timezone_set('Europe/Prague');
var_dump(unserialize('O:8:"DateTime":0:{}') == new DateTime);
?>
--EXPECTF--
Warning: %s: Trying to compare an incomplete DateTime object in %s on line %d
bool(false)
Fatal error: Invalid serialization data for DateTime object in %sbug55397.php on line %d
+2 -24
View File
@@ -1,36 +1,14 @@
--TEST--
Bug #62852 (Unserialize invalid DateTime causes crash)
Bug #62852 (Unserialize invalid DateTime causes crash), variation 1
--INI--
date.timezone=GMT
--XFAIL--
bug is not fixed yet
--FILE--
<?php
$s1 = 'O:8:"DateTime":3:{s:4:"date";s:20:"10007-06-07 03:51:49";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}';
$s2 = 'O:3:"Foo":3:{s:4:"date";s:20:"10007-06-07 03:51:49";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}';
global $foo;
class Foo extends DateTime {
function __wakeup() {
global $foo;
$foo = $this;
parent::__wakeup();
}
}
// Old test case
try {
unserialize( $s1 );
} catch ( Exception $e ) {}
// My test case
try {
unserialize( $s2 );
} catch ( Exception $e ) {}
var_dump( $foo );
echo "okey";
?>
--EXPECTF--
okey
Fatal error: Invalid serialization data for DateTime object in %sbug62852.php on line %d
+25
View File
@@ -0,0 +1,25 @@
--TEST--
Bug #62852 (Unserialize invalid DateTime causes crash), variation 2
--INI--
date.timezone=GMT
--FILE--
<?php
$s2 = 'O:3:"Foo":3:{s:4:"date";s:20:"10007-06-07 03:51:49";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}';
global $foo;
class Foo extends DateTime {
function __wakeup() {
global $foo;
$foo = $this;
parent::__wakeup();
}
}
try {
unserialize( $s2 );
} catch ( Exception $e ) {}
var_dump( $foo );
--EXPECTF--
Fatal error: Invalid serialization data for DateTime object in %sbug62852_var2.php on line %d
+25
View File
@@ -0,0 +1,25 @@
--TEST--
Bug #62852 (Unserialize invalid DateTime causes crash), variation 3
--INI--
date.timezone=GMT
--FILE--
<?php
$s2 = 'O:3:"Foo":3:{s:4:"date";s:19:"0000-00-00 00:00:00";s:13:"timezone_type";i:0;s:8:"timezone";s:3:"UTC";}';
global $foo;
class Foo extends DateTime {
function __wakeup() {
global $foo;
$foo = $this;
parent::__wakeup();
}
}
try {
unserialize( $s2 );
} catch ( Exception $e ) {}
var_dump( $foo );
--EXPECTF--
Fatal error: Invalid serialization data for DateTime object in %sbug62852_var3.php on line %d
+16 -2
View File
@@ -28,7 +28,7 @@ object(DateTime)#2 (3) {
["timezone"]=>
string(3) "EDT"
}
object(DateInterval)#3 (8) {
object(DateInterval)#3 (15) {
["y"]=>
int(0)
["m"]=>
@@ -41,8 +41,22 @@ object(DateInterval)#3 (8) {
int(19)
["s"]=>
int(40)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
int(33)
string(2) "33"
["special_type"]=>
int(0)
["special_amount"]=>
string(1) "0"
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
-1
View File
@@ -538,7 +538,6 @@ PHP_MINFO_FUNCTION(dba)
*/
static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode)
{
char *v;
int val_len;
zval *id;
dba_info *info = NULL;
+7 -20
View File
@@ -157,35 +157,22 @@ static void php_dom_iterator_current_data(zend_object_iterator *iter, zval ***da
}
/* }}} */
static int php_dom_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
static void php_dom_iterator_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */
{
zval *curobj;
xmlNodePtr curnode = NULL;
dom_object *intern;
zval *object;
int namelen;
php_dom_iterator *iterator = (php_dom_iterator *)iter;
object = (zval *)iterator->intern.data;
zval *object = (zval *)iterator->intern.data;
if (instanceof_function(Z_OBJCE_P(object), dom_nodelist_class_entry TSRMLS_CC)) {
*int_key = iter->index;
return HASH_KEY_IS_LONG;
ZVAL_LONG(key, iter->index);
} else {
curobj = iterator->curobj;
dom_object *intern = (dom_object *)zend_object_store_get_object(iterator->curobj TSRMLS_CC);
intern = (dom_object *)zend_object_store_get_object(curobj TSRMLS_CC);
if (intern != NULL && intern->ptr != NULL) {
curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
xmlNodePtr curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
ZVAL_STRINGL(key, (char *) curnode->name, xmlStrlen(curnode->name), 1);
} else {
return HASH_KEY_NON_EXISTANT;
ZVAL_NULL(key);
}
namelen = xmlStrlen(curnode->name);
*str_key = estrndup(curnode->name, namelen);
*str_key_len = namelen + 1;
return HASH_KEY_IS_STRING;
}
}
/* }}} */
+1 -1
View File
@@ -298,7 +298,7 @@ if test "$PHP_GD" = "yes"; then
libgd/gdcache.c libgd/gdkanji.c libgd/wbmp.c libgd/gd_wbmp.c libgd/gdhelpers.c \
libgd/gd_topal.c libgd/gd_gif_in.c libgd/xbm.c libgd/gd_gif_out.c libgd/gd_security.c \
libgd/gd_filter.c libgd/gd_pixelate.c libgd/gd_arc.c libgd/gd_rotate.c libgd/gd_color.c \
libgd/gd_transform.c libgd/gd_crop.c"
libgd/gd_transform.c libgd/gd_crop.c libgd/gd_interpolation.c libgd/gd_matrix.c"
dnl check for fabsf and floorf which are available since C99
AC_CHECK_FUNCS(fabsf floorf)
+2 -2
View File
@@ -48,7 +48,7 @@ if (PHP_GD != "no") {
gd_io_file.c gd_io_ss.c gd_jpeg.c gdkanji.c gd_png.c gd_ss.c \
gdtables.c gd_topal.c gd_wbmp.c gdxpm.c wbmp.c xbm.c gd_security.c gd_transform.c \
gd_filter.c gd_pixelate.c gd_arc.c gd_rotate.c gd_color.c webpimg.c gd_webp.c \
gd_crop.c", "gd");
gd_crop.c gd_interpolation.c gd_matrix.c", "gd");
AC_DEFINE('HAVE_LIBGD', 1, 'GD support');
ADD_FLAG("CFLAGS_GD", " \
/D HAVE_GD_DYNAMIC_CTX_EX=1 \
@@ -84,7 +84,7 @@ if (PHP_GD != "no") {
");
PHP_INSTALL_HEADERS("", "ext/gd ext/gd/libgd" );
} else {
} else {
WARNING("gd not enabled; libraries and headers not found");
}
}
+420 -5
View File
@@ -58,7 +58,6 @@
# include "libgd/gd_compat.h"
#endif
static int le_gd, le_gd_font;
#if HAVE_LIBT1
#include <t1lib.h>
@@ -195,6 +194,10 @@ ZEND_BEGIN_ARG_INFO(arginfo_imagetruecolortopalette, 0)
ZEND_ARG_INFO(0, colorsWanted)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_imagepalettetotruecolor, 0)
ZEND_ARG_INFO(0, im)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_imagecolormatch, 0)
ZEND_ARG_INFO(0, im1)
ZEND_ARG_INFO(0, im2)
@@ -902,6 +905,35 @@ ZEND_BEGIN_ARG_INFO(arginfo_imagecropauto, 0)
ZEND_ARG_INFO(0, threshold)
ZEND_ARG_INFO(0, color)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_imagescale, 0)
ZEND_ARG_INFO(0, im)
ZEND_ARG_INFO(0, new_width)
ZEND_ARG_INFO(0, new_height)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_imageaffine, 0)
ZEND_ARG_INFO(0, im)
ZEND_ARG_INFO(0, affine)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_imageaffinematrixget, 0)
ZEND_ARG_INFO(0, im)
ZEND_ARG_INFO(0, matrox)
ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_imageaffinematrixconcat, 0)
ZEND_ARG_INFO(0, m1)
ZEND_ARG_INFO(0, m2)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_imagesetinterpolation, 0)
ZEND_ARG_INFO(0, im)
ZEND_ARG_INFO(0, method)
ZEND_END_ARG_INFO()
#endif
/* }}} */
@@ -941,6 +973,7 @@ const zend_function_entry gd_functions[] = {
PHP_FE(imagecreatetruecolor, arginfo_imagecreatetruecolor)
PHP_FE(imageistruecolor, arginfo_imageistruecolor)
PHP_FE(imagetruecolortopalette, arginfo_imagetruecolortopalette)
PHP_FE(imagepalettetotruecolor, arginfo_imagepalettetotruecolor)
PHP_FE(imagesetthickness, arginfo_imagesetthickness)
PHP_FE(imagefilledarc, arginfo_imagefilledarc)
PHP_FE(imagefilledellipse, arginfo_imagefilledellipse)
@@ -964,6 +997,11 @@ const zend_function_entry gd_functions[] = {
PHP_FE(imageflip, arginfo_imageflip)
PHP_FE(imagecrop, arginfo_imagecrop)
PHP_FE(imagecropauto, arginfo_imagecropauto)
PHP_FE(imagescale, arginfo_imagescale)
PHP_FE(imageaffine, arginfo_imageaffine)
PHP_FE(imageaffinematrixconcat, arginfo_imageaffinematrixconcat)
PHP_FE(imageaffinematrixget, arginfo_imageaffinematrixget)
PHP_FE(imagesetinterpolation, arginfo_imagesetinterpolation)
#endif
#if HAVE_GD_IMAGESETTILE
@@ -1218,13 +1256,43 @@ PHP_MINIT_FUNCTION(gd)
REGISTER_LONG_CONSTANT("IMG_FLIP_HORIZONTAL", GD_FLIP_HORINZONTAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_FLIP_VERTICAL", GD_FLIP_VERTICAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_FLIP_BOTH", GD_FLIP_BOTH, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CROP_DEFAULT", GD_CROP_DEFAULT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CROP_TRANSPARENT", GD_CROP_TRANSPARENT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CROP_BLACK", GD_CROP_BLACK, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CROP_WHITE", GD_CROP_WHITE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CROP_SIDES", GD_CROP_SIDES, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CROP_THRESHOLD", GD_CROP_THRESHOLD, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_BELL", GD_BILINEAR_FIXED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_BESSEL", GD_BESSEL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_BILINEAR_FIXED", GD_BILINEAR_FIXED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_BICUBIC", GD_BICUBIC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_BICUBIC_FIXED", GD_BICUBIC_FIXED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_BLACKMAN", GD_BLACKMAN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_BOX", GD_BOX, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_BSPLINE", GD_BSPLINE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_CATMULLROM", GD_CATMULLROM, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_GAUSSIAN", GD_GAUSSIAN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_GENERALIZED_CUBIC", GD_GENERALIZED_CUBIC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_HERMITE", GD_HERMITE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_HAMMING", GD_HAMMING, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_HANNING", GD_HANNING, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_MITCHELL", GD_MITCHELL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_POWER", GD_POWER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_QUADRATIC", GD_QUADRATIC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_SINC", GD_SINC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_NEAREST_NEIGHBOUR", GD_NEAREST_NEIGHBOUR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_WEIGHTED4", GD_WEIGHTED4, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_TRIANGLE", GD_TRIANGLE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_AFFINE_TRANSLATE", GD_AFFINE_TRANSLATE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_AFFINE_SCALE", GD_AFFINE_SCALE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_AFFINE_ROTATE", GD_AFFINE_ROTATE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_AFFINE_SHEAR_HORIZONTAL", GD_AFFINE_SHEAR_HORIZONTAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("IMG_AFFINE_SHEAR_VERTICAL", GD_AFFINE_SHEAR_VERTICAL, CONST_CS | CONST_PERSISTENT);
#else
REGISTER_LONG_CONSTANT("GD_BUNDLED", 0, CONST_CS | CONST_PERSISTENT);
#endif
@@ -1370,6 +1438,9 @@ PHP_MINFO_FUNCTION(gd)
#endif
#if defined(USE_GD_JISX0208) && defined(HAVE_GD_BUNDLED)
php_info_print_table_row(2, "JIS-mapped Japanese Font Support", "enabled");
#endif
#ifdef HAVE_GD_WEBP
php_info_print_table_row(2, "WebP Support", "enabled");
#endif
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
@@ -1730,6 +1801,29 @@ PHP_FUNCTION(imagetruecolortopalette)
}
/* }}} */
/* {{{ proto void imagetruecolortopalette(resource im, bool ditherFlag, int colorsWanted)
Convert a true colour image to a palette based image with a number of colours, optionally using dithering. */
PHP_FUNCTION(imagepalettetotruecolor)
{
zval *IM;
gdImagePtr im;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &IM) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd);
if (gdImagePaletteToTrueColor(im) == 0) {
RETURN_FALSE;
}
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool imagecolormatch(resource im1, resource im2)
Makes the colors of the palette version of an image more closely match the true color version */
PHP_FUNCTION(imagecolormatch)
@@ -2172,7 +2266,7 @@ PHP_FUNCTION(imagerotate)
ZEND_FETCH_RESOURCE(im_src, gdImagePtr, &SIM, -1, "Image", le_gd);
im_dst = gdImageRotate(im_src, degrees, color, ignoretransparent);
im_dst = gdImageRotateInterpolated(im_src, (float)degrees, color);
if (im_dst != NULL) {
ZEND_REGISTER_RESOURCE(return_value, im_dst, le_gd);
@@ -5127,11 +5221,11 @@ PHP_FUNCTION(imageflip)
switch (mode) {
case GD_FLIP_VERTICAL:
gdImageFlipHorizontal(im);
gdImageFlipVertical(im);
break;
case GD_FLIP_HORINZONTAL:
gdImageFlipVertical(im);
gdImageFlipHorizontal(im);
break;
case GD_FLIP_BOTH:
@@ -5252,6 +5346,327 @@ PHP_FUNCTION(imagecropauto)
}
}
/* }}} */
/* {{{ proto resource imagescale(resource im, new_width[, new_height[, method]])
Crop an image using the given coordinates and size, x, y, width and height. */
PHP_FUNCTION(imagescale)
{
zval *IM;
long mode = -1;
long color = -1;
double threshold = 0.5f;
gdImagePtr im;
gdImagePtr im_scaled;
int new_width, new_height = -1;
gdInterpolationMethod method = GD_BILINEAR_FIXED;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|ll", &IM, &new_width, &new_height, &method) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd);
im_scaled = gdImageScale(im, new_width, new_height);
goto finish;
switch (method) {
case GD_NEAREST_NEIGHBOUR:
im_scaled = gdImageScaleNearestNeighbour(im, new_width, new_height);
break;
case GD_BILINEAR_FIXED:
im_scaled = gdImageScaleBilinear(im, new_width, new_height);
break;
case GD_BICUBIC:
im_scaled = gdImageScaleBicubicFixed(im, new_width, new_height);
break;
case GD_BICUBIC_FIXED:
im_scaled = gdImageScaleBicubicFixed(im, new_width, new_height);
break;
default:
im_scaled = gdImageScaleTwoPass(im, im->sx, im->sy, new_width, new_height);
break;
}
finish:
if (im_scaled == NULL) {
RETURN_FALSE;
} else {
ZEND_REGISTER_RESOURCE(return_value, im_scaled, le_gd);
}
}
/* }}} */
/* {{{ proto resource imageaffine(resource dst, resource src, array affine, array clip)
Return an image containing the affine tramsformed src image, using an optional clipping area */
PHP_FUNCTION(imageaffine)
{
zval *IM;
long mode = -1;
long color = -1;
double threshold = 0.5f;
gdImagePtr src;
gdImagePtr dst;
gdRect rect;
gdRectPtr pRect = NULL;
zval *z_rect = NULL;
zval *z_affine;
zval **tmp;
double affine[6];
int i, nelems;
zval **zval_affine_elem = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra|a", &IM, &z_affine, &z_rect) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(src, gdImagePtr, &IM, -1, "Image", le_gd);
if ((nelems = zend_hash_num_elements(Z_ARRVAL_P(z_affine))) != 6) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Affine array must have six elements");
RETURN_FALSE;
}
for (i = 0; i < nelems; i++) {
if (zend_hash_index_find(Z_ARRVAL_P(z_affine), i, (void **) &zval_affine_elem) == SUCCESS) {
switch (Z_TYPE_PP(zval_affine_elem)) {
case IS_LONG:
affine[i] = Z_LVAL_PP(zval_affine_elem);
break;
case IS_DOUBLE:
affine[i] = Z_DVAL_PP(zval_affine_elem);
break;
case IS_STRING:
convert_to_double_ex(zval_affine_elem);
affine[i] = Z_DVAL_PP(zval_affine_elem);
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i);
RETURN_FALSE;
}
}
}
if (z_rect != NULL) {
if (zend_hash_find(HASH_OF(z_rect), "x", sizeof("x"), (void **)&tmp) != FAILURE) {
convert_to_long_ex(tmp);
rect.x = Z_LVAL_PP(tmp);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing x position");
RETURN_FALSE;
}
if (zend_hash_find(HASH_OF(z_rect), "y", sizeof("x"), (void **)&tmp) != FAILURE) {
convert_to_long_ex(tmp);
rect.y = Z_LVAL_PP(tmp);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing y position");
RETURN_FALSE;
}
if (zend_hash_find(HASH_OF(z_rect), "width", sizeof("width"), (void **)&tmp) != FAILURE) {
convert_to_long_ex(tmp);
rect.width = Z_LVAL_PP(tmp);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing width");
RETURN_FALSE;
}
if (zend_hash_find(HASH_OF(z_rect), "height", sizeof("height"), (void **)&tmp) != FAILURE) {
convert_to_long_ex(tmp);
rect.height = Z_LVAL_PP(tmp);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing height");
RETURN_FALSE;
}
pRect = &rect;
} else {
rect.x = -1;
rect.y = -1;
rect.width = gdImageSX(src);
rect.height = gdImageSY(src);
pRect = NULL;
}
//int gdTransformAffineGetImage(gdImagePtr *dst, const gdImagePtr src, gdRectPtr src_area, const double affine[6]);
if (gdTransformAffineGetImage(&dst, src, pRect, affine) != GD_TRUE) {
RETURN_FALSE;
}
if (dst == NULL) {
RETURN_FALSE;
} else {
ZEND_REGISTER_RESOURCE(return_value, dst, le_gd);
}
}
/* }}} */
/* {{{ proto array imageaffinematrixget(type[, options])
Return an image containing the affine tramsformed src image, using an optional clipping area */
PHP_FUNCTION(imageaffinematrixget)
{
double affine[6];
gdAffineStandardMatrix type;
zval *options;
zval **tmp;
int res, i;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &type, &options) == FAILURE) {
return;
}
switch(type) {
case GD_AFFINE_TRANSLATE:
case GD_AFFINE_SCALE: {
double x, y;
if (Z_TYPE_P(options) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array expected as options");
}
if (zend_hash_find(HASH_OF(options), "x", sizeof("x"), (void **)&tmp) != FAILURE) {
convert_to_double_ex(tmp);
x = Z_DVAL_PP(tmp);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing x position");
RETURN_FALSE;
}
if (zend_hash_find(HASH_OF(options), "y", sizeof("y"), (void **)&tmp) != FAILURE) {
convert_to_double_ex(tmp);
y = Z_DVAL_PP(tmp);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing y position");
RETURN_FALSE;
}
if (type == GD_AFFINE_TRANSLATE) {
res = gdAffineTranslate(affine, x, y);
} else {
res = gdAffineScale(affine, x, y);
}
break;
}
case GD_AFFINE_ROTATE:
case GD_AFFINE_SHEAR_HORIZONTAL:
case GD_AFFINE_SHEAR_VERTICAL: {
double angle;
convert_to_double_ex(&options);
angle = Z_DVAL_P(options);
if (type == GD_AFFINE_SHEAR_HORIZONTAL) {
res = gdAffineShearHorizontal(affine, angle);
} else if (type == GD_AFFINE_SHEAR_VERTICAL) {
res = gdAffineShearVertical(affine, angle);
} else {
res = gdAffineRotate(affine, angle);
}
break;
}
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", type);
RETURN_FALSE;
}
array_init(return_value);
for (i = 0; i < 6; i++) {
add_index_double(return_value, i, affine[i]);
}
}
/* {{{ proto array imageaffineconcat(array m1, array m2)
Concat two matrices (as in doing many ops in one go) */
PHP_FUNCTION(imageaffinematrixconcat)
{
double m1[6];
double m2[6];
double mr[6];
zval **tmp;
zval *z_m1;
zval *z_m2;
int i, nelems;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa", &z_m1, &z_m2) == FAILURE) {
return;
}
if (((nelems = zend_hash_num_elements(Z_ARRVAL_P(z_m1))) != 6) || (nelems = zend_hash_num_elements(Z_ARRVAL_P(z_m2))) != 6) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Affine arrays must have six elements");
RETURN_FALSE;
}
for (i = 0; i < 6; i++) {
if (zend_hash_index_find(Z_ARRVAL_P(z_m1), i, (void **) &tmp) == SUCCESS) {
switch (Z_TYPE_PP(tmp)) {
case IS_LONG:
m1[i] = Z_LVAL_PP(tmp);
break;
case IS_DOUBLE:
m1[i] = Z_DVAL_PP(tmp);
break;
case IS_STRING:
convert_to_double_ex(tmp);
m1[i] = Z_DVAL_PP(tmp);
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i);
RETURN_FALSE;
}
}
if (zend_hash_index_find(Z_ARRVAL_P(z_m2), i, (void **) &tmp) == SUCCESS) {
switch (Z_TYPE_PP(tmp)) {
case IS_LONG:
m2[i] = Z_LVAL_PP(tmp);
break;
case IS_DOUBLE:
m2[i] = Z_DVAL_PP(tmp);
break;
case IS_STRING:
convert_to_double_ex(tmp);
m2[i] = Z_DVAL_PP(tmp);
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i);
RETURN_FALSE;
}
}
}
if (gdAffineConcat (mr, m1, m2) != GD_TRUE) {
RETURN_FALSE;
}
array_init(return_value);
for (i = 0; i < 6; i++) {
add_index_double(return_value, i, mr[i]);
}
}
/* {{{ proto resource imagesetinterpolation(resource im, [, method]])
Set the default interpolation method, passing -1 or 0 sets it to the libgd default (bilinear). */
PHP_FUNCTION(imagesetinterpolation)
{
zval *IM;
gdImagePtr im;
gdInterpolationMethod method = GD_BILINEAR_FIXED;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &IM, &method) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd);
if (method == -1) {
method = GD_BILINEAR_FIXED;
}
RETURN_BOOL(gdImageSetInterpolationMethod(im, (gdInterpolationMethod) method));
}
/* }}} */
#endif
+72 -1
View File
@@ -168,6 +168,8 @@ gdImagePtr gdImageCreate (int sx, int sy)
im->cy1 = 0;
im->cx2 = im->sx - 1;
im->cy2 = im->sy - 1;
im->interpolation = NULL;
im->interpolation_id = GD_BILINEAR_FIXED;
return im;
}
@@ -183,7 +185,7 @@ gdImagePtr gdImageCreateTrueColor (int sx, int sy)
if (overflow2(sizeof(unsigned char *), sy)) {
return NULL;
}
if (overflow2(sizeof(int), sx)) {
return NULL;
}
@@ -221,6 +223,8 @@ gdImagePtr gdImageCreateTrueColor (int sx, int sy)
im->cy1 = 0;
im->cx2 = im->sx - 1;
im->cy2 = im->sy - 1;
im->interpolation = NULL;
im->interpolation_id = GD_BILINEAR_FIXED;
return im;
}
@@ -3009,3 +3013,70 @@ void gdImageGetClip (gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P)
*y2P = im->cy2;
}
/* convert a palette image to true color */
int gdImagePaletteToTrueColor(gdImagePtr src)
{
unsigned int y;
unsigned char alloc_y = 0, alloc_aa = 0;
unsigned int yy;
if (src == NULL) {
return 0;
}
if (src->trueColor == 1) {
return 1;
} else {
unsigned int x;
const unsigned int sy = gdImageSY(src);
const unsigned int sx = gdImageSX(src);
src->tpixels = (int **) gdMalloc(sizeof(int *) * sy);
if (src->tpixels == NULL) {
return 0;
}
for (y = 0; y < sy; y++) {
const unsigned char *src_row = src->pixels[y];
int * dst_row;
/* no need to calloc it, we overwrite all pxl anyway */
src->tpixels[y] = (int *) gdMalloc(sx * sizeof(int));
if (src->tpixels[y] == NULL) {
goto clean_on_error;
}
dst_row = src->tpixels[y];
for (x = 0; x < sx; x++) {
const unsigned char c = *(src_row + x);
if (c == src->transparent) {
*(dst_row + x) = gdTrueColorAlpha(0, 0, 0, 127);;
} else {
*(dst_row + x) = gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]);
}
}
}
}
/* free old palette buffer */
for (yy = y - 1; yy >= yy - 1; yy--) {
gdFree(src->pixels[yy]);
}
gdFree(src->pixels);
src->trueColor = 1;
src->pixels = NULL;
src->alphaBlendingFlag = 0;
src->saveAlphaFlag = 1;
return 1;
clean_on_error:
if (y > 0) {
for (yy = y; yy >= yy - 1; y--) {
gdFree(src->tpixels[y]);
}
gdFree(src->tpixels);
}
return 0;
}
+140 -1
View File
@@ -93,6 +93,10 @@ void php_gd_error(const char *format, ...);
#define gdEffectNormal 2
#define gdEffectOverlay 3
#define GD_TRUE 1
#define GD_FALSE 0
#define GD_EPSILON 1e-6
/* This function accepts truecolor pixel values only. The
source color is composited with the destination color
@@ -101,6 +105,67 @@ void php_gd_error(const char *format, ...);
int gdAlphaBlend(int dest, int src);
/**
* Group: Transform
*
* Constants: gdInterpolationMethod
* GD_BELL - Bell
* GD_BESSEL - Bessel
* GD_BILINEAR_FIXED - fixed point bilinear
* GD_BICUBIC - Bicubic
* GD_BICUBIC_FIXED - fixed point bicubic integer
* GD_BLACKMAN - Blackman
* GD_BOX - Box
* GD_BSPLINE - BSpline
* GD_CATMULLROM - Catmullrom
* GD_GAUSSIAN - Gaussian
* GD_GENERALIZED_CUBIC - Generalized cubic
* GD_HERMITE - Hermite
* GD_HAMMING - Hamming
* GD_HANNING - Hannig
* GD_MITCHELL - Mitchell
* GD_NEAREST_NEIGHBOUR - Nearest neighbour interpolation
* GD_POWER - Power
* GD_QUADRATIC - Quadratic
* GD_SINC - Sinc
* GD_TRIANGLE - Triangle
* GD_WEIGHTED4 - 4 pixels weighted bilinear interpolation
*
* See also:
* <gdSetInterpolationMethod>
**/
typedef enum {
GD_DEFAULT = 0,
GD_BELL,
GD_BESSEL,
GD_BILINEAR_FIXED,
GD_BICUBIC,
GD_BICUBIC_FIXED,
GD_BLACKMAN,
GD_BOX,
GD_BSPLINE,
GD_CATMULLROM,
GD_GAUSSIAN,
GD_GENERALIZED_CUBIC,
GD_HERMITE,
GD_HAMMING,
GD_HANNING,
GD_MITCHELL,
GD_NEAREST_NEIGHBOUR,
GD_POWER,
GD_QUADRATIC,
GD_SINC,
GD_TRIANGLE,
GD_WEIGHTED4,
GD_METHOD_COUNT = 21
} gdInterpolationMethod;
/* define struct with name and func ptr and add it to gdImageStruct gdInterpolationMethod interpolation; */
/* Interpolation function ptr */
typedef double (* interpolation_method )(double);
typedef struct gdImageStruct {
/* Palette-based image pixels */
unsigned char ** pixels;
@@ -188,10 +253,35 @@ typedef struct gdImageStruct {
int cy1;
int cx2;
int cy2;
gdInterpolationMethod interpolation_id;
interpolation_method interpolation;
} gdImage;
typedef gdImage * gdImagePtr;
/* Point type for use in polygon drawing. */
/**
* Group: Types
*
* typedef: gdPointF
* Defines a point in a 2D coordinate system using floating point
* values.
* x - Floating point position (increase from left to right)
* y - Floating point Row position (increase from top to bottom)
*
* typedef: gdPointFPtr
* Pointer to a <gdPointF>
*
* See also:
* <gdImageCreate>, <gdImageCreateTrueColor>,
**/
typedef struct
{
double x, y;
}
gdPointF, *gdPointFPtr;
typedef struct {
/* # of characters in font */
int nchars;
@@ -469,7 +559,7 @@ void gdImageColorDeallocate(gdImagePtr im, int color);
gdImagePtr gdImageCreatePaletteFromTrueColor (gdImagePtr im, int ditherFlag, int colorsWanted);
void gdImageTrueColorToPalette(gdImagePtr im, int ditherFlag, int colorsWanted);
int gdImagePaletteToTrueColor(gdImagePtr src);
/* An attempt at getting the results of gdImageTrueColorToPalette
to look a bit more like the original (im1 is the original
@@ -600,6 +690,7 @@ gdImagePtr gdImageRotate180(gdImagePtr src, int ignoretransparent);
gdImagePtr gdImageRotate270(gdImagePtr src, int ignoretransparent);
gdImagePtr gdImageRotate45(gdImagePtr src, double dAngle, int clrBack, int ignoretransparent);
gdImagePtr gdImageRotate (gdImagePtr src, double dAngle, int clrBack, int ignoretransparent);
gdImagePtr gdImageRotateInterpolated(const gdImagePtr src, const float angle, int bgcolor);
void gdImageSetBrush(gdImagePtr im, gdImagePtr brush);
void gdImageSetTile(gdImagePtr im, gdImagePtr tile);
@@ -741,6 +832,54 @@ gdImagePtr gdImageCrop(gdImagePtr src, const gdRectPtr crop);
gdImagePtr gdImageCropAuto(gdImagePtr im, const unsigned int mode);
gdImagePtr gdImageCropThreshold(gdImagePtr im, const unsigned int color, const float threshold);
int gdImageSetInterpolationMethod(gdImagePtr im, gdInterpolationMethod id);
gdImagePtr gdImageScaleBilinear(gdImagePtr im, const unsigned int new_width, const unsigned int new_height);
gdImagePtr gdImageScaleBicubic(gdImagePtr src_img, const unsigned int new_width, const unsigned int new_height);
gdImagePtr gdImageScaleBicubicFixed(gdImagePtr src, const unsigned int width, const unsigned int height);
gdImagePtr gdImageScaleNearestNeighbour(gdImagePtr im, const unsigned int width, const unsigned int height);
gdImagePtr gdImageScaleTwoPass(const gdImagePtr pOrigImage, const unsigned int uOrigWidth, const unsigned int uOrigHeight, const unsigned int uNewWidth, const unsigned int uNewHeight);
gdImagePtr gdImageScale(const gdImagePtr src, const unsigned int new_width, const unsigned int new_height);
gdImagePtr gdImageRotateNearestNeighbour(gdImagePtr src, const float degrees, const int bgColor);
gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int bgColor);
gdImagePtr gdImageRotateBicubicFixed(gdImagePtr src, const float degrees, const int bgColor);
gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int bgColor);
typedef enum {
GD_AFFINE_TRANSLATE = 0,
GD_AFFINE_SCALE,
GD_AFFINE_ROTATE,
GD_AFFINE_SHEAR_HORIZONTAL,
GD_AFFINE_SHEAR_VERTICAL,
} gdAffineStandardMatrix;
int gdAffineApplyToPointF (gdPointFPtr dst, const gdPointFPtr src, const double affine[6]);
int gdAffineInvert (double dst[6], const double src[6]);
int gdAffineFlip (double dst_affine[6], const double src_affine[6], const int flip_h, const int flip_v);
int gdAffineConcat (double dst[6], const double m1[6], const double m2[6]);
int gdAffineIdentity (double dst[6]);
int gdAffineScale (double dst[6], const double scale_x, const double scale_y);
int gdAffineRotate (double dst[6], const double angle);
int gdAffineShearHorizontal (double dst[6], const double angle);
int gdAffineShearVertical(double dst[6], const double angle);
int gdAffineTranslate (double dst[6], const double offset_x, const double offset_y);
double gdAffineExpansion (const double src[6]);
int gdAffineRectilinear (const double src[6]);
int gdAffineEqual (const double matrix1[6], const double matrix2[6]);
int gdTransformAffineGetImage(gdImagePtr *dst, const gdImagePtr src, gdRectPtr src_area, const double affine[6]);
int gdTransformAffineCopy(gdImagePtr dst, int dst_x, int dst_y, const gdImagePtr src, gdRectPtr src_region, const double affine[6]);
/*
gdTransformAffineCopy(gdImagePtr dst, int x0, int y0, int x1, int y1,
const gdImagePtr src, int src_width, int src_height,
const double affine[6]);
*/
int gdTransformAffineBoundingBox(gdRectPtr src, const double affine[6], gdRectPtr bbox);
#define GD_CMP_IMAGE 1 /* Actual image IS different */
#define GD_CMP_NUM_COLORS 2 /* Number of Colours in pallette differ */
#define GD_CMP_COLOR 4 /* Image colours differ */
File diff suppressed because it is too large Load Diff
+334
View File
@@ -0,0 +1,334 @@
#include "gd.h"
#include <math.h>
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
/**
* Title: Matrix
* Group: Affine Matrix
*/
/**
* Function: gdAffineApplyToPointF
* Applies an affine transformation to a point (floating point
* gdPointF)
*
*
* Parameters:
* dst - Where to store the resulting point
* affine - Source Point
* flip_horz - affine matrix
*
* Returns:
* GD_TRUE if the affine is rectilinear or GD_FALSE
*/
int gdAffineApplyToPointF (gdPointFPtr dst, const gdPointFPtr src,
const double affine[6])
{
double x = src->x;
double y = src->y;
x = src->x;
y = src->y;
dst->x = x * affine[0] + y * affine[2] + affine[4];
dst->y = x * affine[1] + y * affine[3] + affine[5];
return GD_TRUE;
}
/**
* Function: gdAffineInvert
* Find the inverse of an affine transformation.
*
* All non-degenerate affine transforms are invertible. Applying the
* inverted matrix will restore the original values. Multiplying <src>
* by <dst> (commutative) will return the identity affine (rounding
* error possible).
*
* Parameters:
* dst - Where to store the resulting affine transform
* src_affine - Original affine matrix
* flip_horz - Whether or not to flip horizontally
* flip_vert - Whether or not to flip vertically
*
* See also:
* <gdAffineIdentity>
*
* Returns:
* GD_TRUE if the affine is rectilinear or GD_FALSE
*/
int gdAffineInvert (double dst[6], const double src[6])
{
double r_det = (src[0] * src[3] - src[1] * src[2]);
if (r_det <= 0.0) {
return GD_FALSE;
}
r_det = 1.0 / r_det;
dst[0] = src[3] * r_det;
dst[1] = -src[1] * r_det;
dst[2] = -src[2] * r_det;
dst[3] = src[0] * r_det;
dst[4] = -src[4] * dst[0] - src[5] * dst[2];
dst[5] = -src[4] * dst[1] - src[5] * dst[3];
return GD_TRUE;
}
/**
* Function: gdAffineFlip
* Flip an affine transformation horizontally or vertically.
*
* Flips the affine transform, giving GD_FALSE for <flip_horz> and
* <flip_vert> will clone the affine matrix. GD_TRUE for both will
* copy a 180° rotation.
*
* Parameters:
* dst - Where to store the resulting affine transform
* src_affine - Original affine matrix
* flip_h - Whether or not to flip horizontally
* flip_v - Whether or not to flip vertically
*
* Returns:
* GD_SUCCESS on success or GD_FAILURE
*/
int gdAffineFlip (double dst[6], const double src[6], const int flip_h, const int flip_v)
{
dst[0] = flip_h ? - src[0] : src[0];
dst[1] = flip_h ? - src[1] : src[1];
dst[2] = flip_v ? - src[2] : src[2];
dst[3] = flip_v ? - src[3] : src[3];
dst[4] = flip_h ? - src[4] : src[4];
dst[5] = flip_v ? - src[5] : src[5];
return GD_TRUE;
}
/**
* Function: gdAffineConcat
* Concat (Multiply) two affine transformation matrices.
*
* Concats two affine transforms together, i.e. the result
* will be the equivalent of doing first the transformation m1 and then
* m2. All parameters can be the same matrix (safe to call using
* the same array for all three arguments).
*
* Parameters:
* dst - Where to store the resulting affine transform
* m1 - First affine matrix
* m2 - Second affine matrix
*
* Returns:
* GD_SUCCESS on success or GD_FAILURE
*/
int gdAffineConcat (double dst[6], const double m1[6], const double m2[6])
{
double dst0, dst1, dst2, dst3, dst4, dst5;
dst0 = m1[0] * m2[0] + m1[1] * m2[2];
dst1 = m1[0] * m2[1] + m1[1] * m2[3];
dst2 = m1[2] * m2[0] + m1[3] * m2[2];
dst3 = m1[2] * m2[1] + m1[3] * m2[3];
dst4 = m1[4] * m2[0] + m1[5] * m2[2] + m2[4];
dst5 = m1[4] * m2[1] + m1[5] * m2[3] + m2[5];
dst[0] = dst0;
dst[1] = dst1;
dst[2] = dst2;
dst[3] = dst3;
dst[4] = dst4;
dst[5] = dst5;
return GD_TRUE;
}
/**
* Function: gdAffineIdentity
* Set up the identity matrix.
*
* Parameters:
* dst - Where to store the resulting affine transform
*
* Returns:
* GD_SUCCESS on success or GD_FAILURE
*/
int gdAffineIdentity (double dst[6])
{
dst[0] = 1;
dst[1] = 0;
dst[2] = 0;
dst[3] = 1;
dst[4] = 0;
dst[5] = 0;
return GD_TRUE;
}
/**
* Function: gdAffineScale
* Set up a scaling matrix.
*
* Parameters:
* scale_x - X scale factor
* scale_y - Y scale factor
*
* Returns:
* GD_SUCCESS on success or GD_FAILURE
*/
int gdAffineScale (double dst[6], const double scale_x, const double scale_y)
{
dst[0] = scale_x;
dst[1] = 0;
dst[2] = 0;
dst[3] = scale_y;
dst[4] = 0;
dst[5] = 0;
return GD_TRUE;
}
/**
* Function: gdAffineRotate
* Set up a rotation affine transform.
*
* Like the other angle in libGD, in which increasing y moves
* downward, this is a counterclockwise rotation.
*
* Parameters:
* dst - Where to store the resulting affine transform
* angle - Rotation angle in degrees
*
* Returns:
* GD_SUCCESS on success or GD_FAILURE
*/
int gdAffineRotate (double dst[6], const double angle)
{
const double sin_t = sin (angle * M_PI / 180.0);
const double cos_t = cos (angle * M_PI / 180.0);
dst[0] = cos_t;
dst[1] = sin_t;
dst[2] = -sin_t;
dst[3] = cos_t;
dst[4] = 0;
dst[5] = 0;
return GD_TRUE;
}
/**
* Function: gdAffineShearHorizontal
* Set up a horizontal shearing matrix || becomes \\.
*
* Parameters:
* dst - Where to store the resulting affine transform
* angle - Shear angle in degrees
*
* Returns:
* GD_SUCCESS on success or GD_FAILURE
*/
int gdAffineShearHorizontal(double dst[6], const double angle)
{
dst[0] = 1;
dst[1] = 0;
dst[2] = tan(angle * M_PI / 180.0);
dst[3] = 1;
dst[4] = 0;
dst[5] = 0;
return GD_TRUE;
}
/**
* Function: gdAffineShearVertical
* Set up a vertical shearing matrix, columns are untouched.
*
* Parameters:
* dst - Where to store the resulting affine transform
* angle - Shear angle in degrees
*
* Returns:
* GD_SUCCESS on success or GD_FAILURE
*/
int gdAffineShearVertical(double dst[6], const double angle)
{
dst[0] = 1;
dst[1] = tan(angle * M_PI / 180.0);;
dst[2] = 0;
dst[3] = 1;
dst[4] = 0;
dst[5] = 0;
return GD_TRUE;
}
/**
* Function: gdAffineTranslate
* Set up a translation matrix.
*
* Parameters:
* dst - Where to store the resulting affine transform
* offset_x - Horizontal translation amount
* offset_y - Vertical translation amount
*
* Returns:
* GD_SUCCESS on success or GD_FAILURE
*/
int gdAffineTranslate (double dst[6], const double offset_x, const double offset_y)
{
dst[0] = 1;
dst[1] = 0;
dst[2] = 0;
dst[3] = 1;
dst[4] = offset_x;
dst[5] = offset_y;
return GD_TRUE;
}
/**
* gdAffineexpansion: Find the affine's expansion factor.
* @src: The affine transformation.
*
* Finds the expansion factor, i.e. the square root of the factor
* by which the affine transform affects area. In an affine transform
* composed of scaling, rotation, shearing, and translation, returns
* the amount of scaling.
*
* GD_SUCCESS on success or GD_FAILURE
**/
double gdAffineExpansion (const double src[6])
{
return sqrt (fabs (src[0] * src[3] - src[1] * src[2]));
}
/**
* Function: gdAffineRectilinear
* Determines whether the affine transformation is axis aligned. A
* tolerance has been implemented using GD_EPSILON.
*
* Parameters:
* m - The affine transformation
*
* Returns:
* GD_TRUE if the affine is rectilinear or GD_FALSE
*/
int gdAffineRectilinear (const double m[6])
{
return ((fabs (m[1]) < GD_EPSILON && fabs (m[2]) < GD_EPSILON) ||
(fabs (m[0]) < GD_EPSILON && fabs (m[3]) < GD_EPSILON));
}
/**
* Function: gdAffineEqual
* Determines whether two affine transformations are equal. A tolerance
* has been implemented using GD_EPSILON.
*
* Parameters:
* m1 - The first affine transformation
* m2 - The first affine transformation
*
* Returns:
* GD_SUCCESS on success or GD_FAILURE
*/
int gdAffineEqual (const double m1[6], const double m2[6])
{
return (fabs (m1[0] - m2[0]) < GD_EPSILON &&
fabs (m1[1] - m2[1]) < GD_EPSILON &&
fabs (m1[2] - m2[2]) < GD_EPSILON &&
fabs (m1[3] - m2[3]) < GD_EPSILON &&
fabs (m1[4] - m2[4]) < GD_EPSILON &&
fabs (m1[5] - m2[5]) < GD_EPSILON);
}
+6
View File
@@ -104,6 +104,7 @@ PHP_FUNCTION(imagefttext);
PHP_FUNCTION(imagecreatetruecolor);
PHP_FUNCTION(imagetruecolortopalette);
PHP_FUNCTION(imagepalettetotruecolor);
PHP_FUNCTION(imagesetthickness);
PHP_FUNCTION(imagefilledellipse);
PHP_FUNCTION(imagefilledarc);
@@ -127,6 +128,11 @@ PHP_FUNCTION(imageantialias);
PHP_FUNCTION(imageflip);
PHP_FUNCTION(imagecrop);
PHP_FUNCTION(imagecropauto);
PHP_FUNCTION(imagescale);
PHP_FUNCTION(imageaffine);
PHP_FUNCTION(imageaffinematrixget);
PHP_FUNCTION(imageaffinematrixconcat);
PHP_FUNCTION(imagesetinterpolation);
#endif
PHP_FUNCTION(imagesetthickness);
@@ -139,14 +139,10 @@ static void _breakiterator_parts_destroy_it(zend_object_iterator *iter TSRMLS_DC
zval_ptr_dtor(reinterpret_cast<zval**>(&iter->data));
}
static int _breakiterator_parts_get_current_key(zend_object_iterator *iter,
char **str_key,
uint *str_key_len,
ulong *int_key TSRMLS_DC)
static void _breakiterator_parts_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
/* the actual work is done in move_forward and rewind */
*int_key = iter->index;
return HASH_KEY_IS_LONG;
ZVAL_LONG(key, iter->index);
}
static void _breakiterator_parts_move_forward(zend_object_iterator *iter TSRMLS_DC)
@@ -343,4 +339,4 @@ U_CFUNC void breakiterator_register_IntlPartsIterator_class(TSRMLS_D)
PARTSITER_DECL_LONG_CONST(KEY_RIGHT);
#undef PARTSITER_DECL_LONG_CONST
}
}
@@ -53,7 +53,7 @@ static void _breakiter_factory(const char *func_name,
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!",
&locale_str, &dummy) == FAILURE) {
spprintf(&msg, NULL, "%s: bad arguments", func_name);
spprintf(&msg, 0, "%s: bad arguments", func_name);
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC);
efree(msg);
RETURN_NULL();
@@ -66,7 +66,7 @@ static void _breakiter_factory(const char *func_name,
biter = func(Locale::createFromName(locale_str), status);
intl_error_set_code(NULL, status TSRMLS_CC);
if (U_FAILURE(status)) {
spprintf(&msg, NULL, "%s: error creating BreakIterator",
spprintf(&msg, 0, "%s: error creating BreakIterator",
func_name);
intl_error_set_custom_msg(NULL, msg, 1 TSRMLS_CC);
efree(msg);
@@ -201,7 +201,7 @@ static void _breakiter_no_args_ret_int32(
object = getThis();
if (zend_parse_parameters_none() == FAILURE) {
spprintf(&msg, NULL, "%s: bad arguments", func_name);
spprintf(&msg, 0, "%s: bad arguments", func_name);
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC);
efree(msg);
RETURN_FALSE;
@@ -225,7 +225,7 @@ static void _breakiter_int32_ret_int32(
object = getThis();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &arg) == FAILURE) {
spprintf(&msg, NULL, "%s: bad arguments", func_name);
spprintf(&msg, 0, "%s: bad arguments", func_name);
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC);
efree(msg);
RETURN_FALSE;
@@ -234,7 +234,7 @@ static void _breakiter_int32_ret_int32(
BREAKITER_METHOD_FETCH_OBJECT;
if (arg < INT32_MIN || arg > INT32_MAX) {
spprintf(&msg, NULL, "%s: offset argument is outside bounds of "
spprintf(&msg, 0, "%s: offset argument is outside bounds of "
"a 32-bit wide integer", func_name);
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC);
efree(msg);
+1 -13
View File
@@ -251,19 +251,7 @@ static PHP_METHOD(IntlIterator, key)
INTLITERATOR_METHOD_FETCH_OBJECT;
if (ii->iterator->funcs->get_current_key) {
char *str_key;
uint str_key_len;
ulong int_key;
switch (ii->iterator->funcs->get_current_key(
ii->iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) {
case HASH_KEY_IS_LONG:
RETURN_LONG(int_key);
break;
case HASH_KEY_IS_STRING:
RETURN_STRINGL(str_key, str_key_len-1, 0);
break;
}
ii->iterator->funcs->get_current_key(ii->iterator, return_value TSRMLS_CC);
} else {
RETURN_LONG(ii->iterator->index);
}
@@ -101,21 +101,18 @@ static void resourcebundle_iterator_current( zend_object_iterator *iter, zval **
/* }}} */
/* {{{ resourcebundle_iterator_key */
static int resourcebundle_iterator_key( zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC )
static void resourcebundle_iterator_key( zend_object_iterator *iter, zval *key TSRMLS_DC )
{
ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
if (!iterator->current) {
resourcebundle_iterator_read( iterator TSRMLS_CC);
}
if (iterator->is_table) {
*str_key = estrdup( iterator->currentkey );
*str_key_len = strlen( iterator->currentkey ) + 1;
return HASH_KEY_IS_STRING;
}
else {
*int_key = iterator->i;
return HASH_KEY_IS_LONG;
ZVAL_STRING(key, iterator->currentkey, 1);
} else {
ZVAL_LONG(key, iterator->i);
}
}
/* }}} */
+3 -3
View File
@@ -45,12 +45,12 @@ mysql_free_result($res);
$version = mysql_get_server_info($link);
if (!preg_match('@(\d+)\.(\d+)\.(\d+)@ism', $version, $matches))
printf("[009] Cannot get server version\n");
$version = ($matches[1] * 100) + ($matches[2] * 10) + $matches[3];
$version = ($matches[1] * 1000) + ($matches[2] * 100) + $matches[3];
$tables = array(
'label INT, UNIQUE KEY (label)' => array(
array('label', '1'),
'label' => array(($version < 500) ? 'multiple_key' : 'unique_key')
'label' => array(($version < 5000) ? 'multiple_key' : 'unique_key')
),
'labela INT, label2 CHAR(1), KEY keyname (labela, label2)' => array(
array('labela, label2', "1, 'a'"),
@@ -86,7 +86,7 @@ $tables = array(
),
);
if ($version < 560) {
if ($version < 5600) {
$tables['label1 TIMESTAMP']['label1'][] = 'zerofill';
$tables['label1 TIMESTAMP']['label1'][] = 'unsigned';
}
+1 -1
View File
@@ -74,7 +74,7 @@ mysql_field_name(): id
mysql_field_type(): int
Field Offset 1
mysql_field_flags()%s
mysql_field_len(): 1
mysql_field_len(): %s
mysql_field_name(): label
mysql_field_type(): string
done!
+2 -3
View File
@@ -150,12 +150,11 @@ static void php_mysqli_result_iterator_rewind(zend_object_iterator *iter TSRMLS_
/* {{{ php_mysqli_result_iterator_current_key */
static int php_mysqli_result_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
static void php_mysqli_result_iterator_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
{
php_mysqli_result_iterator *iterator = (php_mysqli_result_iterator*) iter;
*int_key = (ulong) iterator->row_num;
return HASH_KEY_IS_LONG;
ZVAL_LONG(key, iterator->row_num);
}
/* }}} */
+9 -11
View File
@@ -445,12 +445,12 @@ mysqlnd_mbcharlen_utf32(unsigned int utf32 __attribute((unused)))
const MYSQLND_CHARSET mysqlnd_charsets[] =
{
{ 1, "big5","big5_chinese_ci", 1, 2, "", mysqlnd_mbcharlen_big5, check_mb_big5},
{ 3, "dec8", "dec8_swedisch_ci", 1, 1, "", NULL, NULL},
{ 3, "dec8", "dec8_swedish_ci", 1, 1, "", NULL, NULL},
{ 4, "cp850", "cp850_general_ci", 1, 1, "", NULL, NULL},
{ 6, "hp8", "hp8_english_ci", 1, 1, "", NULL, NULL},
{ 7, "koi8r", "koi8r_general_ci", 1, 1, "", NULL, NULL},
{ 8, "latin1", "latin1_swedish_ci", 1, 1, "", NULL, NULL},
{ 5, "latin1", "latin1_german_ci", 1, 1, "", NULL, NULL}, /* should be after 0x9 because swedish_ci is the default collation */
{ 5, "latin1", "latin1_german1_ci", 1, 1, "", NULL, NULL}, /* should be after 0x8 because swedish_ci is the default collation */
{ 9, "latin2", "latin2_general_ci", 1, 1, "", NULL, NULL},
{ 2, "latin2", "latin2_czech_cs", 1, 1, "", NULL, NULL}, /* should be after 0x9 because general_ci is the default collation */
{ 10, "swe7", "swe7_swedish_ci", 1, 1, "", NULL, NULL},
@@ -485,7 +485,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 59, "cp1257", "cp1257_general_ci", 1, 1, "", NULL, NULL},
{ 63, "binary", "binary", 1, 1, "", NULL, NULL},
{ 97, "eucjpms", "eucjpms_japanese_ci", 1, 3, "", mysqlnd_mbcharlen_eucjpms, check_mb_eucjpms},
{ 29, "cp1257", "cp1257_lithunian_ci", 1, 1, "", NULL, NULL},
{ 29, "cp1257", "cp1257_lithuanian_ci", 1, 1, "", NULL, NULL},
{ 31, "latin1", "latin1_german2_ci", 1, 1, "", NULL, NULL},
{ 34, "cp1250", "cp1250_czech_cs", 1, 1, "", NULL, NULL},
{ 42, "latin7", "latin7_general_cs", 1, 1, "", NULL, NULL},
@@ -506,19 +506,17 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 55, "utf16", "utf16_bin", 2, 4, "UTF-16 Unicode", mysqlnd_mbcharlen_utf16, check_mb_utf16},
{ 56, "utf16le", "utf16le_general_ci", 2, 4, "UTF-16LE Unicode", mysqlnd_mbcharlen_utf16, check_mb_utf16},
{ 58, "cp1257", "cp1257_bin", 1, 1, "", NULL, NULL},
#ifdef USED_TO_BE_SO_BEFORE_MYSQL_5_5
{ 60, "armascii8", "armascii8_bin", 1, 1, "", NULL, NULL},
#endif
/*55*/{ 60, "utf32", "utf32_general_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*55*/{ 61, "utf32", "utf32_bin", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
{ 62, "utf16le", "utf16le_bin", 2, 4, "UTF-16LE Unicode", mysqlnd_mbcharlen_utf16, check_mb_utf16},
{ 64, "armscii8", "armscii8_bin", 1, 1, "", NULL, NULL},
{ 65, "ascii", "ascii_bin", 1, 1, "", NULL, NULL},
{ 66, "cp1250", "cp1250_bin", 1, 1, "", NULL, NULL},
{ 67, "cp1256", "cp1256_bin", 1, 1, "", NULL, NULL},
{ 68, "cp866", "cp866_bin", 1, 1, "", NULL, NULL},
{ 69, "dec8", "dec8_bin", 1, 1, "", NULL, NULL},
{ 70, "greek", "greek_bin", 1, 1, "", NULL, NULL},
{ 71, "hebew", "hebrew_bin", 1, 1, "", NULL, NULL},
{ 71, "hebrew", "hebrew_bin", 1, 1, "", NULL, NULL},
{ 72, "hp8", "hp8_bin", 1, 1, "", NULL, NULL},
{ 73, "keybcs2", "keybcs2_bin", 1, 1, "", NULL, NULL},
{ 74, "koi8r", "koi8r_bin", 1, 1, "", NULL, NULL},
@@ -558,7 +556,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 137, "ucs2", "ucs2_turkish_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 138, "ucs2", "ucs2_czech_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 139, "ucs2", "ucs2_danish_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 140, "ucs2", "ucs2_lithunian_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 140, "ucs2", "ucs2_lithuanian_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 141, "ucs2", "ucs2_slovak_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 142, "ucs2", "ucs2_spanish2_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
{ 143, "ucs2", "ucs2_roman_ci", 2, 2, "", mysqlnd_mbcharlen_ucs2, check_mb_ucs2},
@@ -596,7 +594,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
/*56*/{182, "utf32", "utf32_unicode_520_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
/*56*/{183, "utf32", "utf32_vietnamese_ci", 4, 4, "UTF-32 Unicode", mysqlnd_mbcharlen_utf32, check_mb_utf32},
{ 192, UTF8_MB3, UTF8_MB3"_general_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 192, UTF8_MB3, UTF8_MB3"_unicode_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 193, UTF8_MB3, UTF8_MB3"_icelandic_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 194, UTF8_MB3, UTF8_MB3"_latvian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 195, UTF8_MB3, UTF8_MB3"_romanian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
@@ -608,7 +606,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 201, UTF8_MB3, UTF8_MB3"_turkish_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 202, UTF8_MB3, UTF8_MB3"_czech_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 203, UTF8_MB3, UTF8_MB3"_danish_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid },
{ 204, UTF8_MB3, UTF8_MB3"_lithunian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid },
{ 204, UTF8_MB3, UTF8_MB3"_lithuanian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid },
{ 205, UTF8_MB3, UTF8_MB3"_slovak_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 206, UTF8_MB3, UTF8_MB3"_spanish2_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 207, UTF8_MB3, UTF8_MB3"_roman_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
@@ -616,7 +614,7 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 209, UTF8_MB3, UTF8_MB3"_esperanto_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 210, UTF8_MB3, UTF8_MB3"_hungarian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 211, UTF8_MB3, UTF8_MB3"_sinhala_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 211, UTF8_MB3, UTF8_MB3"_german2_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 212, UTF8_MB3, UTF8_MB3"_german2_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 213, UTF8_MB3, UTF8_MB3"_croatian_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 214, UTF8_MB3, UTF8_MB3"_unicode_520_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
{ 215, UTF8_MB3, UTF8_MB3"_vietnamese_ci", 1, 3, "", mysqlnd_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+1 -1
View File
@@ -1463,7 +1463,7 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigne
if (stmt->param_count) {
if (!stmt->param_bind) {
stmt->param_bind = mnd_ecalloc(stmt->param_count, sizeof(MYSQLND_PARAM_BIND));
stmt->param_bind = mnd_pecalloc(stmt->param_count, sizeof(MYSQLND_PARAM_BIND), stmt->persistent);
if (!stmt->param_bind) {
DBG_RETURN(FAIL);
}
File diff suppressed because it is too large Load Diff
+126
View File
@@ -0,0 +1,126 @@
/* pass 10:
* - remove NOPs
*/
static void nop_removal(zend_op_array *op_array)
{
zend_op *end, *opline;
zend_uint new_count, i, shift;
int j;
zend_uint *shiftlist;
ALLOCA_FLAG(use_heap);
shiftlist = (zend_uint *)DO_ALLOCA(sizeof(zend_uint) * op_array->last);
i = new_count = shift = 0;
end = op_array->opcodes + op_array->last;
for (opline = op_array->opcodes; opline < end; opline++) {
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
/* GOTO target is unresolved yet. We can't optimize. */
if (opline->opcode == ZEND_GOTO &&
Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) {
/* TODO: in general we can avoid this restriction */
FREE_ALLOCA(shiftlist);
return;
}
#endif
/* Kill JMP-over-NOP-s */
if (opline->opcode == ZEND_JMP && ZEND_OP1(opline).opline_num > i) {
/* check if there are only NOPs under the branch */
zend_op *target = op_array->opcodes + ZEND_OP1(opline).opline_num - 1;
while (target->opcode == ZEND_NOP) {
target--;
}
if (target == opline) {
/* only NOPs */
opline->opcode = ZEND_NOP;
}
}
shiftlist[i++] = shift;
if (opline->opcode == ZEND_NOP) {
shift++;
} else {
if (shift) {
op_array->opcodes[new_count] = *opline;
}
new_count++;
}
}
if (shift) {
op_array->last = new_count;
end = op_array->opcodes + op_array->last;
/* update JMPs */
for (opline = op_array->opcodes; opline<end; opline++) {
switch (opline->opcode) {
case ZEND_JMP:
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_GOTO:
#endif
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
case ZEND_FAST_CALL:
#endif
ZEND_OP1(opline).opline_num -= shiftlist[ZEND_OP1(opline).opline_num];
break;
case ZEND_JMPZ:
case ZEND_JMPNZ:
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
case ZEND_FE_FETCH:
case ZEND_FE_RESET:
case ZEND_NEW:
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_JMP_SET:
#endif
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
case ZEND_JMP_SET_VAR:
#endif
ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num];
break;
case ZEND_JMPZNZ:
ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num];
opline->extended_value -= shiftlist[opline->extended_value];
break;
case ZEND_CATCH:
opline->extended_value -= shiftlist[opline->extended_value];
break;
}
}
/* update brk/cont array */
for (j = 0; j < op_array->last_brk_cont; j++) {
op_array->brk_cont_array[j].brk -= shiftlist[op_array->brk_cont_array[j].brk];
op_array->brk_cont_array[j].cont -= shiftlist[op_array->brk_cont_array[j].cont];
op_array->brk_cont_array[j].start -= shiftlist[op_array->brk_cont_array[j].start];
}
/* update try/catch array */
for (j = 0; j < op_array->last_try_catch; j++) {
op_array->try_catch_array[j].try_op -= shiftlist[op_array->try_catch_array[j].try_op];
op_array->try_catch_array[j].catch_op -= shiftlist[op_array->try_catch_array[j].catch_op];
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
if (op_array->try_catch_array[j].finally_op) {
op_array->try_catch_array[j].finally_op -= shiftlist[op_array->try_catch_array[j].finally_op];
op_array->try_catch_array[j].finally_end -= shiftlist[op_array->try_catch_array[j].finally_end];
}
#endif
}
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
/* update early binding list */
if (op_array->early_binding != (zend_uint)-1) {
zend_uint *opline_num = &op_array->early_binding;
do {
*opline_num -= shiftlist[*opline_num];
opline_num = &ZEND_RESULT(&op_array->opcodes[*opline_num]).opline_num;
} while (*opline_num != (zend_uint)-1);
}
#endif
}
FREE_ALLOCA(shiftlist);
}
@@ -0,0 +1,222 @@
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
/* ops that use CLs:
op1:
ZEND_FETCH_CONSTANT:
ZEND_INIT_CTOR_CALL:
ZEND_INIT_STATIC_METHOD_CALL:
ZEND_INIT_METHOD_CALL:
ZEND_IMPORT_CLASS:
ZEND_IMPORT_FUNCTION:
ZEND_IMPORT_CONST:
ZEND_ADD_INTERFACE:
ZEND_VERIFY_ABSTRACT_CLASS:
ZEND_NEW:
ZEND_CATCH:
ZEND_INIT_FCALL_BY_NAME:
op2:
ZEND_UNSET_VAR:
ZEND_ISSET_ISEMPTY_VAR:
ZEND_FETCH_UNSET:
ZEND_FETCH_IS:
ZEND_FETCH_R:
ZEND_FETCH_W:
ZEND_FETCH_RW:
ZEND_FETCH_FUNC_ARG:
ZEND_ADD_INTERFACE:
ZEND_INSTANCEOF:
extended_value:
ZEND_DECLARE_INHERITED_CLASS:
ignore result
INIT_METHOD_CALL:
*/
#define OP1_CONST_IS_CLASS 1
#define OP2_CONST_IS_CLASS 2
#define EXT_CONST_IS_CLASS 4
#define RESULT_IS_UNUSED 8
static const char op_const_means_class[256] = {
/* 0 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 32 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
/* 64 */
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2,
/* 96 */
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 9, 1, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 128 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 160 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 192 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 224 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#endif
#define GET_AVAILABLE_T() \
for (i = 0; i < T; i++) { \
if (!taken_T[i]) { \
break; \
} \
} \
taken_T[i] = 1; \
if (i > max) { \
max = i; \
}
static void optimize_temporary_variables(zend_op_array *op_array)
{
int T = op_array->T;
char *taken_T; /* T index in use */
zend_op **start_of_T; /* opline where T is first used */
char *valid_T; /* Is the map_T valid */
int *map_T; /* Map's the T to its new index */
zend_op *opline, *end;
int currT;
int i;
int max = -1;
int var_to_free = -1;
taken_T = (char *) emalloc(T);
start_of_T = (zend_op **) emalloc(T * sizeof(zend_op *));
valid_T = (char *) emalloc(T);
map_T = (int *) emalloc(T * sizeof(int));
end = op_array->opcodes;
opline = &op_array->opcodes[op_array->last - 1];
/* Find T definition points */
while (opline >= end) {
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR | IS_CONST)) {
if (!(op_const_means_class[opline->opcode] & RESULT_IS_UNUSED)) {
start_of_T[VAR_NUM(ZEND_RESULT(opline).var)] = opline;
}
}
#else
if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) {
start_of_T[VAR_NUM(ZEND_RESULT(opline).var)] = opline;
}
#endif
opline--;
}
memset(valid_T, 0, T);
memset(taken_T, 0, T);
end = op_array->opcodes;
opline = &op_array->opcodes[op_array->last - 1];
while (opline >= end) {
if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_TMP_VAR))
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
|| ((op_const_means_class[opline->opcode] & OP1_CONST_IS_CLASS) && ZEND_OP1_TYPE(opline) == IS_CONST)
#endif
) {
currT = VAR_NUM(ZEND_OP1(opline).var);
if (!valid_T[currT]) {
GET_AVAILABLE_T();
map_T[currT] = i;
valid_T[currT] = 1;
}
ZEND_OP1(opline).var = NUM_VAR(map_T[currT]);
}
/* Skip OP_DATA */
if (opline->opcode == ZEND_OP_DATA &&
(opline-1)->opcode == ZEND_ASSIGN_DIM) {
opline--;
continue;
}
if ((ZEND_OP2_TYPE(opline) & (IS_VAR | IS_TMP_VAR))
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
|| ((op_const_means_class[opline->opcode] & OP2_CONST_IS_CLASS) && ZEND_OP2_TYPE(opline) == IS_CONST)
#endif
) {
currT = VAR_NUM(ZEND_OP2(opline).var);
if (!valid_T[currT]) {
GET_AVAILABLE_T();
map_T[currT] = i;
valid_T[currT] = 1;
}
ZEND_OP2(opline).var = NUM_VAR(map_T[currT]);
}
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
if ((op_const_means_class[opline->opcode] & EXT_CONST_IS_CLASS)) {
#else
if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS ||
opline->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED) {
#endif
currT = VAR_NUM(opline->extended_value);
if (!valid_T[currT]) {
GET_AVAILABLE_T();
map_T[currT] = i;
valid_T[currT] = 1;
}
opline->extended_value = NUM_VAR(map_T[currT]);
}
/* Allocate OP_DATA->op2 after "operands", but before "result" */
if (opline->opcode == ZEND_ASSIGN_DIM &&
(opline + 1)->opcode == ZEND_OP_DATA &&
ZEND_OP2_TYPE(opline + 1) & (IS_VAR | IS_TMP_VAR)) {
currT = VAR_NUM(ZEND_OP2(opline + 1).var);
GET_AVAILABLE_T();
map_T[currT] = i;
valid_T[currT] = 1;
taken_T[i] = 0;
ZEND_OP2(opline + 1).var = NUM_VAR(i);
var_to_free = i;
}
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR | IS_CONST)) {
if (!(op_const_means_class[opline->opcode] & RESULT_IS_UNUSED)) {
#else
if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) {
#endif
currT = VAR_NUM(ZEND_RESULT(opline).var);
if (valid_T[currT]) {
if (start_of_T[currT] == opline) {
taken_T[map_T[currT]] = 0;
}
ZEND_RESULT(opline).var = NUM_VAR(map_T[currT]);
} else { /* Au still needs to be assigned a T which is a bit dumb. Should consider changing Zend */
GET_AVAILABLE_T();
if (RESULT_UNUSED(opline)) {
taken_T[i] = 0;
} else {
/* Code which gets here is using a wrongly built opcode such as RECV() */
map_T[currT] = i;
valid_T[currT] = 1;
}
ZEND_RESULT(opline).var = NUM_VAR(i);
}
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
}
#endif
}
if (var_to_free >= 0) {
taken_T[var_to_free] = 0;
var_to_free = -1;
}
opline--;
}
efree(taken_T);
efree(start_of_T);
efree(valid_T);
efree(map_T);
op_array->T = max + 1;
}
+3
View File
@@ -0,0 +1,3 @@
if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & OPTIMIZATION_LEVEL) == ZEND_OPTIMIZER_PASS_10) {
nop_removal(op_array);
}
+395
View File
@@ -0,0 +1,395 @@
/* pass 1
* - substitute persistent constants (true, false, null, etc)
* - perform compile-time evaluation of constant binary and unary operations
* - optimize series of ADD_STRING and/or ADD_CHAR
* - convert CAST(IS_BOOL,x) into BOOL(x)
* - convert INTI_FCALL_BY_NAME, DO_FCALL_BY_NAME into DO_FCALL
*/
if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
int i = 0;
zend_op *opline = op_array->opcodes;
zend_op *end = opline + op_array->last;
while (opline < end) {
switch (opline->opcode) {
case ZEND_ADD:
case ZEND_SUB:
case ZEND_MUL:
case ZEND_DIV:
case ZEND_MOD:
case ZEND_SL:
case ZEND_SR:
case ZEND_CONCAT:
case ZEND_IS_EQUAL:
case ZEND_IS_NOT_EQUAL:
case ZEND_IS_SMALLER:
case ZEND_IS_SMALLER_OR_EQUAL:
case ZEND_IS_IDENTICAL:
case ZEND_IS_NOT_IDENTICAL:
case ZEND_BW_OR:
case ZEND_BW_AND:
case ZEND_BW_XOR:
case ZEND_BOOL_XOR:
if (ZEND_OP1_TYPE(opline) == IS_CONST &&
ZEND_OP2_TYPE(opline) == IS_CONST) {
/* binary operation with constant operands */
int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) = get_binary_op(opline->opcode);
zend_uint tv = ZEND_RESULT(opline).var; /* temporary variable */
zval result;
zend_op *tmp_opline;
int er;
if (opline->opcode == ZEND_DIV &&
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG &&
Z_LVAL(ZEND_OP2_LITERAL(opline)) == 0) {
/* div by 0 */
break;
}
er = EG(error_reporting);
EG(error_reporting) = 0;
/* evaluate constant expression */
if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline) TSRMLS_CC) != SUCCESS) {
EG(error_reporting) = er;
break;
}
EG(error_reporting) = er;
PZ_SET_REFCOUNT_P(&result, 1);
PZ_UNSET_ISREF_P(&result);
literal_dtor(&ZEND_OP1_LITERAL(opline));
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
/* substitute the following TMP_VAR usage with constant */
for (tmp_opline = opline + 1; tmp_opline < end; tmp_opline++) {
if (ZEND_OP1_TYPE(tmp_opline) == IS_TMP_VAR &&
ZEND_OP1(tmp_opline).var == tv) {
if (tmp_opline->opcode == ZEND_FREE) {
MAKE_NOP(tmp_opline);
zval_dtor(&result);
} else {
ZEND_OP1_TYPE(tmp_opline) = IS_CONST;
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
tmp_opline->op1.constant = zend_optimizer_add_literal(op_array, &result TSRMLS_CC);
if (Z_TYPE(result) == IS_STRING) {
Z_HASH_P(&ZEND_OP1_LITERAL(tmp_opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(tmp_opline)), Z_STRLEN(ZEND_OP1_LITERAL(tmp_opline)) + 1);
if (tmp_opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
tmp_opline->opcode == ZEND_DO_FCALL ||
tmp_opline->opcode == ZEND_CATCH ||
tmp_opline->opcode == ZEND_FETCH_CONSTANT) {
op_array->literals[tmp_opline->op1.constant].cache_slot = op_array->last_cache_slot++;
}
}
#else
ZEND_OP1_LITERAL(tmp_opline) = result;
#endif
}
/* TMP_VAR my be used only once */
break;
}
if (ZEND_OP2_TYPE(tmp_opline) == IS_TMP_VAR &&
ZEND_OP2(tmp_opline).var == tv) {
ZEND_OP2_TYPE(tmp_opline) = IS_CONST;
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
tmp_opline->op2.constant = zend_optimizer_add_literal(op_array, &result TSRMLS_CC);
if (Z_TYPE(result) == IS_STRING) {
Z_HASH_P(&ZEND_OP2_LITERAL(tmp_opline)) = zend_hash_func(Z_STRVAL(ZEND_OP2_LITERAL(tmp_opline)), Z_STRLEN(ZEND_OP2_LITERAL(tmp_opline)) + 1);
if (tmp_opline->opcode == ZEND_FETCH_R ||
tmp_opline->opcode == ZEND_FETCH_W ||
tmp_opline->opcode == ZEND_FETCH_RW ||
tmp_opline->opcode == ZEND_FETCH_IS ||
tmp_opline->opcode == ZEND_FETCH_UNSET ||
tmp_opline->opcode == ZEND_FETCH_FUNC_ARG ||
tmp_opline->opcode == ZEND_FETCH_CLASS ||
tmp_opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
tmp_opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
tmp_opline->opcode == ZEND_UNSET_VAR ||
tmp_opline->opcode == ZEND_ISSET_ISEMPTY_VAR ||
tmp_opline->opcode == ZEND_ADD_INTERFACE ||
tmp_opline->opcode == ZEND_ADD_TRAIT) {
op_array->literals[tmp_opline->op2.constant].cache_slot = op_array->last_cache_slot++;
} else if (tmp_opline->opcode == ZEND_INIT_METHOD_CALL ||
tmp_opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
tmp_opline->opcode == ZEND_FETCH_CONSTANT ||
tmp_opline->opcode == ZEND_ASSIGN_OBJ ||
tmp_opline->opcode == ZEND_FETCH_OBJ_R ||
tmp_opline->opcode == ZEND_FETCH_OBJ_W ||
tmp_opline->opcode == ZEND_FETCH_OBJ_RW ||
tmp_opline->opcode == ZEND_FETCH_OBJ_IS ||
tmp_opline->opcode == ZEND_FETCH_OBJ_UNSET ||
tmp_opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG ||
tmp_opline->opcode == ZEND_UNSET_OBJ ||
tmp_opline->opcode == ZEND_PRE_INC_OBJ ||
tmp_opline->opcode == ZEND_PRE_DEC_OBJ ||
tmp_opline->opcode == ZEND_POST_INC_OBJ ||
tmp_opline->opcode == ZEND_POST_DEC_OBJ ||
tmp_opline->opcode == ZEND_ISSET_ISEMPTY_PROP_OBJ) {
op_array->literals[tmp_opline->op2.constant].cache_slot = op_array->last_cache_slot;
op_array->last_cache_slot += 2;
} else if (tmp_opline->opcode == ZEND_ASSIGN_ADD ||
tmp_opline->opcode == ZEND_ASSIGN_SUB ||
tmp_opline->opcode == ZEND_ASSIGN_MUL ||
tmp_opline->opcode == ZEND_ASSIGN_DIV ||
tmp_opline->opcode == ZEND_ASSIGN_MOD ||
tmp_opline->opcode == ZEND_ASSIGN_SL ||
tmp_opline->opcode == ZEND_ASSIGN_SR ||
tmp_opline->opcode == ZEND_ASSIGN_CONCAT ||
tmp_opline->opcode == ZEND_ASSIGN_BW_OR ||
tmp_opline->opcode == ZEND_ASSIGN_BW_AND ||
tmp_opline->opcode == ZEND_ASSIGN_BW_XOR) {
if (tmp_opline->extended_value == ZEND_ASSIGN_OBJ) {
op_array->literals[tmp_opline->op2.constant].cache_slot = op_array->last_cache_slot;
op_array->last_cache_slot += 2;
}
}
}
#else
ZEND_OP2_LITERAL(tmp_opline) = result;
#endif
break;
}
}
}
break;
case ZEND_CAST:
if (ZEND_OP1_TYPE(opline) == IS_CONST &&
opline->extended_value != IS_ARRAY &&
opline->extended_value != IS_OBJECT &&
opline->extended_value != IS_RESOURCE) {
/* cast of constant operand */
zval res;
res = ZEND_OP1_LITERAL(opline);
zval_copy_ctor(&res);
switch (opline->extended_value) {
case IS_NULL:
convert_to_null(&res);
break;
case IS_BOOL:
convert_to_boolean(&res);
break;
case IS_LONG:
convert_to_long(&res);
break;
case IS_DOUBLE:
convert_to_double(&res);
break;
case IS_STRING:
convert_to_string(&res);
break;
}
literal_dtor(&ZEND_OP1_LITERAL(opline));
opline->opcode = ZEND_QM_ASSIGN;
opline->extended_value = 0;
ZEND_OP1_LITERAL(opline) = res;
SET_UNUSED(opline->op2);
} else if (opline->extended_value == IS_BOOL) {
/* T = CAST(X, IS_BOOL) => T = BOOL(X) */
opline->opcode = ZEND_BOOL;
opline->extended_value = 0;
}
break;
case ZEND_BW_NOT:
case ZEND_BOOL_NOT:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
/* unary operation on constant operand */
unary_op_type unary_op = get_unary_op(opline->opcode);
zval result;
zend_op *tmp_opline;
zend_uint tv = ZEND_RESULT(opline).var; /* temporary variable */
int er;
er = EG(error_reporting);
EG(error_reporting) = 0;
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
if (unary_op(&result, &ZEND_OP1_LITERAL(opline)) != SUCCESS) {
#else
if (unary_op(&result, &ZEND_OP1_LITERAL(opline) TSRMLS_CC) != SUCCESS) {
#endif
EG(error_reporting) = er;
break;
}
EG(error_reporting) = er;
PZ_SET_REFCOUNT_P(&result, 1);
PZ_UNSET_ISREF_P(&result);
literal_dtor(&ZEND_OP1_LITERAL(opline));
MAKE_NOP(opline);
/* substitute the following TMP_VAR usage with constant */
for (tmp_opline = opline + 1; tmp_opline < end; tmp_opline++) {
if (ZEND_OP1_TYPE(tmp_opline) == IS_TMP_VAR &&
ZEND_OP1(tmp_opline).var == tv) {
if (tmp_opline->opcode == ZEND_FREE) {
MAKE_NOP(tmp_opline);
zval_dtor(&result);
} else {
ZEND_OP1_TYPE(tmp_opline) = IS_CONST;
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
tmp_opline->op1.constant = zend_optimizer_add_literal(op_array, &result TSRMLS_CC);
#else
ZEND_OP1_LITERAL(tmp_opline) = result;
#endif
}
break;
}
if (ZEND_OP2_TYPE(tmp_opline) == IS_TMP_VAR &&
ZEND_OP2(tmp_opline).var == tv) {
ZEND_OP2_TYPE(tmp_opline) = IS_CONST;
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
tmp_opline->op2.constant = zend_optimizer_add_literal(op_array, &result TSRMLS_CC);
#else
ZEND_OP2_LITERAL(tmp_opline) = result;
#endif
break;
}
}
}
break;
case ZEND_ADD_STRING:
case ZEND_ADD_CHAR:
{
zend_op *next_op = opline + 1;
int requires_conversion = (opline->opcode == ZEND_ADD_CHAR? 1 : 0);
size_t final_length = 0;
char *ptr;
zend_op *last_op;
/* There is always a ZEND_RETURN at the end
if (next_op>=end) {
break;
}
*/
while (next_op->opcode == ZEND_ADD_STRING || next_op->opcode == ZEND_ADD_CHAR) {
if (ZEND_RESULT(opline).var != ZEND_RESULT(next_op).var) {
break;
}
if (next_op->opcode == ZEND_ADD_CHAR) {
final_length += 1;
} else { /* ZEND_ADD_STRING */
final_length += ZEND_OP2_LITERAL(next_op).value.str.len;
}
next_op++;
}
if (final_length == 0) {
break;
}
last_op = next_op;
final_length += (requires_conversion? 1 : ZEND_OP2_LITERAL(opline).value.str.len);
ptr = (char *)emalloc(final_length + 1);
ptr[final_length] = '\0';
if (requires_conversion) { /* ZEND_ADD_CHAR */
char chval = (char)ZEND_OP2_LITERAL(opline).value.lval;
ZEND_OP2_LITERAL(opline).value.str.val = ptr;
ptr[0] = chval;
ZEND_OP2_LITERAL(opline).type = IS_STRING;
opline->opcode = ZEND_ADD_STRING;
ptr++;
} else { /* ZEND_ADD_STRING */
memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)));
if (!IS_INTERNED(Z_STRVAL(ZEND_OP2_LITERAL(opline)))) {
efree(Z_STRVAL(ZEND_OP2_LITERAL(opline)));
}
Z_STRVAL(ZEND_OP2_LITERAL(opline)) = ptr;
ptr += Z_STRLEN(ZEND_OP2_LITERAL(opline));
}
ZEND_OP2_LITERAL(opline).value.str.len = final_length;
next_op = opline + 1;
while (next_op < last_op) {
if (next_op->opcode == ZEND_ADD_STRING) {
memcpy(ptr, ZEND_OP2_LITERAL(next_op).value.str.val, ZEND_OP2_LITERAL(next_op).value.str.len);
ptr += ZEND_OP2_LITERAL(next_op).value.str.len;
literal_dtor(&ZEND_OP2_LITERAL(next_op));
} else { /* ZEND_ADD_CHAR */
*ptr = (char)ZEND_OP2_LITERAL(next_op).value.lval;
ptr++;
}
MAKE_NOP(next_op);
next_op++;
}
if (!((ZEND_OPTIMIZER_PASS_5|ZEND_OPTIMIZER_PASS_10) & OPTIMIZATION_LEVEL)) {
/* NOP removal is disabled => insert JMP over NOPs */
if (last_op-opline >= 3) { /* If we have more than 2 NOPS then JMP over them */
(opline + 1)->opcode = ZEND_JMP;
ZEND_OP1(opline + 1).opline_num = last_op - op_array->opcodes; /* that's OK even for ZE2, since opline_num's are resolved in pass 2 later */
}
}
}
break;
case ZEND_FETCH_CONSTANT:
if (ZEND_OP1_TYPE(opline) == IS_UNUSED &&
ZEND_OP2_TYPE(opline) == IS_CONST &&
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 &&
memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) {
/* substitute __COMPILER_HALT_OFFSET__ constant */
zend_bool orig_in_execution = EG(in_execution);
zend_op_array *orig_op_array = EG(active_op_array);
zval offset;
EG(in_execution) = 1;
EG(active_op_array) = op_array;
if (zend_get_constant("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1, &offset TSRMLS_CC)) {
literal_dtor(&ZEND_OP2_LITERAL(opline));
ZEND_OP1_TYPE(opline) = IS_CONST;
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
opline->op1.constant = zend_optimizer_add_literal(op_array, &offset TSRMLS_CC);
#else
ZEND_OP1_LITERAL(opline) = offset;
#endif
SET_UNUSED(opline->op2);
opline->opcode = ZEND_QM_ASSIGN;
}
EG(active_op_array) = orig_op_array;
EG(in_execution) = orig_in_execution;
break;
}
if (ZEND_OP1_TYPE(opline) == IS_UNUSED &&
ZEND_OP2_TYPE(opline) == IS_CONST &&
ZEND_OP2_LITERAL(opline).type == IS_STRING) {
/* substitute persistent constants */
zval c;
if (!zend_get_persistent_constant(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), &c, 1 TSRMLS_CC)) {
break;
}
literal_dtor(&ZEND_OP2_LITERAL(opline));
ZEND_OP1_TYPE(opline) = IS_CONST;
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
opline->op1.constant = zend_optimizer_add_literal(op_array, &c TSRMLS_CC);
#else
ZEND_OP1_LITERAL(opline) = c;
#endif
SET_UNUSED(opline->op2);
opline->opcode = ZEND_QM_ASSIGN;
}
break;
case ZEND_INIT_FCALL_BY_NAME:
if (opline->extended_value == 0 /* not method */ &&
ZEND_OP1_TYPE(opline) == IS_UNUSED &&
ZEND_OP2_TYPE(opline) == IS_CONST) {
if ((opline + 1)->opcode == ZEND_DO_FCALL_BY_NAME &&
(opline + 1)->extended_value == 0) {
(opline + 1)->opcode = ZEND_DO_FCALL;
COPY_NODE((opline + 1)->op1, opline->op2);
zend_str_tolower(Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
Z_HASH_P(&ZEND_OP1_LITERAL(opline + 1)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)) + 1);
op_array->literals[(opline + 1)->op1.constant].cache_slot = op_array->last_cache_slot++;
#endif
MAKE_NOP(opline);
}
}
break;
}
opline++;
i++;
}
}
+211
View File
@@ -0,0 +1,211 @@
/* pass 2:
* - convert non-numeric constants to numeric constants in numeric operators
* - optimize constant conditional JMPs
* - optimize static BRKs and CONTs
*/
if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
zend_op *opline;
zend_op *end = op_array->opcodes + op_array->last;
opline = op_array->opcodes;
while (opline < end) {
switch (opline->opcode) {
case ZEND_ADD:
case ZEND_SUB:
case ZEND_MUL:
case ZEND_DIV:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
if (ZEND_OP1_LITERAL(opline).type == IS_STRING) {
convert_scalar_to_number(&ZEND_OP1_LITERAL(opline) TSRMLS_CC);
}
}
/* break missing *intentionally* - the assign_op's may only optimize op2 */
case ZEND_ASSIGN_ADD:
case ZEND_ASSIGN_SUB:
case ZEND_ASSIGN_MUL:
case ZEND_ASSIGN_DIV:
if (opline->extended_value != 0) {
/* object tristate op - don't attempt to optimize it! */
break;
}
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
if (ZEND_OP2_LITERAL(opline).type == IS_STRING) {
convert_scalar_to_number(&ZEND_OP2_LITERAL(opline) TSRMLS_CC);
}
}
break;
case ZEND_MOD:
case ZEND_SL:
case ZEND_SR:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
if (ZEND_OP1_LITERAL(opline).type != IS_LONG) {
convert_to_long(&ZEND_OP1_LITERAL(opline));
}
}
/* break missing *intentionally - the assign_op's may only optimize op2 */
case ZEND_ASSIGN_MOD:
case ZEND_ASSIGN_SL:
case ZEND_ASSIGN_SR:
if (opline->extended_value != 0) {
/* object tristate op - don't attempt to optimize it! */
break;
}
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
if (ZEND_OP2_LITERAL(opline).type != IS_LONG) {
convert_to_long(&ZEND_OP2_LITERAL(opline));
}
}
break;
case ZEND_CONCAT:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
if (ZEND_OP1_LITERAL(opline).type != IS_STRING) {
convert_to_string(&ZEND_OP1_LITERAL(opline));
}
}
/* break missing *intentionally - the assign_op's may only optimize op2 */
case ZEND_ASSIGN_CONCAT:
if (opline->extended_value != 0) {
/* object tristate op - don't attempt to optimize it! */
break;
}
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
if (ZEND_OP2_LITERAL(opline).type != IS_STRING) {
convert_to_string(&ZEND_OP2_LITERAL(opline));
}
}
break;
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
/* convert Ti = JMPZ_EX(Ti, L) to JMPZ(Ti, L) */
if (0 && /* FIXME: temporary disable unsafe pattern */
ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
ZEND_RESULT_TYPE(opline) == IS_TMP_VAR &&
ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
opline->opcode -= 3;
/* convert Ti = JMPZ_EX(C, L) => Ti = QM_ASSIGN(C)
in case we know it wouldn't jump */
} else if (ZEND_OP1_TYPE(opline) == IS_CONST) {
int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
if (opline->opcode == ZEND_JMPZ_EX) {
should_jmp = !should_jmp;
}
if (!should_jmp) {
opline->opcode = ZEND_QM_ASSIGN;
SET_UNUSED(opline->op2);
}
}
break;
case ZEND_JMPZ:
case ZEND_JMPNZ:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
if (opline->opcode == ZEND_JMPZ) {
should_jmp = !should_jmp;
}
literal_dtor(&ZEND_OP1_LITERAL(opline));
ZEND_OP1_TYPE(opline) = IS_UNUSED;
if (should_jmp) {
opline->opcode = ZEND_JMP;
COPY_NODE(opline->op1, opline->op2);
} else {
MAKE_NOP(opline);
}
break;
}
if ((opline + 1)->opcode == ZEND_JMP) {
/* JMPZ(X, L1), JMP(L2) => JMPZNZ(X, L1, L2) */
/* JMPNZ(X, L1), JMP(L2) => JMPZNZ(X, L2, L1) */
if (ZEND_OP2(opline).opline_num == ZEND_OP1(opline + 1).opline_num) {
/* JMPZ(X, L1), JMP(L1) => NOP, JMP(L1) */
MAKE_NOP(opline);
} else {
if (opline->opcode == ZEND_JMPZ) {
opline->extended_value = ZEND_OP1(opline + 1).opline_num;
} else {
opline->extended_value = ZEND_OP2(opline).opline_num;
COPY_NODE(opline->op2, (opline + 1)->op1);
}
opline->opcode = ZEND_JMPZNZ;
}
}
break;
case ZEND_JMPZNZ:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
int opline_num;
if (zend_is_true(&ZEND_OP1_LITERAL(opline))) {
opline_num = opline->extended_value; /* JMPNZ */
} else {
opline_num = ZEND_OP2(opline).opline_num; /* JMPZ */
}
literal_dtor(&ZEND_OP1_LITERAL(opline));
ZEND_OP1(opline).opline_num = opline_num;
ZEND_OP1_TYPE(opline) = IS_UNUSED;
opline->opcode = ZEND_JMP;
}
break;
case ZEND_BRK:
case ZEND_CONT:
{
zend_brk_cont_element *jmp_to;
int array_offset;
int nest_levels;
int dont_optimize = 0;
if (ZEND_OP2_TYPE(opline) != IS_CONST) {
break;
}
convert_to_long(&ZEND_OP2_LITERAL(opline));
nest_levels = ZEND_OP2_LITERAL(opline).value.lval;
array_offset = ZEND_OP1(opline).opline_num;
while (1) {
if (array_offset == -1) {
dont_optimize = 1; /* don't optimize this bogus break/continue, let the executor shout */
break;
}
jmp_to = &op_array->brk_cont_array[array_offset];
array_offset = jmp_to->parent;
if (--nest_levels > 0) {
if (opline->opcode == ZEND_BRK &&
(op_array->opcodes[jmp_to->brk].opcode == ZEND_FREE ||
op_array->opcodes[jmp_to->brk].opcode == ZEND_SWITCH_FREE)) {
dont_optimize = 1;
break;
}
} else {
break;
}
}
if (dont_optimize) {
break;
}
/* optimize - convert to a JMP */
switch (opline->opcode) {
case ZEND_BRK:
MAKE_NOP(opline);
ZEND_OP1(opline).opline_num = jmp_to->brk;
break;
case ZEND_CONT:
MAKE_NOP(opline);
ZEND_OP1(opline).opline_num = jmp_to->cont;
break;
}
opline->opcode = ZEND_JMP;
/* MAKE_NOP() already set op1 and op2 to IS_UNUSED */
}
break;
}
opline++;
}
}
+442
View File
@@ -0,0 +1,442 @@
/* pass 3:
* - optimize $i = $i+expr to $i+=expr
* - optimize series of JMPs
* - change $i++ to ++$i where possible
*/
/* compares opcodes with allowing oc1 be _EX of oc2 */
#define SAME_OPCODE_EX(oc1, oc2) ((oc1 == oc2) || (oc1 == ZEND_JMPZ_EX && oc2 == ZEND_JMPZ) || (oc1 == ZEND_JMPNZ_EX && oc2 == ZEND_JMPNZ))
/* we use "jmp_hitlist" to avoid infinity loops during jmp optimization */
#define CHECK_JMP(target, label) \
for (i=0; i<jmp_hitlist_count; i++) { \
if (jmp_hitlist[i] == ZEND_OP1(&op_array->opcodes[target]).opline_num) { \
goto label; \
} \
} \
jmp_hitlist[jmp_hitlist_count++] = ZEND_OP1(&op_array->opcodes[target]).opline_num;
#define CHECK_JMP2(target, label) \
for (i=0; i<jmp_hitlist_count; i++) { \
if (jmp_hitlist[i] == ZEND_OP2(&op_array->opcodes[target]).opline_num) { \
goto label; \
} \
} \
jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2(&op_array->opcodes[target]).opline_num;
if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
zend_op *opline;
zend_op *end = op_array->opcodes + op_array->last;
zend_uint *jmp_hitlist;
int jmp_hitlist_count;
int i;
zend_uint opline_num = 0;
ALLOCA_FLAG(use_heap);
jmp_hitlist = (zend_uint *)DO_ALLOCA(sizeof(zend_uint)*op_array->last);
opline = op_array->opcodes;
while (opline < end) {
jmp_hitlist_count = 0;
switch (opline->opcode) {
case ZEND_ADD:
case ZEND_SUB:
case ZEND_MUL:
case ZEND_DIV:
case ZEND_MOD:
case ZEND_CONCAT:
case ZEND_SL:
case ZEND_SR:
case ZEND_BW_OR:
case ZEND_BW_AND:
case ZEND_BW_XOR:
{
zend_op *next_opline = opline + 1;
while (next_opline < end && next_opline->opcode == ZEND_NOP) {
++next_opline;
}
if (next_opline >= end || next_opline->opcode != ZEND_ASSIGN) {
break;
}
if ((ZEND_OP2_TYPE(opline) == IS_VAR || ZEND_OP2_TYPE(opline) == IS_CV)
&& ZEND_OP2(opline).var == ZEND_OP1(next_opline).var &&
(opline->opcode == ZEND_ADD ||
opline->opcode == ZEND_MUL ||
opline->opcode == ZEND_BW_OR ||
opline->opcode == ZEND_BW_AND ||
opline->opcode == ZEND_BW_XOR)) {
/* change $i=expr+$i to $i=$i+expr so that the next
* optimization works on it
*/
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
zend_uchar tmp_type = opline->op1_type;
znode_op tmp = opline->op1;
#else
znode tmp = opline->op1;
#endif
if (opline->opcode != ZEND_ADD || ZEND_OP1_TYPE(opline) == IS_CONST) {
/* protection from array add: $a = array + $a is not commutative! */
COPY_NODE(opline->op1, opline->op2);
COPY_NODE(opline->op2, tmp);
}
}
if ((ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_CV)
&& ZEND_OP1(opline).var == ZEND_OP1(next_opline).var
&& ZEND_OP1_TYPE(opline) == ZEND_OP1_TYPE(next_opline)) {
switch (opline->opcode) {
case ZEND_ADD:
opline->opcode = ZEND_ASSIGN_ADD;
break;
case ZEND_SUB:
opline->opcode = ZEND_ASSIGN_SUB;
break;
case ZEND_MUL:
opline->opcode = ZEND_ASSIGN_MUL;
break;
case ZEND_DIV:
opline->opcode = ZEND_ASSIGN_DIV;
break;
case ZEND_MOD:
opline->opcode = ZEND_ASSIGN_MOD;
break;
case ZEND_CONCAT:
opline->opcode = ZEND_ASSIGN_CONCAT;
break;
case ZEND_SL:
opline->opcode = ZEND_ASSIGN_SL;
break;
case ZEND_SR:
opline->opcode = ZEND_ASSIGN_SR;
break;
case ZEND_BW_OR:
opline->opcode = ZEND_ASSIGN_BW_OR;
break;
case ZEND_BW_AND:
opline->opcode = ZEND_ASSIGN_BW_AND;
break;
case ZEND_BW_XOR:
opline->opcode = ZEND_ASSIGN_BW_XOR;
break;
}
COPY_NODE(opline->result, next_opline->result);
MAKE_NOP(next_opline);
opline++;
opline_num++;
}
}
break;
case ZEND_JMP:
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
if (op_array->has_finally_block) {
break;
}
#endif
/* convert L: JMP L+1 to NOP */
if (ZEND_OP1(opline).opline_num == opline_num + 1) {
MAKE_NOP(opline);
goto done_jmp_optimization;
}
/* convert JMP L1 ... L1: JMP L2 to JMP L2 .. L1: JMP L2 */
while (ZEND_OP1(opline).opline_num < op_array->last
&& op_array->opcodes[ZEND_OP1(opline).opline_num].opcode == ZEND_JMP) {
int target = ZEND_OP1(opline).opline_num;
CHECK_JMP(target, done_jmp_optimization);
ZEND_OP1(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
}
break;
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_JMP_SET:
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
case ZEND_JMP_SET_VAR:
#endif
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
if (op_array->has_finally_block) {
break;
}
#endif
while (ZEND_OP2(opline).opline_num < op_array->last) {
int target = ZEND_OP2(opline).opline_num;
if (op_array->opcodes[target].opcode == ZEND_JMP) {
ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
} else {
break;
}
}
break;
#endif
case ZEND_JMPZ:
case ZEND_JMPNZ:
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
if (op_array->has_finally_block) {
break;
}
#endif
/* convert L: JMPZ L+1 to NOP */
if (ZEND_OP2(opline).opline_num == opline_num + 1) {
MAKE_NOP(opline);
goto done_jmp_optimization;
}
while (ZEND_OP2(opline).opline_num < op_array->last) {
int target = ZEND_OP2(opline).opline_num;
if (op_array->opcodes[target].opcode == ZEND_JMP) {
/* plain JMP */
/* JMPZ(X,L1), L1: JMP(L2) => JMPZ(X,L2), L1: JMP(L2) */
CHECK_JMP(target, done_jmp_optimization);
ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
} else if (op_array->opcodes[target].opcode == opline->opcode &&
SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
/* same opcode and same var as this opcode */
/* JMPZ(X,L1), L1: JMPZ(X,L2) => JMPZ(X,L2), L1: JMPZ(X,L2) */
CHECK_JMP2(target, done_jmp_optimization);
ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;
} else if (op_array->opcodes[target].opcode == opline->opcode + 3 &&
SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
/* convert JMPZ(X,L1), L1: T JMPZ_EX(X,L2) to
T = JMPZ_EX(X, L2) */
ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;opline->opcode += 3;
COPY_NODE(opline->result, op_array->opcodes[target].result);
break;
} else if (op_array->opcodes[target].opcode == INV_COND(opline->opcode) &&
SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
/* convert JMPZ(X,L1), L1: JMPNZ(X,L2) to
JMPZ(X,L1+1) */
ZEND_OP2(opline).opline_num = target + 1;
break;
} else if (op_array->opcodes[target].opcode == INV_COND_EX(opline->opcode) &&
SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
/* convert JMPZ(X,L1), L1: T = JMPNZ_EX(X,L2) to
T = JMPZ_EX(X,L1+1) */
ZEND_OP2(opline).opline_num = target + 1;
opline->opcode += 3;
COPY_NODE(opline->result, op_array->opcodes[target].result);
break;
} else {
break;
}
}
break;
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX: {
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
zend_uchar T_type = opline->result_type;
znode_op T = opline->result;
#else
znode T = opline->result;
#endif
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
if (op_array->has_finally_block) {
break;
}
#endif
/* convert L: T = JMPZ_EX X,L+1 to T = BOOL(X) */
/* convert L: T = JMPZ_EX T,L+1 to NOP */
if (ZEND_OP2(opline).opline_num == opline_num + 1) {
if (ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
MAKE_NOP(opline);
} else {
opline->opcode = ZEND_BOOL;
SET_UNUSED(opline->op2);
}
goto done_jmp_optimization;
}
while (ZEND_OP2(opline).opline_num < op_array->last) {
int target = ZEND_OP2(opline).opline_num;
if (SAME_OPCODE_EX(opline->opcode, op_array->opcodes[target].opcode) &&
SAME_VAR(op_array->opcodes[target].op1, T)) {
/* Check for JMPZ_EX to JMPZ[_EX] with the same condition, either with _EX or not */
if (op_array->opcodes[target].opcode == opline->opcode) {
/* change T only if we have _EX opcode there */
COPY_NODE(T, op_array->opcodes[target].result);
}
CHECK_JMP2(target, continue_jmp_ex_optimization);
ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;
} else if (op_array->opcodes[target].opcode == ZEND_JMPZNZ &&
SAME_VAR(op_array->opcodes[target].op1, T)) {
/* Check for JMPZNZ with same cond variable */
int new_target;
CHECK_JMP2(target, continue_jmp_ex_optimization);
if (opline->opcode == ZEND_JMPZ_EX) {
new_target = ZEND_OP2(&op_array->opcodes[target]).opline_num;
} else {
/* JMPNZ_EX */
new_target = op_array->opcodes[target].extended_value;
}
ZEND_OP2(opline).opline_num = new_target;
} else if ((op_array->opcodes[target].opcode == INV_EX_COND_EX(opline->opcode) ||
op_array->opcodes[target].opcode == INV_EX_COND(opline->opcode)) &&
SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
/* convert JMPZ_EX(X,L1), L1: JMPNZ_EX(X,L2) to
JMPZ_EX(X,L1+1) */
ZEND_OP2(opline).opline_num = target + 1;
break;
} else {
break;
}
} /* while */
continue_jmp_ex_optimization:
break;
#if 0
/* If Ti = JMPZ_EX(X, L) and Ti is not used, convert to JMPZ(X, L) */
{
zend_op *op;
for(op = opline+1; op<end; op++) {
if(ZEND_RESULT_TYPE(op) == IS_TMP_VAR &&
ZEND_RESULT(op).var == ZEND_RESULT(opline).var) {
break; /* can pass to part 2 */
}
if(op->opcode == ZEND_JMP ||
op->opcode == ZEND_JMPZ ||
op->opcode == ZEND_JMPZ_EX ||
op->opcode == ZEND_JMPNZ ||
op->opcode == ZEND_JMPNZ_EX ||
op->opcode == ZEND_JMPZNZ ||
op->opcode == ZEND_BRK ||
op->opcode == ZEND_CONT ||
op->opcode == ZEND_CASE ||
op->opcode == ZEND_RETURN ||
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
op->opcode == ZEND_RETURN_BY_REF ||
#endif
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
op->opcode == ZEND_FAST_RET ||
#endif
op->opcode == ZEND_FE_FETCH ||
op->opcode == ZEND_EXIT) {
break;
}
if(ZEND_OP1_TYPE(op) == IS_TMP_VAR &&
ZEND_OP1(op).var == ZEND_RESULT(opline).var) {
goto done_jmp_optimization;
}
if(ZEND_OP2_TYPE(op) == IS_TMP_VAR &&
ZEND_OP2(op).var == ZEND_RESULT(opline).var) {
goto done_jmp_optimization;
}
} /* for */
for(op = &op_array->opcodes[ZEND_OP2(opline).opline_num]; op<end; op++) {
if(ZEND_RESULT_TYPE(op) == IS_TMP_VAR &&
ZEND_RESULT(op).var == ZEND_RESULT(opline).var) {
break; /* can pass to optimization */
}
if(op->opcode == ZEND_JMP ||
op->opcode == ZEND_JMPZ ||
op->opcode == ZEND_JMPZ_EX ||
op->opcode == ZEND_JMPNZ ||
op->opcode == ZEND_JMPNZ_EX ||
op->opcode == ZEND_JMPZNZ ||
op->opcode == ZEND_BRK ||
op->opcode == ZEND_CONT ||
op->opcode == ZEND_CASE ||
op->opcode == ZEND_RETURN ||
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
op->opcode == ZEND_RETURN_BY_REF ||
#endif
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
op->opcode == ZEND_FAST_RET ||
#endif
op->opcode == ZEND_FE_FETCH ||
op->opcode == ZEND_EXIT) {
break;
}
if(ZEND_OP1_TYPE(op) == IS_TMP_VAR &&
ZEND_OP1(op).var == ZEND_RESULT(opline).var) {
goto done_jmp_optimization;
}
if(ZEND_OP2_TYPE(op) == IS_TMP_VAR &&
ZEND_OP2(op).var == ZEND_RESULT(opline).var) {
goto done_jmp_optimization;
}
}
opline->opcode = opline->opcode-3; /* JMP_EX -> JMP */
SET_UNUSED(opline->result);
break;
}
#endif
}
break;
case ZEND_JMPZNZ:
#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
if (op_array->has_finally_block) {
break;
}
#endif
/* JMPZNZ(X,L1,L2), L1: JMP(L3) => JMPZNZ(X,L3,L2), L1: JMP(L3) */
while (ZEND_OP2(opline).opline_num < op_array->last
&& op_array->opcodes[ZEND_OP2(opline).opline_num].opcode == ZEND_JMP) {
int target = ZEND_OP2(opline).opline_num;
CHECK_JMP(target, continue_jmpznz_optimization);
ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
}
continue_jmpznz_optimization:
/* JMPZNZ(X,L1,L2), L2: JMP(L3) => JMPZNZ(X,L1,L3), L2: JMP(L3) */
while (opline->extended_value < op_array->last
&& op_array->opcodes[opline->extended_value].opcode == ZEND_JMP) {
int target = opline->extended_value;
CHECK_JMP(target, done_jmp_optimization);
opline->extended_value = ZEND_OP1(&op_array->opcodes[target]).opline_num;
}
break;
case ZEND_POST_INC:
case ZEND_POST_DEC: {
/* POST_INC, FREE => PRE_INC */
zend_op *next_op = opline + 1;
if (next_op >= end) {
break;
}
if (next_op->opcode == ZEND_FREE &&
ZEND_OP1(next_op).var == ZEND_RESULT(opline).var) {
MAKE_NOP(next_op);
switch (opline->opcode) {
case ZEND_POST_INC:
opline->opcode = ZEND_PRE_INC;
break;
case ZEND_POST_DEC:
opline->opcode = ZEND_PRE_DEC;
break;
}
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
ZEND_RESULT_TYPE(opline) = IS_VAR | EXT_TYPE_UNUSED;
#else
ZEND_RESULT_TYPE(opline) = IS_VAR;
ZEND_RESULT(opline).EA.type = 0;
ZEND_RESULT(opline).EA.type |= EXT_TYPE_UNUSED;
#endif
}
}
break;
}
done_jmp_optimization:
opline++;
opline_num++;
}
FREE_ALLOCA(jmp_hitlist);
}
+3
View File
@@ -0,0 +1,3 @@
if (ZEND_OPTIMIZER_PASS_5 & OPTIMIZATION_LEVEL) {
zend_block_optimization(op_array TSRMLS_CC);
}
+8
View File
@@ -0,0 +1,8 @@
/* pass 9
*
* - optimize usage of temporary variables
*/
if (ZEND_OPTIMIZER_PASS_9 & OPTIMIZATION_LEVEL) {
optimize_temporary_variables(op_array);
}
+139
View File
@@ -0,0 +1,139 @@
/*
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
| Copyright (c) 1998-2013 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Andi Gutmans <andi@zend.com> |
| Zeev Suraski <zeev@zend.com> |
| Stanislav Malyshev <stas@zend.com> |
| Dmitry Stogov <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
#include "Optimizer/zend_optimizer.h"
#include "Optimizer/zend_optimizer_internal.h"
#include "zend_API.h"
#include "zend_constants.h"
#include "zend_execute.h"
#define OPTIMIZATION_LEVEL \
ZCG(accel_directives).optimization_level
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC)
{
int i = op_array->last_literal;
op_array->last_literal++;
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
{
if (i >= CG(context).literals_size) {
CG(context).literals_size += 16; /* FIXME */
op_array->literals = (zend_literal*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zend_literal));
}
}
#else
if (i >= op_array->size_literal) {
op_array->size_literal += 16; /* FIXME */
op_array->literals = (zend_literal*)erealloc(op_array->literals, op_array->size_literal * sizeof(zend_literal));
}
#endif
op_array->literals[i].constant = *zv;
Z_SET_REFCOUNT(op_array->literals[i].constant, 2);
Z_SET_ISREF(op_array->literals[i].constant);
return i;
}
# define LITERAL_LONG(op, val) do { \
zval _c; \
ZVAL_LONG(&_c, val); \
op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
} while (0)
# define LITERAL_BOOL(op, val) do { \
zval _c; \
ZVAL_BOOL(&_c, val); \
op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
} while (0)
# define literal_dtor(zv) do { \
zval_dtor(zv); \
Z_TYPE_P(zv) = IS_NULL; \
} while (0)
#define COPY_NODE(target, src) do { \
target ## _type = src ## _type; \
target = src; \
} while (0)
#else
# define LITERAL_LONG(op, val) ZVAL_LONG(&op.u.constant, val)
# define LITERAL_BOOL(op, val) ZVAL_BOOL(&op.u.constant, val)
# define literal_dtor(zv) zval_dtor(zv)
#define COPY_NODE(target, src) do { \
target = src; \
} while (0)
#endif
#include "Optimizer/nop_removal.c"
#include "Optimizer/block_pass.c"
#include "Optimizer/optimize_temp_vars_5.c"
void zend_optimizer(zend_op_array *op_array TSRMLS_DC)
{
if (op_array->type == ZEND_EVAL_CODE ||
(op_array->fn_flags & ZEND_ACC_INTERACTIVE)) {
return;
}
/* pass 1
* - substitute persistent constants (true, false, null, etc)
* - perform compile-time evaluation of constant binary and unary operations
* - optimize series of ADD_STRING and/or ADD_CHAR
* - convert CAST(IS_BOOL,x) into BOOL(x)
* - convert INTI_FCALL_BY_NAME + DO_FCALL_BY_NAME into DO_FCALL
*/
#include "Optimizer/pass1_5.c"
/* pass 2:
* - convert non-numeric constants to numeric constants in numeric operators
* - optimize constant conditional JMPs
* - optimize static BRKs and CONTs
*/
#include "Optimizer/pass2.c"
/* pass 3:
* - optimize $i = $i+expr to $i+=expr
* - optimize series of JMPs
* - change $i++ to ++$i where possible
*/
#include "Optimizer/pass3.c"
/* pass 5:
* - CFG optimization
*/
#include "Optimizer/pass5.c"
/* pass 9:
* - Optimize temp variables usage
*/
#include "Optimizer/pass9.c"
/* pass 10:
* - remove NOPs
*/
#include "Optimizer/pass10.c"
}

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