summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
Diffstat (limited to 'Zend')
-rw-r--r--Zend/tests/024.phpt2
-rw-r--r--Zend/tests/bug27669.phpt2
-rw-r--r--Zend/tests/bug30080.phpt4
-rw-r--r--Zend/tests/bug39304.phpt4
-rw-r--r--Zend/tests/bug39304_2_4.phpt4
-rw-r--r--Zend/tests/bug43450.phpt6
-rw-r--r--Zend/tests/bug44414.phpt2
-rw-r--r--Zend/tests/bug55007.phpt2
-rw-r--r--Zend/tests/bug60099.phpt2
-rw-r--r--Zend/tests/bug60825.phpt9
-rw-r--r--Zend/tests/bug67436/bug67436_nohandler.phpt2
-rw-r--r--Zend/tests/bug67874.phpt14
-rw-r--r--Zend/tests/bug67922.phpt19
-rw-r--r--Zend/tests/bug67938.phpt27
-rw-r--r--Zend/tests/bug67985.phpt16
-rw-r--r--Zend/tests/closure_026.phpt5
-rw-r--r--Zend/tests/closure_call.phpt65
-rw-r--r--Zend/tests/concat_002.phpt24
-rw-r--r--Zend/tests/constants/dir-constant-includes.phpt8
-rw-r--r--Zend/tests/constants/dir-constant-nested_includes.phpt40
-rwxr-xr-xZend/tests/constants/fixtures/folder1/fixture.inc (renamed from Zend/tests/constants/fixtures/folder1/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder1/subfolder1/fixture.inc (renamed from Zend/tests/constants/fixtures/folder1/subfolder1/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder1/subfolder2/fixture.inc (renamed from Zend/tests/constants/fixtures/folder1/subfolder2/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder1/subfolder3/fixture.inc (renamed from Zend/tests/constants/fixtures/folder1/subfolder3/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder1/subfolder4/fixture.inc (renamed from Zend/tests/constants/fixtures/folder1/subfolder4/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder2/fixture.inc (renamed from Zend/tests/constants/fixtures/folder2/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder2/subfolder1/fixture.inc (renamed from Zend/tests/constants/fixtures/folder2/subfolder1/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder2/subfolder2/fixture.inc (renamed from Zend/tests/constants/fixtures/folder2/subfolder2/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder2/subfolder3/fixture.inc (renamed from Zend/tests/constants/fixtures/folder2/subfolder3/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder2/subfolder4/fixture.inc (renamed from Zend/tests/constants/fixtures/folder2/subfolder4/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder3/fixture.inc (renamed from Zend/tests/constants/fixtures/folder3/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder3/subfolder1/fixture.inc (renamed from Zend/tests/constants/fixtures/folder3/subfolder1/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder3/subfolder2/fixture.inc (renamed from Zend/tests/constants/fixtures/folder3/subfolder2/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder3/subfolder3/fixture.inc (renamed from Zend/tests/constants/fixtures/folder3/subfolder3/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder3/subfolder4/fixture.inc (renamed from Zend/tests/constants/fixtures/folder3/subfolder4/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder4/fixture.inc (renamed from Zend/tests/constants/fixtures/folder4/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder4/subfolder1/fixture.inc (renamed from Zend/tests/constants/fixtures/folder4/subfolder1/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder4/subfolder2/fixture.inc (renamed from Zend/tests/constants/fixtures/folder4/subfolder2/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder4/subfolder3/fixture.inc (renamed from Zend/tests/constants/fixtures/folder4/subfolder3/fixture.php)0
-rwxr-xr-xZend/tests/constants/fixtures/folder4/subfolder4/fixture.inc (renamed from Zend/tests/constants/fixtures/folder4/subfolder4/fixture.php)0
-rw-r--r--Zend/tests/declare_001.phpt5
-rw-r--r--Zend/tests/declare_003.phpt5
-rw-r--r--Zend/tests/errmsg_014.phpt17
-rw-r--r--Zend/tests/eval_parse_error_with_doc_comment.phpt15
-rw-r--r--Zend/tests/foreach_list_002.phpt2
-rw-r--r--Zend/tests/gc_033.phpt28
-rw-r--r--Zend/tests/isset_003.phpt2
-rw-r--r--Zend/tests/isset_003_2_4.phpt2
-rw-r--r--Zend/tests/isset_func_error.phpt2
-rw-r--r--Zend/tests/list_005.phpt16
-rw-r--r--Zend/tests/list_006.phpt4
-rw-r--r--Zend/tests/strlen.phpt51
-rw-r--r--Zend/tests/use_const/no_global_fallback.phpt3
-rw-r--r--Zend/tests/varSyntax/globalNonSimpleVariableError.phpt10
-rw-r--r--Zend/tests/varSyntax/indirectFcall.phpt53
-rw-r--r--Zend/tests/varSyntax/issetOnTemp.phpt26
-rw-r--r--Zend/tests/varSyntax/newVariable.phpt39
-rw-r--r--Zend/tests/varSyntax/parenthesesDeref.phpt20
-rw-r--r--Zend/tests/varSyntax/propertyOfStringError.phpt10
-rw-r--r--Zend/tests/varSyntax/staticMember.phpt37
-rw-r--r--Zend/tests/varSyntax/tempDimFetchByRefError.phpt11
-rw-r--r--Zend/tests/varSyntax/tempPropFetchByRefError.phpt11
-rw-r--r--Zend/tests/varSyntax/writeToTempExpr.phpt10
-rw-r--r--Zend/zend.c166
-rw-r--r--Zend/zend.h80
-rw-r--r--Zend/zend_API.c278
-rw-r--r--Zend/zend_API.h119
-rw-r--r--Zend/zend_alloc.c3842
-rw-r--r--Zend/zend_alloc.h157
-rw-r--r--Zend/zend_alloc_sizes.h46
-rw-r--r--Zend/zend_arena.h9
-rw-r--r--Zend/zend_ast.c516
-rw-r--r--Zend/zend_ast.h247
-rw-r--r--Zend/zend_builtin_functions.c286
-rw-r--r--Zend/zend_closures.c86
-rw-r--r--Zend/zend_compile.c9475
-rw-r--r--Zend/zend_compile.h417
-rw-r--r--Zend/zend_constants.c52
-rw-r--r--Zend/zend_constants.h8
-rw-r--r--Zend/zend_exceptions.c59
-rw-r--r--Zend/zend_exceptions.h6
-rw-r--r--Zend/zend_execute.c367
-rw-r--r--Zend/zend_execute.h37
-rw-r--r--Zend/zend_execute_API.c156
-rw-r--r--Zend/zend_extensions.c10
-rw-r--r--Zend/zend_gc.c26
-rw-r--r--Zend/zend_gc.h19
-rw-r--r--Zend/zend_generators.c8
-rw-r--r--Zend/zend_generators.h2
-rw-r--r--Zend/zend_globals.h40
-rw-r--r--Zend/zend_hash.c385
-rw-r--r--Zend/zend_hash.h113
-rw-r--r--Zend/zend_highlight.c14
-rw-r--r--Zend/zend_indent.c2
-rw-r--r--Zend/zend_ini.c208
-rw-r--r--Zend/zend_ini.h47
-rw-r--r--Zend/zend_ini_parser.y48
-rw-r--r--Zend/zend_ini_scanner.c3665
-rw-r--r--Zend/zend_ini_scanner.h1
-rw-r--r--Zend/zend_ini_scanner.l65
-rw-r--r--Zend/zend_interfaces.c13
-rw-r--r--Zend/zend_interfaces.h8
-rw-r--r--Zend/zend_iterators.c35
-rw-r--r--Zend/zend_iterators.h11
-rw-r--r--Zend/zend_language_parser.y1467
-rw-r--r--Zend/zend_language_scanner.c949
-rw-r--r--Zend/zend_language_scanner.l244
-rw-r--r--Zend/zend_list.c2
-rw-r--r--Zend/zend_llist.c38
-rw-r--r--Zend/zend_llist.h2
-rw-r--r--Zend/zend_long.h122
-rw-r--r--Zend/zend_multiply.h25
-rw-r--r--Zend/zend_object_handlers.c64
-rw-r--r--Zend/zend_object_handlers.h4
-rw-r--r--Zend/zend_objects.c4
-rw-r--r--Zend/zend_objects_API.c12
-rw-r--r--Zend/zend_objects_API.h6
-rw-r--r--Zend/zend_opcode.c125
-rw-r--r--Zend/zend_operators.c313
-rw-r--r--Zend/zend_operators.h94
-rw-r--r--Zend/zend_qsort.c2
-rw-r--r--Zend/zend_static_allocator.c8
-rw-r--r--Zend/zend_static_allocator.h8
-rw-r--r--Zend/zend_stream.c13
-rw-r--r--Zend/zend_stream.h25
-rw-r--r--Zend/zend_string.c24
-rw-r--r--Zend/zend_string.h90
-rw-r--r--Zend/zend_ts_hash.c8
-rw-r--r--Zend/zend_ts_hash.h10
-rw-r--r--Zend/zend_types.h103
-rw-r--r--Zend/zend_variables.c26
-rw-r--r--Zend/zend_variables.h8
-rw-r--r--Zend/zend_virtual_cwd.c54
-rw-r--r--Zend/zend_virtual_cwd.h24
-rw-r--r--Zend/zend_vm_def.h679
-rw-r--r--Zend/zend_vm_execute.h5303
-rw-r--r--Zend/zend_vm_execute.skl1
-rw-r--r--Zend/zend_vm_gen.php22
-rw-r--r--Zend/zend_vm_opcodes.c4
-rw-r--r--Zend/zend_vm_opcodes.h2
140 files changed, 17136 insertions, 14514 deletions
diff --git a/Zend/tests/024.phpt b/Zend/tests/024.phpt
index ff35a5c895..f89c49e613 100644
--- a/Zend/tests/024.phpt
+++ b/Zend/tests/024.phpt
@@ -11,7 +11,7 @@ var_dump($a++);
var_dump(++$b);
var_dump($a->$b);
var_dump($a->$b);
-var_dump($a->$b->$c[1]);
+var_dump($a->$b->{$c[1]});
?>
--EXPECTF--
diff --git a/Zend/tests/bug27669.phpt b/Zend/tests/bug27669.phpt
index 4d513e91aa..43591a9386 100644
--- a/Zend/tests/bug27669.phpt
+++ b/Zend/tests/bug27669.phpt
@@ -10,7 +10,7 @@ Bug #27669 (PHP 5 didn't support all possibilities for calling static methods dy
}
}
$y[0] = 'hello';
- A::$y[0]();
+ A::{$y[0]}();
?>
===DONE===
--EXPECTF--
diff --git a/Zend/tests/bug30080.phpt b/Zend/tests/bug30080.phpt
index bd8401e1be..8cac75ab8d 100644
--- a/Zend/tests/bug30080.phpt
+++ b/Zend/tests/bug30080.phpt
@@ -10,9 +10,9 @@ class foo {
new foo(array(new stdClass));
?>
---EXPECT--
+--EXPECTF--
array(1) {
[0]=>
- object(stdClass)#2 (0) {
+ object(stdClass)#%d (0) {
}
}
diff --git a/Zend/tests/bug39304.phpt b/Zend/tests/bug39304.phpt
index 8303b82573..5540135fa4 100644
--- a/Zend/tests/bug39304.phpt
+++ b/Zend/tests/bug39304.phpt
@@ -9,8 +9,8 @@ echo "I am alive";
--EXPECTF--
Notice: Uninitialized string offset: 0 in %sbug39304.php on line %d
-Notice: Uninitialized string offset: 1 in %sbug39304.php on line %d
-
Notice: Uninitialized string offset: 0 in %sbug39304.php on line %d
+
+Notice: Uninitialized string offset: 1 in %sbug39304.php on line %d
I am alive
diff --git a/Zend/tests/bug39304_2_4.phpt b/Zend/tests/bug39304_2_4.phpt
index b0e6ddc72c..cc0709b424 100644
--- a/Zend/tests/bug39304_2_4.phpt
+++ b/Zend/tests/bug39304_2_4.phpt
@@ -11,8 +11,8 @@ Bug #39304 (Segmentation fault with list unpacking of string offset)
--EXPECTF--
Notice: Uninitialized string offset: 0 in %sbug39304_2_4.php on line %d
-Notice: Uninitialized string offset: 1 in %sbug39304_2_4.php on line %d
-
Notice: Uninitialized string offset: 0 in %sbug39304_2_4.php on line %d
+
+Notice: Uninitialized string offset: 1 in %sbug39304_2_4.php on line %d
string(0) ""
string(0) ""
diff --git a/Zend/tests/bug43450.phpt b/Zend/tests/bug43450.phpt
index a94eba312e..f0cd4f75bc 100644
--- a/Zend/tests/bug43450.phpt
+++ b/Zend/tests/bug43450.phpt
@@ -18,15 +18,15 @@ class Foo
$num_repeats = 100000;
-$start = (memory_get_usage() / 1024) + 16;
+$start = memory_get_usage() / 1024;
for ($i=1;$i<$num_repeats;$i++)
{
$foo = new Foo();
md5($foo);
}
-$end = memory_get_peak_usage() / 1024;
+$end = memory_get_usage() / 1024;
-if ($start < $end) {
+if ($start + 16 < $end) {
echo 'FAIL';
} else {
echo 'PASS';
diff --git a/Zend/tests/bug44414.phpt b/Zend/tests/bug44414.phpt
index 1f3a2583d7..e9e6de7b45 100644
--- a/Zend/tests/bug44414.phpt
+++ b/Zend/tests/bug44414.phpt
@@ -12,4 +12,4 @@ class C extends A implements B {
}
?>
--EXPECTF--
-Fatal error: Class C contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (A::foo, B::bar) in %sbug44414.php on line 9
+Fatal error: Class C contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (A::foo, B::bar) in %sbug44414.php on line 8
diff --git a/Zend/tests/bug55007.phpt b/Zend/tests/bug55007.phpt
index 12fbf120a8..425ce8f296 100644
--- a/Zend/tests/bug55007.phpt
+++ b/Zend/tests/bug55007.phpt
@@ -4,7 +4,7 @@ Bug #55007 (compiler fail after previous fail)
<?php
function __autoload($classname) {
- if ('CompileErrorClass'==$classname) eval('class CompileErrorClass { function foo() { $a[] } }');
+ if ('CompileErrorClass'==$classname) eval('class CompileErrorClass { function foo() { $a[]; } }');
if ('MyErrorHandler'==$classname) eval('class MyErrorHandler { function __construct() { print "My error handler runs.\n"; } }');
}
diff --git a/Zend/tests/bug60099.phpt b/Zend/tests/bug60099.phpt
index 13e2f54b09..8cca3440fb 100644
--- a/Zend/tests/bug60099.phpt
+++ b/Zend/tests/bug60099.phpt
@@ -7,4 +7,4 @@ namespace foo {
?>
--EXPECTF--
-Fatal error: __HALT_COMPILER() can only be used from the outermost scope in %s on line %d
+Parse error: syntax error, unexpected end of file in %s on line %d
diff --git a/Zend/tests/bug60825.phpt b/Zend/tests/bug60825.phpt
index 0aeb8f77e3..f2f5b602ad 100644
--- a/Zend/tests/bug60825.phpt
+++ b/Zend/tests/bug60825.phpt
@@ -1,5 +1,5 @@
--TEST--
-Bug #60825 (Segfault when running symfony 2 tests)
+Bug #60825 (Segfault when running symfony 2 tests) (PHP7)
--DESCRIPTION--
run this with valgrind
--FILE--
@@ -13,7 +13,10 @@ class test {
}
$a = new test;
require_once $a;
-debug_zval_dump(test::$x);
+debug_zval_dump($a, test::$x);
?>
--EXPECTF--
-string(%d) "%sbug60825.php" refcount(2)
+object(test)#%d (0) refcount(%d){
+}
+object(test)#%d (0) refcount(%d){
+}
diff --git a/Zend/tests/bug67436/bug67436_nohandler.phpt b/Zend/tests/bug67436/bug67436_nohandler.phpt
index 464f711532..f1760c6462 100644
--- a/Zend/tests/bug67436/bug67436_nohandler.phpt
+++ b/Zend/tests/bug67436/bug67436_nohandler.phpt
@@ -19,6 +19,6 @@ $b = new b();
$b->test();
--EXPECTF--
-Strict Standards: Declaration of b::test() should be compatible with a::test($arg = c::TESTCONSTANT) in %s/bug67436/b.php on line %d
+Strict Standards: Declaration of b::test() should be compatible with a::test($arg = c::TESTCONSTANT) in %s%ebug67436%eb.php on line %d
b::test()
a::test(c::TESTCONSTANT)
diff --git a/Zend/tests/bug67874.phpt b/Zend/tests/bug67874.phpt
new file mode 100644
index 0000000000..d851c9a4c1
--- /dev/null
+++ b/Zend/tests/bug67874.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Bug #67874 Crash in array_map()
+--FILE--
+<?php
+$a = array(1,2,3);
+$data = array($a);
+$data = array_map('current', $data);
+var_dump($data);
+?>
+--EXPECT--
+array(1) {
+ [0]=>
+ int(1)
+}
diff --git a/Zend/tests/bug67922.phpt b/Zend/tests/bug67922.phpt
new file mode 100644
index 0000000000..8be3f2eba0
--- /dev/null
+++ b/Zend/tests/bug67922.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #67922: Member function not found when dereferencing in write-context
+--FILE--
+<?php
+
+class C {
+ public function test() {
+ return new stdClass;
+ }
+}
+
+$b = new stdClass;
+$b->c = new C;
+$b->c->test()->d = 'str';
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/bug67938.phpt b/Zend/tests/bug67938.phpt
new file mode 100644
index 0000000000..6597c4895f
--- /dev/null
+++ b/Zend/tests/bug67938.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #67938: Segfault when extending interface method with variadic
+--FILE--
+<?php
+
+interface TestInterface {
+ public function foo();
+ public function bar(array $bar);
+}
+
+class Test implements TestInterface {
+ public function foo(...$args) {
+ echo __METHOD__, "\n";
+ }
+ public function bar(array $bar, ...$args) {
+ echo __METHOD__, "\n";
+ }
+}
+
+$obj = new Test;
+$obj->foo();
+$obj->bar([]);
+
+?>
+--EXPECT--
+Test::foo
+Test::bar
diff --git a/Zend/tests/bug67985.phpt b/Zend/tests/bug67985.phpt
new file mode 100644
index 0000000000..6f032643f4
--- /dev/null
+++ b/Zend/tests/bug67985.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #67985 - Last used array index not copied to new array at assignment
+--FILE--
+<?php
+
+$a = ['zero', 'one', 'two'];
+unset($a[2]);
+$b = $a;
+$a[] = 'three';
+$b[] = 'three';
+
+var_dump($a === $b);
+
+?>
+--EXPECT--
+bool(true)
diff --git a/Zend/tests/closure_026.phpt b/Zend/tests/closure_026.phpt
index 150cc86584..82a948d1a0 100644
--- a/Zend/tests/closure_026.phpt
+++ b/Zend/tests/closure_026.phpt
@@ -47,7 +47,10 @@ array(1) {
["this"]=>
object(foo)#%d (1) {
["a"]=>
- *RECURSION*
+ array(1) {
+ [0]=>
+ *RECURSION*
+ }
}
}
}
diff --git a/Zend/tests/closure_call.phpt b/Zend/tests/closure_call.phpt
new file mode 100644
index 0000000000..d53b6077ee
--- /dev/null
+++ b/Zend/tests/closure_call.phpt
@@ -0,0 +1,65 @@
+--TEST--
+Closure::call
+--FILE--
+<?php
+
+class Foo {
+ public $x = 0;
+ function bar() {
+ return function () {
+ return $this->x;
+ };
+ }
+}
+
+$foo = new Foo;
+$qux = $foo->bar();
+
+$foobar = new Foo;
+$foobar->x = 3;
+
+var_dump($qux());
+
+var_dump($qux->call($foo));
+
+// Try on an object other than the one already bound
+var_dump($qux->call($foobar));
+
+
+$bar = function () {
+ return $this->x;
+};
+
+$elePHPant = new StdClass;
+$elePHPant->x = 7;
+
+// Try on a StdClass
+var_dump($bar->call($elePHPant));
+
+
+$beta = function ($z) {
+ return $this->x * $z;
+};
+
+// Ensure argument passing works
+var_dump($beta->call($elePHPant, 3));
+
+// Ensure ->call calls with scope of passed object
+class FooBar {
+ private $x = 3;
+}
+
+$foo = function () {
+ var_dump($this->x);
+};
+
+$foo->call(new FooBar);
+
+?>
+--EXPECT--
+int(0)
+int(0)
+int(3)
+int(7)
+int(21)
+int(3) \ No newline at end of file
diff --git a/Zend/tests/concat_002.phpt b/Zend/tests/concat_002.phpt
new file mode 100644
index 0000000000..3cb182ee7d
--- /dev/null
+++ b/Zend/tests/concat_002.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Stress test $x .= $x
+--FILE--
+<?php
+
+/*
+ * Test case for a concat_function() change that broke a test outside of Zend
+ *
+ * @see https://github.com/php/php-src/commit/29397f8fd2b4bc8d95e18448ca2d27a62241a407
+**/
+
+$result = 'f';
+
+for ($i = 0; $i < 25; ++$i) {
+ $result .= $result;
+}
+
+var_dump(strlen($result));
+echo "Done\n";
+?>
+--EXPECT--
+int(33554432)
+Done
+
diff --git a/Zend/tests/constants/dir-constant-includes.phpt b/Zend/tests/constants/dir-constant-includes.phpt
index 8ea65292de..c004cbb6a4 100644
--- a/Zend/tests/constants/dir-constant-includes.phpt
+++ b/Zend/tests/constants/dir-constant-includes.phpt
@@ -4,10 +4,10 @@ __DIR__ constant test with includes
<?php
echo __DIR__ . "\n";
echo dirname(__FILE__) . "\n";
-include 'fixtures/folder1/fixture.php';
-include 'fixtures/folder2/fixture.php';
-include 'fixtures/folder3/fixture.php';
-include 'fixtures/folder4/fixture.php';
+include 'fixtures/folder1/fixture.inc';
+include 'fixtures/folder2/fixture.inc';
+include 'fixtures/folder3/fixture.inc';
+include 'fixtures/folder4/fixture.inc';
?>
--EXPECTF--
%stests%sconstants
diff --git a/Zend/tests/constants/dir-constant-nested_includes.phpt b/Zend/tests/constants/dir-constant-nested_includes.phpt
index 18bdfa8912..c67fbf85e4 100644
--- a/Zend/tests/constants/dir-constant-nested_includes.phpt
+++ b/Zend/tests/constants/dir-constant-nested_includes.phpt
@@ -4,26 +4,26 @@ __DIR__ constant test with nested includes
<?php
echo __DIR__ . "\n";
echo dirname(__FILE__) . "\n";
-include 'fixtures/folder1/fixture.php';
-include 'fixtures/folder1/subfolder1/fixture.php';
-include 'fixtures/folder1/subfolder2/fixture.php';
-include 'fixtures/folder1/subfolder3/fixture.php';
-include 'fixtures/folder1/subfolder4/fixture.php';
-include 'fixtures/folder2/fixture.php';
-include 'fixtures/folder2/subfolder1/fixture.php';
-include 'fixtures/folder2/subfolder2/fixture.php';
-include 'fixtures/folder2/subfolder3/fixture.php';
-include 'fixtures/folder2/subfolder4/fixture.php';
-include 'fixtures/folder3/fixture.php';
-include 'fixtures/folder3/subfolder1/fixture.php';
-include 'fixtures/folder3/subfolder2/fixture.php';
-include 'fixtures/folder3/subfolder3/fixture.php';
-include 'fixtures/folder3/subfolder4/fixture.php';
-include 'fixtures/folder4/fixture.php';
-include 'fixtures/folder4/subfolder1/fixture.php';
-include 'fixtures/folder4/subfolder2/fixture.php';
-include 'fixtures/folder4/subfolder3/fixture.php';
-include 'fixtures/folder4/subfolder4/fixture.php';
+include 'fixtures/folder1/fixture.inc';
+include 'fixtures/folder1/subfolder1/fixture.inc';
+include 'fixtures/folder1/subfolder2/fixture.inc';
+include 'fixtures/folder1/subfolder3/fixture.inc';
+include 'fixtures/folder1/subfolder4/fixture.inc';
+include 'fixtures/folder2/fixture.inc';
+include 'fixtures/folder2/subfolder1/fixture.inc';
+include 'fixtures/folder2/subfolder2/fixture.inc';
+include 'fixtures/folder2/subfolder3/fixture.inc';
+include 'fixtures/folder2/subfolder4/fixture.inc';
+include 'fixtures/folder3/fixture.inc';
+include 'fixtures/folder3/subfolder1/fixture.inc';
+include 'fixtures/folder3/subfolder2/fixture.inc';
+include 'fixtures/folder3/subfolder3/fixture.inc';
+include 'fixtures/folder3/subfolder4/fixture.inc';
+include 'fixtures/folder4/fixture.inc';
+include 'fixtures/folder4/subfolder1/fixture.inc';
+include 'fixtures/folder4/subfolder2/fixture.inc';
+include 'fixtures/folder4/subfolder3/fixture.inc';
+include 'fixtures/folder4/subfolder4/fixture.inc';
?>
--EXPECTF--
%stests%sconstants
diff --git a/Zend/tests/constants/fixtures/folder1/fixture.php b/Zend/tests/constants/fixtures/folder1/fixture.inc
index 3406c998ac..3406c998ac 100755
--- a/Zend/tests/constants/fixtures/folder1/fixture.php
+++ b/Zend/tests/constants/fixtures/folder1/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder1/subfolder1/fixture.php b/Zend/tests/constants/fixtures/folder1/subfolder1/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder1/subfolder1/fixture.php
+++ b/Zend/tests/constants/fixtures/folder1/subfolder1/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder1/subfolder2/fixture.php b/Zend/tests/constants/fixtures/folder1/subfolder2/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder1/subfolder2/fixture.php
+++ b/Zend/tests/constants/fixtures/folder1/subfolder2/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder1/subfolder3/fixture.php b/Zend/tests/constants/fixtures/folder1/subfolder3/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder1/subfolder3/fixture.php
+++ b/Zend/tests/constants/fixtures/folder1/subfolder3/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder1/subfolder4/fixture.php b/Zend/tests/constants/fixtures/folder1/subfolder4/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder1/subfolder4/fixture.php
+++ b/Zend/tests/constants/fixtures/folder1/subfolder4/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder2/fixture.php b/Zend/tests/constants/fixtures/folder2/fixture.inc
index 3406c998ac..3406c998ac 100755
--- a/Zend/tests/constants/fixtures/folder2/fixture.php
+++ b/Zend/tests/constants/fixtures/folder2/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder2/subfolder1/fixture.php b/Zend/tests/constants/fixtures/folder2/subfolder1/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder2/subfolder1/fixture.php
+++ b/Zend/tests/constants/fixtures/folder2/subfolder1/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder2/subfolder2/fixture.php b/Zend/tests/constants/fixtures/folder2/subfolder2/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder2/subfolder2/fixture.php
+++ b/Zend/tests/constants/fixtures/folder2/subfolder2/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder2/subfolder3/fixture.php b/Zend/tests/constants/fixtures/folder2/subfolder3/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder2/subfolder3/fixture.php
+++ b/Zend/tests/constants/fixtures/folder2/subfolder3/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder2/subfolder4/fixture.php b/Zend/tests/constants/fixtures/folder2/subfolder4/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder2/subfolder4/fixture.php
+++ b/Zend/tests/constants/fixtures/folder2/subfolder4/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder3/fixture.php b/Zend/tests/constants/fixtures/folder3/fixture.inc
index 3406c998ac..3406c998ac 100755
--- a/Zend/tests/constants/fixtures/folder3/fixture.php
+++ b/Zend/tests/constants/fixtures/folder3/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder3/subfolder1/fixture.php b/Zend/tests/constants/fixtures/folder3/subfolder1/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder3/subfolder1/fixture.php
+++ b/Zend/tests/constants/fixtures/folder3/subfolder1/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder3/subfolder2/fixture.php b/Zend/tests/constants/fixtures/folder3/subfolder2/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder3/subfolder2/fixture.php
+++ b/Zend/tests/constants/fixtures/folder3/subfolder2/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder3/subfolder3/fixture.php b/Zend/tests/constants/fixtures/folder3/subfolder3/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder3/subfolder3/fixture.php
+++ b/Zend/tests/constants/fixtures/folder3/subfolder3/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder3/subfolder4/fixture.php b/Zend/tests/constants/fixtures/folder3/subfolder4/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder3/subfolder4/fixture.php
+++ b/Zend/tests/constants/fixtures/folder3/subfolder4/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder4/fixture.php b/Zend/tests/constants/fixtures/folder4/fixture.inc
index 3406c998ac..3406c998ac 100755
--- a/Zend/tests/constants/fixtures/folder4/fixture.php
+++ b/Zend/tests/constants/fixtures/folder4/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder4/subfolder1/fixture.php b/Zend/tests/constants/fixtures/folder4/subfolder1/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder4/subfolder1/fixture.php
+++ b/Zend/tests/constants/fixtures/folder4/subfolder1/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder4/subfolder2/fixture.php b/Zend/tests/constants/fixtures/folder4/subfolder2/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder4/subfolder2/fixture.php
+++ b/Zend/tests/constants/fixtures/folder4/subfolder2/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder4/subfolder3/fixture.php b/Zend/tests/constants/fixtures/folder4/subfolder3/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder4/subfolder3/fixture.php
+++ b/Zend/tests/constants/fixtures/folder4/subfolder3/fixture.inc
diff --git a/Zend/tests/constants/fixtures/folder4/subfolder4/fixture.php b/Zend/tests/constants/fixtures/folder4/subfolder4/fixture.inc
index 86e6859363..86e6859363 100755
--- a/Zend/tests/constants/fixtures/folder4/subfolder4/fixture.php
+++ b/Zend/tests/constants/fixtures/folder4/subfolder4/fixture.inc
diff --git a/Zend/tests/declare_001.phpt b/Zend/tests/declare_001.phpt
index 21d797880e..4eff18045c 100644
--- a/Zend/tests/declare_001.phpt
+++ b/Zend/tests/declare_001.phpt
@@ -13,7 +13,6 @@ zend.multibyte=1
declare(encoding = 1);
declare(encoding = 112313123213131232100);
-declare(encoding = NULL);
declare(encoding = 'utf-8');
declare(encoding = M_PI);
@@ -25,6 +24,4 @@ Warning: Unsupported encoding [1] in %sdeclare_001.php on line %d
Warning: Unsupported encoding [1.1231312321313E+20] in %sdeclare_001.php on line %d
-Warning: Unsupported encoding [] in %sdeclare_001.php on line %d
-
-Fatal error: Cannot use constants as encoding in %sdeclare_001.php on line %d
+Fatal error: Encoding must be a literal in %s on line %d
diff --git a/Zend/tests/declare_003.phpt b/Zend/tests/declare_003.phpt
index 2980f7589b..2f3e887380 100644
--- a/Zend/tests/declare_003.phpt
+++ b/Zend/tests/declare_003.phpt
@@ -8,7 +8,6 @@ zend.multibyte=1
declare(encoding = 1);
declare(encoding = 11111111111111);
-declare(encoding = NULL);
declare(encoding = M_PI);
print 'DONE';
@@ -19,6 +18,4 @@ Warning: Unsupported encoding [1] in %sdeclare_003.php on line %d
Warning: Unsupported encoding [11111111111111] in %sdeclare_003.php on line %d
-Warning: Unsupported encoding [] in %sdeclare_003.php on line %d
-
-Fatal error: Cannot use constants as encoding in %sdeclare_003.php on line %d
+Fatal error: Encoding must be a literal in %s on line %d
diff --git a/Zend/tests/errmsg_014.phpt b/Zend/tests/errmsg_014.phpt
deleted file mode 100644
index 77e12b05e9..0000000000
--- a/Zend/tests/errmsg_014.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-errmsg: cannot call __clone() method on objects
---FILE--
-<?php
-
-class test {
- function __clone() {
- }
-}
-
-$t = new test;
-$t->__clone();
-
-echo "Done\n";
-?>
---EXPECTF--
-Fatal error: Cannot call __clone() method on objects - use 'clone $obj' instead in %s on line %d
diff --git a/Zend/tests/eval_parse_error_with_doc_comment.phpt b/Zend/tests/eval_parse_error_with_doc_comment.phpt
new file mode 100644
index 0000000000..62561aaa79
--- /dev/null
+++ b/Zend/tests/eval_parse_error_with_doc_comment.phpt
@@ -0,0 +1,15 @@
+--TEST--
+eval() parse error on function with doc comment
+--FILE--
+<?php
+
+eval(
+<<<EOC
+/** doc comment */
+function f() {
+EOC
+);
+
+?>
+--EXPECTF--
+Parse error: syntax error, unexpected end of file in %s(%d) : eval()'d code on line %d
diff --git a/Zend/tests/foreach_list_002.phpt b/Zend/tests/foreach_list_002.phpt
index 251870ba09..bc17d94268 100644
--- a/Zend/tests/foreach_list_002.phpt
+++ b/Zend/tests/foreach_list_002.phpt
@@ -9,7 +9,7 @@ foreach (array(array(1,2), array(3,4)) as list($a, )) {
$array = [['a', 'b'], 'c', 'd'];
-foreach($array as list(list(), $a)) {
+foreach($array as list(, $a)) {
var_dump($a);
}
diff --git a/Zend/tests/gc_033.phpt b/Zend/tests/gc_033.phpt
new file mode 100644
index 0000000000..bcd1541254
--- /dev/null
+++ b/Zend/tests/gc_033.phpt
@@ -0,0 +1,28 @@
+--TEST--
+GC 033: Crash in GC while run with phpspec
+--FILE--
+<?php
+$a = new stdClass();
+$a->a = array();
+$a->a[0] = new Stdclass();
+$a->a[0]->a = $a;
+$a->a[1] = &$a->a;
+
+/* remove the self-reference array out of roots */
+gc_collect_cycles();
+
+/* do unset */
+unset($a);
+
+/* let's full the gc roots */
+for ($i=0; $i<9999; $i++) {
+ $b = range(0, 1);
+ $b[0] = &$b;
+ unset($b);
+}
+
+/* then $a will be freed, but $a->a[0] is not. reference to a freed $a */
+var_dump(gc_collect_cycles());
+?>
+--EXPECT--
+int(20001)
diff --git a/Zend/tests/isset_003.phpt b/Zend/tests/isset_003.phpt
index 4db42a933b..92225b5906 100644
--- a/Zend/tests/isset_003.phpt
+++ b/Zend/tests/isset_003.phpt
@@ -14,7 +14,7 @@ var_dump(isset($a[0]->a));
var_dump(isset($c[0][1][2]->a->b->c->d));
-var_dump(isset(${$a}->{$b->$c[$d]}));
+var_dump(isset(${$a}->{$b->{$c[$d]}}));
var_dump(isset($GLOBALS));
diff --git a/Zend/tests/isset_003_2_4.phpt b/Zend/tests/isset_003_2_4.phpt
index c05f3e26f4..42d8cc6a08 100644
--- a/Zend/tests/isset_003_2_4.phpt
+++ b/Zend/tests/isset_003_2_4.phpt
@@ -16,7 +16,7 @@ var_dump(isset($a[0]->a));
var_dump(isset($c[0][1][2]->a->b->c->d));
-var_dump(isset(${$a}->{$b->$c[$d]}));
+var_dump(isset(${$a}->{$b->{$c[$d]}}));
var_dump(isset($GLOBALS));
diff --git a/Zend/tests/isset_func_error.phpt b/Zend/tests/isset_func_error.phpt
index 7d1036def8..7d6616b96d 100644
--- a/Zend/tests/isset_func_error.phpt
+++ b/Zend/tests/isset_func_error.phpt
@@ -5,4 +5,4 @@ Error message for isset(func())
isset(abc());
?>
--EXPECTF--
-Fatal error: Cannot use isset() on the result of a function call (you can use "null !== func()" instead) in %s on line %d
+Fatal error: Cannot use isset() on the result of an expression (you can use "null !== expression" instead) in %s on line %d
diff --git a/Zend/tests/list_005.phpt b/Zend/tests/list_005.phpt
index 4afc353b2f..ec5640a60a 100644
--- a/Zend/tests/list_005.phpt
+++ b/Zend/tests/list_005.phpt
@@ -3,33 +3,33 @@ Testing list() with several variables
--FILE--
<?php
-$a = "foo";
+$str = "foo";
-list($a, $b, $c) = $a;
+list($a, $b, $c) = $str;
var_dump($a, $b, $c);
print "----\n";
-$a = 1;
+$int = 1;
-list($a, $b, $c) = $a;
+list($a, $b, $c) = $int;
var_dump($a, $b, $c);
print "----\n";
-$a = new stdClass;
+$obj = new stdClass;
-list($a, $b, $c) = $a;
+list($a, $b, $c) = $obj;
var_dump($a, $b, $c);
print "----\n";
-$a = array(1, 2, 3);
+$arr = array(1, 2, 3);
-list($a, $b, $c) = $a;
+list($a, $b, $c) = $arr;
var_dump($a, $b, $c);
diff --git a/Zend/tests/list_006.phpt b/Zend/tests/list_006.phpt
index f5f5970be4..d380235d25 100644
--- a/Zend/tests/list_006.phpt
+++ b/Zend/tests/list_006.phpt
@@ -7,8 +7,6 @@ list($a, list($b, list(list($d)))) = array();
?>
--EXPECTF--
-Notice: Undefined offset: 1 in %s on line %d
+Notice: Undefined offset: 0 in %s on line %d
Notice: Undefined offset: 1 in %s on line %d
-
-Notice: Undefined offset: 0 in %s on line %d
diff --git a/Zend/tests/strlen.phpt b/Zend/tests/strlen.phpt
new file mode 100644
index 0000000000..ddf0141386
--- /dev/null
+++ b/Zend/tests/strlen.phpt
@@ -0,0 +1,51 @@
+--TEST--
+Fixed execute_data corruption with __toString()
+--FILE--
+<?php
+
+class Test
+{
+ public $something = 'hello';
+
+ public function __toString()
+ {
+ return $this->something;
+ }
+}
+
+$t = new Test;
+var_dump(strlen($t));
+var_dump($t->something);
+
+class Test2
+{
+ public $something;
+
+ public function __construct(&$a)
+ {
+ $this->something = &$a;
+ }
+
+ public function __toString()
+ {
+ return $this->something;
+ }
+}
+
+$a = 'world';
+$t2 = new Test2($a);
+var_dump(strlen($t2));
+var_dump($t2->something);
+var_dump($a);
+
+$a = 'foobar';
+var_dump(strlen($t2));
+var_dump($t2->something);
+--EXPECT--
+int(5)
+string(5) "hello"
+int(5)
+string(5) "world"
+string(5) "world"
+int(6)
+string(6) "foobar"
diff --git a/Zend/tests/use_const/no_global_fallback.phpt b/Zend/tests/use_const/no_global_fallback.phpt
index a128f353ed..64e2a154ce 100644
--- a/Zend/tests/use_const/no_global_fallback.phpt
+++ b/Zend/tests/use_const/no_global_fallback.phpt
@@ -10,5 +10,4 @@ var_dump(baz);
?>
--EXPECTF--
-Notice: Use of undefined constant baz - assumed 'baz' in %s on line %d
-string(3) "baz"
+Fatal error: Undefined constant 'foo\bar\baz' in %s on line %d
diff --git a/Zend/tests/varSyntax/globalNonSimpleVariableError.phpt b/Zend/tests/varSyntax/globalNonSimpleVariableError.phpt
new file mode 100644
index 0000000000..ed04921f89
--- /dev/null
+++ b/Zend/tests/varSyntax/globalNonSimpleVariableError.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Global keyword only accepts simple variables
+--FILE--
+<?php
+
+global $$foo->bar;
+
+?>
+--EXPECTF--
+Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR), expecting ',' or ';' in %s on line %d
diff --git a/Zend/tests/varSyntax/indirectFcall.phpt b/Zend/tests/varSyntax/indirectFcall.phpt
new file mode 100644
index 0000000000..4cc5c1171a
--- /dev/null
+++ b/Zend/tests/varSyntax/indirectFcall.phpt
@@ -0,0 +1,53 @@
+--TEST--
+Indirect function calls
+--FILE--
+<?php
+
+function id($x = 'id') { return $x; }
+
+var_dump(0);
+
+id('var_dump')(1);
+id('id')('var_dump')(2);
+id('id')('id')('var_dump')(3);
+id()()('var_dump')(4);
+
+id(['udef', 'id'])[1]()('var_dump')(5);
+(id((object) ['a' => 'id', 'b' => 'udef'])->a)()()()()('var_dump')(6);
+
+$id = function($x) { return $x; };
+
+$id($id)('var_dump')(7);
+
+(function($x) { return $x; })('id')('var_dump')(8);
+
+($f = function($x = null) use (&$f) {
+ return $x ?: $f;
+})()()()('var_dump')(9);
+
+class Test {
+ public static function id($x = [__CLASS__, 'id']) { return $x; }
+}
+
+$obj = new Test;
+[$obj, 'id']()('id')($id)('var_dump')(10);
+['Test', 'id']()()('var_dump')(11);
+'id'()('id')('var_dump')(12);
+('i' . 'd')()('var_dump')(13);
+
+?>
+--EXPECT--
+int(0)
+int(1)
+int(2)
+int(3)
+int(4)
+int(5)
+int(6)
+int(7)
+int(8)
+int(9)
+int(10)
+int(11)
+int(12)
+int(13)
diff --git a/Zend/tests/varSyntax/issetOnTemp.phpt b/Zend/tests/varSyntax/issetOnTemp.phpt
new file mode 100644
index 0000000000..cd7bc006cd
--- /dev/null
+++ b/Zend/tests/varSyntax/issetOnTemp.phpt
@@ -0,0 +1,26 @@
+--TEST--
+isset() can be used on dereferences of temporary expressions
+--FILE--
+<?php
+
+var_dump(isset([0, 1][0]));
+var_dump(isset(([0, 1] + [])[0]));
+var_dump(isset([[0, 1]][0][0]));
+var_dump(isset(([[0, 1]] + [])[0][0]));
+var_dump(isset(((object) ['a' => 'b'])->a));
+var_dump(isset(['a' => 'b']->a));
+var_dump(isset("str"->a));
+var_dump(isset((['a' => 'b'] + [])->a));
+var_dump(isset((['a' => 'b'] + [])->a->b));
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
diff --git a/Zend/tests/varSyntax/newVariable.phpt b/Zend/tests/varSyntax/newVariable.phpt
new file mode 100644
index 0000000000..360f99ac36
--- /dev/null
+++ b/Zend/tests/varSyntax/newVariable.phpt
@@ -0,0 +1,39 @@
+--TEST--
+Variable as class name for new expression
+--FILE--
+<?php
+
+$className = 'stdClass';
+$array = ['className' => 'stdClass'];
+$obj = (object) ['className' => 'stdClass'];
+
+class Test {
+ public static $className = 'stdClass';
+}
+$test = 'Test';
+$weird = [0 => (object) ['foo' => 'Test']];
+
+var_dump(new $className);
+var_dump(new $array['className']);
+var_dump(new $array{'className'});
+var_dump(new $obj->className);
+var_dump(new Test::$className);
+var_dump(new $test::$className);
+var_dump(new $weird[0]->foo::$className);
+
+?>
+--EXPECTF--
+object(stdClass)#%d (0) {
+}
+object(stdClass)#%d (0) {
+}
+object(stdClass)#%d (0) {
+}
+object(stdClass)#%d (0) {
+}
+object(stdClass)#%d (0) {
+}
+object(stdClass)#%d (0) {
+}
+object(stdClass)#%d (0) {
+}
diff --git a/Zend/tests/varSyntax/parenthesesDeref.phpt b/Zend/tests/varSyntax/parenthesesDeref.phpt
new file mode 100644
index 0000000000..0ebfe9c5d7
--- /dev/null
+++ b/Zend/tests/varSyntax/parenthesesDeref.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Dereferencing expression parentheses
+--FILE--
+<?php
+
+$array = [&$array, 1];
+var_dump(($array)[1]);
+var_dump((($array[0][0])[0])[1]);
+
+var_dump(((object) ['a' => 0, 'b' => 1])->b);
+
+$obj = (object) ['a' => 0, 'b' => ['var_dump', 1]];
+(clone $obj)->b[0](1);
+
+?>
+--EXPECT--
+int(1)
+int(1)
+int(1)
+int(1)
diff --git a/Zend/tests/varSyntax/propertyOfStringError.phpt b/Zend/tests/varSyntax/propertyOfStringError.phpt
new file mode 100644
index 0000000000..85abc5849a
--- /dev/null
+++ b/Zend/tests/varSyntax/propertyOfStringError.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Cannot take property of a string
+--FILE--
+<?php
+
+"foo"->bar;
+
+?>
+--EXPECTF--
+Notice: Trying to get property of non-object in %s on line %d
diff --git a/Zend/tests/varSyntax/staticMember.phpt b/Zend/tests/varSyntax/staticMember.phpt
new file mode 100644
index 0000000000..22a1fa2b13
--- /dev/null
+++ b/Zend/tests/varSyntax/staticMember.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Static member access
+--FILE--
+<?php
+
+class A {
+ public static $b = 0;
+ public static $c = [0, 1];
+ public static $A_str = 'A';
+}
+
+$A_str = 'A';
+$A_obj = new A;
+$b_str = 'b';
+$c_str = 'c';
+
+var_dump(A::$b);
+var_dump($A_str::$b);
+var_dump($A_obj::$b);
+var_dump(('A' . '')::$b);
+var_dump('A'::$b);
+var_dump('A'[0]::$b);
+var_dump(A::$$b_str);
+var_dump(A::$$c_str[1]);
+var_dump(A::$A_str::$b);
+
+?>
+--EXPECT--
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(1)
+int(0)
diff --git a/Zend/tests/varSyntax/tempDimFetchByRefError.phpt b/Zend/tests/varSyntax/tempDimFetchByRefError.phpt
new file mode 100644
index 0000000000..dbcac75ea9
--- /dev/null
+++ b/Zend/tests/varSyntax/tempDimFetchByRefError.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Passing a dimention fetch on a temporary by reference is not allowed
+--FILE--
+<?php
+
+$fn = function(&$ref) {};
+$fn([0, 1][0]);
+
+?>
+--EXPECTF--
+Fatal error: Cannot use temporary expression in write context in %s on line %d
diff --git a/Zend/tests/varSyntax/tempPropFetchByRefError.phpt b/Zend/tests/varSyntax/tempPropFetchByRefError.phpt
new file mode 100644
index 0000000000..f8298a936d
--- /dev/null
+++ b/Zend/tests/varSyntax/tempPropFetchByRefError.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Passing a property fetch on a temporary by reference is not allowed
+--FILE--
+<?php
+
+$fn = function(&$ref) {};
+$fn([0, 1]->prop);
+
+?>
+--EXPECTF--
+Fatal error: Cannot use temporary expression in write context in %s on line %d
diff --git a/Zend/tests/varSyntax/writeToTempExpr.phpt b/Zend/tests/varSyntax/writeToTempExpr.phpt
new file mode 100644
index 0000000000..daeaf24938
--- /dev/null
+++ b/Zend/tests/varSyntax/writeToTempExpr.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Writing to a temporary expression is not allowed
+--FILE--
+<?php
+
+[0, 1][0] = 1;
+
+?>
+--EXPECTF--
+Fatal error: Cannot use temporary expression in write context in %s on line %d
diff --git a/Zend/zend.c b/Zend/zend.c
index 913462bec7..46719b4ac1 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -46,7 +46,7 @@
/* true multithread-shared globals */
ZEND_API zend_class_entry *zend_standard_class_def = NULL;
-ZEND_API int (*zend_printf)(const char *format, ...);
+ZEND_API size_t (*zend_printf)(const char *format, ...);
ZEND_API zend_write_func_t zend_write;
ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path TSRMLS_DC);
ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
@@ -54,22 +54,22 @@ ZEND_API void (*zend_block_interruptions)(void);
ZEND_API void (*zend_unblock_interruptions)(void);
ZEND_API void (*zend_ticks_function)(int ticks TSRMLS_DC);
ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
-int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
+size_t (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
zend_string *(*zend_vstrpprintf)(size_t max_len, const char *format, va_list ap);
ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
void (*zend_on_timeout)(int seconds TSRMLS_DC);
-static void (*zend_message_dispatcher_p)(long message, const void *data TSRMLS_DC);
-static int (*zend_get_configuration_directive_p)(const char *name, uint name_length, zval *contents);
+static void (*zend_message_dispatcher_p)(zend_long message, const void *data TSRMLS_DC);
+static zval *(*zend_get_configuration_directive_p)(zend_string *name);
static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */
{
if (!new_value) {
EG(error_reporting) = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED;
} else {
- EG(error_reporting) = atoi(new_value);
+ EG(error_reporting) = atoi(new_value->val);
}
return SUCCESS;
}
@@ -77,7 +77,7 @@ static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */
static ZEND_INI_MH(OnUpdateGCEnabled) /* {{{ */
{
- OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+ OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
if (GC_G(gc_enabled)) {
gc_init(TSRMLS_C);
@@ -95,7 +95,7 @@ static ZEND_INI_MH(OnUpdateScriptEncoding) /* {{{ */
if (!zend_multibyte_get_functions(TSRMLS_C)) {
return SUCCESS;
}
- return zend_multibyte_set_script_encoding_by_string(new_value, new_value_length TSRMLS_CC);
+ return zend_multibyte_set_script_encoding_by_string(new_value->val, new_value->len TSRMLS_CC);
}
/* }}} */
@@ -134,7 +134,7 @@ static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent,
{
zval *tmp;
zend_string *string_key;
- ulong num_key;
+ zend_ulong num_key;
int i;
for (i = 0; i < indent; i++) {
@@ -156,8 +156,8 @@ static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent,
if (string_key) {
if (is_object) {
const char *prop_name, *class_name;
- int prop_len;
- int mangled = zend_unmangle_property_name_ex(string_key->val, string_key->len, &class_name, &prop_name, &prop_len);
+ size_t prop_len;
+ int mangled = zend_unmangle_property_name_ex(string_key, &class_name, &prop_name, &prop_len);
ZEND_WRITE_EX(prop_name, prop_len);
if (class_name && mangled == SUCCESS) {
@@ -174,7 +174,7 @@ static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent,
}
} else {
char key[25];
- snprintf(key, sizeof(key), "%ld", num_key);
+ snprintf(key, sizeof(key), ZEND_LONG_FMT, num_key);
ZEND_PUTS_EX(key);
}
ZEND_PUTS_EX("] => ");
@@ -193,7 +193,7 @@ static void print_flat_hash(HashTable *ht TSRMLS_DC) /* {{{ */
{
zval *tmp;
zend_string *string_key;
- ulong num_key;
+ zend_ulong num_key;
int i = 0;
ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, string_key, tmp) {
@@ -204,7 +204,7 @@ static void print_flat_hash(HashTable *ht TSRMLS_DC) /* {{{ */
if (string_key) {
ZEND_WRITE(string_key->val, string_key->len);
} else {
- zend_printf("%ld", num_key);
+ zend_printf(ZEND_ULONG_FMT, num_key);
}
ZEND_PUTS("] => ");
zend_print_flat_zval_r(tmp TSRMLS_CC);
@@ -226,23 +226,23 @@ again:
break;
case IS_TRUE:
if (CG(one_char_string)['1']) {
- ZVAL_INT_STR(expr_copy, CG(one_char_string)['1']);
+ ZVAL_INTERNED_STR(expr_copy, CG(one_char_string)['1']);
} else {
- ZVAL_NEW_STR(expr_copy, STR_INIT("1", 1, 0));
+ ZVAL_NEW_STR(expr_copy, zend_string_init("1", 1, 0));
}
break;
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
int len;
- len = snprintf(buf, sizeof(buf), "Resource id #%ld", Z_RES_HANDLE_P(expr));
- ZVAL_NEW_STR(expr_copy, STR_INIT(buf, len, 0));
+ len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT, Z_RES_HANDLE_P(expr));
+ ZVAL_NEW_STR(expr_copy, zend_string_init(buf, len, 0));
}
break;
case IS_ARRAY:
zend_error(E_NOTICE, "Array to string conversion");
// TODO: use interned string ???
- ZVAL_NEW_STR(expr_copy, STR_INIT("Array", sizeof("Array") - 1, 0));
+ ZVAL_NEW_STR(expr_copy, zend_string_init("Array", sizeof("Array") - 1, 0));
break;
case IS_OBJECT:
if (Z_OBJ_HANDLER_P(expr, cast_object)) {
@@ -278,7 +278,7 @@ again:
case IS_REFERENCE:
expr = Z_REFVAL_P(expr);
if (Z_TYPE_P(expr) == IS_STRING) {
- ZVAL_STR(expr_copy, STR_COPY(Z_STR_P(expr)));
+ ZVAL_STR(expr_copy, zend_string_copy(Z_STR_P(expr)));
return 1;
}
goto again;
@@ -301,13 +301,13 @@ ZEND_API int zend_print_zval(zval *expr, int indent TSRMLS_DC) /* {{{ */
ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC) /* {{{ */
{
zend_string *str = zval_get_string(expr);
- int len = str->len;
+ size_t len = str->len;
if (len != 0) {
write_func(str->val, len);
}
- STR_RELEASE(str);
+ zend_string_release(str);
return len;
}
/* }}} */
@@ -343,7 +343,7 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) /* {{{ */
zend_printf("%s Object (", "Unknown Class");
}
if (class_name) {
- STR_RELEASE(class_name);
+ zend_string_release(class_name);
}
if (Z_OBJ_HANDLER_P(expr, get_properties)) {
properties = Z_OBJPROP_P(expr);
@@ -406,7 +406,7 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int
}
ZEND_PUTS_EX(" Object\n");
if (class_name) {
- STR_RELEASE(class_name);
+ zend_string_release(class_name);
}
if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) {
break;
@@ -443,7 +443,7 @@ static FILE *zend_fopen_wrapper(const char *filename, char **opened_path TSRMLS_
#ifdef ZTS
static zend_bool asp_tags_default = 0;
static zend_bool short_tags_default = 1;
-static zend_uint compiler_options_default = ZEND_COMPILE_DEFAULT;
+static uint32_t compiler_options_default = ZEND_COMPILE_DEFAULT;
#else
# define asp_tags_default 0
# define short_tags_default 1
@@ -503,15 +503,13 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS
zend_set_default_compile_time_values(TSRMLS_C);
- CG(interactive) = 0;
-
compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable));
zend_hash_init_ex(compiler_globals->auto_globals, 8, NULL, NULL, 1, 0);
zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, NULL /* empty element */);
compiler_globals->last_static_member = zend_hash_num_elements(compiler_globals->class_table);
if (compiler_globals->last_static_member) {
- compiler_globals->static_members_table = calloc(compiler_globals->last_static_member, sizeof(zval**));
+ compiler_globals->static_members_table = calloc(compiler_globals->last_static_member, sizeof(zval*));
} else {
compiler_globals->static_members_table = NULL;
}
@@ -739,7 +737,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
zend_interned_strings_init(TSRMLS_C);
zend_startup_builtin_functions(TSRMLS_C);
zend_register_standard_constants(TSRMLS_C);
- zend_register_auto_global(STR_INIT("GLOBALS", sizeof("GLOBALS") - 1, 1), 1, php_auto_globals_create_globals TSRMLS_CC);
+ zend_register_auto_global(zend_string_init("GLOBALS", sizeof("GLOBALS") - 1, 1), 1, php_auto_globals_create_globals TSRMLS_CC);
#ifndef ZTS
zend_init_rsrc_plist(TSRMLS_C);
@@ -814,10 +812,35 @@ void zend_shutdown(TSRMLS_D) /* {{{ */
zend_shutdown_timeout_thread();
#endif
zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
+ if (EG(active))
+ {
+ /*
+ * The order of destruction is important here.
+ * See bugs #65463 and 66036.
+ */
+ zend_function *func;
+ zend_class_entry *ce;
+
+ ZEND_HASH_REVERSE_FOREACH_PTR(GLOBAL_FUNCTION_TABLE, func) {
+ if (func->type == ZEND_USER_FUNCTION) {
+ zend_cleanup_op_array_data((zend_op_array *) func);
+ }
+ } ZEND_HASH_FOREACH_END();
+ ZEND_HASH_REVERSE_FOREACH_PTR(GLOBAL_CLASS_TABLE, ce) {
+ if (ce->type == ZEND_USER_CLASS) {
+ zend_cleanup_user_class_data(ce TSRMLS_CC);
+ } else {
+ break;
+ }
+ } ZEND_HASH_FOREACH_END();
+ zend_cleanup_internal_classes(TSRMLS_C);
+ zend_hash_reverse_apply(GLOBAL_FUNCTION_TABLE, (apply_func_t) clean_non_persistent_function_full TSRMLS_CC);
+ zend_hash_reverse_apply(GLOBAL_CLASS_TABLE, (apply_func_t) clean_non_persistent_class_full TSRMLS_CC);
+ }
zend_destroy_modules();
- virtual_cwd_deactivate(TSRMLS_C);
- virtual_cwd_shutdown();
+ virtual_cwd_deactivate(TSRMLS_C);
+ virtual_cwd_shutdown();
zend_hash_destroy(GLOBAL_FUNCTION_TABLE);
zend_hash_destroy(GLOBAL_CLASS_TABLE);
@@ -972,7 +995,7 @@ ZEND_API void zend_deactivate(TSRMLS_D) /* {{{ */
/* }}} */
BEGIN_EXTERN_C()
-ZEND_API void zend_message_dispatcher(long message, const void *data TSRMLS_DC) /* {{{ */
+ZEND_API void zend_message_dispatcher(zend_long message, const void *data TSRMLS_DC) /* {{{ */
{
if (zend_message_dispatcher_p) {
zend_message_dispatcher_p(message, data TSRMLS_CC);
@@ -981,12 +1004,12 @@ ZEND_API void zend_message_dispatcher(long message, const void *data TSRMLS_DC)
/* }}} */
END_EXTERN_C()
-ZEND_API int zend_get_configuration_directive(const char *name, uint name_length, zval *contents) /* {{{ */
+ZEND_API zval *zend_get_configuration_directive(zend_string *name) /* {{{ */
{
if (zend_get_configuration_directive_p) {
- return zend_get_configuration_directive_p(name, name_length, contents);
+ return zend_get_configuration_directive_p(name);
} else {
- return FAILURE;
+ return NULL;
}
}
/* }}} */
@@ -1008,11 +1031,17 @@ ZEND_API int zend_get_configuration_directive(const char *name, uint name_length
} \
} while (0)
+#ifndef ZEND_WIN32
ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
+#else
+static void zend_error_va_list(int type, const char *format, va_list args)
+#endif
{
char *str;
int len;
+#ifndef ZEND_WIN32
va_list args;
+#endif
va_list usr_copy;
zval params[5];
zval retval;
@@ -1021,13 +1050,8 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
zval orig_user_error_handler;
zend_bool in_compilation;
zend_class_entry *saved_class_entry;
- zend_stack bp_stack;
- zend_stack function_call_stack;
- zend_stack switch_cond_stack;
- zend_stack foreach_copy_stack;
- zend_stack object_stack;
- zend_stack declare_stack;
- zend_stack list_stack;
+ zend_stack loop_var_stack;
+ zend_stack delayed_oplines_stack;
zend_stack context_stack;
zend_array *symbol_table;
TSRMLS_FETCH();
@@ -1035,7 +1059,7 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
/* Report about uncaught exception in case of fatal errors */
if (EG(exception)) {
zend_execute_data *ex;
- zend_op *opline;
+ const zend_op *opline;
switch (type) {
case E_CORE_ERROR:
@@ -1120,7 +1144,9 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
}
#endif /* HAVE_DTRACE */
+#ifndef ZEND_WIN32
va_start(args, format);
+#endif
/* if we don't have a user defined error handler */
if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF
@@ -1152,7 +1178,7 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
#endif
va_copy(usr_copy, args);
len = zend_vspprintf(&str, 0, format, usr_copy);
- ZVAL_NEW_STR(&params[1], STR_INIT(str, len, 0));
+ ZVAL_NEW_STR(&params[1], zend_string_init(str, len, 0));
efree(str);
#ifdef va_copy
va_end(usr_copy);
@@ -1190,13 +1216,8 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
if (in_compilation) {
saved_class_entry = CG(active_class_entry);
CG(active_class_entry) = NULL;
- SAVE_STACK(bp_stack);
- SAVE_STACK(function_call_stack);
- SAVE_STACK(switch_cond_stack);
- SAVE_STACK(foreach_copy_stack);
- SAVE_STACK(object_stack);
- SAVE_STACK(declare_stack);
- SAVE_STACK(list_stack);
+ SAVE_STACK(loop_var_stack);
+ SAVE_STACK(delayed_oplines_stack);
SAVE_STACK(context_stack);
CG(in_compilation) = 0;
}
@@ -1216,13 +1237,8 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
if (in_compilation) {
CG(active_class_entry) = saved_class_entry;
- RESTORE_STACK(bp_stack);
- RESTORE_STACK(function_call_stack);
- RESTORE_STACK(switch_cond_stack);
- RESTORE_STACK(foreach_copy_stack);
- RESTORE_STACK(object_stack);
- RESTORE_STACK(declare_stack);
- RESTORE_STACK(list_stack);
+ RESTORE_STACK(loop_var_stack);
+ RESTORE_STACK(delayed_oplines_stack);
RESTORE_STACK(context_stack);
CG(in_compilation) = 1;
}
@@ -1241,7 +1257,9 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
break;
}
+#ifndef ZEND_WIN32
va_end(args);
+#endif
if (type == E_PARSE) {
/* eval() errors do not affect exit_status */
@@ -1252,13 +1270,30 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
EG(current_execute_data)->opline->extended_value == ZEND_EVAL)) {
EG(exit_status) = 255;
}
- zend_init_compiler_data_structures(TSRMLS_C);
}
}
/* }}} */
#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__)
void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((alias("zend_error"),noreturn));
+#elif defined(ZEND_WIN32)
+ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
+{
+ va_list va;
+
+ va_start(va, format);
+ zend_error_va_list(type, format, va);
+ va_end(va);
+}
+
+ZEND_API ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...)
+{
+ va_list va;
+
+ va_start(va, format);
+ zend_error_va_list(type, format, va);
+ va_end(va);
+}
#endif
ZEND_API void zend_output_debug_string(zend_bool trigger_break, const char *format, ...) /* {{{ */
@@ -1293,7 +1328,6 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval *retval, int file_cou
int i;
zend_file_handle *file_handle;
zend_op_array *op_array;
- long orig_interactive = CG(interactive);
va_start(files, file_count);
for (i = 0; i < file_count; i++) {
@@ -1301,14 +1335,6 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval *retval, int file_cou
if (!file_handle) {
continue;
}
-
- if (orig_interactive) {
- if (file_handle->filename[0] != '-' || file_handle->filename[1]) {
- CG(interactive) = 0;
- } else {
- CG(interactive) = 1;
- }
- }
op_array = zend_compile_file(file_handle, type TSRMLS_CC);
if (file_handle->opened_path) {
@@ -1344,15 +1370,13 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval *retval, int file_cou
}
}
destroy_op_array(op_array TSRMLS_CC);
- efree(op_array);
+ efree_size(op_array, sizeof(zend_op_array));
} else if (type==ZEND_REQUIRE) {
va_end(files);
- CG(interactive) = orig_interactive;
return FAILURE;
}
}
va_end(files);
- CG(interactive) = orig_interactive;
return SUCCESS;
}
@@ -1390,7 +1414,7 @@ void free_estring(char **str_p) /* {{{ */
void free_string_zval(zval *zv) /* {{{ */
{
zend_string *str = Z_PTR_P(zv);
- STR_RELEASE(str);
+ zend_string_release(str);
}
/* }}} */
diff --git a/Zend/zend.h b/Zend/zend.h
index 0718edba12..635dc9dcff 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -159,13 +159,17 @@ char *alloca ();
# define ZEND_ATTRIBUTE_ALLOC_SIZE2(X,Y)
#endif
-#if ZEND_GCC_VERSION >= 2007
+/* Format string checks are disabled by default, because we use custom format modifiers (like %p),
+ * which cause a large amount of false positives. You can enable format checks by adding
+ * -DZEND_CHECK_FORMAT_STRINGS to CFLAGS. */
+
+#if ZEND_GCC_VERSION >= 2007 && defined(ZEND_CHECK_FORMAT_STRINGS)
# define ZEND_ATTRIBUTE_FORMAT(type, idx, first) __attribute__ ((format(type, idx, first)))
#else
# define ZEND_ATTRIBUTE_FORMAT(type, idx, first)
#endif
-#if ZEND_GCC_VERSION >= 3001 && !defined(__INTEL_COMPILER)
+#if ZEND_GCC_VERSION >= 3001 && !defined(__INTEL_COMPILER) && defined(ZEND_CHECK_FORMAT_STRINGS)
# define ZEND_ATTRIBUTE_PTR_FORMAT(type, idx, first) __attribute__ ((format(type, idx, first)))
#else
# define ZEND_ATTRIBUTE_PTR_FORMAT(type, idx, first)
@@ -273,14 +277,14 @@ char *alloca ();
#define LONG_MIN (- LONG_MAX - 1)
#endif
-#if SIZEOF_LONG == 4
+#if SIZEOF_ZEND_LONG == 4
#define MAX_LENGTH_OF_LONG 11
static const char long_min_digits[] = "2147483648";
-#elif SIZEOF_LONG == 8
+#elif SIZEOF_ZEND_LONG == 8
#define MAX_LENGTH_OF_LONG 20
static const char long_min_digits[] = "9223372036854775808";
#else
-#error "Unknown SIZEOF_LONG"
+#error "Unknown SIZEOF_ZEND_LONG"
#endif
#define MAX_LENGTH_OF_DOUBLE 32
@@ -293,7 +297,7 @@ typedef enum {
#include "zend_hash.h"
#include "zend_llist.h"
-#define INTERNAL_FUNCTION_PARAMETERS zend_uint param_count, zval *return_value TSRMLS_DC
+#define INTERNAL_FUNCTION_PARAMETERS uint32_t param_count, zval *return_value TSRMLS_DC
#define INTERNAL_FUNCTION_PARAM_PASSTHRU param_count, return_value TSRMLS_CC
#define USED_RET() \
@@ -303,13 +307,17 @@ typedef enum {
!(EG(current_execute_data)->prev_execute_data->opline->result_type & EXT_TYPE_UNUSED))
#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__)
+# define ZEND_NORETURN __attribute__((noreturn))
void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((noreturn));
+#elif defined(ZEND_WIN32)
+# define ZEND_NORETURN __declspec(noreturn)
+ZEND_API ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...);
#else
+# define ZEND_NORETURN
# define zend_error_noreturn zend_error
#endif
#include "zend_object_handlers.h"
-#include "zend_ast.h"
/* overloaded elements data types */
#define OE_IS_ARRAY (1<<0)
@@ -388,7 +396,7 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore
# else /* ! (CRAY || __arm) */
# define XtOffset(p_type, field) \
- ((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))
+ ((zend_long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))
# endif /* !CRAY */
@@ -401,23 +409,24 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore
#endif
#include "zend_string.h"
+#include "zend_ast.h"
-static zend_always_inline zend_uint zval_refcount_p(zval* pz) {
+static zend_always_inline uint32_t zval_refcount_p(zval* pz) {
ZEND_ASSERT(Z_REFCOUNTED_P(pz) || Z_IMMUTABLE_P(pz));
return GC_REFCOUNT(Z_COUNTED_P(pz));
}
-static zend_always_inline zend_uint zval_set_refcount_p(zval* pz, zend_uint rc) {
+static zend_always_inline uint32_t zval_set_refcount_p(zval* pz, uint32_t rc) {
ZEND_ASSERT(Z_REFCOUNTED_P(pz));
return GC_REFCOUNT(Z_COUNTED_P(pz)) = rc;
}
-static zend_always_inline zend_uint zval_addref_p(zval* pz) {
+static zend_always_inline uint32_t zval_addref_p(zval* pz) {
ZEND_ASSERT(Z_REFCOUNTED_P(pz));
return ++GC_REFCOUNT(Z_COUNTED_P(pz));
}
-static zend_always_inline zend_uint zval_delref_p(zval* pz) {
+static zend_always_inline uint32_t zval_delref_p(zval* pz) {
ZEND_ASSERT(Z_REFCOUNTED_P(pz));
return --GC_REFCOUNT(Z_COUNTED_P(pz));
}
@@ -463,7 +472,7 @@ struct _zend_trait_alias {
/**
* modifiers to be set on trait method
*/
- zend_uint modifiers;
+ uint32_t modifiers;
};
typedef struct _zend_trait_alias zend_trait_alias;
@@ -472,16 +481,16 @@ struct _zend_class_entry {
zend_string *name;
struct _zend_class_entry *parent;
int refcount;
- zend_uint ce_flags;
+ uint32_t ce_flags;
- HashTable function_table;
- HashTable properties_info;
+ int default_properties_count;
+ int default_static_members_count;
zval *default_properties_table;
zval *default_static_members_table;
zval *static_members_table;
+ HashTable function_table;
+ HashTable properties_info;
HashTable constants_table;
- int default_properties_count;
- int default_static_members_count;
union _zend_function *constructor;
union _zend_function *destructor;
@@ -506,22 +515,22 @@ struct _zend_class_entry {
union _zend_function *(*get_static_method)(zend_class_entry *ce, zend_string* method TSRMLS_DC);
/* serializer callbacks */
- int (*serialize)(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);
- int (*unserialize)(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
+ int (*serialize)(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data TSRMLS_DC);
+ int (*unserialize)(zval *object, zend_class_entry *ce, const unsigned char *buf, size_t buf_len, zend_unserialize_data *data TSRMLS_DC);
+ uint32_t num_interfaces;
+ uint32_t num_traits;
zend_class_entry **interfaces;
- zend_uint num_interfaces;
zend_class_entry **traits;
- zend_uint num_traits;
zend_trait_alias **trait_aliases;
zend_trait_precedence **trait_precedences;
union {
struct {
zend_string *filename;
- zend_uint line_start;
- zend_uint line_end;
+ uint32_t line_start;
+ uint32_t line_end;
zend_string *doc_comment;
} user;
struct {
@@ -534,17 +543,17 @@ struct _zend_class_entry {
#include "zend_stream.h"
typedef struct _zend_utility_functions {
void (*error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
- int (*printf_function)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
- int (*write_function)(const char *str, uint str_length);
+ size_t (*printf_function)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
+ size_t (*write_function)(const char *str, size_t str_length);
FILE *(*fopen_function)(const char *filename, char **opened_path TSRMLS_DC);
- void (*message_handler)(long message, const void *data TSRMLS_DC);
+ void (*message_handler)(zend_long message, const void *data TSRMLS_DC);
void (*block_interruptions)(void);
void (*unblock_interruptions)(void);
- int (*get_configuration_directive)(const char *name, uint name_length, zval *contents);
+ zval *(*get_configuration_directive)(zend_string *name);
void (*ticks_function)(int ticks TSRMLS_DC);
void (*on_timeout)(int seconds TSRMLS_DC);
int (*stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
- int (*vspprintf_function)(char **pbuf, size_t max_len, const char *format, va_list ap);
+ size_t (*vspprintf_function)(char **pbuf, size_t max_len, const char *format, va_list ap);
zend_string *(*vstrpprintf_function)(size_t max_len, const char *format, va_list ap);
char *(*getenv_function)(char *name, size_t name_len TSRMLS_DC);
char *(*resolve_path_function)(const char *filename, int filename_len TSRMLS_DC);
@@ -646,7 +655,7 @@ END_EXTERN_C()
#define ZEND_PUTC(c) zend_write(&(c), 1)
BEGIN_EXTERN_C()
-extern ZEND_API int (*zend_printf)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
+extern ZEND_API size_t (*zend_printf)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
extern ZEND_API zend_write_func_t zend_write;
extern ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path TSRMLS_DC);
extern ZEND_API void (*zend_block_interruptions)(void);
@@ -655,7 +664,7 @@ extern ZEND_API void (*zend_ticks_function)(int ticks TSRMLS_DC);
extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
extern ZEND_API void (*zend_on_timeout)(int seconds TSRMLS_DC);
extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
-extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
+extern size_t (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
extern zend_string *(*zend_vstrpprintf)(size_t max_len, const char *format, va_list ap);
extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
extern ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
@@ -685,9 +694,9 @@ END_EXTERN_C()
#endif
BEGIN_EXTERN_C()
-ZEND_API void zend_message_dispatcher(long message, const void *data TSRMLS_DC);
+ZEND_API void zend_message_dispatcher(zend_long message, const void *data TSRMLS_DC);
-ZEND_API int zend_get_configuration_directive(const char *name, uint name_length, zval *contents);
+ZEND_API zval *zend_get_configuration_directive(zend_string *name);
END_EXTERN_C()
/* Messages for applications of Zend */
@@ -744,7 +753,7 @@ END_EXTERN_C()
ZEND_ASSERT(Z_ISREF_P(_z)); \
ref = Z_REF_P(_z); \
ZVAL_COPY_VALUE(_z, &ref->val); \
- efree(ref); \
+ efree_size(ref, sizeof(zend_reference)); \
} while (0)
#define SEPARATE_STRING(zv) do { \
@@ -818,9 +827,6 @@ END_EXTERN_C()
} \
} while (0)
-#define READY_TO_DESTROY(zv) \
- (Z_REFCOUNTED_P(zv) && Z_REFCOUNT_P(zv) == 1)
-
#define ZEND_MAX_RESERVED_RESOURCES 4
#include "zend_gc.h"
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 9881740c06..5675c05d54 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -221,7 +221,7 @@ ZEND_API zend_string *zend_get_object_classname(const zend_object *object TSRMLS
}
/* }}} */
-static int parse_arg_object_to_string(zval *arg, char **p, int *pl, int type TSRMLS_DC) /* {{{ */
+static int parse_arg_object_to_string(zval *arg, char **p, size_t *pl, int type TSRMLS_DC) /* {{{ */
{
if (Z_OBJ_HANDLER_P(arg, cast_object)) {
zval obj;
@@ -413,7 +413,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
case 'l':
case 'L':
{
- long *p = va_arg(*va, long *);
+ zend_long *p = va_arg(*va, zend_long *);
if (check_null) {
zend_bool *p = va_arg(*va, zend_bool *);
@@ -430,11 +430,11 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
return "long";
} else if (type == IS_DOUBLE) {
if (c == 'L') {
- if (d > LONG_MAX) {
- *p = LONG_MAX;
+ if (d > ZEND_LONG_MAX) {
+ *p = ZEND_LONG_MAX;
break;
- } else if (d < LONG_MIN) {
- *p = LONG_MIN;
+ } else if (d < ZEND_LONG_MIN) {
+ *p = ZEND_LONG_MIN;
break;
}
}
@@ -446,11 +446,11 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
case IS_DOUBLE:
if (c == 'L') {
- if (Z_DVAL_P(arg) > LONG_MAX) {
- *p = LONG_MAX;
+ if (Z_DVAL_P(arg) > ZEND_LONG_MAX) {
+ *p = ZEND_LONG_MAX;
break;
- } else if (Z_DVAL_P(arg) < LONG_MIN) {
- *p = LONG_MIN;
+ } else if (Z_DVAL_P(arg) < ZEND_LONG_MIN) {
+ *p = ZEND_LONG_MIN;
break;
}
}
@@ -483,7 +483,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
switch (Z_TYPE_P(arg)) {
case IS_STRING:
{
- long l;
+ zend_long l;
int type;
if ((type = is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), &l, p, -1)) == 0) {
@@ -516,7 +516,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
case 's':
{
char **p = va_arg(*va, char **);
- int *pl = va_arg(*va, int *);
+ size_t *pl = va_arg(*va, size_t *);
switch (Z_TYPE_P(arg)) {
case IS_NULL:
if (check_null) {
@@ -871,6 +871,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
case 'f': case 'A':
case 'H': case 'p':
case 'S': case 'P':
+ case 'L':
max_num_args++;
break;
@@ -1143,7 +1144,7 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties TSRMLS_DC)
if (key) {
zval member;
- ZVAL_STR(&member, STR_COPY(key));
+ ZVAL_STR(&member, zend_string_copy(key));
obj_ht->write_property(obj, &member, value, NULL TSRMLS_CC);
zval_ptr_dtor(&member);
}
@@ -1267,13 +1268,12 @@ ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properti
{
object->properties = properties;
if (object->ce->default_properties_count) {
- zval *prop, tmp;
+ zval *prop;
zend_string *key;
zend_property_info *property_info;
ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
- ZVAL_STR(&tmp, key);
- property_info = zend_get_property_info(object->ce, &tmp, 1 TSRMLS_CC);
+ property_info = zend_get_property_info(object->ce, key, 1 TSRMLS_CC);
if (property_info &&
(property_info->flags & ZEND_ACC_STATIC) == 0 &&
property_info->offset >= 0) {
@@ -1292,8 +1292,7 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties
zend_property_info *property_info;
ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
- ZVAL_STR(&tmp, key);
- property_info = zend_get_property_info(object->ce, &tmp, 1 TSRMLS_CC);
+ property_info = zend_get_property_info(object->ce, key, 1 TSRMLS_CC);
if (property_info &&
(property_info->flags & ZEND_ACC_STATIC) == 0 &&
property_info->offset >= 0) {
@@ -1302,7 +1301,7 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties
zval_add_ref(&object->properties_table[property_info->offset]);
if (object->properties) {
ZVAL_INDIRECT(&tmp, &object->properties_table[property_info->offset]);
- prop = zend_hash_update(object->properties, key, &tmp);
+ zend_hash_update(object->properties, key, &tmp);
}
} else {
if (!object->properties) {
@@ -1363,7 +1362,7 @@ ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)
}
/* }}} */
-ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n) /* {{{ */
+ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, zend_long n) /* {{{ */
{
zval *ret, tmp;
@@ -1433,7 +1432,7 @@ ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char
}
/* }}} */
-ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length) /* {{{ */
+ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, size_t length) /* {{{ */
{
zval *ret, tmp;
@@ -1452,7 +1451,7 @@ ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *v
}
/* }}} */
-ZEND_API int add_index_long(zval *arg, ulong index, long n) /* {{{ */
+ZEND_API int add_index_long(zval *arg, zend_ulong index, zend_long n) /* {{{ */
{
zval tmp;
@@ -1461,7 +1460,7 @@ ZEND_API int add_index_long(zval *arg, ulong index, long n) /* {{{ */
}
/* }}} */
-ZEND_API int add_index_null(zval *arg, ulong index) /* {{{ */
+ZEND_API int add_index_null(zval *arg, zend_ulong index) /* {{{ */
{
zval tmp;
@@ -1470,7 +1469,7 @@ ZEND_API int add_index_null(zval *arg, ulong index) /* {{{ */
}
/* }}} */
-ZEND_API int add_index_bool(zval *arg, ulong index, int b) /* {{{ */
+ZEND_API int add_index_bool(zval *arg, zend_ulong index, int b) /* {{{ */
{
zval tmp;
@@ -1479,7 +1478,7 @@ ZEND_API int add_index_bool(zval *arg, ulong index, int b) /* {{{ */
}
/* }}} */
-ZEND_API int add_index_resource(zval *arg, ulong index, zend_resource *r) /* {{{ */
+ZEND_API int add_index_resource(zval *arg, zend_ulong index, zend_resource *r) /* {{{ */
{
zval tmp;
@@ -1488,7 +1487,7 @@ ZEND_API int add_index_resource(zval *arg, ulong index, zend_resource *r) /* {{{
}
/* }}} */
-ZEND_API int add_index_double(zval *arg, ulong index, double d) /* {{{ */
+ZEND_API int add_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
{
zval tmp;
@@ -1497,7 +1496,7 @@ ZEND_API int add_index_double(zval *arg, ulong index, double d) /* {{{ */
}
/* }}} */
-ZEND_API int add_index_str(zval *arg, ulong index, zend_string *str) /* {{{ */
+ZEND_API int add_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
{
zval tmp;
@@ -1506,7 +1505,7 @@ ZEND_API int add_index_str(zval *arg, ulong index, zend_string *str) /* {{{ */
}
/* }}} */
-ZEND_API int add_index_string(zval *arg, ulong index, const char *str) /* {{{ */
+ZEND_API int add_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
{
zval tmp;
@@ -1515,7 +1514,7 @@ ZEND_API int add_index_string(zval *arg, ulong index, const char *str) /* {{{ */
}
/* }}} */
-ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint length) /* {{{ */
+ZEND_API int add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
{
zval tmp;
@@ -1524,13 +1523,13 @@ ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint len
}
/* }}} */
-ZEND_API int add_index_zval(zval *arg, ulong index, zval *value) /* {{{ */
+ZEND_API int add_index_zval(zval *arg, zend_ulong index, zval *value) /* {{{ */
{
return zend_hash_index_update(Z_ARRVAL_P(arg), index, value) ? SUCCESS : FAILURE;
}
/* }}} */
-ZEND_API int add_next_index_long(zval *arg, long n) /* {{{ */
+ZEND_API int add_next_index_long(zval *arg, zend_long n) /* {{{ */
{
zval tmp;
@@ -1593,7 +1592,7 @@ ZEND_API int add_next_index_string(zval *arg, const char *str) /* {{{ */
}
/* }}} */
-ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length) /* {{{ */
+ZEND_API int add_next_index_stringl(zval *arg, const char *str, size_t length) /* {{{ */
{
zval tmp;
@@ -1618,7 +1617,7 @@ ZEND_API zval *add_get_assoc_string_ex(zval *arg, const char *key, uint key_len,
}
/* }}} */
-ZEND_API zval *add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length) /* {{{ */
+ZEND_API zval *add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, size_t length) /* {{{ */
{
zval tmp, *ret;
@@ -1628,7 +1627,7 @@ ZEND_API zval *add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len
}
/* }}} */
-ZEND_API zval *add_get_index_long(zval *arg, ulong index, long l) /* {{{ */
+ZEND_API zval *add_get_index_long(zval *arg, zend_ulong index, zend_long l) /* {{{ */
{
zval tmp;
@@ -1637,7 +1636,7 @@ ZEND_API zval *add_get_index_long(zval *arg, ulong index, long l) /* {{{ */
}
/* }}} */
-ZEND_API zval *add_get_index_double(zval *arg, ulong index, double d) /* {{{ */
+ZEND_API zval *add_get_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
{
zval tmp;
@@ -1646,7 +1645,7 @@ ZEND_API zval *add_get_index_double(zval *arg, ulong index, double d) /* {{{ */
}
/* }}} */
-ZEND_API zval *add_get_index_str(zval *arg, ulong index, zend_string *str) /* {{{ */
+ZEND_API zval *add_get_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
{
zval tmp;
@@ -1655,7 +1654,7 @@ ZEND_API zval *add_get_index_str(zval *arg, ulong index, zend_string *str) /* {{
}
/* }}} */
-ZEND_API zval *add_get_index_string(zval *arg, ulong index, const char *str) /* {{{ */
+ZEND_API zval *add_get_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
{
zval tmp;
@@ -1664,7 +1663,7 @@ ZEND_API zval *add_get_index_string(zval *arg, ulong index, const char *str) /*
}
/* }}} */
-ZEND_API zval *add_get_index_stringl(zval *arg, ulong index, const char *str, uint length) /* {{{ */
+ZEND_API zval *add_get_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
{
zval tmp;
@@ -1685,7 +1684,7 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value TSRMLS_DC)
result = zend_symtable_update(ht, STR_EMPTY_ALLOC(), value);
break;
case IS_RESOURCE:
- zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
+ zend_error(E_STRICT, "Resource ID#" ZEND_LONG_FMT " used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
break;
case IS_FALSE:
@@ -1716,7 +1715,7 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value TSRMLS_DC)
}
/* }}} */
-ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
+ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, zend_long n TSRMLS_DC) /* {{{ */
{
zval tmp;
zval z_key;
@@ -1730,7 +1729,7 @@ ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long
}
/* }}} */
-ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC) /* {{{ */
+ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, zend_long b TSRMLS_DC) /* {{{ */
{
zval tmp;
zval z_key;
@@ -1814,7 +1813,7 @@ ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, co
}
/* }}} */
-ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length TSRMLS_DC) /* {{{ */
+ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, size_t length TSRMLS_DC) /* {{{ */
{
zval tmp;
zval z_key;
@@ -1858,17 +1857,17 @@ ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{
zend_module_entry *req_mod;
name_len = strlen(dep->name);
- lcname = STR_ALLOC(name_len, 0);
+ lcname = zend_string_alloc(name_len, 0);
zend_str_tolower_copy(lcname->val, dep->name, name_len);
if ((req_mod = zend_hash_find_ptr(&module_registry, lcname)) == NULL || !req_mod->module_started) {
- STR_FREE(lcname);
+ zend_string_free(lcname);
/* TODO: Check version relationship */
zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, dep->name);
module->module_started = 0;
return FAILURE;
}
- STR_FREE(lcname);
+ zend_string_free(lcname);
}
++dep;
}
@@ -2047,31 +2046,31 @@ ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TS
while (dep->name) {
if (dep->type == MODULE_DEP_CONFLICTS) {
name_len = strlen(dep->name);
- lcname = STR_ALLOC(name_len, 0);
+ lcname = zend_string_alloc(name_len, 0);
zend_str_tolower_copy(lcname->val, dep->name, name_len);
if (zend_hash_exists(&module_registry, lcname)) {
- STR_FREE(lcname);
+ zend_string_free(lcname);
/* TODO: Check version relationship */
zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
return NULL;
}
- STR_FREE(lcname);
+ zend_string_free(lcname);
}
++dep;
}
}
name_len = strlen(module->name);
- lcname = STR_ALLOC(name_len, 1);
+ lcname = zend_string_alloc(name_len, 1);
zend_str_tolower_copy(lcname->val, module->name, name_len);
if ((module_ptr = zend_hash_add_mem(&module_registry, lcname, module, sizeof(zend_module_entry))) == NULL) {
zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
- STR_RELEASE(lcname);
+ zend_string_release(lcname);
return NULL;
}
- STR_RELEASE(lcname);
+ zend_string_release(lcname);
module = module_ptr;
EG(current_module) = module;
@@ -2199,7 +2198,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
while (ptr->fname) {
fname_len = strlen(ptr->fname);
internal_function->handler = ptr->handler;
- internal_function->function_name = zend_new_interned_string(STR_INIT(ptr->fname, fname_len, 1) TSRMLS_CC);
+ internal_function->function_name = zend_new_interned_string(zend_string_init(ptr->fname, fname_len, 1) TSRMLS_CC);
internal_function->scope = scope;
internal_function->prototype = NULL;
if (ptr->flags) {
@@ -2265,7 +2264,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
return FAILURE;
}
}
- lowercase_name = STR_ALLOC(fname_len, 1);
+ lowercase_name = zend_string_alloc(fname_len, 1);
zend_str_tolower_copy(lowercase_name->val, ptr->fname, fname_len);
lowercase_name = zend_new_interned_string(lowercase_name TSRMLS_CC);
reg_function = malloc(sizeof(zend_internal_function));
@@ -2273,13 +2272,13 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
if (zend_hash_add_ptr(target_function_table, lowercase_name, reg_function) == NULL) {
unload=1;
free(reg_function);
- STR_RELEASE(lowercase_name);
+ zend_string_release(lowercase_name);
break;
}
/* If types of arguments have to be checked */
if (reg_function->common.arg_info && reg_function->common.num_args) {
- int i;
+ uint32_t i;
for (i = 0; i < reg_function->common.num_args; i++) {
if (reg_function->common.arg_info[i].class_name ||
reg_function->common.arg_info[i].type_hint) {
@@ -2296,30 +2295,30 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
*/
if ((fname_len == class_name_len) && !ctor && !memcmp(lowercase_name->val, lc_class_name, class_name_len+1)) {
ctor = reg_function;
- } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name->val, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME) - 1)) {
+ } else if (zend_string_equals_literal(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME)) {
ctor = reg_function;
- } else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name->val, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1)) {
+ } else if (zend_string_equals_literal(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME)) {
dtor = reg_function;
if (internal_function->num_args) {
zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name->val, ptr->fname);
}
- } else if ((fname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !memcmp(lowercase_name->val, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME) - 1)) {
+ } else if (zend_string_equals_literal(lowercase_name, ZEND_CLONE_FUNC_NAME)) {
clone = reg_function;
- } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name->val, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - 1)) {
+ } else if (zend_string_equals_literal(lowercase_name, ZEND_CALL_FUNC_NAME)) {
__call = reg_function;
- } else if ((fname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && !memcmp(lowercase_name->val, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1)) {
+ } else if (zend_string_equals_literal(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME)) {
__callstatic = reg_function;
- } else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name->val, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME) - 1)) {
+ } else if (zend_string_equals_literal(lowercase_name, ZEND_TOSTRING_FUNC_NAME)) {
__tostring = reg_function;
- } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name->val, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME) - 1)) {
+ } else if (zend_string_equals_literal(lowercase_name, ZEND_GET_FUNC_NAME)) {
__get = reg_function;
- } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name->val, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME) - 1)) {
+ } else if (zend_string_equals_literal(lowercase_name, ZEND_SET_FUNC_NAME)) {
__set = reg_function;
- } else if ((fname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && !memcmp(lowercase_name->val, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME) - 1)) {
+ } else if (zend_string_equals_literal(lowercase_name, ZEND_UNSET_FUNC_NAME)) {
__unset = reg_function;
- } else if ((fname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && !memcmp(lowercase_name->val, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME) - 1)) {
+ } else if (zend_string_equals_literal(lowercase_name, ZEND_ISSET_FUNC_NAME)) {
__isset = reg_function;
- } else if ((fname_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && !memcmp(lowercase_name->val, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME) - 1)) {
+ } else if (zend_string_equals_literal(lowercase_name, ZEND_DEBUGINFO_FUNC_NAME)) {
__debugInfo = reg_function;
} else {
reg_function = NULL;
@@ -2330,7 +2329,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
ptr++;
count++;
- STR_RELEASE(lowercase_name);
+ zend_string_release(lowercase_name);
}
if (unload) { /* before unloading, display all remaining bad function in the module */
if (scope) {
@@ -2338,12 +2337,12 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
while (ptr->fname) {
fname_len = strlen(ptr->fname);
- lowercase_name = STR_ALLOC(fname_len, 0);
+ lowercase_name = zend_string_alloc(fname_len, 0);
zend_str_tolower_copy(lowercase_name->val, ptr->fname, fname_len);
if (zend_hash_exists(target_function_table, lowercase_name)) {
zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name->val : "", scope ? "::" : "", ptr->fname);
}
- STR_FREE(lowercase_name);
+ zend_string_free(lowercase_name);
ptr++;
}
zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
@@ -2454,10 +2453,10 @@ ZEND_API void zend_unregister_functions(const zend_function_entry *functions, in
break;
}
fname_len = strlen(ptr->fname);
- lowercase_name = STR_ALLOC(fname_len, 0);
+ lowercase_name = zend_string_alloc(fname_len, 0);
zend_str_tolower_copy(lowercase_name->val, ptr->fname, fname_len);
zend_hash_del(target_function_table, lowercase_name);
- STR_FREE(lowercase_name);
+ zend_string_free(lowercase_name);
ptr++;
i++;
}
@@ -2656,10 +2655,10 @@ int zend_next_free_module(void) /* {{{ */
}
/* }}} */
-static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */
+static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags TSRMLS_DC) /* {{{ */
{
zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
- zend_string *lowercase_name = STR_ALLOC(orig_class_entry->name->len, 1);
+ zend_string *lowercase_name = zend_string_alloc(orig_class_entry->name->len, 1);
*class_entry = *orig_class_entry;
class_entry->type = ZEND_INTERNAL_CLASS;
@@ -2674,7 +2673,7 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class
zend_str_tolower_copy(lowercase_name->val, orig_class_entry->name->val, class_entry->name->len);
lowercase_name = zend_new_interned_string(lowercase_name TSRMLS_CC);
zend_hash_update_ptr(CG(class_table), lowercase_name, class_entry);
- STR_RELEASE(lowercase_name);
+ zend_string_release(lowercase_name);
return class_entry;
}
/* }}} */
@@ -2731,14 +2730,14 @@ ZEND_API int zend_register_class_alias_ex(const char *name, int name_len, zend_c
zend_string *lcname;
if (name[0] == '\\') {
- lcname = STR_ALLOC(name_len-1, 1);
+ lcname = zend_string_alloc(name_len-1, 1);
zend_str_tolower_copy(lcname->val, name+1, name_len-1);
} else {
- lcname = STR_ALLOC(name_len, 1);
+ lcname = zend_string_alloc(name_len, 1);
zend_str_tolower_copy(lcname->val, name, name_len);
}
ce = zend_hash_add_ptr(CG(class_table), lcname, ce);
- STR_RELEASE(lcname);
+ zend_string_release(lcname);
if (ce) {
ce->refcount++;
return SUCCESS;
@@ -2824,7 +2823,7 @@ ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_
zend_class_entry *disabled_class;
zend_string *key;
- key = STR_ALLOC(class_name_length, 0);
+ key = zend_string_alloc(class_name_length, 0);
zend_str_tolower_copy(key->val, class_name, class_name_length);
disabled_class = zend_hash_find_ptr(CG(class_table), key);
if (!disabled_class) {
@@ -2846,11 +2845,10 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
ALLOCA_FLAG(use_heap);
STR_ALLOCA_ALLOC(lcname, name_len, use_heap);
- zend_str_tolower_copy(lcname->val, name->val, name_len + 1);
+ zend_str_tolower_copy(lcname->val, name->val, name_len);
*strict_class = 0;
- if (name_len == sizeof("self") - 1 &&
- !memcmp(lcname->val, "self", sizeof("self") - 1)) {
+ if (zend_string_equals_literal(lcname, "self")) {
if (!EG(scope)) {
if (error) *error = estrdup("cannot access self:: when no class scope is active");
} else {
@@ -2861,8 +2859,7 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
}
ret = 1;
}
- } else if (name_len == sizeof("parent") - 1 &&
- !memcmp(lcname->val, "parent", sizeof("parent") - 1)) {
+ } else if (zend_string_equals_literal(lcname, "parent")) {
if (!EG(scope)) {
if (error) *error = estrdup("cannot access parent:: when no class scope is active");
} else if (!EG(scope)->parent) {
@@ -2876,8 +2873,7 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
*strict_class = 1;
ret = 1;
}
- } else if (name_len == sizeof("static") - 1 &&
- !memcmp(lcname->val, "static", sizeof("static") - 1)) {
+ } else if (zend_string_equals_literal(lcname, "static")) {
if (!EG(current_execute_data) || !EG(current_execute_data)->called_scope) {
if (error) *error = estrdup("cannot access static:: when no class scope is active");
} else {
@@ -2956,7 +2952,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
if (lmname == Z_STR_P(callable)) {
STR_ALLOCA_INIT(lmname, Z_STRVAL_P(callable), Z_STRLEN_P(callable), use_heap);
} else {
- STR_FORGET_HASH_VAL(lmname);
+ zend_string_forget_hash_val(lmname);
}
zend_str_tolower(lmname->val, lmname->len);
if ((fcc->function_handler = zend_hash_find_ptr(EG(function_table), lmname)) != NULL) {
@@ -2990,13 +2986,13 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
EG(scope) = ce_org;
}
- cname = STR_INIT(Z_STRVAL_P(callable), clen, 0);
+ cname = zend_string_init(Z_STRVAL_P(callable), clen, 0);
if (!zend_is_callable_check_class(cname, fcc, &strict_class, error TSRMLS_CC)) {
- STR_RELEASE(cname);
+ zend_string_release(cname);
EG(scope) = last_scope;
return 0;
}
- STR_RELEASE(cname);
+ zend_string_release(cname);
EG(scope) = last_scope;
ftable = &fcc->calling_scope->function_table;
@@ -3004,12 +3000,12 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
if (error) zend_spprintf(error, 0, "class '%s' is not a subclass of '%s'", ce_org->name->val, fcc->calling_scope->name->val);
return 0;
}
- mname = STR_INIT(Z_STRVAL_P(callable) + clen + 2, mlen, 0);
+ mname = zend_string_init(Z_STRVAL_P(callable) + clen + 2, mlen, 0);
} else if (ce_org) {
/* Try to fetch find static method of given class. */
mlen = Z_STRLEN_P(callable);
mname = Z_STR_P(callable);
- STR_ADDREF(mname);
+ zend_string_addref(mname);
ftable = &ce_org->function_table;
fcc->calling_scope = ce_org;
} else {
@@ -3020,12 +3016,11 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
return 0;
}
- lmname = STR_ALLOC(mlen, 0);
+ lmname = zend_string_alloc(mlen, 0);
zend_str_tolower_copy(lmname->val, mname->val, mlen);
if (strict_class &&
fcc->calling_scope &&
- mlen == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1 &&
- !memcmp(lmname->val, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME) - 1)) {
+ zend_string_equals_literal(lmname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
fcc->function_handler = fcc->calling_scope->constructor;
if (fcc->function_handler) {
retval = 1;
@@ -3074,7 +3069,7 @@ get_function_via_handler:
fcc->function_handler->internal_function.scope = ce_org;
fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
fcc->function_handler->internal_function.function_name = mname;
- STR_ADDREF(mname);
+ zend_string_addref(mname);
call_via_handler = 1;
retval = 1;
} else if (fcc->object->handlers->get_method) {
@@ -3085,7 +3080,7 @@ get_function_via_handler:
!instanceof_function(ce_org, fcc->function_handler->common.scope TSRMLS_CC))) {
if ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) {
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
- STR_RELEASE(fcc->function_handler->common.function_name);
+ zend_string_release(fcc->function_handler->common.function_name);
}
efree(fcc->function_handler);
}
@@ -3188,8 +3183,8 @@ get_function_via_handler:
if (error) zend_spprintf(error, 0, "function '%s' does not exist", mname->val);
}
}
- STR_FREE(lmname);
- STR_RELEASE(mname);
+ zend_string_free(lmname);
+ zend_string_release(mname);
if (fcc->object) {
fcc->called_scope = zend_get_class_entry(fcc->object TSRMLS_CC);
@@ -3237,7 +3232,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint
if (callable_name) {
char *ptr;
- *callable_name = STR_ALLOC(fcc->calling_scope->name->len + Z_STRLEN_P(callable) + sizeof("::") - 1, 0);
+ *callable_name = zend_string_alloc(fcc->calling_scope->name->len + Z_STRLEN_P(callable) + sizeof("::") - 1, 0);
ptr = (*callable_name)->val;
memcpy(ptr, fcc->calling_scope->name->val, fcc->calling_scope->name->len);
ptr += fcc->calling_scope->name->len;
@@ -3246,7 +3241,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint
memcpy(ptr, Z_STRVAL_P(callable), Z_STRLEN_P(callable) + 1);
}
} else if (callable_name) {
- *callable_name = STR_COPY(Z_STR_P(callable));
+ *callable_name = zend_string_copy(Z_STR_P(callable));
}
if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
fcc->called_scope = fcc->calling_scope;
@@ -3261,7 +3256,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
- STR_RELEASE(fcc->function_handler->common.function_name);
+ zend_string_release(fcc->function_handler->common.function_name);
}
efree(fcc->function_handler);
}
@@ -3294,7 +3289,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint
char *ptr;
- *callable_name = STR_ALLOC(Z_STRLEN_P(obj) + Z_STRLEN_P(method) + sizeof("::") - 1, 0);
+ *callable_name = zend_string_alloc(Z_STRLEN_P(obj) + Z_STRLEN_P(method) + sizeof("::") - 1, 0);
ptr = (*callable_name)->val;
memcpy(ptr, Z_STRVAL_P(obj), Z_STRLEN_P(obj));
ptr += Z_STRLEN_P(obj);
@@ -3324,7 +3319,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint
if (callable_name) {
char *ptr;
- *callable_name = STR_ALLOC(fcc->calling_scope->name->len + Z_STRLEN_P(method) + sizeof("::") - 1, 0);
+ *callable_name = zend_string_alloc(fcc->calling_scope->name->len + Z_STRLEN_P(method) + sizeof("::") - 1, 0);
ptr = (*callable_name)->val;
memcpy(ptr, fcc->calling_scope->name->val, fcc->calling_scope->name->len);
ptr += fcc->calling_scope->name->len;
@@ -3349,7 +3344,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
- STR_RELEASE(fcc->function_handler->common.function_name);
+ zend_string_release(fcc->function_handler->common.function_name);
}
efree(fcc->function_handler);
}
@@ -3368,7 +3363,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint
if (error) zend_spprintf(error, 0, "array must have exactly two members");
}
if (callable_name) {
- *callable_name = STR_INIT("Array", sizeof("Array")-1, 0);
+ *callable_name = zend_string_init("Array", sizeof("Array")-1, 0);
}
}
return 0;
@@ -3379,7 +3374,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint
if (callable_name) {
zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */
- *callable_name = STR_ALLOC(ce->name->len + sizeof("::__invoke") - 1, 0);
+ *callable_name = zend_string_alloc(ce->name->len + sizeof("::__invoke") - 1, 0);
memcpy((*callable_name)->val, ce->name->val, ce->name->len);
memcpy((*callable_name)->val + ce->name->len, "::__invoke", sizeof("::__invoke"));
}
@@ -3411,8 +3406,8 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_nam
if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
zval_dtor(callable);
array_init(callable);
- add_next_index_str(callable, STR_COPY(fcc.calling_scope->name));
- add_next_index_str(callable, STR_COPY(fcc.function_handler->common.function_name));
+ add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name));
+ add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
}
if (fcc.function_handler &&
((fcc.function_handler->type == ZEND_INTERNAL_FUNCTION &&
@@ -3420,7 +3415,7 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_nam
fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) {
- STR_RELEASE(fcc.function_handler->common.function_name);
+ zend_string_release(fcc.function_handler->common.function_name);
}
efree(fcc.function_handler);
}
@@ -3453,7 +3448,7 @@ ZEND_API int zend_fcall_info_init(zval *callable, uint check_flags, zend_fcall_i
ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */
{
if (fci->params) {
- int i;
+ uint32_t i;
for (i = 0; i < fci->param_count; i++) {
zval_ptr_dtor(&fci->params[i]);
@@ -3484,9 +3479,10 @@ ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count
}
/* }}} */
-ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* {{{ */
+ZEND_API int zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args TSRMLS_DC) /* {{{ */
{
zval *arg, *params;
+ uint32_t n = 1;
zend_fcall_info_args_clear(fci, !args);
@@ -3502,14 +3498,28 @@ ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /*
fci->params = params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), arg) {
- ZVAL_COPY(params, arg);
+ if (func && !Z_ISREF_P(arg) && ARG_SHOULD_BE_SENT_BY_REF(func, n)) {
+ ZVAL_NEW_REF(params, arg);
+ if (Z_REFCOUNTED_P(arg)) {
+ Z_ADDREF_P(arg);
+ }
+ } else {
+ ZVAL_COPY(params, arg);
+ }
params++;
+ n++;
} ZEND_HASH_FOREACH_END();
return SUCCESS;
}
/* }}} */
+ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* {{{ */
+{
+ return zend_fcall_info_args_ex(fci, NULL, args TSRMLS_CC);
+}
+/* }}} */
+
ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval *argv) /* {{{ */
{
int i;
@@ -3599,10 +3609,10 @@ ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
int name_len = strlen(module_name);
zend_module_entry *module;
- lname = STR_ALLOC(name_len, 0);
+ lname = zend_string_alloc(name_len, 0);
zend_str_tolower_copy(lname->val, module_name, name_len);
module = zend_hash_find_ptr(&module_registry, lname);
- STR_FREE(lname);
+ zend_string_free(lname);
return module ? module->version : NULL;
}
/* }}} */
@@ -3670,7 +3680,7 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
}
break;
case ZEND_ACC_PUBLIC:
- property_info->name = STR_COPY(name);
+ property_info->name = zend_string_copy(name);
break;
}
@@ -3686,9 +3696,9 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */
{
- zend_string *key = STR_INIT(name, name_length, ce->type & ZEND_INTERNAL_CLASS);
+ zend_string *key = zend_string_init(name, name_length, ce->type & ZEND_INTERNAL_CLASS);
int ret = zend_declare_property_ex(ce, key, property, access_type, NULL TSRMLS_CC);
- STR_RELEASE(key);
+ zend_string_release(key);
return ret;
}
/* }}} */
@@ -3702,7 +3712,7 @@ ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name,
}
/* }}} */
-ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, zend_long value, int access_type TSRMLS_DC) /* {{{ */
{
zval property;
@@ -3711,7 +3721,7 @@ ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name,
}
/* }}} */
-ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, zend_long value, int access_type TSRMLS_DC) /* {{{ */
{
zval property;
@@ -3733,16 +3743,16 @@ ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name
{
zval property;
- ZVAL_NEW_STR(&property, STR_INIT(value, strlen(value), ce->type & ZEND_INTERNAL_CLASS));
+ ZVAL_NEW_STR(&property, zend_string_init(value, strlen(value), ce->type & ZEND_INTERNAL_CLASS));
return zend_declare_property(ce, name, name_length, &property, access_type TSRMLS_CC);
}
/* }}} */
-ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, int value_len, int access_type TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, size_t value_len, int access_type TSRMLS_DC) /* {{{ */
{
zval property;
- ZVAL_NEW_STR(&property, STR_INIT(value, value_len, ce->type & ZEND_INTERNAL_CLASS));
+ ZVAL_NEW_STR(&property, zend_string_init(value, value_len, ce->type & ZEND_INTERNAL_CLASS));
return zend_declare_property(ce, name, name_length, &property, access_type TSRMLS_CC);
}
/* }}} */
@@ -3766,7 +3776,7 @@ ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *
}
/* }}} */
-ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value TSRMLS_DC) /* {{{ */
{
zval constant;
@@ -3797,7 +3807,7 @@ ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const cha
{
zval constant;
- ZVAL_NEW_STR(&constant, STR_INIT(value, value_length, ce->type & ZEND_INTERNAL_CLASS));
+ ZVAL_NEW_STR(&constant, zend_string_init(value, value_length, ce->type & ZEND_INTERNAL_CLASS));
return zend_declare_class_constant(ce, name, name_length, &constant TSRMLS_CC);
}
/* }}} */
@@ -3836,7 +3846,7 @@ ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, c
}
/* }}} */
-ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
+ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_long value TSRMLS_DC) /* {{{ */
{
zval tmp;
@@ -3845,7 +3855,7 @@ ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, c
}
/* }}} */
-ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
+ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_long value TSRMLS_DC) /* {{{ */
{
zval tmp;
@@ -3882,7 +3892,7 @@ ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object,
}
/* }}} */
-ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
+ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, size_t value_len TSRMLS_DC) /* {{{ */
{
zval tmp;
@@ -3896,12 +3906,12 @@ ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *na
{
zval *property;
zend_class_entry *old_scope = EG(scope);
- zend_string *key = STR_INIT(name, name_length, 0);
+ zend_string *key = zend_string_init(name, name_length, 0);
EG(scope) = scope;
property = zend_std_get_static_property(scope, key, 0, NULL TSRMLS_CC);
EG(scope) = old_scope;
- STR_FREE(key);
+ zend_string_free(key);
if (!property) {
return FAILURE;
} else {
@@ -3938,7 +3948,7 @@ ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const cha
}
/* }}} */
-ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
+ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, zend_long value TSRMLS_DC) /* {{{ */
{
zval tmp;
@@ -3947,7 +3957,7 @@ ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const cha
}
/* }}} */
-ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
+ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, zend_long value TSRMLS_DC) /* {{{ */
{
zval tmp;
@@ -3975,7 +3985,7 @@ ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const c
}
/* }}} */
-ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
+ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, size_t value_len TSRMLS_DC) /* {{{ */
{
zval tmp;
@@ -4011,12 +4021,12 @@ ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *na
{
zval *property;
zend_class_entry *old_scope = EG(scope);
- zend_string *key = STR_INIT(name, name_length, 0);
+ zend_string *key = zend_string_init(name, name_length, 0);
EG(scope) = scope;
property = zend_std_get_static_property(scope, key, silent, NULL TSRMLS_CC);
EG(scope) = old_scope;
- STR_FREE(key);
+ zend_string_free(key);
return property;
}
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 0268374fc4..657d1d04de 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -36,8 +36,8 @@ typedef struct _zend_function_entry {
const char *fname;
void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
const struct _zend_arg_info *arg_info;
- zend_uint num_args;
- zend_uint flags;
+ uint32_t num_args;
+ uint32_t flags;
} zend_function_entry;
typedef struct _zend_fcall_info {
@@ -46,10 +46,10 @@ typedef struct _zend_fcall_info {
zval function_name;
zend_array *symbol_table;
zval *retval;
- zend_uint param_count;
zval *params;
zend_object *object;
zend_bool no_separation;
+ uint32_t param_count;
} zend_fcall_info;
typedef struct _zend_fcall_info_cache {
@@ -68,9 +68,9 @@ typedef struct _zend_fcall_info_cache {
#define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))
#define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_MN(classname##_##name))
-#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },
+#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },
-#define ZEND_RAW_FENTRY(zend_name, name, arg_info, flags) { zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },
+#define ZEND_RAW_FENTRY(zend_name, name, arg_info, flags) { zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },
#define ZEND_RAW_NAMED_FE(zend_name, name, arg_info) ZEND_RAW_FENTRY(#zend_name, name, arg_info, 0)
#define ZEND_NAMED_FE(zend_name, name, arg_info) ZEND_FENTRY(zend_name, name, arg_info, 0)
@@ -171,7 +171,7 @@ typedef struct _zend_fcall_info_cache {
#define INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
{ \
zend_string *cl_name; \
- cl_name = STR_INIT(class_name, class_name_len, 1); \
+ cl_name = zend_string_init(class_name, class_name_len, 1); \
class_container.name = zend_new_interned_string(cl_name TSRMLS_CC); \
INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
}
@@ -303,15 +303,15 @@ ZEND_API int zend_get_module_started(const char *module_name);
ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment TSRMLS_DC);
ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type TSRMLS_DC);
ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC);
-ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC);
-ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC);
+ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, zend_long value, int access_type TSRMLS_DC);
+ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, zend_long value, int access_type TSRMLS_DC);
ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, int name_length, double value, int access_type TSRMLS_DC);
ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, int name_length, const char *value, int access_type TSRMLS_DC);
-ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, int value_len, int access_type TSRMLS_DC);
+ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, size_t value_len, int access_type TSRMLS_DC);
ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC);
ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC);
-ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC);
+ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value TSRMLS_DC);
ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value TSRMLS_DC);
ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC);
ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length TSRMLS_DC);
@@ -320,20 +320,20 @@ ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC);
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC);
ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC);
-ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC);
-ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC);
+ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_long value TSRMLS_DC);
+ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_long value TSRMLS_DC);
ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC);
ZEND_API void zend_update_property_str(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_string *value TSRMLS_DC);
ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC);
-ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, int value_length TSRMLS_DC);
+ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, size_t value_length TSRMLS_DC);
ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC);
ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC);
-ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
-ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
+ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, zend_long value TSRMLS_DC);
+ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, zend_long value TSRMLS_DC);
ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC);
ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC);
-ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, int value_length TSRMLS_DC);
+ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, size_t value_length TSRMLS_DC);
ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_bool silent TSRMLS_DC);
@@ -374,14 +374,14 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties TSRMLS_DC);
/* no longer supported */
ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS));
-ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n);
+ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, zend_long n);
ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len);
ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b);
ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, zend_resource *r);
ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d);
ZEND_API int add_assoc_str_ex(zval *arg, const char *key, uint key_len, zend_string *str);
ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str);
-ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length);
+ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, size_t length);
ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value);
#define add_assoc_long(__arg, __key, __n) add_assoc_long_ex(__arg, __key, strlen(__key), __n)
@@ -400,48 +400,48 @@ ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *v
#define add_next_index_unset(__arg) add_next_index_null(__arg)
#define add_property_unset(__arg, __key) add_property_null(__arg, __key)
-ZEND_API int add_index_long(zval *arg, ulong idx, long n);
-ZEND_API int add_index_null(zval *arg, ulong idx);
-ZEND_API int add_index_bool(zval *arg, ulong idx, int b);
-ZEND_API int add_index_resource(zval *arg, ulong idx, zend_resource *r);
-ZEND_API int add_index_double(zval *arg, ulong idx, double d);
-ZEND_API int add_index_str(zval *arg, ulong idx, zend_string *str);
-ZEND_API int add_index_string(zval *arg, ulong idx, const char *str);
-ZEND_API int add_index_stringl(zval *arg, ulong idx, const char *str, uint length);
-ZEND_API int add_index_zval(zval *arg, ulong index, zval *value);
-
-ZEND_API int add_next_index_long(zval *arg, long n);
+ZEND_API int add_index_long(zval *arg, zend_ulong idx, zend_long n);
+ZEND_API int add_index_null(zval *arg, zend_ulong idx);
+ZEND_API int add_index_bool(zval *arg, zend_ulong idx, int b);
+ZEND_API int add_index_resource(zval *arg, zend_ulong idx, zend_resource *r);
+ZEND_API int add_index_double(zval *arg, zend_ulong idx, double d);
+ZEND_API int add_index_str(zval *arg, zend_ulong idx, zend_string *str);
+ZEND_API int add_index_string(zval *arg, zend_ulong idx, const char *str);
+ZEND_API int add_index_stringl(zval *arg, zend_ulong idx, const char *str, size_t length);
+ZEND_API int add_index_zval(zval *arg, zend_ulong index, zval *value);
+
+ZEND_API int add_next_index_long(zval *arg, zend_long n);
ZEND_API int add_next_index_null(zval *arg);
ZEND_API int add_next_index_bool(zval *arg, int b);
ZEND_API int add_next_index_resource(zval *arg, zend_resource *r);
ZEND_API int add_next_index_double(zval *arg, double d);
ZEND_API int add_next_index_str(zval *arg, zend_string *str);
ZEND_API int add_next_index_string(zval *arg, const char *str);
-ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length);
+ZEND_API int add_next_index_stringl(zval *arg, const char *str, size_t length);
ZEND_API int add_next_index_zval(zval *arg, zval *value);
ZEND_API zval *add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str);
-ZEND_API zval *add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length);
+ZEND_API zval *add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, size_t length);
#define add_get_assoc_string(__arg, __key, __str) add_get_assoc_string_ex(__arg, __key, strlen(__key), __str)
#define add_get_assoc_stringl(__arg, __key, __str, __length) add_get_assoc_stringl_ex(__arg, __key, strlen(__key), __str, __length)
-ZEND_API zval *add_get_index_long(zval *arg, ulong idx, long l);
-ZEND_API zval *add_get_index_double(zval *arg, ulong idx, double d);
-ZEND_API zval *add_get_index_str(zval *arg, ulong index, zend_string *str);
-ZEND_API zval *add_get_index_string(zval *arg, ulong idx, const char *str);
-ZEND_API zval *add_get_index_stringl(zval *arg, ulong idx, const char *str, uint length);
+ZEND_API zval *add_get_index_long(zval *arg, zend_ulong idx, zend_long l);
+ZEND_API zval *add_get_index_double(zval *arg, zend_ulong idx, double d);
+ZEND_API zval *add_get_index_str(zval *arg, zend_ulong index, zend_string *str);
+ZEND_API zval *add_get_index_string(zval *arg, zend_ulong idx, const char *str);
+ZEND_API zval *add_get_index_stringl(zval *arg, zend_ulong idx, const char *str, size_t length);
ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value TSRMLS_DC);
-ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long l TSRMLS_DC);
+ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, zend_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);
+ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, zend_long b TSRMLS_DC);
ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, zend_resource *r TSRMLS_DC);
ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, double d TSRMLS_DC);
ZEND_API int add_property_str_ex(zval *arg, const char *key, uint key_len, zend_string *str TSRMLS_DC);
ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, const char *str TSRMLS_DC);
-ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length TSRMLS_DC);
+ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, size_t length TSRMLS_DC);
ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC);
#define add_property_long(__arg, __key, __n) add_property_long_ex(__arg, __key, strlen(__key), __n TSRMLS_CC)
@@ -455,8 +455,8 @@ ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval
#define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key), __value TSRMLS_CC)
-ZEND_API int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, zend_uint param_count, zval params[] TSRMLS_DC);
-ZEND_API int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, zend_uint param_count, zval params[], int no_separation, zend_array *symbol_table TSRMLS_DC);
+ZEND_API int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[] TSRMLS_DC);
+ZEND_API int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation, zend_array *symbol_table TSRMLS_DC);
ZEND_API extern const zend_fcall_info empty_fcall_info;
ZEND_API extern const zend_fcall_info_cache empty_fcall_info_cache;
@@ -491,6 +491,7 @@ ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count
* refcount. If args is NULL and arguments are set then those are cleared.
*/
ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC);
+ZEND_API int zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args TSRMLS_DC);
/** Set arguments in the zend_fcall_info struct taking care of refcount.
* If argc is 0 the arguments which are set will be cleared, else pass
@@ -550,7 +551,7 @@ END_EXTERN_C()
#define CHECK_NULL_PATH(p, l) (strlen(p) != l)
#define ZVAL_STRINGL(z, s, l) do { \
- ZVAL_NEW_STR(z, STR_INIT(s, l, 0)); \
+ ZVAL_NEW_STR(z, zend_string_init(s, l, 0)); \
} while (0)
#define ZVAL_STRING(z, s) do { \
@@ -559,11 +560,11 @@ END_EXTERN_C()
} while (0)
#define ZVAL_EMPTY_STRING(z) do { \
- ZVAL_INT_STR(z, STR_EMPTY_ALLOC()); \
+ ZVAL_INTERNED_STR(z, STR_EMPTY_ALLOC()); \
} while (0)
#define ZVAL_PSTRINGL(z, s, l) do { \
- ZVAL_NEW_STR(z, STR_INIT(s, l, 1)); \
+ ZVAL_NEW_STR(z, zend_string_init(s, l, 1)); \
} while (0)
#define ZVAL_PSTRING(z, s) do { \
@@ -600,7 +601,7 @@ END_EXTERN_C()
#define RETVAL_LONG(l) ZVAL_LONG(return_value, l)
#define RETVAL_DOUBLE(d) ZVAL_DOUBLE(return_value, d)
#define RETVAL_STR(s) ZVAL_STR(return_value, s)
-#define RETVAL_INT_STR(s) ZVAL_INT_STR(return_value, s)
+#define RETVAL_LONG_STR(s) ZVAL_INTERNED_STR(return_value, s)
#define RETVAL_NEW_STR(s) ZVAL_NEW_STR(return_value, s)
#define RETVAL_STRING(s) ZVAL_STRING(return_value, s)
#define RETVAL_STRINGL(s, l) ZVAL_STRINGL(return_value, s, l)
@@ -616,7 +617,7 @@ END_EXTERN_C()
#define RETURN_LONG(l) { RETVAL_LONG(l); return; }
#define RETURN_DOUBLE(d) { RETVAL_DOUBLE(d); return; }
#define RETURN_STR(s) { RETVAL_STR(s); return; }
-#define RETURN_INT_STR(s) { RETVAL_INT_STR(s); return; }
+#define RETURN_LONG_STR(s) { RETVAL_LONG_STR(s); return; }
#define RETURN_NEW_STR(s) { RETVAL_NEW_STR(s); return; }
#define RETURN_STRING(s) { RETVAL_STRING(s); return; }
#define RETURN_STRINGL(s, l) { RETVAL_STRINGL(s, l); return; }
@@ -1072,7 +1073,7 @@ static zend_always_inline int _z_param_bool(zval *arg, zend_bool *dest, zend_boo
return 1;
}
-static zend_always_inline int _z_param_long(zval *arg, long *dest, zend_bool *is_null, int check_null, int strict)
+static zend_always_inline int _z_param_long(zval *arg, zend_long *dest, zend_bool *is_null, int check_null, int strict)
{
if (check_null) {
*is_null = 0;
@@ -1080,10 +1081,10 @@ static zend_always_inline int _z_param_long(zval *arg, long *dest, zend_bool *is
if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
*dest = Z_LVAL_P(arg);
} else if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
- if (strict && UNEXPECTED(Z_DVAL_P(arg) > LONG_MAX)) {
- *dest = LONG_MAX;
- } else if (strict && UNEXPECTED(Z_DVAL_P(arg) < LONG_MIN)) {
- *dest = LONG_MIN;
+ if (strict && UNEXPECTED(Z_DVAL_P(arg) > ZEND_LONG_MAX)) {
+ *dest = ZEND_LONG_MAX;
+ } else if (strict && UNEXPECTED(Z_DVAL_P(arg) < ZEND_LONG_MIN)) {
+ *dest = ZEND_LONG_MIN;
} else {
*dest = zend_dval_to_lval(Z_DVAL_P(arg));
}
@@ -1093,10 +1094,10 @@ static zend_always_inline int _z_param_long(zval *arg, long *dest, zend_bool *is
if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
if (EXPECTED(type != 0)) {
- if (strict && UNEXPECTED(d > LONG_MAX)) {
- *dest = LONG_MAX;
- } else if (strict && UNEXPECTED(d < LONG_MIN)) {
- *dest = LONG_MIN;
+ if (strict && UNEXPECTED(d > ZEND_LONG_MAX)) {
+ *dest = ZEND_LONG_MAX;
+ } else if (strict && UNEXPECTED(d < ZEND_LONG_MIN)) {
+ *dest = ZEND_LONG_MIN;
} else {
*dest = zend_dval_to_lval(d);
}
@@ -1127,7 +1128,7 @@ static zend_always_inline int _z_param_double(zval *arg, double *dest, zend_bool
} else if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
*dest = (double)Z_LVAL_P(arg);
} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
- long l;
+ zend_long l;
int type;
if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) {
@@ -1172,7 +1173,7 @@ static zend_always_inline int _z_param_str(zval *arg, zend_string **dest, int ch
return 1;
}
-static zend_always_inline int _z_param_string(zval *arg, char **dest, int *dest_len, int check_null TSRMLS_DC)
+static zend_always_inline int _z_param_string(zval *arg, char **dest, size_t *dest_len, int check_null TSRMLS_DC)
{
zend_string *str;
@@ -1192,14 +1193,14 @@ static zend_always_inline int _z_param_string(zval *arg, char **dest, int *dest_
static zend_always_inline int _z_param_path_str(zval *arg, zend_string **dest, int check_null TSRMLS_DC)
{
if (!_z_param_str(arg, dest, check_null TSRMLS_CC) ||
- (check_null && UNEXPECTED(!(*dest)->val)) ||
+ (check_null && UNEXPECTED(!(*dest)->val[0])) ||
UNEXPECTED(CHECK_NULL_PATH((*dest)->val, (*dest)->len))) {
return 0;
}
return 1;
}
-static zend_always_inline int _z_param_path(zval *arg, char **dest, int *dest_len, int check_null TSRMLS_DC)
+static zend_always_inline int _z_param_path(zval *arg, char **dest, size_t *dest_len, int check_null TSRMLS_DC)
{
zend_string *str;
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index bb3e66c989..8b6a105e98 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -20,6 +20,39 @@
/* $Id$ */
+/*
+ * zend_alloc is designed to be a modern CPU cache friendly memory manager
+ * for PHP. Most ideas are taken from jemalloc and tcmalloc implementations.
+ *
+ * All allocations are split into 3 categories:
+ *
+ * Huge - the size is greater than CHUNK size (~2M by default), allocation is
+ * performed using mmap(). The result is aligned on 2M boundary.
+ *
+ * Large - a number of 4096K pages inside a CHUNK. Large blocks
+ * are always alligned on page boundary.
+ *
+ * Small - less than 3/4 of page size. Small sizes are rounded up to nearest
+ * greater predefined small size (there are 30 predefined sizes:
+ * 8, 16, 24, 32, ... 3072). Small blocks are allocated from
+ * RUNs. Each RUN is allocated as a single or few following pages.
+ * Allocation inside RUNs implemented using linked list of free
+ * elements. The result is aligned to 8 bytes.
+ *
+ * zend_alloc allocates memory from OS by CHUNKs, these CHUNKs and huge memory
+ * blocks are always aligned to CHUNK boundary. So it's very easy to determine
+ * the CHUNK owning the certain pointer. Regular CHUNKs reserve a single
+ * page at start for special purpose. It contains bitset of free pages,
+ * few bitset for available runs of predefined small sizes, map of pages that
+ * keeps information about usage of each page in this CHUNK, etc.
+ *
+ * zend_alloc provides familiar emalloc/efree/erealloc API, but in addition it
+ * provides specialized and optimized routines to allocate blocks of predefined
+ * sizes (e.g. emalloc_2(), emallc_4(), ..., emalloc_large(), etc)
+ * The library uses C preprocessor tricks that substitute calls to emalloc()
+ * with more specialized routines when the requested size is known.
+ */
+
#include "zend.h"
#include "zend_alloc.h"
#include "zend_globals.h"
@@ -37,71 +70,9 @@
# include <process.h>
#endif
-#ifndef ZEND_MM_HEAP_PROTECTION
-# define ZEND_MM_HEAP_PROTECTION ZEND_DEBUG
-#endif
-
-#ifndef ZEND_MM_SAFE_UNLINKING
-# define ZEND_MM_SAFE_UNLINKING 1
-#endif
-
-#ifndef ZEND_MM_COOKIES
-# define ZEND_MM_COOKIES ZEND_DEBUG
-#endif
-
-#ifdef _WIN64
-# define PTR_FMT "0x%0.16I64x"
-/*
-#elif sizeof(long) == 8
-# define PTR_FMT "0x%0.16lx"
-*/
-#else
-# define PTR_FMT "0x%0.8lx"
-#endif
-
-#if ZEND_DEBUG
-void zend_debug_alloc_output(char *format, ...)
-{
- char output_buf[256];
- va_list args;
-
- va_start(args, format);
- vsprintf(output_buf, format, args);
- va_end(args);
-
-#ifdef ZEND_WIN32
- OutputDebugString(output_buf);
-#else
- fprintf(stderr, "%s", output_buf);
-#endif
-}
-#endif
-
-#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
-static void zend_mm_panic(const char *message) __attribute__ ((noreturn));
-#endif
-
-static void zend_mm_panic(const char *message)
-{
- fprintf(stderr, "%s\n", message);
-/* See http://support.microsoft.com/kb/190351 */
-#ifdef PHP_WIN32
- fflush(stderr);
-#endif
-#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
- kill(getpid(), SIGSEGV);
-#endif
- exit(1);
-}
-
-/*******************/
-/* Storage Manager */
-/*******************/
-
-#ifdef ZEND_WIN32
-# define HAVE_MEM_WIN32 /* use VirtualAlloc() to allocate memory */
-#endif
-#define HAVE_MEM_MALLOC /* use malloc() to allocate segments */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -111,7 +82,7 @@ static void zend_mm_panic(const char *message)
#include <fcntl.h>
#include <errno.h>
-#if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO)
+#ifndef _WIN32
# ifdef HAVE_MREMAP
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
@@ -132,2281 +103,1864 @@ static void zend_mm_panic(const char *message)
# ifndef MAP_FAILED
# define MAP_FAILED ((void*)-1)
# endif
+# ifndef MAP_POPULATE
+# define MAP_POPULATE 0
+#endif
#endif
-static zend_mm_storage* zend_mm_mem_dummy_init(void *params)
-{
- return malloc(sizeof(zend_mm_storage));
-}
-
-static void zend_mm_mem_dummy_dtor(zend_mm_storage *storage)
-{
- free(storage);
-}
-
-static void zend_mm_mem_dummy_compact(zend_mm_storage *storage)
-{
-}
-
-#if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO)
-
-static zend_mm_segment* zend_mm_mem_mmap_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size)
-{
- zend_mm_segment *ret;
-#ifdef HAVE_MREMAP
-#if defined(__NetBSD__)
- /* NetBSD 5 supports mremap but takes an extra newp argument */
- ret = (zend_mm_segment*)mremap(segment, segment->size, segment, size, MREMAP_MAYMOVE);
-#else
- ret = (zend_mm_segment*)mremap(segment, segment->size, size, MREMAP_MAYMOVE);
+#ifndef ZEND_MM_STAT
+# define ZEND_MM_STAT 1 /* track current and peak memory usage */
#endif
- if (ret == MAP_FAILED) {
+#ifndef ZEND_MM_LIMIT
+# define ZEND_MM_LIMIT 1 /* support for user-defined memory limit */
#endif
- ret = storage->handlers->_alloc(storage, size);
- if (ret) {
- memcpy(ret, segment, size > segment->size ? segment->size : size);
- storage->handlers->_free(storage, segment);
- }
-#ifdef HAVE_MREMAP
- }
+#ifndef ZEND_MM_CUSTOM
+# define ZEND_MM_CUSTOM 1 /* support for custom memory allocator */
+ /* USE_ZEND_ALLOC=0 may switch to system malloc() */
#endif
- return ret;
-}
-
-static void zend_mm_mem_mmap_free(zend_mm_storage *storage, zend_mm_segment* segment)
-{
- munmap((void*)segment, segment->size);
-}
-
+#ifndef ZEND_MM_ERROR
+# define ZEND_MM_ERROR 1 /* report system errors */
#endif
-#ifdef HAVE_MEM_MMAP_ANON
-
-static zend_mm_segment* zend_mm_mem_mmap_anon_alloc(zend_mm_storage *storage, size_t size)
-{
- zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
- if (ret == MAP_FAILED) {
- ret = NULL;
- }
- return ret;
-}
-
-# define ZEND_MM_MEM_MMAP_ANON_DSC {"mmap_anon", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_anon_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}
-
+#ifndef ZEND_MM_CHECK
+# define ZEND_MM_CHECK(condition, message) do { \
+ if (UNEXPECTED(!(condition))) { \
+ zend_mm_panic(message); \
+ } \
+ } while (0)
#endif
-#ifdef HAVE_MEM_MMAP_ZERO
+typedef uint32_t zend_mm_page_info; /* 4-byte integer */
+typedef zend_ulong zend_mm_bitset; /* 4-byte or 8-byte integer */
-static int zend_mm_dev_zero_fd = -1;
+#define ZEND_MM_ALIGNED_OFFSET(size, alignment) \
+ (((size_t)(size)) & ((alignment) - 1))
+#define ZEND_MM_ALIGNED_BASE(size, alignment) \
+ (((size_t)(size)) & ~((alignment) - 1))
+#define ZEND_MM_ALIGNED_SIZE_EX(size, alignment) \
+ (((size_t)(size) + ((alignment) - 1)) & ~((alignment) - 1))
+#define ZEND_MM_SIZE_TO_NUM(size, alignment) \
+ (((size_t)(size) + ((alignment) - 1)) / (alignment))
-static zend_mm_storage* zend_mm_mem_mmap_zero_init(void *params)
-{
- if (zend_mm_dev_zero_fd == -1) {
- zend_mm_dev_zero_fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
- }
- if (zend_mm_dev_zero_fd >= 0) {
- return malloc(sizeof(zend_mm_storage));
- } else {
- return NULL;
- }
-}
+#define ZEND_MM_BITSET_LEN (sizeof(zend_mm_bitset) * 8) /* 32 or 64 */
+#define ZEND_MM_PAGE_MAP_LEN (ZEND_MM_PAGES / ZEND_MM_BITSET_LEN) /* 16 or 8 */
-static void zend_mm_mem_mmap_zero_dtor(zend_mm_storage *storage)
-{
- close(zend_mm_dev_zero_fd);
- free(storage);
-}
+typedef zend_mm_bitset zend_mm_page_map[ZEND_MM_PAGE_MAP_LEN]; /* 64B */
-static zend_mm_segment* zend_mm_mem_mmap_zero_alloc(zend_mm_storage *storage, size_t size)
-{
- zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zend_mm_dev_zero_fd, 0);
- if (ret == MAP_FAILED) {
- ret = NULL;
- }
- return ret;
-}
-
-# define ZEND_MM_MEM_MMAP_ZERO_DSC {"mmap_zero", zend_mm_mem_mmap_zero_init, zend_mm_mem_mmap_zero_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_zero_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}
-
-#endif
-
-#ifdef HAVE_MEM_WIN32
-
-static zend_mm_storage* zend_mm_mem_win32_init(void *params)
-{
- HANDLE heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
- zend_mm_storage* storage;
+#define ZEND_MM_IS_FRUN 0x00000000
+#define ZEND_MM_IS_LRUN 0x40000000
+#define ZEND_MM_IS_SRUN 0x80000000
- if (heap == NULL) {
- return NULL;
- }
- storage = (zend_mm_storage*)malloc(sizeof(zend_mm_storage));
- if (storage == NULL) {
- HeapDestroy(heap);
- return NULL;
- }
- storage->data = (void*) heap;
- return storage;
-}
-
-static void zend_mm_mem_win32_dtor(zend_mm_storage *storage)
-{
- HeapDestroy((HANDLE)storage->data);
- free(storage);
-}
+#define ZEND_MM_LRUN_PAGES_MASK 0x000003ff
+#define ZEND_MM_LRUN_PAGES_OFFSET 0
-static void zend_mm_mem_win32_compact(zend_mm_storage *storage)
-{
- HeapDestroy((HANDLE)storage->data);
- storage->data = (void*)HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
-}
+#define ZEND_MM_SRUN_BIN_NUM_MASK 0x0000001f
+#define ZEND_MM_SRUN_BIN_NUM_OFFSET 0
-static zend_mm_segment* zend_mm_mem_win32_alloc(zend_mm_storage *storage, size_t size)
-{
- return (zend_mm_segment*) HeapAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, size);
-}
+#define ZEND_MM_LRUN_PAGES(info) (((info) & ZEND_MM_LRUN_PAGES_MASK) >> ZEND_MM_LRUN_PAGES_OFFSET)
+#define ZEND_MM_SRUN_BIN_NUM(info) (((info) & ZEND_MM_SRUN_BIN_NUM_MASK) >> ZEND_MM_SRUN_BIN_NUM_OFFSET)
-static void zend_mm_mem_win32_free(zend_mm_storage *storage, zend_mm_segment* segment)
-{
- HeapFree((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment);
-}
+#define ZEND_MM_FRUN() ZEND_MM_IS_FRUN
+#define ZEND_MM_LRUN(count) (ZEND_MM_IS_LRUN | ((count) << ZEND_MM_LRUN_PAGES_OFFSET))
+#define ZEND_MM_SRUN(bin_num) (ZEND_MM_IS_SRUN | ((bin_num) << ZEND_MM_SRUN_BIN_NUM_OFFSET))
-static zend_mm_segment* zend_mm_mem_win32_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size)
-{
- return (zend_mm_segment*) HeapReAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment, size);
-}
+#define ZEND_MM_BINS 30
-# define ZEND_MM_MEM_WIN32_DSC {"win32", zend_mm_mem_win32_init, zend_mm_mem_win32_dtor, zend_mm_mem_win32_compact, zend_mm_mem_win32_alloc, zend_mm_mem_win32_realloc, zend_mm_mem_win32_free}
+typedef struct _zend_mm_page zend_mm_page;
+typedef struct _zend_mm_bin zend_mm_bin;
+typedef struct _zend_mm_free_slot zend_mm_free_slot;
+typedef struct _zend_mm_chunk zend_mm_chunk;
+typedef struct _zend_mm_huge_list zend_mm_huge_list;
+#ifdef _WIN64
+# define PTR_FMT "0x%0.16I64x"
+#elif SIZEOF_LONG == 8
+# define PTR_FMT "0x%0.16lx"
+#else
+# define PTR_FMT "0x%0.8lx"
#endif
-#ifdef HAVE_MEM_MALLOC
-
-static zend_mm_segment* zend_mm_mem_malloc_alloc(zend_mm_storage *storage, size_t size)
-{
- return (zend_mm_segment*)malloc(size);
-}
-
-static zend_mm_segment* zend_mm_mem_malloc_realloc(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size)
-{
- return (zend_mm_segment*)realloc(ptr, size);
-}
-
-static void zend_mm_mem_malloc_free(zend_mm_storage *storage, zend_mm_segment *ptr)
-{
- free(ptr);
-}
-
-# define ZEND_MM_MEM_MALLOC_DSC {"malloc", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_malloc_alloc, zend_mm_mem_malloc_realloc, zend_mm_mem_malloc_free}
+/*
+ * Memory is retrived from OS by chunks of fixed size 2MB.
+ * Inside chunk it's managed by pages of fixed size 4096B.
+ * So each chunk consists from 512 pages.
+ * The first page of each chunk is reseved for chunk header.
+ * It contains service information about all pages.
+ *
+ * free_pages - current number of free pages in this chunk
+ *
+ * free_tail - number of continuous free pages at the end of chunk
+ *
+ * free_map - bitset (a bit for each page). The bit is set if the corresponding
+ * page is allocated. Allocator for "lage sizes" may easily find a
+ * free page (or a continuous number of pages) searching for zero
+ * bits.
+ *
+ * map - contains service information for each page. (32-bits for each
+ * page).
+ * usage:
+ * (2 bits)
+ * FRUN - free page,
+ * LRUN - first page of "large" allocation
+ * SRUN - first page of a bin used for "small" allocation
+ *
+ * lrun_pages:
+ * (10 bits) number of allocated pages
+ *
+ * srun_bin_num:
+ * (5 bits) bin number (e.g. 0 for sizes 0-2, 1 for 3-4,
+ * 2 for 5-8, 3 for 9-16 etc) see zend_alloc_sizes.h
+ */
+struct _zend_mm_heap {
+#if ZEND_MM_CUSTOM
+ int use_custom_heap;
#endif
-
-static const zend_mm_mem_handlers mem_handlers[] = {
-#ifdef HAVE_MEM_WIN32
- ZEND_MM_MEM_WIN32_DSC,
+#if ZEND_MM_STAT
+ size_t size; /* current memory usage */
+ size_t peak; /* peak memory usage */
#endif
-#ifdef HAVE_MEM_MALLOC
- ZEND_MM_MEM_MALLOC_DSC,
+ zend_mm_free_slot *free_slot[ZEND_MM_BINS]; /* free lists for small sizes */
+#if ZEND_MM_STAT || ZEND_MM_LIMIT
+ size_t real_size; /* current size of allocated pages */
#endif
-#ifdef HAVE_MEM_MMAP_ANON
- ZEND_MM_MEM_MMAP_ANON_DSC,
+#if ZEND_MM_STAT
+ size_t real_peak; /* peak size of allocated pages */
#endif
-#ifdef HAVE_MEM_MMAP_ZERO
- ZEND_MM_MEM_MMAP_ZERO_DSC,
+#if ZEND_MM_LIMIT
+ size_t limit; /* memory limit */
+ int overflow; /* memory overflow flag */
#endif
- {NULL, NULL, NULL, NULL, NULL, NULL}
-};
-
-# define ZEND_MM_STORAGE_DTOR() heap->storage->handlers->dtor(heap->storage)
-# define ZEND_MM_STORAGE_ALLOC(size) heap->storage->handlers->_alloc(heap->storage, size)
-# define ZEND_MM_STORAGE_REALLOC(ptr, size) heap->storage->handlers->_realloc(heap->storage, ptr, size)
-# define ZEND_MM_STORAGE_FREE(ptr) heap->storage->handlers->_free(heap->storage, ptr)
-
-/****************/
-/* Heap Manager */
-/****************/
-#define MEM_BLOCK_VALID 0x7312F8DC
-#define MEM_BLOCK_FREED 0x99954317
-#define MEM_BLOCK_CACHED 0xFB8277DC
-#define MEM_BLOCK_GUARD 0x2A8FCC84
-#define MEM_BLOCK_LEAK 0x6C5E8F2D
+ zend_mm_huge_list *huge_list; /* list of huge allocated blocks */
-/* mm block type */
-typedef struct _zend_mm_block_info {
-#if ZEND_MM_COOKIES
- size_t _cookie;
+ zend_mm_chunk *main_chunk;
+ zend_mm_chunk *cached_chunks; /* list of unused chunks */
+ int chunks_count; /* number of alocated chunks */
+ int peak_chunks_count; /* peak number of allocated chunks for current request */
+ int cached_chunks_count; /* number of cached chunks */
+ double avg_chunks_count; /* average number of chunks allocated per request */
+#if ZEND_MM_CUSTOM
+ void *(*_malloc)(size_t);
+ void (*_free)(void*);
+ void *(*_realloc)(void*, size_t);
#endif
- size_t _size;
- size_t _prev;
-} zend_mm_block_info;
+};
-#if ZEND_DEBUG
+struct _zend_mm_chunk {
+ zend_mm_heap *heap;
+ zend_mm_chunk *next;
+ zend_mm_chunk *prev;
+ int free_pages; /* number of free pages */
+ int free_tail; /* number of free pages at the end of chunk */
+ int num;
+ char reserve[64 - (sizeof(void*) * 3 + sizeof(int) * 3)];
+ zend_mm_heap heap_slot; /* used only in main chunk */
+ zend_mm_page_map free_map; /* 512 bits or 64 bytes */
+ zend_mm_page_info map[ZEND_MM_PAGES]; /* 2 KB = 512 * 4 */
+};
-typedef struct _zend_mm_debug_info {
- const char *filename;
- uint lineno;
- const char *orig_filename;
- uint orig_lineno;
- size_t size;
-#if ZEND_MM_HEAP_PROTECTION
- unsigned int start_magic;
-#endif
-} zend_mm_debug_info;
+struct _zend_mm_page {
+ char bytes[ZEND_MM_PAGE_SIZE];
+};
-#elif ZEND_MM_HEAP_PROTECTION
+/*
+ * bin - is one or few continuous pages (up to 8) used for alocation of
+ * a particular "small size".
+ */
+struct _zend_mm_bin {
+ char bytes[ZEND_MM_PAGE_SIZE * 8];
+};
+#if ZEND_DEBUG
typedef struct _zend_mm_debug_info {
- size_t size;
- unsigned int start_magic;
+ size_t size;
+ const char *filename;
+ const char *orig_filename;
+ uint lineno;
+ uint orig_lineno;
} zend_mm_debug_info;
-
-#endif
-
-typedef struct _zend_mm_block {
- zend_mm_block_info info;
-#if ZEND_DEBUG
- unsigned int magic;
-# ifdef ZTS
- THREAD_T thread_id;
-# endif
- zend_mm_debug_info debug;
-#elif ZEND_MM_HEAP_PROTECTION
- zend_mm_debug_info debug;
#endif
-} zend_mm_block;
-typedef struct _zend_mm_small_free_block {
- zend_mm_block_info info;
-#if ZEND_DEBUG
- unsigned int magic;
-# ifdef ZTS
- THREAD_T thread_id;
-# endif
-#endif
- struct _zend_mm_free_block *prev_free_block;
- struct _zend_mm_free_block *next_free_block;
-} zend_mm_small_free_block;
+struct _zend_mm_free_slot {
+ zend_mm_free_slot *next_free_slot;
+};
-typedef struct _zend_mm_free_block {
- zend_mm_block_info info;
+struct _zend_mm_huge_list {
+ void *ptr;
+ size_t size;
+ zend_mm_huge_list *next;
#if ZEND_DEBUG
- unsigned int magic;
-# ifdef ZTS
- THREAD_T thread_id;
-# endif
-#endif
- struct _zend_mm_free_block *prev_free_block;
- struct _zend_mm_free_block *next_free_block;
-
- struct _zend_mm_free_block **parent;
- struct _zend_mm_free_block *child[2];
-} zend_mm_free_block;
-
-#define ZEND_MM_NUM_BUCKETS (sizeof(size_t) << 3)
-
-#define ZEND_MM_CACHE 1
-#define ZEND_MM_CACHE_SIZE (ZEND_MM_NUM_BUCKETS * 4 * 1024)
-
-#ifndef ZEND_MM_CACHE_STAT
-# define ZEND_MM_CACHE_STAT 0
-#endif
-
-struct _zend_mm_heap {
- int use_zend_alloc;
- void *(*_malloc)(size_t);
- void (*_free)(void*);
- void *(*_realloc)(void*, size_t);
- size_t free_bitmap;
- size_t large_free_bitmap;
- size_t block_size;
- size_t compact_size;
- zend_mm_segment *segments_list;
- zend_mm_storage *storage;
- size_t real_size;
- size_t real_peak;
- size_t limit;
- size_t size;
- size_t peak;
- size_t reserve_size;
- void *reserve;
- int overflow;
- int internal;
-#if ZEND_MM_CACHE
- unsigned int cached;
- zend_mm_free_block *cache[ZEND_MM_NUM_BUCKETS];
-#endif
- zend_mm_free_block *free_buckets[ZEND_MM_NUM_BUCKETS*2];
- zend_mm_free_block *large_free_buckets[ZEND_MM_NUM_BUCKETS];
- zend_mm_free_block *rest_buckets[2];
- int rest_count;
-#if ZEND_MM_CACHE_STAT
- struct {
- int count;
- int max_count;
- int hit;
- int miss;
- } cache_stat[ZEND_MM_NUM_BUCKETS+1];
+ zend_mm_debug_info dbg;
#endif
};
-#define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \
- (zend_mm_free_block*) ((char*)&heap->free_buckets[index * 2] + \
- sizeof(zend_mm_free_block*) * 2 - \
- sizeof(zend_mm_small_free_block))
+#define ZEND_MM_PAGE_ADDR(chunk, page_num) \
+ ((void*)(((zend_mm_page*)(chunk)) + (page_num)))
-#define ZEND_MM_REST_BUCKET(heap) \
- (zend_mm_free_block*)((char*)&heap->rest_buckets[0] + \
- sizeof(zend_mm_free_block*) * 2 - \
- sizeof(zend_mm_small_free_block))
+#define _BIN_DATA_SIZE(num, size, elements, pages, x, y) size,
+static const unsigned int bin_data_size[] = {
+ ZEND_MM_BINS_INFO(_BIN_DATA_SIZE, x, y)
+};
-#define ZEND_MM_REST_BLOCK ((zend_mm_free_block**)(zend_uintptr_t)(1))
+#define _BIN_DATA_ELEMENTS(num, size, elements, pages, x, y) elements,
+static const int bin_elements[] = {
+ ZEND_MM_BINS_INFO(_BIN_DATA_ELEMENTS, x, y)
+};
-#define ZEND_MM_MAX_REST_BLOCKS 16
+#define _BIN_DATA_PAGES(num, size, elements, pages, x, y) pages,
+static const int bin_pages[] = {
+ ZEND_MM_BINS_INFO(_BIN_DATA_PAGES, x, y)
+};
-#if ZEND_MM_COOKIES
+#if ZEND_DEBUG
+void zend_debug_alloc_output(char *format, ...)
+{
+ char output_buf[256];
+ va_list args;
-static unsigned int _zend_mm_cookie = 0;
+ va_start(args, format);
+ vsprintf(output_buf, format, args);
+ va_end(args);
-# define ZEND_MM_COOKIE(block) \
- (((size_t)(block)) ^ _zend_mm_cookie)
-# define ZEND_MM_SET_COOKIE(block) \
- (block)->info._cookie = ZEND_MM_COOKIE(block)
-# define ZEND_MM_CHECK_COOKIE(block) \
- if (UNEXPECTED((block)->info._cookie != ZEND_MM_COOKIE(block))) { \
- zend_mm_panic("zend_mm_heap corrupted"); \
- }
+#ifdef ZEND_WIN32
+ OutputDebugString(output_buf);
#else
-# define ZEND_MM_SET_COOKIE(block)
-# define ZEND_MM_CHECK_COOKIE(block)
+ fprintf(stderr, "%s", output_buf);
#endif
-
-/* Default memory segment size */
-#define ZEND_MM_SEG_SIZE (256 * 1024)
-
-/* Reserved space for error reporting in case of memory overflow */
-#define ZEND_MM_RESERVE_SIZE (8*1024)
-
-#ifdef _WIN64
-# define ZEND_MM_LONG_CONST(x) (x##i64)
-#else
-# define ZEND_MM_LONG_CONST(x) (x##L)
+}
#endif
-#define ZEND_MM_TYPE_MASK ZEND_MM_LONG_CONST(0x3)
-
-#define ZEND_MM_FREE_BLOCK ZEND_MM_LONG_CONST(0x0)
-#define ZEND_MM_USED_BLOCK ZEND_MM_LONG_CONST(0x1)
-#define ZEND_MM_GUARD_BLOCK ZEND_MM_LONG_CONST(0x3)
-
-#define ZEND_MM_BLOCK(b, type, size) do { \
- size_t _size = (size); \
- (b)->info._size = (type) | _size; \
- ZEND_MM_BLOCK_AT(b, _size)->info._prev = (type) | _size; \
- ZEND_MM_SET_COOKIE(b); \
- } while (0);
-#define ZEND_MM_LAST_BLOCK(b) do { \
- (b)->info._size = ZEND_MM_GUARD_BLOCK | ZEND_MM_ALIGNED_HEADER_SIZE; \
- ZEND_MM_SET_MAGIC(b, MEM_BLOCK_GUARD); \
- } while (0);
-#define ZEND_MM_BLOCK_SIZE(b) ((b)->info._size & ~ZEND_MM_TYPE_MASK)
-#define ZEND_MM_IS_FREE_BLOCK(b) (!((b)->info._size & ZEND_MM_USED_BLOCK))
-#define ZEND_MM_IS_USED_BLOCK(b) ((b)->info._size & ZEND_MM_USED_BLOCK)
-#define ZEND_MM_IS_GUARD_BLOCK(b) (((b)->info._size & ZEND_MM_TYPE_MASK) == ZEND_MM_GUARD_BLOCK)
-
-#define ZEND_MM_NEXT_BLOCK(b) ZEND_MM_BLOCK_AT(b, ZEND_MM_BLOCK_SIZE(b))
-#define ZEND_MM_PREV_BLOCK(b) ZEND_MM_BLOCK_AT(b, -(ssize_t)((b)->info._prev & ~ZEND_MM_TYPE_MASK))
-
-#define ZEND_MM_PREV_BLOCK_IS_FREE(b) (!((b)->info._prev & ZEND_MM_USED_BLOCK))
-
-#define ZEND_MM_MARK_FIRST_BLOCK(b) ((b)->info._prev = ZEND_MM_GUARD_BLOCK)
-#define ZEND_MM_IS_FIRST_BLOCK(b) ((b)->info._prev == ZEND_MM_GUARD_BLOCK)
-
-/* optimized access */
-#define ZEND_MM_FREE_BLOCK_SIZE(b) (b)->info._size
-
-/* Aligned header size */
-#define ZEND_MM_ALIGNED_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block))
-#define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block))
-#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE)
-#define ZEND_MM_ALIGNED_MIN_HEADER_SIZE (ZEND_MM_MIN_ALLOC_BLOCK_SIZE>ZEND_MM_ALIGNED_FREE_HEADER_SIZE?ZEND_MM_MIN_ALLOC_BLOCK_SIZE:ZEND_MM_ALIGNED_FREE_HEADER_SIZE)
-#define ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment))
-
-#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE)):0)
-
-#define ZEND_MM_MAX_SMALL_SIZE ((ZEND_MM_NUM_BUCKETS<<ZEND_MM_ALIGNMENT_LOG2)+ZEND_MM_ALIGNED_MIN_HEADER_SIZE)
-
-#define ZEND_MM_TRUE_SIZE(size) ((size<ZEND_MM_MIN_SIZE)?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE):(ZEND_MM_ALIGNED_SIZE(size+ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE)))
-
-#define ZEND_MM_BUCKET_INDEX(true_size) ((true_size>>ZEND_MM_ALIGNMENT_LOG2)-(ZEND_MM_ALIGNED_MIN_HEADER_SIZE>>ZEND_MM_ALIGNMENT_LOG2))
-
-#define ZEND_MM_SMALL_SIZE(true_size) (true_size < ZEND_MM_MAX_SMALL_SIZE)
-
-/* Memory calculations */
-#define ZEND_MM_BLOCK_AT(blk, offset) ((zend_mm_block *) (((char *) (blk))+(offset)))
-#define ZEND_MM_DATA_OF(p) ((void *) (((char *) (p))+ZEND_MM_ALIGNED_HEADER_SIZE))
-#define ZEND_MM_HEADER_OF(blk) ZEND_MM_BLOCK_AT(blk, -(int)ZEND_MM_ALIGNED_HEADER_SIZE)
+static ZEND_NORETURN void zend_mm_panic(const char *message)
+{
+ fprintf(stderr, "%s\n", message);
+/* See http://support.microsoft.com/kb/190351 */
+#ifdef PHP_WIN32
+ fflush(stderr);
+#endif
+#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
+ kill(getpid(), SIGSEGV);
+#endif
+ exit(1);
+}
-/* Debug output */
+static ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
+ const char *format,
+ size_t limit,
#if ZEND_DEBUG
+ const char *filename,
+ uint lineno,
+#endif
+ size_t size)
+{
+ TSRMLS_FETCH();
-# ifdef ZTS
-# define ZEND_MM_SET_THREAD_ID(block) \
- ((zend_mm_block*)(block))->thread_id = tsrm_thread_id()
-# define ZEND_MM_BAD_THREAD_ID(block) ((block)->thread_id != tsrm_thread_id())
-# else
-# define ZEND_MM_SET_THREAD_ID(block)
-# define ZEND_MM_BAD_THREAD_ID(block) 0
-# endif
-
-# define ZEND_MM_VALID_PTR(block) \
- zend_mm_check_ptr(heap, block, 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)
+ heap->overflow = 1;
+ zend_try {
+ zend_error_noreturn(E_ERROR,
+ format,
+ limit,
+#if ZEND_DEBUG
+ filename,
+ lineno,
+#endif
+ size);
+ } zend_catch {
+ } zend_end_try();
+ heap->overflow = 0;
+ zend_bailout();
+ exit(1);
+}
-# define ZEND_MM_SET_MAGIC(block, val) do { \
- (block)->magic = (val); \
- } while (0)
+#ifdef _WIN32
+void
+stderr_last_error(char *msg)
+{
+ LPSTR buf = NULL;
+ DWORD err = GetLastError();
-# define ZEND_MM_CHECK_MAGIC(block, val) do { \
- if ((block)->magic != (val)) { \
- zend_mm_panic("zend_mm_heap corrupted"); \
- } \
- } while (0)
+ if (!FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&buf,
+ 0, NULL)) {
+ fprintf(stderr, "\n%s: [0x%08x]\n", msg, err);
+ }
+ else {
+ fprintf(stderr, "\n%s: [0x%08x] %s\n", msg, err, buf);
+ }
+}
+#endif
-# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) do { \
- ((zend_mm_block*)(block))->debug.filename = __zend_filename; \
- ((zend_mm_block*)(block))->debug.lineno = __zend_lineno; \
- ((zend_mm_block*)(block))->debug.orig_filename = __zend_orig_filename; \
- ((zend_mm_block*)(block))->debug.orig_lineno = __zend_orig_lineno; \
- ZEND_MM_SET_BLOCK_SIZE(block, __size); \
- if (set_valid) { \
- ZEND_MM_SET_MAGIC(block, MEM_BLOCK_VALID); \
- } \
- if (set_thread) { \
- ZEND_MM_SET_THREAD_ID(block); \
- } \
- } while (0)
+/*****************/
+/* OS Allocation */
+/*****************/
+static void *zend_mm_mmap_fixed(void *addr, size_t size)
+{
+#ifdef _WIN32
+ return VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#else
+ /* MAP_FIXED leads to discarding of the old mapping, so it can't be used. */
+ void *ptr = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON /*| MAP_POPULATE | MAP_HUGETLB*/, -1, 0);
-# define ZEND_MM_VALID_PTR(ptr) EXPECTED(ptr != NULL)
-
-# define ZEND_MM_SET_MAGIC(block, val)
-
-# define ZEND_MM_CHECK_MAGIC(block, val)
-
-# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) ZEND_MM_SET_BLOCK_SIZE(block, __size)
-
+ if (ptr == MAP_FAILED) {
+#if ZEND_MM_ERROR
+ fprintf(stderr, "\nmmap() failed: [%d] %s\n", errno, strerror(errno));
#endif
+ return NULL;
+ } else if (ptr != addr) {
+ if (munmap(ptr, size) != 0) {
+#if ZEND_MM_ERROR
+ fprintf(stderr, "\nmunmap() failed: [%d] %s\n", errno, strerror(errno));
+#endif
+ }
+ return NULL;
+ }
+ return ptr;
+#endif
+}
+static void *zend_mm_mmap(size_t size)
+{
+#ifdef _WIN32
+ void *ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
-#if ZEND_MM_HEAP_PROTECTION
-
-# define ZEND_MM_CHECK_PROTECTION(block) \
- do { \
- if ((block)->debug.start_magic != _mem_block_start_magic || \
- memcmp(ZEND_MM_END_MAGIC_PTR(block), &_mem_block_end_magic, END_MAGIC_SIZE) != 0) { \
- zend_mm_panic("zend_mm_heap corrupted"); \
- } \
- } while (0)
-
-# define ZEND_MM_END_MAGIC_PTR(block) \
- (((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block*)(block))->debug.size)
-
-# define END_MAGIC_SIZE sizeof(unsigned int)
-
-# define ZEND_MM_SET_BLOCK_SIZE(block, __size) do { \
- char *p; \
- ((zend_mm_block*)(block))->debug.size = (__size); \
- p = ZEND_MM_END_MAGIC_PTR(block); \
- ((zend_mm_block*)(block))->debug.start_magic = _mem_block_start_magic; \
- memcpy(p, &_mem_block_end_magic, END_MAGIC_SIZE); \
- } while (0)
-
-static unsigned int _mem_block_start_magic = 0;
-static unsigned int _mem_block_end_magic = 0;
-
+ if (ptr == NULL) {
+#if ZEND_MM_ERROR
+ stderr_last_error("VirtualAlloc() failed");
+#endif
+ return NULL;
+ }
+ return ptr;
#else
+ void *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON /*| MAP_POPULATE | MAP_HUGETLB*/, -1, 0);
-# if ZEND_DEBUG
-# define ZEND_MM_SET_BLOCK_SIZE(block, _size) \
- ((zend_mm_block*)(block))->debug.size = (_size)
-# else
-# define ZEND_MM_SET_BLOCK_SIZE(block, _size)
-# endif
-
-# define ZEND_MM_CHECK_PROTECTION(block)
-
-# define END_MAGIC_SIZE 0
-
+ if (ptr == MAP_FAILED) {
+#if ZEND_MM_ERROR
+ fprintf(stderr, "\nmmap() failed: [%d] %s\n", errno, strerror(errno));
#endif
-
-#if ZEND_MM_SAFE_UNLINKING
-# define ZEND_MM_CHECK_BLOCK_LINKAGE(block) \
- if (UNEXPECTED((block)->info._size != ZEND_MM_BLOCK_AT(block, ZEND_MM_FREE_BLOCK_SIZE(block))->info._prev) || \
- UNEXPECTED(!UNEXPECTED(ZEND_MM_IS_FIRST_BLOCK(block)) && \
- UNEXPECTED(ZEND_MM_PREV_BLOCK(block)->info._size != (block)->info._prev))) { \
- zend_mm_panic("zend_mm_heap corrupted"); \
- }
-#define ZEND_MM_CHECK_TREE(block) \
- if (UNEXPECTED(*((block)->parent) != (block))) { \
- zend_mm_panic("zend_mm_heap corrupted"); \
+ return NULL;
}
-#else
-# define ZEND_MM_CHECK_BLOCK_LINKAGE(block)
-# define ZEND_MM_CHECK_TREE(block)
+ return ptr;
#endif
+}
-#define ZEND_MM_LARGE_BUCKET_INDEX(S) zend_mm_high_bit(S)
-
-static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(2);
-static void _zend_mm_free_int(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
-static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(3);
-
-static inline unsigned int zend_mm_high_bit(size_t _size)
+static void zend_mm_munmap(void *addr, size_t size)
{
-#if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
- unsigned int n;
-
- __asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm" (_size) : "cc");
- return n;
-#elif defined(__GNUC__) && defined(__x86_64__)
- unsigned long n;
-
- __asm__("bsr %1,%0\n\t" : "=r" (n) : "rm" (_size) : "cc");
- return (unsigned int)n;
-#elif defined(_MSC_VER) && defined(_M_IX86)
- __asm {
- bsr eax, _size
+#ifdef _WIN32
+ if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
+#if ZEND_MM_ERROR
+ stderr_last_error("VirtualFree() failed");
+#endif
}
-#elif defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))
- return (8 * SIZEOF_SIZE_T - 1) - __builtin_clzl(_size);
#else
- unsigned int n = 0;
- while (_size != 0) {
- _size = _size >> 1;
- n++;
+ if (munmap(addr, size) != 0) {
+#if ZEND_MM_ERROR
+ fprintf(stderr, "\nmunmap() failed: [%d] %s\n", errno, strerror(errno));
+#endif
}
- return n-1;
#endif
}
-static inline unsigned int zend_mm_low_bit(size_t _size)
-{
-#if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
- unsigned int n;
+/***********/
+/* Bitmask */
+/***********/
- __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm" (_size) : "cc");
- return n;
-#elif defined(__GNUC__) && defined(__x86_64__)
- unsigned long n;
-
- __asm__("bsf %1,%0\n\t" : "=r" (n) : "rm" (_size) : "cc");
- return (unsigned int)n;
-#elif defined(_MSC_VER) && defined(_M_IX86)
- __asm {
- bsf eax, _size
- }
-#elif defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))
- return __builtin_ctzl(_size);
+/* number of trailing set (1) bits */
+static zend_always_inline int zend_mm_bitset_nts(zend_mm_bitset bitset)
+{
+#if defined(__GNUC__)
+ return __builtin_ctzl(~bitset);
#else
- static const int offset[16] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
- unsigned int n;
- unsigned int index = 0;
-
- n = offset[_size & 15];
- while (n == 4) {
- _size >>= 4;
- index += n;
- n = offset[_size & 15];
- }
+ int n;
+
+ if (bitset == (zend_mm_bitset)-1) return ZEND_MM_BITSET_LEN;
- return index + n;
+ n = 0;
+#if SIZEOF_ZEND_LONG == 8
+ if (sizeof(zend_mm_bitset) == 8) {
+ if ((bitset & 0xffffffff) == 0xffffffff) {n += 32; bitset = bitset >> Z_UL(32);}
+ }
+#endif
+ if ((bitset & 0x0000ffff) == 0x0000ffff) {n += 16; bitset = bitset >> 16;}
+ if ((bitset & 0x000000ff) == 0x000000ff) {n += 8; bitset = bitset >> 8;}
+ if ((bitset & 0x0000000f) == 0x0000000f) {n += 4; bitset = bitset >> 4;}
+ if ((bitset & 0x00000003) == 0x00000003) {n += 2; bitset = bitset >> 2;}
+ return n + (bitset & 1);
#endif
}
-static inline void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
+/* number of trailing zero bits (0x01 -> 1; 0x40 -> 6; 0x00 -> LEN) */
+static zend_always_inline int zend_mm_bitset_ntz(zend_mm_bitset bitset)
{
- size_t size;
- size_t index;
-
- ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
-
- size = ZEND_MM_FREE_BLOCK_SIZE(mm_block);
- if (EXPECTED(!ZEND_MM_SMALL_SIZE(size))) {
- zend_mm_free_block **p;
-
- index = ZEND_MM_LARGE_BUCKET_INDEX(size);
- p = &heap->large_free_buckets[index];
- mm_block->child[0] = mm_block->child[1] = NULL;
- if (!*p) {
- *p = mm_block;
- mm_block->parent = p;
- mm_block->prev_free_block = mm_block->next_free_block = mm_block;
- heap->large_free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
- } else {
- size_t m;
-
- for (m = size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
- zend_mm_free_block *prev = *p;
-
- if (ZEND_MM_FREE_BLOCK_SIZE(prev) != size) {
- p = &prev->child[(m >> (ZEND_MM_NUM_BUCKETS-1)) & 1];
- if (!*p) {
- *p = mm_block;
- mm_block->parent = p;
- mm_block->prev_free_block = mm_block->next_free_block = mm_block;
- break;
- }
- } else {
- zend_mm_free_block *next = prev->next_free_block;
-
- prev->next_free_block = next->prev_free_block = mm_block;
- mm_block->next_free_block = next;
- mm_block->prev_free_block = prev;
- mm_block->parent = NULL;
- break;
- }
- }
- }
- } else {
- zend_mm_free_block *prev, *next;
-
- index = ZEND_MM_BUCKET_INDEX(size);
+#if defined(__GNUC__)
+ return __builtin_ctzl(bitset);
+#else
+ int n;
- prev = ZEND_MM_SMALL_FREE_BUCKET(heap, index);
- if (prev->prev_free_block == prev) {
- heap->free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
- }
- next = prev->next_free_block;
+ if (bitset == (zend_mm_bitset)0) return ZEND_MM_BITSET_LEN;
- mm_block->prev_free_block = prev;
- mm_block->next_free_block = next;
- prev->next_free_block = next->prev_free_block = mm_block;
+ n = 1;
+#if SIZEOF_ZEND_LONG == 8
+ if (sizeof(zend_mm_bitset) == 8) {
+ if ((bitset & 0xffffffff) == 0) {n += 32; bitset = bitset >> Z_UL(32);}
}
+#endif
+ if ((bitset & 0x0000ffff) == 0) {n += 16; bitset = bitset >> 16;}
+ if ((bitset & 0x000000ff) == 0) {n += 8; bitset = bitset >> 8;}
+ if ((bitset & 0x0000000f) == 0) {n += 4; bitset = bitset >> 4;}
+ if ((bitset & 0x00000003) == 0) {n += 2; bitset = bitset >> 2;}
+ return n - (bitset & 1);
+#endif
}
-static inline void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
+static zend_always_inline int zend_mm_bitset_find_zero(zend_mm_bitset *bitset, int size)
{
- zend_mm_free_block *prev = mm_block->prev_free_block;
- zend_mm_free_block *next = mm_block->next_free_block;
+ int i = 0;
- ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED);
+ do {
+ zend_mm_bitset tmp = bitset[i];
+ if (tmp != (zend_mm_bitset)-1) {
+ return i * ZEND_MM_BITSET_LEN + zend_mm_bitset_nts(tmp);
+ }
+ i++;
+ } while (i < size);
+ return -1;
+}
- if (EXPECTED(prev == mm_block)) {
- zend_mm_free_block **rp, **cp;
+static zend_always_inline int zend_mm_bitset_find_one(zend_mm_bitset *bitset, int size)
+{
+ int i = 0;
-#if ZEND_MM_SAFE_UNLINKING
- if (UNEXPECTED(next != mm_block)) {
- zend_mm_panic("zend_mm_heap corrupted");
+ do {
+ zend_mm_bitset tmp = bitset[i];
+ if (tmp != 0) {
+ return i * ZEND_MM_BITSET_LEN + zend_mm_bitset_ntz(tmp);
}
-#endif
+ i++;
+ } while (i < size);
+ return -1;
+}
- rp = &mm_block->child[mm_block->child[1] != NULL];
- prev = *rp;
- if (EXPECTED(prev == NULL)) {
- size_t index = ZEND_MM_LARGE_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
+static zend_always_inline int zend_mm_bitset_find_zero_and_set(zend_mm_bitset *bitset, int size)
+{
+ int i = 0;
- ZEND_MM_CHECK_TREE(mm_block);
- *mm_block->parent = NULL;
- if (mm_block->parent == &heap->large_free_buckets[index]) {
- heap->large_free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
- }
- } else {
- while (*(cp = &(prev->child[prev->child[1] != NULL])) != NULL) {
- prev = *cp;
- rp = cp;
- }
- *rp = NULL;
-
-subst_block:
- ZEND_MM_CHECK_TREE(mm_block);
- *mm_block->parent = prev;
- prev->parent = mm_block->parent;
- if ((prev->child[0] = mm_block->child[0])) {
- ZEND_MM_CHECK_TREE(prev->child[0]);
- prev->child[0]->parent = &prev->child[0];
- }
- if ((prev->child[1] = mm_block->child[1])) {
- ZEND_MM_CHECK_TREE(prev->child[1]);
- prev->child[1]->parent = &prev->child[1];
- }
+ do {
+ zend_mm_bitset tmp = bitset[i];
+ if (tmp != (zend_mm_bitset)-1) {
+ int n = zend_mm_bitset_nts(tmp);
+ bitset[i] |= Z_UL(1) << n;
+ return i * ZEND_MM_BITSET_LEN + n;
}
- } else {
+ i++;
+ } while (i < size);
+ return -1;
+}
-#if ZEND_MM_SAFE_UNLINKING
- if (UNEXPECTED(prev->next_free_block != mm_block) || UNEXPECTED(next->prev_free_block != mm_block)) {
- zend_mm_panic("zend_mm_heap corrupted");
- }
-#endif
+static zend_always_inline int zend_mm_bitset_is_set(zend_mm_bitset *bitset, int bit)
+{
+ return (bitset[bit / ZEND_MM_BITSET_LEN] & (Z_L(1) << (bit & (ZEND_MM_BITSET_LEN-1)))) != 0;
+}
- prev->next_free_block = next;
- next->prev_free_block = prev;
+static zend_always_inline void zend_mm_bitset_set_bit(zend_mm_bitset *bitset, int bit)
+{
+ bitset[bit / ZEND_MM_BITSET_LEN] |= (Z_L(1) << (bit & (ZEND_MM_BITSET_LEN-1)));
+}
- if (EXPECTED(ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block)))) {
- if (EXPECTED(prev == next)) {
- size_t index = ZEND_MM_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
+static zend_always_inline void zend_mm_bitset_reset_bit(zend_mm_bitset *bitset, int bit)
+{
+ bitset[bit / ZEND_MM_BITSET_LEN] &= ~(Z_L(1) << (bit & (ZEND_MM_BITSET_LEN-1)));
+}
- if (EXPECTED(heap->free_buckets[index*2] == heap->free_buckets[index*2+1])) {
- heap->free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
- }
+static zend_always_inline void zend_mm_bitset_set_range(zend_mm_bitset *bitset, int start, int len)
+{
+ if (len == 1) {
+ zend_mm_bitset_set_bit(bitset, start);
+ } else {
+ int pos = start / ZEND_MM_BITSET_LEN;
+ int end = (start + len - 1) / ZEND_MM_BITSET_LEN;
+ int bit = start & (ZEND_MM_BITSET_LEN - 1);
+ zend_mm_bitset tmp;
+
+ if (pos != end) {
+ /* set bits from "bit" to ZEND_MM_BITSET_LEN-1 */
+ tmp = (zend_mm_bitset)-1 << bit;
+ bitset[pos++] |= tmp;
+ while (pos != end) {
+ /* set all bits */
+ bitset[pos++] = (zend_mm_bitset)-1;
}
- } else if (UNEXPECTED(mm_block->parent == ZEND_MM_REST_BLOCK)) {
- heap->rest_count--;
- } else if (UNEXPECTED(mm_block->parent != NULL)) {
- goto subst_block;
+ end = (start + len - 1) & (ZEND_MM_BITSET_LEN - 1);
+ /* set bits from "0" to "end" */
+ tmp = (zend_mm_bitset)-1 >> ((ZEND_MM_BITSET_LEN - 1) - end);
+ bitset[pos] |= tmp;
+ } else {
+ end = (start + len - 1) & (ZEND_MM_BITSET_LEN - 1);
+ /* set bits from "bit" to "end" */
+ tmp = (zend_mm_bitset)-1 << bit;
+ tmp &= (zend_mm_bitset)-1 >> ((ZEND_MM_BITSET_LEN - 1) - end);
+ bitset[pos] |= tmp;
}
}
}
-static inline void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
+static zend_always_inline void zend_mm_bitset_reset_range(zend_mm_bitset *bitset, int start, int len)
{
- zend_mm_free_block *prev, *next;
-
- while (heap->rest_count >= ZEND_MM_MAX_REST_BLOCKS) {
- zend_mm_free_block *p = heap->rest_buckets[1];
-
- if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(p))) {
- heap->rest_count--;
+ if (len == 1) {
+ zend_mm_bitset_reset_bit(bitset, start);
+ } else {
+ int pos = start / ZEND_MM_BITSET_LEN;
+ int end = (start + len - 1) / ZEND_MM_BITSET_LEN;
+ int bit = start & (ZEND_MM_BITSET_LEN - 1);
+ zend_mm_bitset tmp;
+
+ if (pos != end) {
+ /* reset bits from "bit" to ZEND_MM_BITSET_LEN-1 */
+ tmp = ~((Z_L(1) << bit) - 1);
+ bitset[pos++] &= ~tmp;
+ while (pos != end) {
+ /* set all bits */
+ bitset[pos++] = 0;
+ }
+ end = (start + len - 1) & (ZEND_MM_BITSET_LEN - 1);
+ /* reset bits from "0" to "end" */
+ tmp = (zend_mm_bitset)-1 >> ((ZEND_MM_BITSET_LEN - 1) - end);
+ bitset[pos] &= ~tmp;
+ } else {
+ end = (start + len - 1) & (ZEND_MM_BITSET_LEN - 1);
+ /* reset bits from "bit" to "end" */
+ tmp = (zend_mm_bitset)-1 << bit;
+ tmp &= (zend_mm_bitset)-1 >> ((ZEND_MM_BITSET_LEN - 1) - end);
+ bitset[pos] &= ~tmp;
}
- prev = p->prev_free_block;
- next = p->next_free_block;
- prev->next_free_block = next;
- next->prev_free_block = prev;
- zend_mm_add_to_free_list(heap, p);
}
+}
- if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block))) {
- mm_block->parent = ZEND_MM_REST_BLOCK;
- heap->rest_count++;
+static zend_always_inline int zend_mm_bitset_is_free_range(zend_mm_bitset *bitset, int start, int len)
+{
+ if (len == 1) {
+ return !zend_mm_bitset_is_set(bitset, start);
+ } else {
+ int pos = start / ZEND_MM_BITSET_LEN;
+ int end = (start + len - 1) / ZEND_MM_BITSET_LEN;
+ int bit = start & (ZEND_MM_BITSET_LEN - 1);
+ zend_mm_bitset tmp;
+
+ if (pos != end) {
+ /* set bits from "bit" to ZEND_MM_BITSET_LEN-1 */
+ tmp = (zend_mm_bitset)-1 << bit;
+ if ((bitset[pos++] & tmp) != 0) {
+ return 0;
+ }
+ while (pos != end) {
+ /* set all bits */
+ if (bitset[pos++] != 0) {
+ return 0;
+ }
+ }
+ end = (start + len - 1) & (ZEND_MM_BITSET_LEN - 1);
+ /* set bits from "0" to "end" */
+ tmp = (zend_mm_bitset)-1 >> ((ZEND_MM_BITSET_LEN - 1) - end);
+ return (bitset[pos] & tmp) == 0;
+ } else {
+ end = (start + len - 1) & (ZEND_MM_BITSET_LEN - 1);
+ /* set bits from "bit" to "end" */
+ tmp = (zend_mm_bitset)-1 << bit;
+ tmp &= (zend_mm_bitset)-1 >> ((ZEND_MM_BITSET_LEN - 1) - end);
+ return (bitset[pos] & tmp) == 0;
+ }
}
-
- ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
-
- prev = heap->rest_buckets[0];
- next = prev->next_free_block;
- mm_block->prev_free_block = prev;
- mm_block->next_free_block = next;
- prev->next_free_block = next->prev_free_block = mm_block;
}
-static inline void zend_mm_init(zend_mm_heap *heap)
+/**********/
+/* Chunks */
+/**********/
+
+static void *zend_mm_chunk_alloc(size_t size, size_t alignment)
{
- zend_mm_free_block* p;
- int i;
+ void *ptr = zend_mm_mmap(size);
- heap->free_bitmap = 0;
- heap->large_free_bitmap = 0;
-#if ZEND_MM_CACHE
- heap->cached = 0;
- memset(heap->cache, 0, sizeof(heap->cache));
+ if (ptr == NULL) {
+ return NULL;
+ } else if (ZEND_MM_ALIGNED_OFFSET(ptr, alignment) == 0) {
+#ifdef MADV_HUGEPAGE
+ madvise(ptr, size, MADV_HUGEPAGE);
#endif
-#if ZEND_MM_CACHE_STAT
- for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
- heap->cache_stat[i].count = 0;
- }
+ return ptr;
+ } else {
+ size_t offset;
+
+ /* chunk has to be aligned */
+ zend_mm_munmap(ptr, size);
+ ptr = zend_mm_mmap(size + alignment - ZEND_MM_PAGE_SIZE);
+#ifdef _WIN32
+ offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
+ zend_mm_munmap(ptr, size + alignment - ZEND_MM_PAGE_SIZE);
+ ptr = zend_mm_mmap_fixed((void*)((char*)ptr + (alignment - offset)), size);
+ offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
+ if (offset != 0) {
+ zend_mm_munmap(ptr, size);
+ return NULL;
+ }
+ return ptr;
+#else
+ offset = ZEND_MM_ALIGNED_OFFSET(ptr, alignment);
+ if (offset != 0) {
+ offset = alignment - offset;
+ zend_mm_munmap(ptr, offset);
+ ptr = (char*)ptr + offset;
+ } else {
+ zend_mm_munmap((char*)ptr + size, alignment - ZEND_MM_PAGE_SIZE);
+ }
+# ifdef MADV_HUGEPAGE
+ madvise(ptr, size, MADV_HUGEPAGE);
+# endif
#endif
- p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
- for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
- p->next_free_block = p;
- p->prev_free_block = p;
- p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
- heap->large_free_buckets[i] = NULL;
+ return ptr;
}
- heap->rest_buckets[0] = heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(heap);
- heap->rest_count = 0;
}
-static void zend_mm_del_segment(zend_mm_heap *heap, zend_mm_segment *segment)
+static zend_always_inline void zend_mm_chunk_init(zend_mm_heap *heap, zend_mm_chunk *chunk)
{
- zend_mm_segment **p = &heap->segments_list;
-
- while (*p != segment) {
- p = &(*p)->next_segment;
- }
- *p = segment->next_segment;
- heap->real_size -= segment->size;
- ZEND_MM_STORAGE_FREE(segment);
+ chunk->heap = heap;
+ chunk->next = heap->main_chunk;
+ chunk->prev = heap->main_chunk->prev;
+ chunk->prev->next = chunk;
+ chunk->next->prev = chunk;
+ /* mark first pages as allocated */
+ chunk->free_pages = ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE;
+ chunk->free_tail = ZEND_MM_FIRST_PAGE;
+ /* the younger chunks have bigger number */
+ chunk->num = chunk->prev->num + 1;
+ /* mark first pages as allocated */
+ chunk->free_map[0] = (1L << ZEND_MM_FIRST_PAGE) - 1;
+ chunk->map[0] = ZEND_MM_LRUN(ZEND_MM_FIRST_PAGE);
}
-#if ZEND_MM_CACHE
-static void zend_mm_free_cache(zend_mm_heap *heap)
-{
- int i;
+/***********************/
+/* Huge Runs (forward) */
+/***********************/
- for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
- if (heap->cache[i]) {
- zend_mm_free_block *mm_block = heap->cache[i];
+static size_t zend_mm_get_huge_block_size(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
+static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
+static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
- while (mm_block) {
- size_t size = ZEND_MM_BLOCK_SIZE(mm_block);
- zend_mm_free_block *q = mm_block->prev_free_block;
- zend_mm_block *next_block = ZEND_MM_NEXT_BLOCK(mm_block);
+#if ZEND_DEBUG
+static void zend_mm_change_huge_block_size(zend_mm_heap *heap, void *ptr, size_t size, size_t dbg_size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
+#else
+static void zend_mm_change_huge_block_size(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
+#endif
+
+/**************/
+/* Large Runs */
+/**************/
+
+#if ZEND_DEBUG
+static void *zend_mm_alloc_pages(zend_mm_heap *heap, int pages_count, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+#else
+static void *zend_mm_alloc_pages(zend_mm_heap *heap, int pages_count ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+#endif
+{
+ zend_mm_chunk *chunk = heap->main_chunk;
+ int page_num, len;
- heap->cached -= size;
+ while (1) {
+ if (UNEXPECTED(chunk->free_pages < pages_count)) {
+ goto not_found;
+#if 0
+ } else if (UNEXPECTED(chunk->free_pages + chunk->free_tail == ZEND_MM_PAGES)) {
+ if (UNEXPECTED(ZEND_MM_PAGES - chunk->free_tail < pages_count)) {
+ goto not_found;
+ } else {
+ page_num = chunk->free_tail;
+ goto found;
+ }
+ } else if (0) {
+ /* First-Fit Search */
+ int free_tail = chunk->free_tail;
+ zend_mm_bitset *bitset = chunk->free_map;
+ zend_mm_bitset tmp = *(bitset++);
+ int i = 0;
- if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
- mm_block = (zend_mm_free_block*)ZEND_MM_PREV_BLOCK(mm_block);
- size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
- zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) mm_block);
+ while (1) {
+ /* skip allocated blocks */
+ while (tmp == (zend_mm_bitset)-1) {
+ i += ZEND_MM_BITSET_LEN;
+ if (i == ZEND_MM_PAGES) {
+ goto not_found;
+ }
+ tmp = *(bitset++);
}
- if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
- size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
- zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
+ /* find first 0 bit */
+ page_num = i + zend_mm_bitset_nts(tmp);
+ /* reset bits from 0 to "bit" */
+ tmp &= tmp + 1;
+ /* skip free blocks */
+ while (tmp == 0) {
+ i += ZEND_MM_BITSET_LEN;
+ len = i - page_num;
+ if (len >= pages_count) {
+ goto found;
+ } else if (i >= free_tail) {
+ goto not_found;
+ }
+ tmp = *(bitset++);
}
- ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
-
- if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
- ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_NEXT_BLOCK(mm_block))) {
- zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
- } else {
- zend_mm_add_to_free_list(heap, (zend_mm_free_block *) mm_block);
+ /* find first 1 bit */
+ len = (i + zend_mm_bitset_ntz(tmp)) - page_num;
+ if (len >= pages_count) {
+ goto found;
}
-
- mm_block = q;
+ /* set bits from 0 to "bit" */
+ tmp |= tmp - 1;
}
- heap->cache[i] = NULL;
-#if ZEND_MM_CACHE_STAT
- heap->cache_stat[i].count = 0;
-#endif
- }
- }
-}
#endif
+ } else {
+ /* Best-Fit Search */
+ int best = -1;
+ int best_len = ZEND_MM_PAGES;
+ int free_tail = chunk->free_tail;
+ zend_mm_bitset *bitset = chunk->free_map;
+ zend_mm_bitset tmp = *(bitset++);
+ int i = 0;
-#if ZEND_MM_HEAP_PROTECTION || ZEND_MM_COOKIES
-static void zend_mm_random(unsigned char *buf, size_t size) /* {{{ */
-{
- size_t i = 0;
- unsigned char t;
-
-#ifdef ZEND_WIN32
- HCRYPTPROV hCryptProv;
- int has_context = 0;
-
- if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
- /* Could mean that the key container does not exist, let try
- again by asking for a new one */
- if (GetLastError() == NTE_BAD_KEYSET) {
- if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
- has_context = 1;
- }
- }
- } else {
- has_context = 1;
- }
- if (has_context) {
- do {
- BOOL ret = CryptGenRandom(hCryptProv, size, buf);
- CryptReleaseContext(hCryptProv, 0);
- if (ret) {
- while (i < size && buf[i] != 0) {
- i++;
+ while (1) {
+ /* skip allocated blocks */
+ while (tmp == (zend_mm_bitset)-1) {
+ i += ZEND_MM_BITSET_LEN;
+ if (i == ZEND_MM_PAGES) {
+ if (best > 0) {
+ page_num = best;
+ goto found;
+ } else {
+ goto not_found;
+ }
+ }
+ tmp = *(bitset++);
+ }
+ /* find first 0 bit */
+ page_num = i + zend_mm_bitset_nts(tmp);
+ /* reset bits from 0 to "bit" */
+ tmp &= tmp + 1;
+ /* skip free blocks */
+ while (tmp == 0) {
+ i += ZEND_MM_BITSET_LEN;
+ if (i >= free_tail) {
+ len = ZEND_MM_PAGES - page_num;
+ if (len >= pages_count && len < best_len) {
+ chunk->free_tail = page_num + pages_count;
+ goto found;
+ } else {
+ /* set accurate value */
+ chunk->free_tail = page_num;
+ if (best > 0) {
+ page_num = best;
+ goto found;
+ } else {
+ goto not_found;
+ }
+ }
+ }
+ tmp = *(bitset++);
}
- if (i == size) {
- return;
+ /* find first 1 bit */
+ len = i + zend_mm_bitset_ntz(tmp) - page_num;
+ if (len >= pages_count) {
+ if (len == pages_count) {
+ goto found;
+ } else if (len < best_len) {
+ best_len = len;
+ best = page_num;
+ }
}
- }
- } while (0);
- }
-#elif defined(HAVE_DEV_URANDOM)
- int fd = open("/dev/urandom", 0);
-
- if (fd >= 0) {
- if (read(fd, buf, size) == size) {
- while (i < size && buf[i] != 0) {
- i++;
- }
- if (i == size) {
- close(fd);
- return;
+ /* set bits from 0 to "bit" */
+ tmp |= tmp - 1;
}
}
- close(fd);
- }
-#endif
- t = (unsigned char)getpid();
- while (i < size) {
- do {
- buf[i] = ((unsigned char)rand()) ^ t;
- } while (buf[i] == 0);
- t = buf[i++] << 1;
- }
-}
-/* }}} */
-#endif
-/* Notes:
- * - This function may alter the block_sizes values to match platform alignment
- * - This function does *not* perform sanity checks on the arguments
- */
-ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
-{
- zend_mm_storage *storage;
- zend_mm_heap *heap;
-
-#if 0
- int i;
-
- printf("ZEND_MM_ALIGNMENT=%d\n", ZEND_MM_ALIGNMENT);
- printf("ZEND_MM_ALIGNMENT_LOG2=%d\n", ZEND_MM_ALIGNMENT_LOG2);
- printf("ZEND_MM_MIN_SIZE=%d\n", ZEND_MM_MIN_SIZE);
- printf("ZEND_MM_MAX_SMALL_SIZE=%d\n", ZEND_MM_MAX_SMALL_SIZE);
- printf("ZEND_MM_ALIGNED_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_HEADER_SIZE);
- printf("ZEND_MM_ALIGNED_FREE_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_FREE_HEADER_SIZE);
- printf("ZEND_MM_MIN_ALLOC_BLOCK_SIZE=%d\n", ZEND_MM_MIN_ALLOC_BLOCK_SIZE);
- printf("ZEND_MM_ALIGNED_MIN_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_MIN_HEADER_SIZE);
- printf("ZEND_MM_ALIGNED_SEGMENT_SIZE=%d\n", ZEND_MM_ALIGNED_SEGMENT_SIZE);
- for (i = 0; i < ZEND_MM_MAX_SMALL_SIZE; i++) {
- printf("%3d%c: %3ld %d %2ld\n", i, (i == ZEND_MM_MIN_SIZE?'*':' '), (long)ZEND_MM_TRUE_SIZE(i), ZEND_MM_SMALL_SIZE(ZEND_MM_TRUE_SIZE(i)), (long)ZEND_MM_BUCKET_INDEX(ZEND_MM_TRUE_SIZE(i)));
- }
- exit(0);
-#endif
-
-#if ZEND_MM_HEAP_PROTECTION
- if (_mem_block_start_magic == 0) {
- zend_mm_random((unsigned char*)&_mem_block_start_magic, sizeof(_mem_block_start_magic));
- }
- if (_mem_block_end_magic == 0) {
- zend_mm_random((unsigned char*)&_mem_block_end_magic, sizeof(_mem_block_end_magic));
- }
-#endif
-#if ZEND_MM_COOKIES
- if (_zend_mm_cookie == 0) {
- zend_mm_random((unsigned char*)&_zend_mm_cookie, sizeof(_zend_mm_cookie));
- }
+not_found:
+ if (chunk->next == heap->main_chunk) {
+ if (heap->cached_chunks) {
+ heap->cached_chunks_count--;
+ chunk = heap->cached_chunks;
+ heap->cached_chunks = chunk->next;
+ } else {
+#if ZEND_MM_LIMIT
+ if (heap->real_size + ZEND_MM_CHUNK_SIZE > heap->limit) {
+ if (heap->overflow == 0) {
+#if ZEND_DEBUG
+ zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted at %s:%d (tried to allocate " ZEND_ULONG_FMT " bytes)", heap->limit, __zend_filename, __zend_lineno, size);
+#else
+ zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted (tried to allocate " ZEND_ULONG_FMT " bytes)", heap->limit, ZEND_MM_PAGE_SIZE * pages_count);
#endif
-
- if (zend_mm_low_bit(block_size) != zend_mm_high_bit(block_size)) {
- fprintf(stderr, "'block_size' must be a power of two\n");
-/* See http://support.microsoft.com/kb/190351 */
-#ifdef PHP_WIN32
- fflush(stderr);
+ return NULL;
+ }
+ }
#endif
- exit(255);
- }
- storage = handlers->init(params);
- if (!storage) {
- fprintf(stderr, "Cannot initialize zend_mm storage [%s]\n", handlers->name);
-/* See http://support.microsoft.com/kb/190351 */
-#ifdef PHP_WIN32
- fflush(stderr);
+ chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
+ if (UNEXPECTED(chunk == NULL)) {
+ /* insufficient memory */
+#if !ZEND_MM_LIMIT
+ zend_mm_safe_error(heap, "Out of memory");
+#elif ZEND_DEBUG
+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
+#else
+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, ZEND_MM_PAGE_SIZE * pages_count);
#endif
- exit(255);
- }
- storage->handlers = handlers;
+ return NULL;
+ }
+#if ZEND_MM_STAT
+ do {
+ size_t size = heap->real_size + ZEND_MM_CHUNK_SIZE;
+ size_t peak = MAX(heap->real_peak, size);
+ heap->real_size = size;
+ heap->real_peak = peak;
+ } while (0);
+#elif ZEND_MM_LIMIT
+ heap->real_size += ZEND_MM_CHUNK_SIZE;
- heap = malloc(sizeof(struct _zend_mm_heap));
- if (heap == NULL) {
- fprintf(stderr, "Cannot allocate heap for zend_mm storage [%s]\n", handlers->name);
-#ifdef PHP_WIN32
- fflush(stderr);
#endif
- exit(255);
- }
- heap->storage = storage;
- heap->block_size = block_size;
- heap->compact_size = 0;
- heap->segments_list = NULL;
- zend_mm_init(heap);
-# if ZEND_MM_CACHE_STAT
- memset(heap->cache_stat, 0, sizeof(heap->cache_stat));
-# endif
-
- heap->use_zend_alloc = 1;
- heap->real_size = 0;
- heap->overflow = 0;
- heap->real_peak = 0;
- heap->limit = ZEND_MM_LONG_CONST(1)<<(ZEND_MM_NUM_BUCKETS-2);
- heap->size = 0;
- heap->peak = 0;
- heap->internal = internal;
- heap->reserve = NULL;
- heap->reserve_size = reserve_size;
- if (reserve_size > 0) {
- heap->reserve = _zend_mm_alloc_int(heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
- }
- if (internal) {
- int i;
- zend_mm_free_block *p, *q, *orig;
- zend_mm_heap *mm_heap = _zend_mm_alloc_int(heap, sizeof(zend_mm_heap) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
-
- *mm_heap = *heap;
-
- p = ZEND_MM_SMALL_FREE_BUCKET(mm_heap, 0);
- orig = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
- for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
- q = p;
- while (q->prev_free_block != orig) {
- q = q->prev_free_block;
- }
- q->prev_free_block = p;
- q = p;
- while (q->next_free_block != orig) {
- q = q->next_free_block;
}
- q->next_free_block = p;
- p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
- orig = (zend_mm_free_block*)((char*)orig + sizeof(zend_mm_free_block*) * 2);
- if (mm_heap->large_free_buckets[i]) {
- mm_heap->large_free_buckets[i]->parent = &mm_heap->large_free_buckets[i];
+ heap->chunks_count++;
+ if (heap->chunks_count > heap->peak_chunks_count) {
+ heap->peak_chunks_count = heap->chunks_count;
}
+ zend_mm_chunk_init(heap, chunk);
+ page_num = ZEND_MM_FIRST_PAGE;
+ len = ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE;
+ goto found;
+ } else {
+ chunk = chunk->next;
}
- mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(mm_heap);
- mm_heap->rest_count = 0;
+ }
- free(heap);
- heap = mm_heap;
+found:
+ /* mark run as allocated */
+ chunk->free_pages -= pages_count;
+ zend_mm_bitset_set_range(chunk->free_map, page_num, pages_count);
+ chunk->map[page_num] = ZEND_MM_LRUN(pages_count);
+ if (page_num == chunk->free_tail) {
+ chunk->free_tail = page_num + pages_count;
}
- return heap;
+ return ZEND_MM_PAGE_ADDR(chunk, page_num);
}
-ZEND_API zend_mm_heap *zend_mm_startup(void)
+static zend_always_inline void *zend_mm_alloc_large(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- int i;
- size_t seg_size;
- char *mem_type = getenv("ZEND_MM_MEM_TYPE");
- char *tmp;
- const zend_mm_mem_handlers *handlers;
- zend_mm_heap *heap;
-
- if (mem_type == NULL) {
- i = 0;
- } else {
- for (i = 0; mem_handlers[i].name; i++) {
- if (strcmp(mem_handlers[i].name, mem_type) == 0) {
- break;
- }
- }
- if (!mem_handlers[i].name) {
- fprintf(stderr, "Wrong or unsupported zend_mm storage type '%s'\n", mem_type);
- fprintf(stderr, " supported types:\n");
-/* See http://support.microsoft.com/kb/190351 */
-#ifdef PHP_WIN32
- fflush(stderr);
-#endif
- for (i = 0; mem_handlers[i].name; i++) {
- fprintf(stderr, " '%s'\n", mem_handlers[i].name);
- }
-/* See http://support.microsoft.com/kb/190351 */
-#ifdef PHP_WIN32
- fflush(stderr);
-#endif
- exit(255);
- }
- }
- handlers = &mem_handlers[i];
-
- tmp = getenv("ZEND_MM_SEG_SIZE");
- if (tmp) {
- seg_size = zend_atoi(tmp, 0);
- if (zend_mm_low_bit(seg_size) != zend_mm_high_bit(seg_size)) {
- fprintf(stderr, "ZEND_MM_SEG_SIZE must be a power of two\n");
-/* See http://support.microsoft.com/kb/190351 */
-#ifdef PHP_WIN32
- fflush(stderr);
+ int pages_count = ZEND_MM_SIZE_TO_NUM(size, ZEND_MM_PAGE_SIZE);
+#if ZEND_DEBUG
+ void *ptr = zend_mm_alloc_pages(heap, pages_count, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#else
+ void *ptr = zend_mm_alloc_pages(heap, pages_count ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
#endif
- exit(255);
- } else if (seg_size < ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE) {
- fprintf(stderr, "ZEND_MM_SEG_SIZE is too small\n");
-/* See http://support.microsoft.com/kb/190351 */
-#ifdef PHP_WIN32
- fflush(stderr);
+#if ZEND_MM_STAT
+ do {
+ size_t size = heap->size + pages_count * ZEND_MM_PAGE_SIZE;
+ size_t peak = MAX(heap->peak, size);
+ heap->size = size;
+ heap->peak = peak;
+ } while (0);
#endif
- exit(255);
- }
- } else {
- seg_size = ZEND_MM_SEG_SIZE;
- }
+ return ptr;
+}
- heap = zend_mm_startup_ex(handlers, seg_size, ZEND_MM_RESERVE_SIZE, 0, NULL);
- if (heap) {
- tmp = getenv("ZEND_MM_COMPACT");
- if (tmp) {
- heap->compact_size = zend_atoi(tmp, 0);
+static void zend_mm_free_pages(zend_mm_heap *heap, zend_mm_chunk *chunk, int page_num, int pages_count)
+{
+ chunk->free_pages += pages_count;
+ zend_mm_bitset_reset_range(chunk->free_map, page_num, pages_count);
+ chunk->map[page_num] = 0;
+ if (chunk->free_tail == page_num + pages_count) {
+ /* this setting may be not accurate */
+ chunk->free_tail = page_num;
+ }
+ if (chunk->free_pages == ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE) {
+ /* delete chunk */
+ chunk->next->prev = chunk->prev;
+ chunk->prev->next = chunk->next;
+ heap->chunks_count--;
+ if (heap->chunks_count + heap->cached_chunks_count < heap->avg_chunks_count + 0.1) {
+ /* delay deletion */
+ heap->cached_chunks_count++;
+ chunk->next = heap->cached_chunks;
+ heap->cached_chunks = chunk;
} else {
- heap->compact_size = 2 * 1024 * 1024;
+#if ZEND_MM_STAT || ZEND_MM_LIMIT
+ heap->real_size -= ZEND_MM_CHUNK_SIZE;
+#endif
+ if (!heap->cached_chunks || chunk->num > heap->cached_chunks->num) {
+ zend_mm_munmap(chunk, ZEND_MM_CHUNK_SIZE);
+ } else {
+//TODO: select the best chunk to delete???
+ chunk->next = heap->cached_chunks->next;
+ zend_mm_munmap(heap->cached_chunks, ZEND_MM_CHUNK_SIZE);
+ heap->cached_chunks = chunk;
+ }
}
}
- return heap;
}
-#if ZEND_DEBUG
-static long zend_mm_find_leaks(zend_mm_segment *segment, zend_mm_block *b)
+static zend_always_inline void zend_mm_free_large(zend_mm_heap *heap, zend_mm_chunk *chunk, int page_num, int pages_count)
{
- long leaks = 0;
- zend_mm_block *p, *q;
+#if ZEND_MM_STAT
+ heap->size -= pages_count * ZEND_MM_PAGE_SIZE;
+#endif
+ zend_mm_free_pages(heap, chunk, page_num, pages_count);
+}
- p = ZEND_MM_NEXT_BLOCK(b);
- while (1) {
- if (ZEND_MM_IS_GUARD_BLOCK(p)) {
- ZEND_MM_CHECK_MAGIC(p, MEM_BLOCK_GUARD);
- segment = segment->next_segment;
- if (!segment) {
- break;
- }
- p = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
- continue;
- }
- q = ZEND_MM_NEXT_BLOCK(p);
- if (q <= p ||
- (char*)q > (char*)segment + segment->size ||
- p->info._size != q->info._prev) {
- zend_mm_panic("zend_mm_heap corrupted");
- }
- if (!ZEND_MM_IS_FREE_BLOCK(p)) {
- if (p->magic == MEM_BLOCK_VALID) {
- if (p->debug.filename==b->debug.filename && p->debug.lineno==b->debug.lineno) {
- ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
- leaks++;
- }
-#if ZEND_MM_CACHE
- } else if (p->magic == MEM_BLOCK_CACHED) {
- /* skip it */
+/**************/
+/* Small Runs */
+/**************/
+
+/* higher set bit number (0->N/A, 1->1, 2->2, 4->3, 8->4, 127->7, 128->8 etc) */
+static zend_always_inline int zend_mm_small_size_to_bit(int size)
+{
+#if defined(__GNUC__)
+ return (__builtin_clz(size) ^ 0x1f) + 1;
+#else
+ int n = 16;
+ if (size <= 0x00ff) {n -= 8; size = size << 8;}
+ if (size <= 0x0fff) {n -= 4; size = size << 4;}
+ if (size <= 0x3fff) {n -= 2; size = size << 2;}
+ if (size <= 0x7fff) {n -= 1;}
+ return n;
#endif
- } else if (p->magic != MEM_BLOCK_LEAK) {
- zend_mm_panic("zend_mm_heap corrupted");
- }
- }
- p = q;
- }
- return leaks;
}
-static void zend_mm_check_leaks(zend_mm_heap *heap TSRMLS_DC)
+#ifndef MAX
+# define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef MIN
+# define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+static zend_always_inline int zend_mm_small_size_to_bin(size_t size)
{
- zend_mm_segment *segment = heap->segments_list;
- zend_mm_block *p, *q;
- zend_uint total = 0;
+#if 0
+ int n;
+ /*0, 1, 2, 3, 4, 5, 6, 7, 8, 9 10, 11, 12*/
+ static const int f1[] = { 3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9};
+ static const int f2[] = { 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 20, 24};
+
+ if (UNEXPECTED(size <= 2)) return 0;
+ n = zend_mm_small_size_to_bit(size - 1);
+ return ((size-1) >> f1[n]) + f2[n];
+#else
+ int t1, t2, t3;
- if (!segment) {
- return;
- }
- p = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
- while (1) {
- q = ZEND_MM_NEXT_BLOCK(p);
- if (q <= p ||
- (char*)q > (char*)segment + segment->size ||
- p->info._size != q->info._prev) {
- zend_mm_panic("zend_mm_heap corrupted");
- }
- if (!ZEND_MM_IS_FREE_BLOCK(p)) {
- if (p->magic == MEM_BLOCK_VALID) {
- long repeated;
- zend_leak_info leak;
-
- ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
-
- leak.addr = ZEND_MM_DATA_OF(p);
- leak.size = p->debug.size;
- leak.filename = p->debug.filename;
- leak.lineno = p->debug.lineno;
- leak.orig_filename = p->debug.orig_filename;
- leak.orig_lineno = p->debug.orig_lineno;
-
- zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
- zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, &leak TSRMLS_CC);
- repeated = zend_mm_find_leaks(segment, p);
- total += 1 + repeated;
- if (repeated) {
- zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(zend_uintptr_t)repeated TSRMLS_CC);
- }
-#if ZEND_MM_CACHE
- } else if (p->magic == MEM_BLOCK_CACHED) {
- /* skip it */
+ if (UNEXPECTED(size <= 8)) return 0;
+ t1 = (int)(size - 1);
+ t2 = zend_mm_small_size_to_bit(t1);
+ t3 = t2 - 6;
+ t3 = (t3 < 0) ? 0 : t3;
+ t2 = t3 + 3;
+ t1 = t1 >> t2;
+ t3 = t3 << 2;
+ return t1 + t3;
#endif
- } else if (p->magic != MEM_BLOCK_LEAK) {
- zend_mm_panic("zend_mm_heap corrupted");
- }
- }
- if (ZEND_MM_IS_GUARD_BLOCK(q)) {
- segment = segment->next_segment;
- if (!segment) {
- break;
- }
- q = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
- }
- p = q;
- }
- if (total) {
- zend_message_dispatcher(ZMSG_MEMORY_LEAKS_GRAND_TOTAL, &total TSRMLS_CC);
- }
}
-static int zend_mm_check_ptr(zend_mm_heap *heap, void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+#define ZEND_MM_SMALL_SIZE_TO_BIN(size) zend_mm_small_size_to_bin(size)
+
+static zend_never_inline void *zend_mm_alloc_small_slow(zend_mm_heap *heap, int bin_num ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- zend_mm_block *p;
- int no_cache_notice = 0;
- int had_problems = 0;
- int valid_beginning = 1;
+ zend_mm_chunk *chunk;
+ int page_num;
+ zend_mm_bin *bin;
+ zend_mm_free_slot *p, *end;
- if (silent==2) {
- silent = 1;
- no_cache_notice = 1;
- } else if (silent==3) {
- silent = 0;
- no_cache_notice = 1;
- }
- if (!silent) {
- TSRMLS_FETCH();
-
- zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
- zend_debug_alloc_output("---------------------------------------\n");
- zend_debug_alloc_output("%s(%d) : Block "PTR_FMT" status:\n" ZEND_FILE_LINE_RELAY_CC, ptr);
- if (__zend_orig_filename) {
- zend_debug_alloc_output("%s(%d) : Actual location (location was relayed)\n" ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
- if (!ptr) {
- zend_debug_alloc_output("NULL\n");
- zend_debug_alloc_output("---------------------------------------\n");
- return 0;
- }
+#if ZEND_DEBUG
+ bin = (zend_mm_bin*)zend_mm_alloc_pages(heap, bin_pages[bin_num], bin_data_size[bin_num] ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#else
+ bin = (zend_mm_bin*)zend_mm_alloc_pages(heap, bin_pages[bin_num] ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#endif
+ if (UNEXPECTED(bin == NULL)) {
+ /* insufficient memory */
+ return NULL;
}
- if (!ptr) {
- if (silent) {
- return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
+ chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(bin, ZEND_MM_CHUNK_SIZE);
+ page_num = ZEND_MM_ALIGNED_OFFSET(bin, ZEND_MM_CHUNK_SIZE) / ZEND_MM_PAGE_SIZE;
+ chunk->map[page_num] = ZEND_MM_SRUN(bin_num);
+ if (bin_pages[bin_num] > 1) {
+ int i = 1;
+ do {
+ chunk->map[page_num+i] = ZEND_MM_SRUN(bin_num);
+ i++;
+ } while (i < bin_pages[bin_num]);
}
- p = ZEND_MM_HEADER_OF(ptr);
-
-#ifdef ZTS
- if (ZEND_MM_BAD_THREAD_ID(p)) {
- if (!silent) {
- zend_debug_alloc_output("Invalid pointer: ((thread_id=0x%0.8X) != (expected=0x%0.8X))\n", (long)p->thread_id, (long)tsrm_thread_id());
- had_problems = 1;
- } else {
- return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
- }
+ /* create a linked list of elements from 1 to last */
+ end = (zend_mm_free_slot*)((char*)bin + (bin_data_size[bin_num] * (bin_elements[bin_num] - 1)));
+ heap->free_slot[bin_num] = p = (zend_mm_free_slot*)((char*)bin + bin_data_size[bin_num]);
+ do {
+ p->next_free_slot = (zend_mm_free_slot*)((char*)p + bin_data_size[bin_num]);;
+#if ZEND_DEBUG
+ do {
+ zend_mm_debug_info *dbg = (zend_mm_debug_info*)((char*)p + bin_data_size[bin_num] - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ dbg->size = 0;
+ } while (0);
#endif
+ p = (zend_mm_free_slot*)((char*)p + bin_data_size[bin_num]);
+ } while (p != end);
- if (p->info._size != ZEND_MM_NEXT_BLOCK(p)->info._prev) {
- if (!silent) {
- zend_debug_alloc_output("Invalid pointer: ((size="PTR_FMT") != (next.prev="PTR_FMT"))\n", p->info._size, ZEND_MM_NEXT_BLOCK(p)->info._prev);
- had_problems = 1;
- } else {
- return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
- }
- if (p->info._prev != ZEND_MM_GUARD_BLOCK &&
- ZEND_MM_PREV_BLOCK(p)->info._size != p->info._prev) {
- if (!silent) {
- zend_debug_alloc_output("Invalid pointer: ((prev="PTR_FMT") != (prev.size="PTR_FMT"))\n", p->info._prev, ZEND_MM_PREV_BLOCK(p)->info._size);
- had_problems = 1;
- } else {
- return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
- }
+ /* terminate list using NULL */
+ p->next_free_slot = NULL;
+#if ZEND_DEBUG
+ do {
+ zend_mm_debug_info *dbg = (zend_mm_debug_info*)((char*)p + bin_data_size[bin_num] - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ dbg->size = 0;
+ } while (0);
+#endif
- if (had_problems) {
- zend_debug_alloc_output("---------------------------------------\n");
- return 0;
- }
+ /* return first element */
+ return (char*)bin;
+}
- if (!silent) {
- zend_debug_alloc_output("%10s\t","Beginning: ");
- }
+static zend_always_inline void *zend_mm_alloc_small(zend_mm_heap *heap, size_t size, int bin_num ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+{
+#if ZEND_MM_STAT
+ do {
+ size_t size = heap->size + bin_data_size[bin_num];
+ size_t peak = MAX(heap->peak, size);
+ heap->size = size;
+ heap->peak = peak;
+ } while (0);
+#endif
- if (!ZEND_MM_IS_USED_BLOCK(p)) {
- if (!silent) {
- if (p->magic != MEM_BLOCK_FREED) {
- zend_debug_alloc_output("Freed (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
- } else {
- zend_debug_alloc_output("Freed\n");
- }
- had_problems = 1;
- } else {
- return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
- } else if (ZEND_MM_IS_GUARD_BLOCK(p)) {
- if (!silent) {
- if (p->magic != MEM_BLOCK_FREED) {
- zend_debug_alloc_output("Guard (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
- } else {
- zend_debug_alloc_output("Guard\n");
- }
- had_problems = 1;
- } else {
- return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
+ if (EXPECTED(heap->free_slot[bin_num] != NULL)) {
+ zend_mm_free_slot *p = heap->free_slot[bin_num];
+ heap->free_slot[bin_num] = p->next_free_slot;
+ return (void*)p;
} else {
- switch (p->magic) {
- case MEM_BLOCK_VALID:
- case MEM_BLOCK_LEAK:
- if (!silent) {
- zend_debug_alloc_output("OK (allocated on %s:%d, %d bytes)\n", p->debug.filename, p->debug.lineno, (int)p->debug.size);
- }
- break; /* ok */
- case MEM_BLOCK_CACHED:
- if (!no_cache_notice) {
- if (!silent) {
- zend_debug_alloc_output("Cached\n");
- had_problems = 1;
- } else {
- return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
- }
- case MEM_BLOCK_FREED:
- if (!silent) {
- zend_debug_alloc_output("Freed (invalid)\n");
- had_problems = 1;
- } else {
- return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
- break;
- case MEM_BLOCK_GUARD:
- if (!silent) {
- zend_debug_alloc_output("Guard (invalid)\n");
- had_problems = 1;
- } else {
- return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
- break;
- default:
- if (!silent) {
- zend_debug_alloc_output("Unknown (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_VALID);
- had_problems = 1;
- valid_beginning = 0;
- } else {
- return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
- break;
- }
+ return zend_mm_alloc_small_slow(heap, bin_num ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
+}
-#if ZEND_MM_HEAP_PROTECTION
- if (!valid_beginning) {
- if (!silent) {
- zend_debug_alloc_output("%10s\t", "Start:");
- zend_debug_alloc_output("Unknown\n");
- zend_debug_alloc_output("%10s\t", "End:");
- zend_debug_alloc_output("Unknown\n");
- }
- } else {
- char *end_magic = ZEND_MM_END_MAGIC_PTR(p);
+static zend_always_inline void zend_mm_free_small(zend_mm_heap *heap, void *ptr, int bin_num)
+{
+ zend_mm_free_slot *p;
- if (p->debug.start_magic == _mem_block_start_magic) {
- if (!silent) {
- zend_debug_alloc_output("%10s\t", "Start:");
- zend_debug_alloc_output("OK\n");
- }
- } else {
- char *overflow_ptr, *magic_ptr=(char *) &_mem_block_start_magic;
- int overflows=0;
- int i;
+#if ZEND_MM_STAT
+ heap->size -= bin_data_size[bin_num];
+#endif
- if (silent) {
- return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
- had_problems = 1;
- overflow_ptr = (char *) &p->debug.start_magic;
- i = END_MAGIC_SIZE;
- while (--i >= 0) {
- if (overflow_ptr[i]!=magic_ptr[i]) {
- overflows++;
- }
- }
- zend_debug_alloc_output("%10s\t", "Start:");
- zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", p->debug.start_magic, _mem_block_start_magic);
- zend_debug_alloc_output("%10s\t","");
- if (overflows >= END_MAGIC_SIZE) {
- zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
- } else {
- zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
- }
- }
- if (memcmp(end_magic, &_mem_block_end_magic, END_MAGIC_SIZE)==0) {
- if (!silent) {
- zend_debug_alloc_output("%10s\t", "End:");
- zend_debug_alloc_output("OK\n");
- }
- } else {
- char *overflow_ptr, *magic_ptr=(char *) &_mem_block_end_magic;
- int overflows=0;
- int i;
+#if ZEND_DEBUG
+ do {
+ zend_mm_debug_info *dbg = (zend_mm_debug_info*)((char*)ptr + bin_data_size[bin_num] - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ dbg->size = 0;
+ } while (0);
+#endif
- if (silent) {
- return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
- had_problems = 1;
- overflow_ptr = (char *) end_magic;
+ p = (zend_mm_free_slot*)ptr;
+ p->next_free_slot = heap->free_slot[bin_num];
+ heap->free_slot[bin_num] = p;
+}
- for (i=0; i < END_MAGIC_SIZE; i++) {
- if (overflow_ptr[i]!=magic_ptr[i]) {
- overflows++;
- }
- }
+/********/
+/* Heap */
+/********/
- zend_debug_alloc_output("%10s\t", "End:");
- zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", *end_magic, _mem_block_end_magic);
- zend_debug_alloc_output("%10s\t","");
- if (overflows >= END_MAGIC_SIZE) {
- zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
- } else {
- zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
- }
- }
- }
-#endif
+#if ZEND_DEBUG
+static zend_always_inline zend_mm_debug_info *zend_mm_get_debug_info(zend_mm_heap *heap, void *ptr)
+{
+ size_t page_offset = ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE);
+ zend_mm_chunk *chunk;
+ int page_num;
+ zend_mm_page_info info;
- if (!silent) {
- zend_debug_alloc_output("---------------------------------------\n");
+ ZEND_MM_CHECK(page_offset != 0, "zend_mm_heap corrupted");
+ chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE);
+ page_num = page_offset / ZEND_MM_PAGE_SIZE;
+ info = chunk->map[page_num];
+ ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted");
+ if (EXPECTED(info & ZEND_MM_IS_SRUN)) {
+ int bin_num = ZEND_MM_SRUN_BIN_NUM(info);
+ return (zend_mm_debug_info*)((char*)ptr + bin_data_size[bin_num] - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ } else /* if (info & ZEND_MM_IS_LRUN) */ {
+ int pages_count = ZEND_MM_LRUN_PAGES(info);
+
+ return (zend_mm_debug_info*)((char*)ptr + ZEND_MM_PAGE_SIZE * pages_count - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
}
- return ((!had_problems) ? 1 : 0);
}
+#endif
-static int zend_mm_check_heap(zend_mm_heap *heap, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- zend_mm_segment *segment = heap->segments_list;
- zend_mm_block *p, *q;
- int errors = 0;
+ void *ptr;
+#if ZEND_DEBUG
+ size_t real_size = size;
+ zend_mm_debug_info *dbg;
- if (!segment) {
- return 0;
- }
- p = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
- while (1) {
- q = ZEND_MM_NEXT_BLOCK(p);
- if (q <= p ||
- (char*)q > (char*)segment + segment->size ||
- p->info._size != q->info._prev) {
- zend_mm_panic("zend_mm_heap corrupted");
- }
- if (!ZEND_MM_IS_FREE_BLOCK(p)) {
- if (p->magic == MEM_BLOCK_VALID || p->magic == MEM_BLOCK_LEAK) {
- if (!zend_mm_check_ptr(heap, ZEND_MM_DATA_OF(p), (silent?2:3) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)) {
- errors++;
- }
-#if ZEND_MM_CACHE
- } else if (p->magic == MEM_BLOCK_CACHED) {
- /* skip it */
+ /* special handling for zero-size allocation */
+ size = MAX(size, 1);
+ size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
#endif
- } else if (p->magic != MEM_BLOCK_LEAK) {
- zend_mm_panic("zend_mm_heap corrupted");
- }
- }
- if (ZEND_MM_IS_GUARD_BLOCK(q)) {
- segment = segment->next_segment;
- if (!segment) {
- return errors;
- }
- q = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
- }
- p = q;
+ if (size <= ZEND_MM_MAX_SMALL_SIZE) {
+ ptr = zend_mm_alloc_small(heap, size, ZEND_MM_SMALL_SIZE_TO_BIN(size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#if ZEND_DEBUG
+ dbg = zend_mm_get_debug_info(heap, ptr);
+ dbg->size = real_size;
+ dbg->filename = __zend_filename;
+ dbg->orig_filename = __zend_orig_filename;
+ dbg->lineno = __zend_lineno;
+ dbg->orig_lineno = __zend_orig_lineno;
+#endif
+ return ptr;
+ } else if (size <= ZEND_MM_MAX_LARGE_SIZE) {
+ ptr = zend_mm_alloc_large(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#if ZEND_DEBUG
+ dbg = zend_mm_get_debug_info(heap, ptr);
+ dbg->size = real_size;
+ dbg->filename = __zend_filename;
+ dbg->orig_filename = __zend_orig_filename;
+ dbg->lineno = __zend_lineno;
+ dbg->orig_lineno = __zend_orig_lineno;
+#endif
+ return ptr;
+ } else {
+#if ZEND_DEBUG
+ size = real_size;
+#endif
+ return zend_mm_alloc_huge(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
}
-#endif
-ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
+static zend_always_inline void zend_mm_free_heap(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- zend_mm_storage *storage;
- zend_mm_segment *segment;
- zend_mm_segment *prev;
- int internal;
+ size_t page_offset = ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE);
- if (!heap->use_zend_alloc) {
- if (full_shutdown) {
- free(heap);
+ if (UNEXPECTED(page_offset == 0)) {
+ if (ptr != NULL) {
+ zend_mm_free_huge(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
- return;
- }
+ } else {
+ zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE);
+ int page_num = page_offset / ZEND_MM_PAGE_SIZE;
+ zend_mm_page_info info = chunk->map[page_num];
- if (heap->reserve) {
-#if ZEND_DEBUG
- if (!silent) {
- _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
+ ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted");
+ if (EXPECTED(info & ZEND_MM_IS_SRUN)) {
+ zend_mm_free_small(heap, ptr, ZEND_MM_SRUN_BIN_NUM(info));
+ } else /* if (info & ZEND_MM_IS_LRUN) */ {
+ int pages_count = ZEND_MM_LRUN_PAGES(info);
+
+ ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(page_offset, ZEND_MM_PAGE_SIZE) == 0, "zend_mm_heap corrupted");
+ zend_mm_free_large(heap, chunk, page_num, pages_count);
}
-#endif
- heap->reserve = NULL;
}
+}
-#if ZEND_MM_CACHE_STAT
- if (full_shutdown) {
- FILE *f;
+static size_t zend_mm_size(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+{
+ size_t page_offset = ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE);
- f = fopen("zend_mm.log", "w");
- if (f) {
- int i,j;
- size_t size, true_size, min_size, max_size;
- int hit = 0, miss = 0;
+ if (UNEXPECTED(page_offset == 0)) {
+ return zend_mm_get_huge_block_size(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ } else {
+ zend_mm_chunk *chunk;
+#if 0 && ZEND_DEBUG
+ zend_mm_debug_info *dbg = zend_mm_get_debug_info(heap, ptr);
+ return dbg->size;
+#else
+ int page_num;
+ zend_mm_page_info info;
- fprintf(f, "\nidx min_size max_size true_size max_len hits misses\n");
- size = 0;
- while (1) {
- true_size = ZEND_MM_TRUE_SIZE(size);
- if (ZEND_MM_SMALL_SIZE(true_size)) {
- min_size = size;
- i = ZEND_MM_BUCKET_INDEX(true_size);
- size++;
- while (1) {
- true_size = ZEND_MM_TRUE_SIZE(size);
- if (ZEND_MM_SMALL_SIZE(true_size)) {
- j = ZEND_MM_BUCKET_INDEX(true_size);
- if (j > i) {
- max_size = size-1;
- break;
- }
- } else {
- max_size = size-1;
- break;
- }
- size++;
- }
- hit += heap->cache_stat[i].hit;
- miss += heap->cache_stat[i].miss;
- fprintf(f, "%2d %8d %8d %9d %8d %8d %8d\n", i, (int)min_size, (int)max_size, ZEND_MM_TRUE_SIZE(max_size), heap->cache_stat[i].max_count, heap->cache_stat[i].hit, heap->cache_stat[i].miss);
- } else {
- break;
- }
- }
- fprintf(f, " %8d %8d\n", hit, miss);
- fprintf(f, " %8d %8d\n", heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit, heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss);
- fclose(f);
+ chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE);
+ page_num = page_offset / ZEND_MM_PAGE_SIZE;
+ info = chunk->map[page_num];
+ ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted");
+ if (EXPECTED(info & ZEND_MM_IS_SRUN)) {
+ return bin_data_size[ZEND_MM_SRUN_BIN_NUM(info)];
+ } else /* if (info & ZEND_MM_IS_LARGE_RUN) */ {
+ return ZEND_MM_LRUN_PAGES(info) * ZEND_MM_PAGE_SIZE;
}
- }
#endif
+ }
+}
+static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+{
+ size_t page_offset;
+ size_t old_size;
+ size_t new_size;
+ void *ret;
#if ZEND_DEBUG
- if (!silent) {
- zend_mm_check_leaks(heap TSRMLS_CC);
- }
+ size_t real_size;
+ zend_mm_debug_info *dbg;
#endif
- internal = heap->internal;
- storage = heap->storage;
- segment = heap->segments_list;
- if (full_shutdown) {
- while (segment) {
- prev = segment;
- segment = segment->next_segment;
- ZEND_MM_STORAGE_FREE(prev);
- }
- heap->segments_list = NULL;
- storage->handlers->dtor(storage);
- if (!internal) {
- free(heap);
+ page_offset = ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE);
+ if (UNEXPECTED(page_offset == 0)) {
+ if (UNEXPECTED(ptr == NULL)) {
+ return zend_mm_alloc_heap(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
- } else {
- if (segment) {
-#ifndef ZEND_WIN32
- if (heap->reserve_size) {
- while (segment->next_segment) {
- prev = segment;
- segment = segment->next_segment;
- ZEND_MM_STORAGE_FREE(prev);
- }
- heap->segments_list = segment;
- } else {
+ old_size = zend_mm_get_huge_block_size(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#if ZEND_DEBUG
+ real_size = size;
+ size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
#endif
- do {
- prev = segment;
- segment = segment->next_segment;
- ZEND_MM_STORAGE_FREE(prev);
- } while (segment);
- heap->segments_list = NULL;
-#ifndef ZEND_WIN32
- }
+ if (size > ZEND_MM_MAX_LARGE_SIZE) {
+#if ZEND_DEBUG
+ size = real_size;
#endif
- }
- if (heap->compact_size &&
- heap->real_peak > heap->compact_size) {
- storage->handlers->compact(storage);
- }
- zend_mm_init(heap);
- if (heap->segments_list) {
- heap->real_size = heap->segments_list->size;
- heap->real_peak = heap->segments_list->size;
- } else {
- heap->real_size = 0;
- heap->real_peak = 0;
- }
- heap->size = 0;
- heap->peak = 0;
- if (heap->segments_list) {
- /* mark segment as a free block */
- zend_mm_free_block *b = (zend_mm_free_block*)((char*)heap->segments_list + ZEND_MM_ALIGNED_SEGMENT_SIZE);
- size_t block_size = heap->segments_list->size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
-
- ZEND_MM_MARK_FIRST_BLOCK(b);
- ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(b, block_size));
- ZEND_MM_BLOCK(b, ZEND_MM_FREE_BLOCK, block_size);
- zend_mm_add_to_free_list(heap, b);
- }
- if (heap->reserve_size) {
- heap->reserve = _zend_mm_alloc_int(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
- }
- heap->overflow = 0;
- }
-}
-
-static void zend_mm_safe_error(zend_mm_heap *heap,
- const char *format,
- size_t limit,
+ new_size = ZEND_MM_ALIGNED_SIZE_EX(size, ZEND_MM_PAGE_SIZE);
+ if (new_size == old_size) {
#if ZEND_DEBUG
- const char *filename,
- uint lineno,
+ zend_mm_change_huge_block_size(heap, ptr, new_size, real_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#else
+ zend_mm_change_huge_block_size(heap, ptr, new_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#endif
+ return ptr;
+#ifndef _WIN32
+ } else if (new_size < old_size) {
+ /* unmup tail */
+ zend_mm_munmap((char*)ptr + new_size, old_size - new_size);
+#if ZEND_MM_STAT || ZEND_MM_LIMIT
+ heap->real_size -= old_size - new_size;
+#endif
+#if ZEND_MM_STAT
+ heap->size -= old_size - new_size;
#endif
- size_t size)
-{
- if (heap->reserve) {
- _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
- heap->reserve = NULL;
- }
- if (heap->overflow == 0) {
- const char *error_filename;
- uint error_lineno;
- TSRMLS_FETCH();
- if (zend_is_compiling(TSRMLS_C)) {
- zend_string *str = zend_get_compiled_filename(TSRMLS_C);
- error_filename = str ? str->val : NULL;
- error_lineno = zend_get_compiled_lineno(TSRMLS_C);
- } else if (EG(current_execute_data)) {
- zend_execute_data *ex = EG(current_execute_data);
-
- while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
- ex = ex->prev_execute_data;
- }
- if (ex) {
- error_filename = ex->func->op_array.filename->val;
- error_lineno = ex->opline->lineno;
- } else {
- error_filename = NULL;
- error_lineno = 0;
- }
- } else {
- error_filename = NULL;
- error_lineno = 0;
- }
- if (!error_filename) {
- error_filename = "Unknown";
- }
- heap->overflow = 1;
- zend_try {
- zend_error_noreturn(E_ERROR,
- format,
- limit,
#if ZEND_DEBUG
- filename,
- lineno,
-#endif
- size);
- } zend_catch {
- if (heap->overflow == 2) {
- fprintf(stderr, "\nFatal error: ");
- fprintf(stderr,
- format,
- limit,
+ zend_mm_change_huge_block_size(heap, ptr, new_size, real_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#else
+ zend_mm_change_huge_block_size(heap, ptr, new_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#endif
+ return ptr;
+ } else /* if (new_size > old_size) */ {
+#if ZEND_MM_LIMIT
+ if (heap->real_size + (new_size - old_size) > heap->limit) {
+ if (heap->overflow == 0) {
#if ZEND_DEBUG
- filename,
- lineno,
+ zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted at %s:%d (tried to allocate " ZEND_ULONG_FMT " bytes)", heap->limit, __zend_filename, __zend_lineno, size);
+#else
+ zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted (tried to allocate " ZEND_ULONG_FMT " bytes)", heap->limit, size);
#endif
- size);
- fprintf(stderr, " in %s on line %d\n", error_filename, error_lineno);
- }
-/* See http://support.microsoft.com/kb/190351 */
-#ifdef PHP_WIN32
- fflush(stderr);
+ return NULL;
+ }
+ }
+#endif
+ /* try to map tail right after this block */
+ if (zend_mm_mmap_fixed((char*)ptr + old_size, new_size - old_size)) {
+#if ZEND_MM_STAT || ZEND_MM_LIMIT
+ heap->real_size += new_size - old_size;
+#endif
+#if ZEND_MM_STAT
+ heap->size += new_size - old_size;
#endif
- } zend_end_try();
+#if ZEND_DEBUG
+ zend_mm_change_huge_block_size(heap, ptr, new_size, real_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#else
+ zend_mm_change_huge_block_size(heap, ptr, new_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#endif
+ return ptr;
+ }
+#endif
+ }
+ }
} else {
- heap->overflow = 2;
- }
- zend_bailout();
-}
+ zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE);
+ int page_num = page_offset / ZEND_MM_PAGE_SIZE;
+ zend_mm_page_info info = chunk->map[page_num];
+#if ZEND_DEBUG
+ size_t real_size = size;
-static zend_mm_free_block *zend_mm_search_large_block(zend_mm_heap *heap, size_t true_size)
-{
- zend_mm_free_block *best_fit;
- size_t index = ZEND_MM_LARGE_BUCKET_INDEX(true_size);
- size_t bitmap = heap->large_free_bitmap >> index;
- zend_mm_free_block *p;
+ size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
+#endif
- if (bitmap == 0) {
- return NULL;
- }
+ ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted");
+ if (info & ZEND_MM_IS_SRUN) {
+ int old_bin_num, bin_num;
- if (UNEXPECTED((bitmap & 1) != 0)) {
- /* Search for best "large" free block */
- zend_mm_free_block *rst = NULL;
- size_t m;
- size_t best_size = -1;
-
- best_fit = NULL;
- p = heap->large_free_buckets[index];
- for (m = true_size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
- if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
- return p->next_free_block;
- } else if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size &&
- ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
- best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
- best_fit = p;
+ old_bin_num = ZEND_MM_SRUN_BIN_NUM(info);
+ old_size = bin_data_size[old_bin_num];
+ bin_num = ZEND_MM_SMALL_SIZE_TO_BIN(size);
+ if (old_bin_num == bin_num) {
+#if ZEND_DEBUG
+ dbg = zend_mm_get_debug_info(heap, ptr);
+ dbg->size = real_size;
+ dbg->filename = __zend_filename;
+ dbg->orig_filename = __zend_orig_filename;
+ dbg->lineno = __zend_lineno;
+ dbg->orig_lineno = __zend_orig_lineno;
+#endif
+ return ptr;
}
- if ((m & (ZEND_MM_LONG_CONST(1) << (ZEND_MM_NUM_BUCKETS-1))) == 0) {
- if (p->child[1]) {
- rst = p->child[1];
- }
- if (p->child[0]) {
- p = p->child[0];
- } else {
- break;
+ } else /* if (info & ZEND_MM_IS_LARGE_RUN) */ {
+ ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(page_offset, ZEND_MM_PAGE_SIZE) == 0, "zend_mm_heap corrupted");
+ old_size = ZEND_MM_LRUN_PAGES(info) * ZEND_MM_PAGE_SIZE;
+ if (size > ZEND_MM_MAX_SMALL_SIZE && size <= ZEND_MM_MAX_LARGE_SIZE) {
+ new_size = ZEND_MM_ALIGNED_SIZE_EX(size, ZEND_MM_PAGE_SIZE);
+ if (new_size == old_size) {
+#if ZEND_DEBUG
+ dbg = zend_mm_get_debug_info(heap, ptr);
+ dbg->size = real_size;
+ dbg->filename = __zend_filename;
+ dbg->orig_filename = __zend_orig_filename;
+ dbg->lineno = __zend_lineno;
+ dbg->orig_lineno = __zend_orig_lineno;
+#endif
+ return ptr;
+ } else if (new_size < old_size) {
+ /* free tail pages */
+ int new_pages_count = new_size / ZEND_MM_PAGE_SIZE;
+ int rest_pages_count = (old_size - new_size) / ZEND_MM_PAGE_SIZE;
+
+#if ZEND_MM_STAT
+ heap->size -= rest_pages_count * ZEND_MM_PAGE_SIZE;
+#endif
+ chunk->map[page_num] = ZEND_MM_LRUN(new_pages_count);
+ chunk->free_pages += rest_pages_count;
+ zend_mm_bitset_reset_range(chunk->free_map, page_num + new_pages_count, rest_pages_count);
+#if ZEND_DEBUG
+ dbg = zend_mm_get_debug_info(heap, ptr);
+ dbg->size = real_size;
+ dbg->filename = __zend_filename;
+ dbg->orig_filename = __zend_orig_filename;
+ dbg->lineno = __zend_lineno;
+ dbg->orig_lineno = __zend_orig_lineno;
+#endif
+ return ptr;
+ } else /* if (new_size > old_size) */ {
+ int new_pages_count = new_size / ZEND_MM_PAGE_SIZE;
+ int old_pages_count = old_size / ZEND_MM_PAGE_SIZE;
+
+ /* try to allocate tail pages after this block */
+ if (page_num + new_pages_count <= ZEND_MM_PAGES &&
+ zend_mm_bitset_is_free_range(chunk->free_map, page_num + old_pages_count, new_pages_count - old_pages_count)) {
+#if ZEND_MM_STAT
+ do {
+ size_t size = heap->size + (new_size - old_size);
+ size_t peak = MAX(heap->peak, size);
+ heap->size = size;
+ heap->peak = peak;
+ } while (0);
+#endif
+ chunk->free_pages -= new_pages_count - old_pages_count;
+ zend_mm_bitset_set_range(chunk->free_map, page_num + old_pages_count, new_pages_count - old_pages_count);
+ chunk->map[page_num] = ZEND_MM_LRUN(new_pages_count);
+#if ZEND_DEBUG
+ dbg = zend_mm_get_debug_info(heap, ptr);
+ dbg->size = real_size;
+ dbg->filename = __zend_filename;
+ dbg->orig_filename = __zend_orig_filename;
+ dbg->lineno = __zend_lineno;
+ dbg->orig_lineno = __zend_orig_lineno;
+#endif
+ return ptr;
+ }
}
- } else if (p->child[1]) {
- p = p->child[1];
- } else {
- break;
}
}
-
- for (p = rst; p; p = p->child[p->child[0] != NULL]) {
- if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
- return p->next_free_block;
- } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
- ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
- best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
- best_fit = p;
- }
- }
-
- if (best_fit) {
- return best_fit->next_free_block;
- }
- bitmap = bitmap >> 1;
- if (!bitmap) {
- return NULL;
- }
- index++;
+#if ZEND_DEBUG
+ size = real_size;
+#endif
}
- /* Search for smallest "large" free block */
- best_fit = p = heap->large_free_buckets[index + zend_mm_low_bit(bitmap)];
- while ((p = p->child[p->child[0] != NULL])) {
- if (ZEND_MM_FREE_BLOCK_SIZE(p) < ZEND_MM_FREE_BLOCK_SIZE(best_fit)) {
- best_fit = p;
- }
- }
- return best_fit->next_free_block;
+ /* Naive reallocation */
+ old_size = zend_mm_size(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ ret = zend_mm_alloc_heap(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ memcpy(ret, ptr, MIN(old_size, size));
+ zend_mm_free_heap(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ return ret;
}
-static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
-{
- zend_mm_free_block *best_fit;
- size_t true_size = ZEND_MM_TRUE_SIZE(size);
- size_t block_size;
- size_t remaining_size;
- size_t segment_size;
- zend_mm_segment *segment;
- int keep_rest = 0;
-#ifdef ZEND_SIGNALS
- TSRMLS_FETCH();
-#endif
-
- HANDLE_BLOCK_INTERRUPTIONS();
-
- if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
- size_t index = ZEND_MM_BUCKET_INDEX(true_size);
- size_t bitmap;
-
- if (UNEXPECTED(true_size < size)) {
- goto out_of_memory;
- }
-#if ZEND_MM_CACHE
- if (EXPECTED(heap->cache[index] != NULL)) {
- /* Get block from cache */
-#if ZEND_MM_CACHE_STAT
- heap->cache_stat[index].count--;
- heap->cache_stat[index].hit++;
-#endif
- best_fit = heap->cache[index];
- heap->cache[index] = best_fit->prev_free_block;
- heap->cached -= true_size;
- ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
- ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return ZEND_MM_DATA_OF(best_fit);
- }
-#if ZEND_MM_CACHE_STAT
- heap->cache_stat[index].miss++;
-#endif
-#endif
-
- bitmap = heap->free_bitmap >> index;
- if (bitmap) {
- /* Found some "small" free block that can be used */
- index += zend_mm_low_bit(bitmap);
- best_fit = heap->free_buckets[index*2];
-#if ZEND_MM_CACHE_STAT
- heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit++;
-#endif
- goto zend_mm_finished_searching_for_block;
- }
- }
+/*********************/
+/* Huge Runs (again) */
+/*********************/
-#if ZEND_MM_CACHE_STAT
- heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss++;
+#if ZEND_DEBUG
+static void zend_mm_add_huge_block(zend_mm_heap *heap, void *ptr, size_t size, size_t dbg_size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+#else
+static void zend_mm_add_huge_block(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
#endif
+{
+ zend_mm_huge_list *list = (zend_mm_huge_list*)zend_mm_alloc_heap(heap, sizeof(zend_mm_huge_list) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ list->ptr = ptr;
+ list->size = size;
+ list->next = heap->huge_list;
+#if ZEND_DEBUG
+ list->dbg.size = dbg_size;
+ list->dbg.filename = __zend_filename;
+ list->dbg.orig_filename = __zend_orig_filename;
+ list->dbg.lineno = __zend_lineno;
+ list->dbg.orig_lineno = __zend_orig_lineno;
+#endif
+ heap->huge_list = list;
+}
- best_fit = zend_mm_search_large_block(heap, true_size);
-
- if (!best_fit && heap->real_size >= heap->limit - heap->block_size) {
- zend_mm_free_block *p = heap->rest_buckets[0];
- size_t best_size = -1;
+static size_t zend_mm_del_huge_block(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+{
+ zend_mm_huge_list *prev = NULL;
+ zend_mm_huge_list *list = heap->huge_list;
+ while (list != NULL) {
+ if (list->ptr == ptr) {
+ size_t size;
- while (p != ZEND_MM_REST_BUCKET(heap)) {
- if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
- best_fit = p;
- goto zend_mm_finished_searching_for_block;
- } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
- ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
- best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
- best_fit = p;
+ if (prev) {
+ prev->next = list->next;
+ } else {
+ heap->huge_list = list->next;
}
- p = p->prev_free_block;
+ size = list->size;
+ zend_mm_free_heap(heap, list ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ return size;
}
+ prev = list;
+ list = list->next;
}
+ ZEND_MM_CHECK(0, "zend_mm_heap corrupted");
+ return 0;
+}
- if (!best_fit) {
- if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
- /* Make sure we add a memory block which is big enough,
- segment must have header "size" and trailer "guard" block */
- segment_size = true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE;
- segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
- keep_rest = 1;
- } else {
- segment_size = heap->block_size;
+static size_t zend_mm_get_huge_block_size(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+{
+ zend_mm_huge_list *list = heap->huge_list;
+ while (list != NULL) {
+ if (list->ptr == ptr) {
+ return list->size;
}
+ list = list->next;
+ }
+ ZEND_MM_CHECK(0, "zend_mm_heap corrupted");
+ return 0;
+}
- if (segment_size < true_size ||
- heap->real_size + segment_size > heap->limit) {
- /* Memory limit overflow */
-#if ZEND_MM_CACHE
- zend_mm_free_cache(heap);
-#endif
- HANDLE_UNBLOCK_INTERRUPTIONS();
#if ZEND_DEBUG
- zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %lu bytes)", heap->limit, __zend_filename, __zend_lineno, size);
+static void zend_mm_change_huge_block_size(zend_mm_heap *heap, void *ptr, size_t size, size_t dbg_size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
#else
- zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %lu bytes)", heap->limit, size);
+static void zend_mm_change_huge_block_size(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+#endif
+{
+ zend_mm_huge_list *list = heap->huge_list;
+ while (list != NULL) {
+ if (list->ptr == ptr) {
+ list->size = size;
+#if ZEND_DEBUG
+ list->dbg.size = dbg_size;
+ list->dbg.filename = __zend_filename;
+ list->dbg.orig_filename = __zend_orig_filename;
+ list->dbg.lineno = __zend_lineno;
+ list->dbg.orig_lineno = __zend_orig_lineno;
#endif
+ return;
}
+ list = list->next;
+ }
+}
- segment = (zend_mm_segment *) ZEND_MM_STORAGE_ALLOC(segment_size);
+static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+{
+ size_t new_size = ZEND_MM_ALIGNED_SIZE_EX(size, ZEND_MM_PAGE_SIZE);
+ void *ptr;
- if (!segment) {
- /* Storage manager cannot allocate memory */
-#if ZEND_MM_CACHE
- zend_mm_free_cache(heap);
-#endif
-out_of_memory:
- HANDLE_UNBLOCK_INTERRUPTIONS();
+#if ZEND_MM_LIMIT
+ if (heap->real_size + new_size > heap->limit) {
+ if (heap->overflow == 0) {
#if ZEND_DEBUG
- zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
+ zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted at %s:%d (tried to allocate %lu bytes)", heap->limit, __zend_filename, __zend_lineno, size);
#else
- zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, size);
+ zend_mm_safe_error(heap, "Allowed memory size of " ZEND_ULONG_FMT " bytes exhausted (tried to allocate %lu bytes)", heap->limit, size);
#endif
return NULL;
}
-
- heap->real_size += segment_size;
- if (heap->real_size > heap->real_peak) {
- heap->real_peak = heap->real_size;
- }
-
- segment->size = segment_size;
- segment->next_segment = heap->segments_list;
- heap->segments_list = segment;
-
- best_fit = (zend_mm_free_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
- ZEND_MM_MARK_FIRST_BLOCK(best_fit);
-
- block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
-
- ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(best_fit, block_size));
-
- } else {
-zend_mm_finished_searching_for_block:
- /* remove from free list */
- ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_FREED);
- ZEND_MM_CHECK_COOKIE(best_fit);
- ZEND_MM_CHECK_BLOCK_LINKAGE(best_fit);
- zend_mm_remove_from_free_list(heap, best_fit);
-
- block_size = ZEND_MM_FREE_BLOCK_SIZE(best_fit);
- }
-
- remaining_size = block_size - true_size;
-
- if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
- true_size = block_size;
- ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
- } else {
- zend_mm_free_block *new_free_block;
-
- /* prepare new free block */
- ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
- new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(best_fit, true_size);
- ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
-
- /* add the new free block to the free list */
- if (EXPECTED(!keep_rest)) {
- zend_mm_add_to_free_list(heap, new_free_block);
- } else {
- zend_mm_add_to_rest_list(heap, new_free_block);
- }
}
-
- ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1);
-
- heap->size += true_size;
- if (heap->peak < heap->size) {
- heap->peak = heap->size;
+#endif
+ ptr = zend_mm_chunk_alloc(new_size, ZEND_MM_CHUNK_SIZE);
+ if (UNEXPECTED(ptr == NULL)) {
+ /* insufficient memory */
+#if !ZEND_MM_LIMIT
+ zend_mm_safe_error(heap, "Out of memory");
+#elif ZEND_DEBUG
+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
+#else
+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, size);
+#endif
+ return NULL;
}
-
- HANDLE_UNBLOCK_INTERRUPTIONS();
-
- return ZEND_MM_DATA_OF(best_fit);
+#if ZEND_DEBUG
+ zend_mm_add_huge_block(heap, ptr, new_size, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#else
+ zend_mm_add_huge_block(heap, ptr, new_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#endif
+#if ZEND_MM_STAT
+ do {
+ size_t size = heap->real_size + new_size;
+ size_t peak = MAX(heap->real_peak, size);
+ heap->real_size = size;
+ heap->real_peak = peak;
+ } while (0);
+ do {
+ size_t size = heap->size + new_size;
+ size_t peak = MAX(heap->peak, size);
+ heap->size = size;
+ heap->peak = peak;
+ } while (0);
+#elif ZEND_MM_LIMIT
+ heap->real_size += new_size;
+#endif
+ return ptr;
}
-
-static void _zend_mm_free_int(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- zend_mm_block *mm_block;
- zend_mm_block *next_block;
size_t size;
-#ifdef ZEND_SIGNALS
- TSRMLS_FETCH();
+
+ ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE) == 0, "zend_mm_heap corrupted");
+ size = zend_mm_del_huge_block(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ zend_mm_munmap(ptr, size);
+#if ZEND_MM_STAT || ZEND_MM_LIMIT
+ heap->real_size -= size;
#endif
- if (!ZEND_MM_VALID_PTR(p)) {
- return;
- }
+#if ZEND_MM_STAT
+ heap->size -= size;
+#endif
+}
- HANDLE_BLOCK_INTERRUPTIONS();
+/******************/
+/* Initialization */
+/******************/
- mm_block = ZEND_MM_HEADER_OF(p);
- size = ZEND_MM_BLOCK_SIZE(mm_block);
- ZEND_MM_CHECK_PROTECTION(mm_block);
+zend_mm_heap *zend_mm_init(void)
+{
+ zend_mm_chunk *chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
+ zend_mm_heap *heap;
-#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
- memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size);
+ if (UNEXPECTED(chunk == NULL)) {
+#if ZEND_MM_ERROR
+#ifdef _WIN32
+ stderr_last_error("Can't initialize heap");
+#else
+ fprintf(stderr, "\nCan't initialize heap: [%d] %s\n", errno, strerror(errno));
#endif
-
-#if ZEND_MM_CACHE
- if (EXPECTED(ZEND_MM_SMALL_SIZE(size)) && EXPECTED(heap->cached < ZEND_MM_CACHE_SIZE)) {
- size_t index = ZEND_MM_BUCKET_INDEX(size);
- zend_mm_free_block **cache = &heap->cache[index];
-
- ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
- *cache = (zend_mm_free_block*)mm_block;
- heap->cached += size;
- ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
-#if ZEND_MM_CACHE_STAT
- if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
- heap->cache_stat[index].max_count = heap->cache_stat[index].count;
- }
#endif
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return;
+ return NULL;
}
+ heap = &chunk->heap_slot;
+ chunk->heap = heap;
+ chunk->next = chunk;
+ chunk->prev = chunk;
+ chunk->free_pages = ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE;
+ chunk->free_tail = ZEND_MM_FIRST_PAGE;
+ chunk->num = 0;
+ chunk->free_map[0] = (Z_L(1) << ZEND_MM_FIRST_PAGE) - 1;
+ chunk->map[0] = ZEND_MM_LRUN(ZEND_MM_FIRST_PAGE);
+ heap->main_chunk = chunk;
+ heap->cached_chunks = NULL;
+ heap->chunks_count = 1;
+ heap->peak_chunks_count = 1;
+ heap->cached_chunks_count = 0;
+ heap->avg_chunks_count = 1.0;
+#if ZEND_MM_STAT || ZEND_MM_LIMIT
+ heap->real_size = ZEND_MM_CHUNK_SIZE;
+#endif
+#if ZEND_MM_STAT
+ heap->real_peak = ZEND_MM_CHUNK_SIZE;
+ heap->size = 0;
+ heap->peak = 0;
#endif
+#if ZEND_MM_LIMIT
+ heap->limit = (Z_L(-1) >> Z_L(1));
+ heap->overflow = 0;
+#endif
+#if ZEND_MM_CUSTOM
+ heap->use_custom_heap = 0;
+#endif
+ heap->huge_list = NULL;
+ return heap;
+}
- heap->size -= size;
-
- next_block = ZEND_MM_BLOCK_AT(mm_block, size);
- if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
- zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
- size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
- }
- if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
- mm_block = ZEND_MM_PREV_BLOCK(mm_block);
- zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) mm_block);
- size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
+#if ZEND_DEBUG
+/******************/
+/* Leak detection */
+/******************/
+
+static zend_long zend_mm_find_leaks_small(zend_mm_chunk *p, int i, int j, zend_leak_info *leak)
+{
+ int empty = 1;
+ zend_long count = 0;
+ int bin_num = ZEND_MM_SRUN_BIN_NUM(p->map[i]);
+ zend_mm_debug_info *dbg = (zend_mm_debug_info*)((char*)p + ZEND_MM_PAGE_SIZE * i + bin_data_size[bin_num] * (j + 1) - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+
+ while (j < bin_elements[bin_num]) {
+ if (dbg->size != 0) {
+ if (dbg->filename == leak->filename && dbg->lineno == leak->lineno) {
+ count++;
+ dbg->size = 0;
+ dbg->filename = NULL;
+ dbg->lineno = 0;
+ } else {
+ empty = 0;
+ }
+ }
+ j++;
+ dbg = (zend_mm_debug_info*)((char*)dbg + bin_data_size[bin_num]);
}
- if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
- ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(mm_block, size))) {
- zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
- } else {
- ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
- zend_mm_add_to_free_list(heap, (zend_mm_free_block *) mm_block);
+ if (empty) {
+ zend_mm_bitset_reset_range(p->free_map, i, bin_pages[bin_num]);
}
- HANDLE_UNBLOCK_INTERRUPTIONS();
+ return count;
}
-static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+static zend_long zend_mm_find_leaks(zend_mm_heap *heap, zend_mm_chunk *p, int i, zend_leak_info *leak)
{
- zend_mm_block *mm_block = ZEND_MM_HEADER_OF(p);
- zend_mm_block *next_block;
- size_t true_size;
- size_t orig_size;
- void *ptr;
-#ifdef ZEND_SIGNALS
- TSRMLS_FETCH();
-#endif
- if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) {
- return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- }
-
- HANDLE_BLOCK_INTERRUPTIONS();
+ zend_long count = 0;
- mm_block = ZEND_MM_HEADER_OF(p);
- true_size = ZEND_MM_TRUE_SIZE(size);
- orig_size = ZEND_MM_BLOCK_SIZE(mm_block);
- ZEND_MM_CHECK_PROTECTION(mm_block);
+ do {
+ while (i < p->free_tail) {
+ if (zend_mm_bitset_is_set(p->free_map, i)) {
+ if (p->map[i] & ZEND_MM_IS_SRUN) {
+ int bin_num = ZEND_MM_SRUN_BIN_NUM(p->map[i]);
+ count += zend_mm_find_leaks_small(p, i, 0, leak);
+ i += bin_pages[bin_num];
+ } else /* if (p->map[i] & ZEND_MM_IS_LRUN) */ {
+ int pages_count = ZEND_MM_LRUN_PAGES(p->map[i]);
+ zend_mm_debug_info *dbg = (zend_mm_debug_info*)((char*)p + ZEND_MM_PAGE_SIZE * (i + pages_count) - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
- if (UNEXPECTED(true_size < size)) {
- goto out_of_memory;
- }
-
- if (true_size <= orig_size) {
- size_t remaining_size = orig_size - true_size;
-
- if (remaining_size >= ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
- zend_mm_free_block *new_free_block;
-
- next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
- if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
- remaining_size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
- zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
+ if (dbg->filename == leak->filename && dbg->lineno == leak->lineno) {
+ count++;
+ }
+ zend_mm_bitset_reset_range(p->free_map, i, pages_count);
+ i += pages_count;
+ }
+ } else {
+ i++;
}
-
- /* prepare new free block */
- ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
- new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(mm_block, true_size);
-
- ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
-
- /* add the new free block to the free list */
- zend_mm_add_to_free_list(heap, new_free_block);
- heap->size += (true_size - orig_size);
}
- ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return p;
- }
+ p = p->next;
+ } while (p != heap->main_chunk);
+ return count;
+}
-#if ZEND_MM_CACHE
- if (ZEND_MM_SMALL_SIZE(true_size)) {
- size_t index = ZEND_MM_BUCKET_INDEX(true_size);
-
- if (heap->cache[index] != NULL) {
- zend_mm_free_block *best_fit;
- zend_mm_free_block **cache;
-
-#if ZEND_MM_CACHE_STAT
- heap->cache_stat[index].count--;
- heap->cache_stat[index].hit++;
-#endif
- best_fit = heap->cache[index];
- heap->cache[index] = best_fit->prev_free_block;
- ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
- ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
-
- ptr = ZEND_MM_DATA_OF(best_fit);
-
-#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
- memcpy(ptr, p, mm_block->debug.size);
-#else
- memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
-#endif
+static void zend_mm_check_leaks(zend_mm_heap *heap TSRMLS_DC)
+{
+ zend_mm_huge_list *list;
+ zend_mm_chunk *p;
+ zend_leak_info leak;
+ zend_long repeated = 0;
+ uint32_t total = 0;
+ int i, j;
- heap->cached -= true_size - orig_size;
+ /* find leaked huge blocks and free them */
+ list = heap->huge_list;
+ while (list) {
+ zend_mm_huge_list *q = list;
- index = ZEND_MM_BUCKET_INDEX(orig_size);
- cache = &heap->cache[index];
+ heap->huge_list = list->next;
- ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
- *cache = (zend_mm_free_block*)mm_block;
- ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
-#if ZEND_MM_CACHE_STAT
- if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
- heap->cache_stat[index].max_count = heap->cache_stat[index].count;
- }
-#endif
+ leak.addr = list->ptr;
+ leak.size = list->dbg.size;
+ leak.filename = list->dbg.filename;
+ leak.orig_filename = list->dbg.orig_filename;
+ leak.lineno = list->dbg.lineno;
+ leak.orig_lineno = list->dbg.orig_lineno;
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return ptr;
+ zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
+ zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, &leak TSRMLS_CC);
+//??? repeated = zend_mm_find_leaks_huge(segment, p);
+ total += 1 + repeated;
+ if (repeated) {
+ zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(zend_uintptr_t)repeated TSRMLS_CC);
+ }
+
+ list = list->next;
+ zend_mm_munmap(q->ptr, q->size);
+ zend_mm_free_heap(heap, q, NULL, 0, NULL, 0);
+ }
+
+ /* for each chunk */
+ p = heap->main_chunk;
+ do {
+ i = ZEND_MM_FIRST_PAGE;
+ while (i < p->free_tail) {
+ if (zend_mm_bitset_is_set(p->free_map, i)) {
+ if (p->map[i] & ZEND_MM_IS_SRUN) {
+ int bin_num = ZEND_MM_SRUN_BIN_NUM(p->map[i]);
+ zend_mm_debug_info *dbg = (zend_mm_debug_info*)((char*)p + ZEND_MM_PAGE_SIZE * i + bin_data_size[bin_num] - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+
+ j = 0;
+ while (j < bin_elements[bin_num]) {
+ if (dbg->size != 0) {
+ leak.addr = (zend_mm_debug_info*)((char*)p + ZEND_MM_PAGE_SIZE * i + bin_data_size[bin_num] * j);
+ leak.size = dbg->size;
+ leak.filename = dbg->filename;
+ leak.orig_filename = dbg->orig_filename;
+ leak.lineno = dbg->lineno;
+ leak.orig_lineno = dbg->orig_lineno;
+
+ zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
+ zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, &leak TSRMLS_CC);
+
+ dbg->size = 0;
+ dbg->filename = NULL;
+ dbg->lineno = 0;
+
+ repeated = zend_mm_find_leaks_small(p, i, j + 1, &leak) +
+ zend_mm_find_leaks(heap, p, i + bin_pages[bin_num], &leak);
+ total += 1 + repeated;
+ if (repeated) {
+ zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(zend_uintptr_t)repeated TSRMLS_CC);
+ }
+ }
+ dbg = (zend_mm_debug_info*)((char*)dbg + bin_data_size[bin_num]);
+ j++;
+ }
+ i += bin_pages[bin_num];
+ } else /* if (p->map[i] & ZEND_MM_IS_LRUN) */ {
+ int pages_count = ZEND_MM_LRUN_PAGES(p->map[i]);
+ zend_mm_debug_info *dbg = (zend_mm_debug_info*)((char*)p + ZEND_MM_PAGE_SIZE * (i + pages_count) - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+
+ leak.addr = (void*)((char*)p + ZEND_MM_PAGE_SIZE * i);
+ leak.size = dbg->size;
+ leak.filename = dbg->filename;
+ leak.orig_filename = dbg->orig_filename;
+ leak.lineno = dbg->lineno;
+ leak.orig_lineno = dbg->orig_lineno;
+
+ zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
+ zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, &leak TSRMLS_CC);
+
+ zend_mm_bitset_reset_range(p->free_map, i, pages_count);
+
+ repeated = zend_mm_find_leaks(heap, p, i + pages_count, &leak);
+ total += 1 + repeated;
+ if (repeated) {
+ zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(zend_uintptr_t)repeated TSRMLS_CC);
+ }
+ i += pages_count;
+ }
+ } else {
+ i++;
+ }
}
+ p = p->next;
+ } while (p != heap->main_chunk);
+ if (total) {
+ zend_message_dispatcher(ZMSG_MEMORY_LEAKS_GRAND_TOTAL, &total TSRMLS_CC);
}
+}
#endif
- next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
-
- if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
- ZEND_MM_CHECK_COOKIE(next_block);
- ZEND_MM_CHECK_BLOCK_LINKAGE(next_block);
- if (orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block) >= true_size) {
- size_t block_size = orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block);
- size_t remaining_size = block_size - true_size;
-
- zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
-
- if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
- true_size = block_size;
- ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
- } else {
- zend_mm_free_block *new_free_block;
-
- /* prepare new free block */
- ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
- new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(mm_block, true_size);
- ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
-
- /* add the new free block to the free list */
- if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
- ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(new_free_block, remaining_size))) {
- zend_mm_add_to_rest_list(heap, new_free_block);
- } else {
- zend_mm_add_to_free_list(heap, new_free_block);
- }
- }
- ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
- heap->size = heap->size + true_size - orig_size;
- if (heap->peak < heap->size) {
- heap->peak = heap->size;
- }
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return p;
- } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
- ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) {
- zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
- goto realloc_segment;
- }
- } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ZEND_MM_IS_GUARD_BLOCK(next_block)) {
- zend_mm_segment *segment;
- zend_mm_segment *segment_copy;
- size_t segment_size;
- size_t block_size;
- size_t remaining_size;
-
-realloc_segment:
- /* segment size, size of block and size of guard block */
- if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
- segment_size = true_size+ZEND_MM_ALIGNED_SEGMENT_SIZE+ZEND_MM_ALIGNED_HEADER_SIZE;
- segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
- } else {
- segment_size = heap->block_size;
- }
+void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC)
+{
+ zend_mm_chunk *p;
+ zend_mm_huge_list *list;
- segment_copy = (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE);
- if (segment_size < true_size ||
- heap->real_size + segment_size - segment_copy->size > heap->limit) {
- if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
- zend_mm_add_to_free_list(heap, (zend_mm_free_block *) next_block);
- }
-#if ZEND_MM_CACHE
- zend_mm_free_cache(heap);
-#endif
- HANDLE_UNBLOCK_INTERRUPTIONS();
-#if ZEND_DEBUG
- zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %ld bytes)", heap->limit, __zend_filename, __zend_lineno, size);
-#else
- zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %ld bytes)", heap->limit, size);
+#if ZEND_MM_CUSTOM
+ if (heap->use_custom_heap) {
+ return;
+ }
#endif
- return NULL;
- }
- segment = ZEND_MM_STORAGE_REALLOC(segment_copy, segment_size);
- if (!segment) {
-#if ZEND_MM_CACHE
- zend_mm_free_cache(heap);
-#endif
-out_of_memory:
- HANDLE_UNBLOCK_INTERRUPTIONS();
#if ZEND_DEBUG
- zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %ld bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
-#else
- zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %ld bytes)", heap->real_size, size);
+ if (!silent) {
+ zend_mm_check_leaks(heap TSRMLS_CC);
+ }
#endif
- return NULL;
- }
- heap->real_size += segment_size - segment->size;
- if (heap->real_size > heap->real_peak) {
- heap->real_peak = heap->real_size;
- }
-
- segment->size = segment_size;
-
- if (segment != segment_copy) {
- zend_mm_segment **seg = &heap->segments_list;
- while (*seg != segment_copy) {
- seg = &(*seg)->next_segment;
- }
- *seg = segment;
- mm_block = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
- ZEND_MM_MARK_FIRST_BLOCK(mm_block);
- }
-
- block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
- remaining_size = block_size - true_size;
-
- /* setup guard block */
- ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(mm_block, block_size));
-
- if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
- true_size = block_size;
- ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
- } else {
- zend_mm_free_block *new_free_block;
- /* prepare new free block */
- ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
- new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(mm_block, true_size);
- ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
-
- /* add the new free block to the free list */
- zend_mm_add_to_rest_list(heap, new_free_block);
- }
-
- ZEND_MM_SET_DEBUG_INFO(mm_block, size, 1, 1);
-
- heap->size = heap->size + true_size - orig_size;
- if (heap->peak < heap->size) {
- heap->peak = heap->size;
- }
+ /* free huge blocks */
+ list = heap->huge_list;
+ while (list) {
+ zend_mm_huge_list *q = list;
+ list = list->next;
+ zend_mm_munmap(q->ptr, q->size);
+ }
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return ZEND_MM_DATA_OF(mm_block);
+ /* move all chunks except of the first one into the cache */
+ p = heap->main_chunk->next;
+ while (p != heap->main_chunk) {
+ zend_mm_chunk *q = p->next;
+ p->next = heap->cached_chunks;
+ heap->cached_chunks = p;
+ p = q;
+ heap->chunks_count--;
+ heap->cached_chunks_count++;
}
- ptr = _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
-#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
- memcpy(ptr, p, mm_block->debug.size);
-#else
- memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
-#endif
- _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return ptr;
-}
+ if (full) {
+ /* free all cached chunks */
+ while (heap->cached_chunks) {
+ p = heap->cached_chunks;
+ heap->cached_chunks = p->next;
+ zend_mm_munmap(p, ZEND_MM_CHUNK_SIZE);
+ }
+ /* free the first chunk */
+ zend_mm_munmap(heap->main_chunk, ZEND_MM_CHUNK_SIZE);
+ } else {
+ zend_mm_heap old_heap;
+
+ /* free some cached chunks to keep average count */
+ heap->avg_chunks_count = (heap->avg_chunks_count + (double)heap->peak_chunks_count) / 2.0;
+ while ((double)heap->cached_chunks_count + 0.9 > heap->avg_chunks_count &&
+ heap->cached_chunks) {
+ p = heap->cached_chunks;
+ heap->cached_chunks = p->next;
+ zend_mm_munmap(p, ZEND_MM_CHUNK_SIZE);
+ heap->cached_chunks_count--;
+ }
+ /* clear cached chunks */
+ p = heap->cached_chunks;
+ while (p != NULL) {
+ zend_mm_chunk *q = p->next;
+ memset(p, 0, sizeof(zend_mm_chunk));
+ p->next = q;
+ p = q;
+ }
+
+ /* reinitialize the first chunk and heap */
+ old_heap = *heap;
+ p = heap->main_chunk;
+ memset(p, 0, ZEND_MM_FIRST_PAGE * ZEND_MM_PAGE_SIZE);
+ *heap = old_heap;
+ memset(heap->free_slot, 0, sizeof(heap->free_slot));
+ heap->main_chunk = p;
+ p->heap = &p->heap_slot;
+ p->next = p;
+ p->prev = p;
+ p->free_pages = ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE;
+ p->free_tail = ZEND_MM_FIRST_PAGE;
+ p->free_map[0] = (1L << ZEND_MM_FIRST_PAGE) - 1;
+ p->map[0] = ZEND_MM_LRUN(ZEND_MM_FIRST_PAGE);
+ heap->chunks_count = 1;
+ heap->peak_chunks_count = 1;
+#if ZEND_MM_STAT || ZEND_MM_LIMIT
+ heap->real_size = ZEND_MM_CHUNK_SIZE;
+#endif
+#if ZEND_MM_STAT
+ heap->real_peak = ZEND_MM_CHUNK_SIZE;
+#endif
+ }
+}
+
+/**************/
+/* PUBLIC API */
+/**************/
ZEND_API void *_zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ return zend_mm_alloc_heap(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
-ZEND_API void _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ZEND_API void _zend_mm_free(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ zend_mm_free_heap(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
-ZEND_API void *_zend_mm_realloc(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+void *_zend_mm_realloc(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- return _zend_mm_realloc_int(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ return zend_mm_realloc_heap(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
-ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- zend_mm_block *mm_block;
-
- if (!ZEND_MM_VALID_PTR(p)) {
- return 0;
- }
- mm_block = ZEND_MM_HEADER_OF(p);
- ZEND_MM_CHECK_PROTECTION(mm_block);
-#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
- return mm_block->debug.size;
-#else
- return ZEND_MM_BLOCK_SIZE(mm_block);
-#endif
+ return zend_mm_size(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
/**********************/
@@ -2427,46 +1981,144 @@ static zend_alloc_globals alloc_globals;
ZEND_API int is_zend_mm(TSRMLS_D)
{
- return AG(mm_heap)->use_zend_alloc;
+#if ZEND_MM_CUSTOM
+ return !AG(mm_heap)->use_custom_heap;
+#else
+ return 1;
+#endif
+}
+
+#if !ZEND_DEBUG && !defined(_WIN32)
+#undef _emalloc
+
+#if ZEND_MM_CUSTOM
+# define ZEND_MM_CUSTOM_ALLOCATOR(size) do { \
+ if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { \
+ return AG(mm_heap)->_malloc(size); \
+ } \
+ } while (0)
+# define ZEND_MM_CUSTOM_DEALLOCATOR(ptr) do { \
+ if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { \
+ AG(mm_heap)->_free(ptr); \
+ return; \
+ } \
+ } while (0)
+#else
+# define ZEND_MM_CUSTOM_ALLOCATOR(size)
+# define ZEND_MM_CUSTOM_DEALLOCATOR(ptr)
+#endif
+
+# define _ZEND_BIN_ALLOCATOR(_num, _size, _elements, _pages, x, y) \
+ ZEND_API void* ZEND_FASTCALL _emalloc_ ## _size(void) { \
+ TSRMLS_FETCH(); \
+ ZEND_MM_CUSTOM_ALLOCATOR(_size); \
+ return zend_mm_alloc_small(AG(mm_heap), _size, _num ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
+ }
+
+ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR, x, y)
+
+ZEND_API void* ZEND_FASTCALL _emalloc_large(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+{
+ TSRMLS_FETCH();
+
+ ZEND_MM_CUSTOM_ALLOCATOR(size);
+ return zend_mm_alloc_large(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
-ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size)
{
TSRMLS_FETCH();
- if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
+ ZEND_MM_CUSTOM_ALLOCATOR(size);
+ return zend_mm_alloc_huge(AG(mm_heap), size);
+}
+
+# define _ZEND_BIN_FREE(_num, _size, _elements, _pages, x, y) \
+ ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *ptr) { \
+ TSRMLS_FETCH(); \
+ ZEND_MM_CUSTOM_DEALLOCATOR(ptr); \
+ { \
+ size_t page_offset = ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE); \
+ zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); \
+ int page_num = page_offset / ZEND_MM_PAGE_SIZE; \
+ ZEND_MM_CHECK(chunk->heap == AG(mm_heap), "zend_mm_heap corrupted"); \
+ ZEND_ASSERT(chunk->map[page_num] & ZEND_MM_IS_SRUN); \
+ ZEND_ASSERT(ZEND_MM_SRUN_BIN_NUM(chunk->map[page_num]) == _num); \
+ zend_mm_free_small(AG(mm_heap), ptr, _num); \
+ } \
+ }
+
+ZEND_MM_BINS_INFO(_ZEND_BIN_FREE, x, y)
+
+ZEND_API void ZEND_FASTCALL _efree_large(void *ptr, size_t size)
+{
+ TSRMLS_FETCH();
+
+ ZEND_MM_CUSTOM_DEALLOCATOR(ptr);
+ {
+ size_t page_offset = ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE);
+ zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE);
+ int page_num = page_offset / ZEND_MM_PAGE_SIZE;
+ int pages_count = ZEND_MM_ALIGNED_SIZE_EX(size, ZEND_MM_PAGE_SIZE) / ZEND_MM_PAGE_SIZE;
+
+ ZEND_MM_CHECK(chunk->heap == AG(mm_heap) && ZEND_MM_ALIGNED_OFFSET(page_offset, ZEND_MM_PAGE_SIZE) == 0, "zend_mm_heap corrupted");
+ ZEND_ASSERT(chunk->map[page_num] & ZEND_MM_IS_LRUN);
+ ZEND_ASSERT(ZEND_MM_LRUN_PAGES(chunk->map[page_num]) == pages_count);
+ zend_mm_free_large(AG(mm_heap), chunk, page_num, pages_count);
+ }
+}
+
+ZEND_API void ZEND_FASTCALL _efree_huge(void *ptr, size_t size)
+{
+ TSRMLS_FETCH();
+
+ ZEND_MM_CUSTOM_DEALLOCATOR(ptr);
+ // TODO: use size???
+ zend_mm_free_huge(AG(mm_heap), ptr);
+}
+#endif
+
+ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+{
+ TSRMLS_FETCH();
+
+#if ZEND_MM_CUSTOM
+ if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
return AG(mm_heap)->_malloc(size);
}
- return _zend_mm_alloc_int(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#endif
+ return zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
-ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
TSRMLS_FETCH();
- if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
+#if ZEND_MM_CUSTOM
+ if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
AG(mm_heap)->_free(ptr);
return;
}
- _zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+#endif
+ zend_mm_free_heap(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
-ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
TSRMLS_FETCH();
- if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
+ if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
return AG(mm_heap)->_realloc(ptr, size);
}
- return _zend_mm_realloc_int(AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ return zend_mm_realloc_heap(AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
-ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ZEND_API size_t ZEND_FASTCALL _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
+ if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
return 0;
}
- return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ return zend_mm_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
#if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
@@ -2474,14 +2126,14 @@ ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_
static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
{
size_t res = nmemb;
- unsigned long overflow = 0;
+ zend_ulong overflow = 0;
__asm__ ("mull %3\n\taddl %4,%0\n\tadcl $0,%1"
: "=&a"(res), "=&d" (overflow)
: "%0"(res),
"rm"(size),
"rm"(offset));
-
+
if (UNEXPECTED(overflow)) {
zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
return 0;
@@ -2494,7 +2146,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
{
size_t res = nmemb;
- unsigned long overflow = 0;
+ zend_ulong overflow = 0;
#ifdef __ILP32__ /* x32 */
# define LP_SUFF "l"
@@ -2523,7 +2175,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
{
size_t res;
- unsigned long overflow;
+ zend_ulong overflow;
__asm__ ("umlal %0,%1,%2,%3"
: "=r"(res), "=r"(overflow)
@@ -2544,7 +2196,7 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
{
size_t res;
- unsigned long overflow;
+ zend_ulong overflow;
__asm__ ("mul %0,%2,%3\n\tumulh %1,%2,%3\n\tadds %0,%0,%4\n\tadc %1,%1,xzr"
: "=&r"(res), "=&r"(overflow)
@@ -2589,28 +2241,28 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
#endif
-ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ZEND_API void* ZEND_FASTCALL _safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
return emalloc_rel(safe_address(nmemb, size, offset));
}
-ZEND_API void *_safe_malloc(size_t nmemb, size_t size, size_t offset)
+ZEND_API void* ZEND_FASTCALL _safe_malloc(size_t nmemb, size_t size, size_t offset)
{
return pemalloc(safe_address(nmemb, size, offset), 1);
}
-ZEND_API void *_safe_erealloc(void *ptr, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ZEND_API void* ZEND_FASTCALL _safe_erealloc(void *ptr, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
return erealloc_rel(ptr, safe_address(nmemb, size, offset));
}
-ZEND_API void *_safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset)
+ZEND_API void* ZEND_FASTCALL _safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset)
{
return perealloc(ptr, safe_address(nmemb, size, offset), 1);
}
-ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ZEND_API void* ZEND_FASTCALL _ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
void *p;
#ifdef ZEND_SIGNALS
@@ -2628,9 +2280,9 @@ ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LI
return p;
}
-ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- int length;
+ size_t length;
char *p;
#ifdef ZEND_SIGNALS
TSRMLS_FETCH();
@@ -2649,7 +2301,7 @@ ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
return p;
}
-ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
char *p;
#ifdef ZEND_SIGNALS
@@ -2670,7 +2322,7 @@ ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_
}
-ZEND_API char *zend_strndup(const char *s, uint length)
+ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length)
{
char *p;
#ifdef ZEND_SIGNALS
@@ -2695,31 +2347,35 @@ ZEND_API char *zend_strndup(const char *s, uint length)
ZEND_API int zend_set_memory_limit(size_t memory_limit TSRMLS_DC)
{
- AG(mm_heap)->limit = (memory_limit >= AG(mm_heap)->block_size) ? memory_limit : AG(mm_heap)->block_size;
-
+#if ZEND_MM_LIMIT
+ AG(mm_heap)->limit = (memory_limit >= ZEND_MM_CHUNK_SIZE) ? memory_limit : ZEND_MM_CHUNK_SIZE;
+#endif
return SUCCESS;
}
ZEND_API size_t zend_memory_usage(int real_usage TSRMLS_DC)
{
+#if ZEND_MM_STAT
if (real_usage) {
return AG(mm_heap)->real_size;
} else {
size_t usage = AG(mm_heap)->size;
-#if ZEND_MM_CACHE
- usage -= AG(mm_heap)->cached;
-#endif
return usage;
}
+#endif
+ return 0;
}
ZEND_API size_t zend_memory_peak_usage(int real_usage TSRMLS_DC)
{
+#if ZEND_MM_STAT
if (real_usage) {
return AG(mm_heap)->real_peak;
} else {
return AG(mm_heap)->peak;
}
+#endif
+ return 0;
}
ZEND_API void shutdown_memory_manager(int silent, int full_shutdown TSRMLS_DC)
@@ -2729,18 +2385,20 @@ ZEND_API void shutdown_memory_manager(int silent, int full_shutdown TSRMLS_DC)
static void alloc_globals_ctor(zend_alloc_globals *alloc_globals TSRMLS_DC)
{
+#if ZEND_MM_CUSTOM
char *tmp = getenv("USE_ZEND_ALLOC");
if (tmp && !zend_atoi(tmp, 0)) {
- alloc_globals->mm_heap = malloc(sizeof(struct _zend_mm_heap));
- memset(alloc_globals->mm_heap, 0, sizeof(struct _zend_mm_heap));
- alloc_globals->mm_heap->use_zend_alloc = 0;
+ alloc_globals->mm_heap = malloc(sizeof(zend_mm_heap));
+ memset(alloc_globals->mm_heap, 0, sizeof(zend_mm_heap));
+ alloc_globals->mm_heap->use_custom_heap = 1;
alloc_globals->mm_heap->_malloc = malloc;
alloc_globals->mm_heap->_free = free;
alloc_globals->mm_heap->_realloc = realloc;
- } else {
- alloc_globals->mm_heap = zend_mm_startup();
+ return;
}
+#endif
+ alloc_globals->mm_heap = zend_mm_init();
}
#ifdef ZTS
@@ -2764,13 +2422,8 @@ ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap TSRMLS_DC)
zend_mm_heap *old_heap;
old_heap = AG(mm_heap);
- AG(mm_heap) = new_heap;
- return old_heap;
-}
-
-ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap)
-{
- return heap->storage;
+ AG(mm_heap) = (zend_mm_heap*)new_heap;
+ return (zend_mm_heap*)old_heap;
}
ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
@@ -2778,42 +2431,15 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
void (*_free)(void*),
void* (*_realloc)(void*, size_t))
{
- heap->use_zend_alloc = 0;
- heap->_malloc = _malloc;
- heap->_free = _free;
- heap->_realloc = _realloc;
-}
-
-#if ZEND_DEBUG
-ZEND_API int _mem_block_check(void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
-{
- TSRMLS_FETCH();
-
- if (!AG(mm_heap)->use_zend_alloc) {
- return 1;
- }
- return zend_mm_check_ptr(AG(mm_heap), ptr, silent ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
-}
-
-
-ZEND_API void _full_mem_check(int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
-{
- int errors;
- TSRMLS_FETCH();
+#if ZEND_MM_CUSTOM
+ zend_mm_heap *_heap = (zend_mm_heap*)heap;
- if (!AG(mm_heap)->use_zend_alloc) {
- return;
- }
-
- zend_debug_alloc_output("------------------------------------------------\n");
- zend_debug_alloc_output("Full Memory Check at %s:%d\n" ZEND_FILE_LINE_RELAY_CC);
-
- errors = zend_mm_check_heap(AG(mm_heap), silent ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
-
- zend_debug_alloc_output("End of full memory check %s:%d (%d errors)\n" ZEND_FILE_LINE_RELAY_CC, errors);
- zend_debug_alloc_output("------------------------------------------------\n");
-}
+ _heap->use_custom_heap = 1;
+ _heap->_malloc = _malloc;
+ _heap->_free = _free;
+ _heap->_realloc = _realloc;
#endif
+}
/*
* Local variables:
diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h
index 609db22dac..d9853765c3 100644
--- a/Zend/zend_alloc.h
+++ b/Zend/zend_alloc.h
@@ -28,48 +28,122 @@
#include "zend.h"
#ifndef ZEND_MM_ALIGNMENT
-# define ZEND_MM_ALIGNMENT 8
-# define ZEND_MM_ALIGNMENT_LOG2 3
+# define ZEND_MM_ALIGNMENT Z_L(8)
+# define ZEND_MM_ALIGNMENT_LOG2 Z_L(3)
#elif ZEND_MM_ALIGNMENT < 4
# undef ZEND_MM_ALIGNMENT
# undef ZEND_MM_ALIGNMENT_LOG2
-# define ZEND_MM_ALIGNMENT 4
-# define ZEND_MM_ALIGNMENT_LOG2 2
+# define ZEND_MM_ALIGNMENT Z_L(4)
+# define ZEND_MM_ALIGNMENT_LOG2 Z_L(2)
#endif
-#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1)
+#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT - Z_L(1))
-#define ZEND_MM_ALIGNED_SIZE(size) (((size) + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK)
+#define ZEND_MM_ALIGNED_SIZE(size) (((size) + ZEND_MM_ALIGNMENT - Z_L(1)) & ZEND_MM_ALIGNMENT_MASK)
typedef struct _zend_leak_info {
void *addr;
size_t size;
const char *filename;
- uint lineno;
const char *orig_filename;
+ uint lineno;
uint orig_lineno;
} zend_leak_info;
BEGIN_EXTERN_C()
-ZEND_API char *zend_strndup(const char *s, unsigned int length) ZEND_ATTRIBUTE_MALLOC;
+ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length) ZEND_ATTRIBUTE_MALLOC;
+
+ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1);
+ZEND_API void* ZEND_FASTCALL _safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
+ZEND_API void* ZEND_FASTCALL _safe_malloc(size_t nmemb, size_t size, size_t offset) ZEND_ATTRIBUTE_MALLOC;
+ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
+ZEND_API void* ZEND_FASTCALL _ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2);
+ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(2);
+ZEND_API void* ZEND_FASTCALL _safe_erealloc(void *ptr, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
+ZEND_API void* ZEND_FASTCALL _safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset);
+ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
+ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
+ZEND_API size_t ZEND_FASTCALL _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
+
+#include "zend_alloc_sizes.h"
+
+/* _emalloc() & _efree() specialization */
+#if !ZEND_DEBUG && !defined(_WIN32)
+
+# define _ZEND_BIN_ALLOCATOR_DEF(_num, _size, _elements, _pages, x, y) \
+ ZEND_API void* ZEND_FASTCALL _emalloc_ ## _size(void) ZEND_ATTRIBUTE_MALLOC;
+
+ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR_DEF, x, y)
+
+ZEND_API void* ZEND_FASTCALL _emalloc_large(size_t size) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1);
+ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1);
+
+# define _ZEND_BIN_ALLOCATOR_SELECTOR_START(_num, _size, _elements, _pages, size, y) \
+ ((size <= _size) ? _emalloc_ ## _size() :
+# define _ZEND_BIN_ALLOCATOR_SELECTOR_END(_num, _size, _elements, _pages, size, y) \
+ )
+
+# define ZEND_ALLOCATOR(size) \
+ ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR_SELECTOR_START, size, y) \
+ ((size <= ZEND_MM_MAX_LARGE_SIZE) ? _emalloc_large(size) : _emalloc_huge(size)) \
+ ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR_SELECTOR_END, size, y)
+
+# define _emalloc(size) \
+ (__builtin_constant_p(size) ? \
+ ZEND_ALLOCATOR(size) \
+ : \
+ _emalloc(size) \
+ )
+
+# define _ZEND_BIN_DEALLOCATOR_DEF(_num, _size, _elements, _pages, x, y) \
+ ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *);
+
+ZEND_MM_BINS_INFO(_ZEND_BIN_DEALLOCATOR_DEF, x, y)
+
+ZEND_API void ZEND_FASTCALL _efree_large(void *, size_t size);
+ZEND_API void ZEND_FASTCALL _efree_huge(void *, size_t size);
+
+# define _ZEND_BIN_DEALLOCATOR_SELECTOR_START(_num, _size, _elements, _pages, ptr, size) \
+ if (size <= _size) { _efree_ ## _size(ptr); } else
-ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1);
-ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
-ZEND_API void *_safe_malloc(size_t nmemb, size_t size, size_t offset) ZEND_ATTRIBUTE_MALLOC;
-ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
-ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2);
-ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(2);
-ZEND_API void *_safe_erealloc(void *ptr, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
-ZEND_API void *_safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset);
-ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
-ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
-ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
+# define ZEND_DEALLOCATOR(ptr, size) \
+ ZEND_MM_BINS_INFO(_ZEND_BIN_DEALLOCATOR_SELECTOR_START, ptr, size) \
+ if (size <= ZEND_MM_MAX_LARGE_SIZE) { _efree_large(ptr, size); } \
+ else { _efree_huge(ptr, size); }
+
+# define efree_size(ptr, size) do { \
+ if (__builtin_constant_p(size)) { \
+ ZEND_DEALLOCATOR(ptr, size) \
+ } else { \
+ _efree(ptr); \
+ } \
+ } while (0)
+# define efree_size_rel(ptr, size) \
+ efree_size(ptr, size)
+
+#else
+
+# define efree_size(ptr, size) \
+ efree(ptr)
+# define efree_size_rel(ptr, size) \
+ efree_rel(ptr)
+
+#define _emalloc_large _emalloc
+#define _emalloc_huge _emalloc
+#define _efree_large _efree
+#define _efree_huge _efree
+
+#endif
/* Standard wrapper macros */
#define emalloc(size) _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
+#define emalloc_large(size) _emalloc_large((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
+#define emalloc_huge(size) _emalloc_huge((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define safe_emalloc(nmemb, size, offset) _safe_emalloc((nmemb), (size), (offset) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define efree(ptr) _efree((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
+#define efree_large(ptr) _efree_large((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
+#define efree_huge(ptr) _efree_huge((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define ecalloc(nmemb, size) _ecalloc((nmemb), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define erealloc(ptr, size) _erealloc((ptr), (size), 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define safe_erealloc(ptr, nmemb, size, offset) _safe_erealloc((ptr), (nmemb), (size), (offset) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
@@ -122,6 +196,7 @@ inline static void * __zend_realloc(void *p, size_t len)
#define pemalloc(size, persistent) ((persistent)?__zend_malloc(size):emalloc(size))
#define safe_pemalloc(nmemb, size, offset, persistent) ((persistent)?_safe_malloc(nmemb, size, offset):safe_emalloc(nmemb, size, offset))
#define pefree(ptr, persistent) ((persistent)?free(ptr):efree(ptr))
+#define pefree_size(ptr, size, persistent) ((persistent)?free(ptr):efree_size(ptr, size))
#define pecalloc(nmemb, size, persistent) ((persistent)?__zend_calloc((nmemb), (size)):ecalloc((nmemb), (size)))
#define perealloc(ptr, size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc((ptr), (size)))
#define safe_perealloc(ptr, nmemb, size, offset, persistent) ((persistent)?_safe_realloc((ptr), (nmemb), (size), (offset)):safe_erealloc((ptr), (nmemb), (size), (offset)))
@@ -142,34 +217,21 @@ ZEND_API void start_memory_manager(TSRMLS_D);
ZEND_API void shutdown_memory_manager(int silent, int full_shutdown TSRMLS_DC);
ZEND_API int is_zend_mm(TSRMLS_D);
-#if ZEND_DEBUG
-ZEND_API int _mem_block_check(void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
-ZEND_API void _full_mem_check(int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
-void zend_debug_alloc_output(char *format, ...);
-#define mem_block_check(ptr, silent) _mem_block_check(ptr, silent ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
-#define full_mem_check(silent) _full_mem_check(silent ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
-#else
-#define mem_block_check(type, ptr, silent)
-#define full_mem_check(silent)
-#endif
-
ZEND_API size_t zend_memory_usage(int real_usage TSRMLS_DC);
ZEND_API size_t zend_memory_peak_usage(int real_usage TSRMLS_DC);
-END_EXTERN_C()
-
/* fast cache for HashTables */
#define ALLOC_HASHTABLE(ht) \
(ht) = (HashTable *) emalloc(sizeof(HashTable))
#define FREE_HASHTABLE(ht) \
- efree(ht)
+ efree_size(ht, sizeof(HashTable))
#define ALLOC_HASHTABLE_REL(ht) \
(ht) = (HashTable *) emalloc_rel(sizeof(HashTable))
#define FREE_HASHTABLE_REL(ht) \
- efree_rel(ht)
+ efree_size_rel(ht, sizeof(HashTable))
/* Heap functions */
typedef struct _zend_mm_heap zend_mm_heap;
@@ -191,38 +253,15 @@ ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_D
#define zend_mm_realloc_rel(heap, p, size) _zend_mm_realloc((heap), (p), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define zend_mm_block_size_rel(heap, p) _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
-/* Heaps with user defined storage */
-typedef struct _zend_mm_storage zend_mm_storage;
-
-typedef struct _zend_mm_segment {
- size_t size;
- struct _zend_mm_segment *next_segment;
-} zend_mm_segment;
-
-typedef struct _zend_mm_mem_handlers {
- const char *name;
- zend_mm_storage* (*init)(void *params);
- void (*dtor)(zend_mm_storage *storage);
- void (*compact)(zend_mm_storage *storage);
- zend_mm_segment* (*_alloc)(zend_mm_storage *storage, size_t size);
- zend_mm_segment* (*_realloc)(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size);
- void (*_free)(zend_mm_storage *storage, zend_mm_segment *ptr);
-} zend_mm_mem_handlers;
-
-struct _zend_mm_storage {
- const zend_mm_mem_handlers *handlers;
- void *data;
-};
-
-ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params);
ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap TSRMLS_DC);
-ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap);
ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
void* (*_malloc)(size_t),
void (*_free)(void*),
void* (*_realloc)(void*, size_t));
+END_EXTERN_C()
+
#endif
/*
diff --git a/Zend/zend_alloc_sizes.h b/Zend/zend_alloc_sizes.h
new file mode 100644
index 0000000000..177238ae34
--- /dev/null
+++ b/Zend/zend_alloc_sizes.h
@@ -0,0 +1,46 @@
+#ifndef ZEND_ALLOC_SIZES_H
+#define ZEND_ALLOC_SIZES_H
+
+#define ZEND_MM_CHUNK_SIZE (2 * 1024 * 1024) /* 2 MB */
+#define ZEND_MM_PAGE_SIZE (4 * 1024) /* 4 KB */
+#define ZEND_MM_PAGES (ZEND_MM_CHUNK_SIZE / ZEND_MM_PAGE_SIZE) /* 512 */
+#define ZEND_MM_FIRST_PAGE (1)
+
+#define ZEND_MM_MIN_SMALL_SIZE 8
+#define ZEND_MM_MAX_SMALL_SIZE 3072
+#define ZEND_MM_MAX_LARGE_SIZE (ZEND_MM_CHUNK_SIZE - (ZEND_MM_PAGE_SIZE * ZEND_MM_FIRST_PAGE))
+
+/* num, size, count, pages */
+#define ZEND_MM_BINS_INFO(_, x, y) \
+ _( 0, 8, 512, 1, x, y) \
+ _( 1, 16, 256, 1, x, y) \
+ _( 2, 24, 170, 1, x, y) \
+ _( 3, 32, 128, 1, x, y) \
+ _( 4, 40, 102, 1, x, y) \
+ _( 5, 48, 85, 1, x, y) \
+ _( 6, 56, 73, 1, x, y) \
+ _( 7, 64, 64, 1, x, y) \
+ _( 8, 80, 51, 1, x, y) \
+ _( 9, 96, 42, 1, x, y) \
+ _(10, 112, 36, 1, x, y) \
+ _(11, 128, 32, 1, x, y) \
+ _(12, 160, 25, 1, x, y) \
+ _(13, 192, 21, 1, x, y) \
+ _(14, 224, 18, 1, x, y) \
+ _(15, 256, 16, 1, x, y) \
+ _(16, 320, 64, 5, x, y) \
+ _(17, 384, 32, 3, x, y) \
+ _(18, 448, 9, 1, x, y) \
+ _(19, 512, 8, 1, x, y) \
+ _(20, 640, 32, 5, x, y) \
+ _(21, 768, 16, 3, x, y) \
+ _(22, 896, 9, 2, x, y) \
+ _(23, 1024, 8, 2, x, y) \
+ _(24, 1280, 16, 5, x, y) \
+ _(25, 1536, 8, 3, x, y) \
+ _(26, 1792, 16, 7, x, y) \
+ _(27, 2048, 8, 4, x, y) \
+ _(28, 2560, 8, 5, x, y) \
+ _(29, 3072, 4, 3, x, y)
+
+#endif /* ZEND_ALLOC_SIZES_H */
diff --git a/Zend/zend_arena.h b/Zend/zend_arena.h
index 0a1d6f1107..8988eb4ab5 100644
--- a/Zend/zend_arena.h
+++ b/Zend/zend_arena.h
@@ -65,7 +65,7 @@ static zend_always_inline void* zend_arena_alloc(zend_arena **arena_ptr, size_t
size_t arena_size =
UNEXPECTED((size + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena))) > (size_t)(arena->end - (char*) arena)) ?
(size + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena))) :
- (arena->end - (char*) arena);
+ (size_t)(arena->end - (char*) arena);
zend_arena *new_arena = (zend_arena*)emalloc(arena_size);
ptr = (char*) new_arena + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena));
@@ -80,10 +80,13 @@ static zend_always_inline void* zend_arena_alloc(zend_arena **arena_ptr, size_t
static zend_always_inline void* zend_arena_calloc(zend_arena **arena_ptr, size_t count, size_t unit_size)
{
- size_t size = unit_size * count;
+ zend_long overflow;
+ double d;
+ size_t size;
void *ret;
- ZEND_ASSERT(size >= unit_size && size >= count);
+ ZEND_SIGNED_MULTIPLY_LONG(unit_size, count, size, d, overflow);
+ ZEND_ASSERT(overflow == 0);
ret = zend_arena_alloc(arena_ptr, size);
memset(ret, 0, size);
return ret;
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index 810b9b1fe8..9604079a9e 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -23,82 +23,158 @@
#include "zend_API.h"
#include "zend_operators.h"
-ZEND_API zend_ast *zend_ast_create_constant(zval *zv)
-{
- zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zval));
- ast->kind = ZEND_CONST;
- ast->children = 0;
- ZVAL_COPY_VALUE(&ast->u.val, zv);
- return ast;
+static inline void *zend_ast_alloc(size_t size TSRMLS_DC) {
+ return zend_arena_alloc(&CG(ast_arena), size);
}
-ZEND_API zend_ast* zend_ast_create_unary(uint kind, zend_ast *op0)
-{
- zend_ast *ast = emalloc(sizeof(zend_ast));
+static inline void *zend_ast_realloc(void *old, size_t old_size, size_t new_size TSRMLS_DC) {
+ void *new = zend_ast_alloc(new_size TSRMLS_CC);
+ memcpy(new, old, old_size);
+ return new;
+}
+
+static inline size_t zend_ast_size(uint32_t children) {
+ return sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
+}
+
+static inline size_t zend_ast_list_size(uint32_t children) {
+ return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
+}
+
+ZEND_API zend_ast *zend_ast_create_znode(znode *node) {
+ zend_ast_znode *ast;
+ TSRMLS_FETCH();
+
+ ast = zend_ast_alloc(sizeof(zend_ast_znode) TSRMLS_CC);
+ ast->kind = ZEND_AST_ZNODE;
+ ast->attr = 0;
+ ast->lineno = CG(zend_lineno);
+ ast->node = *node;
+ return (zend_ast *) ast;
+}
+
+ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
+ zend_ast_zval *ast;
+ TSRMLS_FETCH();
+
+ ast = zend_ast_alloc(sizeof(zend_ast_zval) TSRMLS_CC);
+ ast->kind = ZEND_AST_ZVAL;
+ ast->attr = attr;
+ ZVAL_COPY_VALUE(&ast->val, zv);
+ ast->val.u2.lineno = CG(zend_lineno);
+ return (zend_ast *) ast;
+}
+
+ZEND_API zend_ast *zend_ast_create_decl(
+ zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
+ zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2
+) {
+ zend_ast_decl *ast;
+ TSRMLS_FETCH();
+
+ ast = zend_ast_alloc(sizeof(zend_ast_decl) TSRMLS_CC);
ast->kind = kind;
- ast->children = 1;
- (&ast->u.child)[0] = op0;
- return ast;
+ ast->attr = 0;
+ ast->start_lineno = start_lineno;
+ ast->end_lineno = CG(zend_lineno);
+ ast->flags = flags;
+ ast->lex_pos = LANG_SCNG(yy_text);
+ ast->doc_comment = doc_comment;
+ ast->name = name;
+ ast->child[0] = child0;
+ ast->child[1] = child1;
+ ast->child[2] = child2;
+
+ return (zend_ast *) ast;
}
-ZEND_API zend_ast* zend_ast_create_binary(uint kind, zend_ast *op0, zend_ast *op1)
-{
- zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*));
+static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
+ uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
+ zend_ast *ast;
+ TSRMLS_FETCH();
+
+ ast = zend_ast_alloc(zend_ast_size(children) TSRMLS_CC);
ast->kind = kind;
- ast->children = 2;
- (&ast->u.child)[0] = op0;
- (&ast->u.child)[1] = op1;
+ ast->attr = attr;
+ ast->lineno = (uint32_t) -1;
+
+ for (i = 0; i < children; ++i) {
+ ast->child[i] = va_arg(va, zend_ast *);
+ if (ast->child[i] != NULL) {
+ uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
+ if (lineno < ast->lineno) {
+ ast->lineno = lineno;
+ }
+ }
+ }
+
+ if (ast->lineno == UINT_MAX) {
+ ast->lineno = CG(zend_lineno);
+ }
+
return ast;
}
-ZEND_API zend_ast* zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2)
-{
- zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 2);
- ast->kind = kind;
- ast->children = 3;
- (&ast->u.child)[0] = op0;
- (&ast->u.child)[1] = op1;
- (&ast->u.child)[2] = op2;
+ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) {
+ va_list va;
+ zend_ast *ast;
+
+ va_start(va, attr);
+ ast = zend_ast_create_from_va_list(kind, attr, va);
+ va_end(va);
+
return ast;
}
-ZEND_API zend_ast* zend_ast_create_dynamic(uint kind)
-{
- zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 3); /* use 4 children as deafult */
- ast->kind = kind;
- ast->children = 0;
+ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
+ va_list va;
+ zend_ast *ast;
+
+ va_start(va, kind);
+ ast = zend_ast_create_from_va_list(kind, 0, va);
+ va_end(va);
+
return ast;
}
-ZEND_API void zend_ast_dynamic_add(zend_ast **ast, zend_ast *op)
-{
- if ((*ast)->children >= 4 && (*ast)->children == ((*ast)->children & -(*ast)->children)) {
- *ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children * 2 + 1));
+ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) {
+ zend_ast *ast;
+ zend_ast_list *list;
+ TSRMLS_FETCH();
+
+ ast = zend_ast_alloc(zend_ast_list_size(4) TSRMLS_CC);
+ list = (zend_ast_list *) ast;
+ list->kind = kind;
+ list->attr = 0;
+ list->lineno = CG(zend_lineno);
+ list->children = 0;
+
+ {
+ va_list va;
+ uint32_t i;
+ va_start(va, kind);
+ for (i = 0; i < init_children; ++i) {
+ ast = zend_ast_list_add(ast, va_arg(va, zend_ast *));
+ }
+ va_end(va);
}
- (&(*ast)->u.child)[(*ast)->children++] = op;
-}
-ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast)
-{
- *ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children - 1));
+ return ast;
}
-ZEND_API int zend_ast_is_ct_constant(zend_ast *ast)
-{
- int i;
+static inline zend_bool is_power_of_two(uint32_t n) {
+ return ((n != 0) && (n == (n & (~n + 1))));
+}
- if (ast->kind == ZEND_CONST) {
- return !Z_CONSTANT(ast->u.val);
- } else {
- for (i = 0; i < ast->children; i++) {
- if ((&ast->u.child)[i]) {
- if (!zend_ast_is_ct_constant((&ast->u.child)[i])) {
- return 0;
- }
- }
- }
- return 1;
+ZEND_API zend_ast *zend_ast_list_add(zend_ast *ast, zend_ast *op) {
+ zend_ast_list *list = zend_ast_get_list(ast);
+ if (list->children >= 4 && is_power_of_two(list->children)) {
+ TSRMLS_FETCH();
+ list = zend_ast_realloc(list,
+ zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2) TSRMLS_CC);
}
+ list->child[list->children++] = op;
+ return (zend_ast *) list;
}
static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr TSRMLS_DC)
@@ -137,167 +213,58 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
zval op1, op2;
switch (ast->kind) {
- case ZEND_ADD:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- add_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_SUB:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- sub_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_MUL:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- mul_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_POW:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- pow_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_DIV:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- div_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_MOD:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- mod_function(result, &op1, &op2 TSRMLS_CC);
+ case ZEND_AST_BINARY_OP:
+ {
+ binary_op_type op = get_binary_op(ast->attr);
+ zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC);
+ op(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
- case ZEND_SL:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- shift_left_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_SR:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- shift_right_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_CONCAT:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- concat_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_BW_OR:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- bitwise_or_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_BW_AND:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- bitwise_and_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_BW_XOR:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- bitwise_xor_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_BW_NOT:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- bitwise_not_function(result, &op1 TSRMLS_CC);
- zval_dtor(&op1);
- break;
- case ZEND_BOOL_NOT:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- boolean_not_function(result, &op1 TSRMLS_CC);
- zval_dtor(&op1);
- break;
- case ZEND_BOOL_XOR:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- boolean_xor_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_IS_IDENTICAL:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- is_identical_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_IS_NOT_IDENTICAL:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- is_not_identical_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_IS_EQUAL:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- is_equal_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_IS_NOT_EQUAL:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- is_not_equal_function(result, &op1, &op2 TSRMLS_CC);
- zval_dtor(&op1);
- zval_dtor(&op2);
- break;
- case ZEND_IS_SMALLER:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- is_smaller_function(result, &op1, &op2 TSRMLS_CC);
+ }
+ case ZEND_AST_GREATER:
+ case ZEND_AST_GREATER_EQUAL:
+ {
+ /* op1 > op2 is the same as op2 < op1 */
+ binary_op_type op = ast->kind == ZEND_AST_GREATER
+ ? is_smaller_function : is_smaller_or_equal_function;
+ zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC);
+ op(result, &op2, &op1 TSRMLS_CC);
zval_dtor(&op1);
zval_dtor(&op2);
break;
- case ZEND_IS_SMALLER_OR_EQUAL:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
- is_smaller_or_equal_function(result, &op1, &op2 TSRMLS_CC);
+ }
+ case ZEND_AST_UNARY_OP:
+ {
+ unary_op_type op = get_unary_op(ast->attr);
+ zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
+ op(result, &op1 TSRMLS_CC);
zval_dtor(&op1);
- zval_dtor(&op2);
break;
- case ZEND_CONST:
- /* class constants may be updated in-place */
+ }
+ case ZEND_AST_ZVAL:
+ {
+ zval *zv = zend_ast_get_zval(ast);
if (scope) {
- if (Z_OPT_CONSTANT(ast->u.val)) {
- zval_update_constant_ex(&ast->u.val, 1, scope TSRMLS_CC);
+ /* class constants may be updated in-place */
+ if (Z_OPT_CONSTANT_P(zv)) {
+ zval_update_constant_ex(zv, 1, scope TSRMLS_CC);
}
- ZVAL_DUP(result, &ast->u.val);
+ ZVAL_DUP(result, zv);
} else {
- ZVAL_DUP(result, &ast->u.val);
+ ZVAL_DUP(result, zv);
if (Z_OPT_CONSTANT_P(result)) {
zval_update_constant_ex(result, 1, scope TSRMLS_CC);
}
}
break;
- case ZEND_BOOL_AND:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
+ }
+ case ZEND_AST_AND:
+ zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
if (zend_is_true(&op1 TSRMLS_CC)) {
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC);
ZVAL_BOOL(result, zend_is_true(&op2 TSRMLS_CC));
zval_dtor(&op2);
} else {
@@ -305,61 +272,63 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
}
zval_dtor(&op1);
break;
- case ZEND_BOOL_OR:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
+ case ZEND_AST_OR:
+ zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
if (zend_is_true(&op1 TSRMLS_CC)) {
ZVAL_BOOL(result, 1);
} else {
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC);
ZVAL_BOOL(result, zend_is_true(&op2 TSRMLS_CC));
zval_dtor(&op2);
}
zval_dtor(&op1);
break;
- case ZEND_SELECT:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
+ case ZEND_AST_CONDITIONAL:
+ zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
if (zend_is_true(&op1 TSRMLS_CC)) {
- if (!(&ast->u.child)[1]) {
+ if (!ast->child[1]) {
*result = op1;
} else {
- zend_ast_evaluate(result, (&ast->u.child)[1], scope TSRMLS_CC);
+ zend_ast_evaluate(result, ast->child[1], scope TSRMLS_CC);
zval_dtor(&op1);
}
} else {
- zend_ast_evaluate(result, (&ast->u.child)[2], scope TSRMLS_CC);
+ zend_ast_evaluate(result, ast->child[2], scope TSRMLS_CC);
zval_dtor(&op1);
}
break;
- case ZEND_UNARY_PLUS:
+ case ZEND_AST_UNARY_PLUS:
ZVAL_LONG(&op1, 0);
- zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->child[0], scope TSRMLS_CC);
add_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op2);
break;
- case ZEND_UNARY_MINUS:
+ case ZEND_AST_UNARY_MINUS:
ZVAL_LONG(&op1, 0);
- zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->child[0], scope TSRMLS_CC);
sub_function(result, &op1, &op2 TSRMLS_CC);
zval_dtor(&op2);
break;
- case ZEND_INIT_ARRAY:
+ case ZEND_AST_ARRAY:
array_init(result);
{
- int i;
- for (i = 0; i < ast->children; i+=2) {
- if ((&ast->u.child)[i]) {
- zend_ast_evaluate(&op1, (&ast->u.child)[i], scope TSRMLS_CC);
+ uint32_t i;
+ zend_ast_list *list = zend_ast_get_list(ast);
+ for (i = 0; i < list->children; i++) {
+ zend_ast *elem = list->child[i];
+ if (elem->child[1]) {
+ zend_ast_evaluate(&op1, elem->child[1], scope TSRMLS_CC);
} else {
ZVAL_UNDEF(&op1);
}
- zend_ast_evaluate(&op2, (&ast->u.child)[i+1], scope TSRMLS_CC);
+ zend_ast_evaluate(&op2, elem->child[0], scope TSRMLS_CC);
zend_ast_add_array_element(result, &op1, &op2 TSRMLS_CC);
}
}
break;
- case ZEND_FETCH_DIM_R:
- zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
- zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
+ case ZEND_AST_DIM:
+ zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
+ zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC);
{
zval tmp;
zend_fetch_dimension_by_zval(&tmp, &op1, &op2 TSRMLS_CC);
@@ -377,35 +346,100 @@ ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
{
if (ast == NULL) {
return NULL;
- } else if (ast->kind == ZEND_CONST) {
- zend_ast *copy = zend_ast_create_constant(&ast->u.val);
- zval_copy_ctor(&copy->u.val);
- return copy;
- } else if (ast->children) {
- zend_ast *new = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
- int i;
+ } else if (ast->kind == ZEND_AST_ZVAL) {
+ zend_ast_zval *new = emalloc(sizeof(zend_ast_zval));
+ new->kind = ZEND_AST_ZVAL;
+ new->attr = ast->attr;
+ ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
+ return (zend_ast *) new;
+ } else if (zend_ast_is_list(ast)) {
+ zend_ast_list *list = zend_ast_get_list(ast);
+ zend_ast_list *new = emalloc(zend_ast_list_size(list->children));
+ uint32_t i;
+ new->kind = list->kind;
+ new->attr = list->attr;
+ new->children = list->children;
+ for (i = 0; i < list->children; i++) {
+ new->child[i] = zend_ast_copy(list->child[i]);
+ }
+ return (zend_ast *) new;
+ } else {
+ uint32_t i, children = zend_ast_get_num_children(ast);
+ zend_ast *new = emalloc(zend_ast_size(children));
new->kind = ast->kind;
- new->children = ast->children;
- for (i = 0; i < ast->children; i++) {
- (&new->u.child)[i] = zend_ast_copy((&ast->u.child)[i]);
+ new->attr = ast->attr;
+ for (i = 0; i < children; i++) {
+ new->child[i] = zend_ast_copy(ast->child[i]);
}
return new;
}
- return zend_ast_create_dynamic(ast->kind);
}
-ZEND_API void zend_ast_destroy(zend_ast *ast)
-{
- int i;
+static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
+ if (!ast) {
+ return;
+ }
- if (ast->kind == ZEND_CONST) {
- zval_dtor(&ast->u.val);
- } else {
- for (i = 0; i < ast->children; i++) {
- if ((&ast->u.child)[i]) {
- zend_ast_destroy((&ast->u.child)[i]);
+ switch (ast->kind) {
+ case ZEND_AST_ZVAL:
+ /* Destroy value without using GC: When opcache moves arrays into SHM it will
+ * free the zend_array structure, so references to it from outside the op array
+ * become invalid. GC would cause such a reference in the root buffer. */
+ zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
+ break;
+ case ZEND_AST_FUNC_DECL:
+ case ZEND_AST_CLOSURE:
+ case ZEND_AST_METHOD:
+ case ZEND_AST_CLASS:
+ {
+ zend_ast_decl *decl = (zend_ast_decl *) ast;
+ zend_string_release(decl->name);
+ if (decl->doc_comment) {
+ zend_string_release(decl->doc_comment);
+ }
+ zend_ast_destroy_ex(decl->child[0], free);
+ zend_ast_destroy_ex(decl->child[1], free);
+ zend_ast_destroy_ex(decl->child[2], free);
+ break;
+ }
+ default:
+ if (zend_ast_is_list(ast)) {
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
+ for (i = 0; i < list->children; i++) {
+ zend_ast_destroy_ex(list->child[i], free);
+ }
+ } else {
+ uint32_t i, children = zend_ast_get_num_children(ast);
+ for (i = 0; i < children; i++) {
+ zend_ast_destroy_ex(ast->child[i], free);
+ }
}
+ }
+
+ if (free) {
+ efree(ast);
+ }
+}
+
+ZEND_API void zend_ast_destroy(zend_ast *ast) {
+ zend_ast_destroy_ex(ast, 0);
+}
+ZEND_API void zend_ast_destroy_and_free(zend_ast *ast) {
+ zend_ast_destroy_ex(ast, 1);
+}
+
+ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn TSRMLS_DC) {
+ if (zend_ast_is_list(ast)) {
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
+ for (i = 0; i < list->children; ++i) {
+ fn(&list->child[i] TSRMLS_CC);
+ }
+ } else {
+ uint32_t i, children = zend_ast_get_num_children(ast);
+ for (i = 0; i < children; ++i) {
+ fn(&ast->child[i] TSRMLS_CC);
}
}
- efree(ast);
}
diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h
index 8678299f0f..2a1582ca24 100644
--- a/Zend/zend_ast.h
+++ b/Zend/zend_ast.h
@@ -14,6 +14,7 @@
+----------------------------------------------------------------------+
| Authors: Bob Weinand <bwoebi@php.net> |
| Dmitry Stogov <dmitry@zend.com> |
+ | Nikita Popov <nikic@php.net> |
+----------------------------------------------------------------------+
*/
@@ -24,39 +25,239 @@
#include "zend.h"
-typedef enum _zend_ast_kind {
- /* first 256 kinds are reserved for opcodes */
- ZEND_CONST = 256,
- ZEND_BOOL_AND,
- ZEND_BOOL_OR,
- ZEND_SELECT,
- ZEND_UNARY_PLUS,
- ZEND_UNARY_MINUS,
-} zend_ast_kind;
+#define ZEND_AST_SPECIAL_SHIFT 6
+#define ZEND_AST_IS_LIST_SHIFT 7
+#define ZEND_AST_NUM_CHILDREN_SHIFT 8
+
+enum _zend_ast_kind {
+ /* special nodes */
+ ZEND_AST_ZVAL = 1 << ZEND_AST_SPECIAL_SHIFT,
+ ZEND_AST_ZNODE,
+
+ /* declaration nodes */
+ ZEND_AST_FUNC_DECL,
+ ZEND_AST_CLOSURE,
+ ZEND_AST_METHOD,
+ ZEND_AST_CLASS,
+
+ /* list nodes */
+ ZEND_AST_ARG_LIST = 1 << ZEND_AST_IS_LIST_SHIFT,
+ ZEND_AST_LIST,
+ ZEND_AST_ARRAY,
+ ZEND_AST_ENCAPS_LIST,
+ ZEND_AST_EXPR_LIST,
+ ZEND_AST_STMT_LIST,
+ ZEND_AST_IF,
+ ZEND_AST_SWITCH_LIST,
+ ZEND_AST_CATCH_LIST,
+ ZEND_AST_PARAM_LIST,
+ ZEND_AST_CLOSURE_USES,
+ ZEND_AST_PROP_DECL,
+ ZEND_AST_CONST_DECL,
+ ZEND_AST_CLASS_CONST_DECL,
+ ZEND_AST_NAME_LIST,
+ ZEND_AST_TRAIT_ADAPTATIONS,
+ ZEND_AST_USE,
+
+ /* 0 child nodes */
+ ZEND_AST_MAGIC_CONST = 0 << ZEND_AST_NUM_CHILDREN_SHIFT,
+ ZEND_AST_TYPE,
+
+ /* 1 child node */
+ ZEND_AST_VAR = 1 << ZEND_AST_NUM_CHILDREN_SHIFT,
+ ZEND_AST_CONST,
+ ZEND_AST_RESOLVE_CLASS_NAME,
+ ZEND_AST_UNPACK,
+ ZEND_AST_UNARY_PLUS,
+ ZEND_AST_UNARY_MINUS,
+ ZEND_AST_CAST,
+ ZEND_AST_EMPTY,
+ ZEND_AST_ISSET,
+ ZEND_AST_SILENCE,
+ ZEND_AST_SHELL_EXEC,
+ ZEND_AST_CLONE,
+ ZEND_AST_EXIT,
+ ZEND_AST_PRINT,
+ ZEND_AST_INCLUDE_OR_EVAL,
+ ZEND_AST_UNARY_OP,
+ ZEND_AST_PRE_INC,
+ ZEND_AST_PRE_DEC,
+ ZEND_AST_POST_INC,
+ ZEND_AST_POST_DEC,
+
+ ZEND_AST_GLOBAL,
+ ZEND_AST_UNSET,
+ ZEND_AST_RETURN,
+ ZEND_AST_LABEL,
+ ZEND_AST_REF,
+ ZEND_AST_HALT_COMPILER,
+ ZEND_AST_ECHO,
+ ZEND_AST_THROW,
+ ZEND_AST_GOTO,
+ ZEND_AST_BREAK,
+ ZEND_AST_CONTINUE,
+
+ /* 2 child nodes */
+ ZEND_AST_DIM = 2 << ZEND_AST_NUM_CHILDREN_SHIFT,
+ ZEND_AST_PROP,
+ ZEND_AST_STATIC_PROP,
+ ZEND_AST_CALL,
+ ZEND_AST_CLASS_CONST,
+ ZEND_AST_ASSIGN,
+ ZEND_AST_ASSIGN_REF,
+ ZEND_AST_ASSIGN_OP,
+ ZEND_AST_BINARY_OP,
+ ZEND_AST_GREATER,
+ ZEND_AST_GREATER_EQUAL,
+ ZEND_AST_AND,
+ ZEND_AST_OR,
+ ZEND_AST_ARRAY_ELEM,
+ ZEND_AST_NEW,
+ ZEND_AST_INSTANCEOF,
+ ZEND_AST_YIELD,
+
+ ZEND_AST_STATIC,
+ ZEND_AST_WHILE,
+ ZEND_AST_DO_WHILE,
+ ZEND_AST_IF_ELEM,
+ ZEND_AST_SWITCH,
+ ZEND_AST_SWITCH_CASE,
+ ZEND_AST_DECLARE,
+ ZEND_AST_PROP_ELEM,
+ ZEND_AST_CONST_ELEM,
+ ZEND_AST_USE_TRAIT,
+ ZEND_AST_TRAIT_PRECEDENCE,
+ ZEND_AST_METHOD_REFERENCE,
+ ZEND_AST_NAMESPACE,
+ ZEND_AST_USE_ELEM,
+ ZEND_AST_TRAIT_ALIAS,
+
+ /* 3 child nodes */
+ ZEND_AST_METHOD_CALL = 3 << ZEND_AST_NUM_CHILDREN_SHIFT,
+ ZEND_AST_STATIC_CALL,
+ ZEND_AST_CONDITIONAL,
+
+ ZEND_AST_TRY,
+ ZEND_AST_CATCH,
+ ZEND_AST_PARAM,
+
+ /* 4 child nodes */
+ ZEND_AST_FOR = 4 << ZEND_AST_NUM_CHILDREN_SHIFT,
+ ZEND_AST_FOREACH,
+};
+
+typedef uint16_t zend_ast_kind;
+typedef uint16_t zend_ast_attr;
struct _zend_ast {
- unsigned short kind;
- unsigned short children;
- union {
- zval val;
- zend_ast *child;
- } u;
+ zend_ast_kind kind; /* Type of the node (ZEND_AST_* enum constant) */
+ zend_ast_attr attr; /* Additional attribute, use depending on node type */
+ uint32_t lineno; /* Line number */
+ zend_ast *child[1]; /* Array of children (using struct hack) */
};
-ZEND_API zend_ast *zend_ast_create_constant(zval *zv);
+/* Same as zend_ast, but with children count, which is updated dynamically */
+typedef struct _zend_ast_list {
+ zend_ast_kind kind;
+ zend_ast_attr attr;
+ uint32_t lineno;
+ uint32_t children;
+ zend_ast *child[1];
+} zend_ast_list;
+
+/* Lineno is stored in val.u2.lineno */
+typedef struct _zend_ast_zval {
+ zend_ast_kind kind;
+ zend_ast_attr attr;
+ zval val;
+} zend_ast_zval;
+
+/* Separate structure for function and class declaration, as they need extra information. */
+typedef struct _zend_ast_decl {
+ zend_ast_kind kind;
+ zend_ast_attr attr; /* Unused - for structure compatibility */
+ uint32_t start_lineno;
+ uint32_t end_lineno;
+ uint32_t flags;
+ unsigned char *lex_pos;
+ zend_string *doc_comment;
+ zend_string *name;
+ zend_ast *child[3];
+} zend_ast_decl;
-ZEND_API zend_ast *zend_ast_create_unary(uint kind, zend_ast *op0);
-ZEND_API zend_ast *zend_ast_create_binary(uint kind, zend_ast *op0, zend_ast *op1);
-ZEND_API zend_ast *zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2);
-ZEND_API zend_ast* zend_ast_create_dynamic(uint kind);
-ZEND_API void zend_ast_dynamic_add(zend_ast **ast, zend_ast *op);
-ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast);
+ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr);
-ZEND_API int zend_ast_is_ct_constant(zend_ast *ast);
+ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...);
+ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...);
+
+ZEND_API zend_ast *zend_ast_create_decl(
+ zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
+ zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2
+);
+
+ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...);
+ZEND_API zend_ast *zend_ast_list_add(zend_ast *list, zend_ast *op);
ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope TSRMLS_DC);
ZEND_API zend_ast *zend_ast_copy(zend_ast *ast);
ZEND_API void zend_ast_destroy(zend_ast *ast);
+ZEND_API void zend_ast_destroy_and_free(zend_ast *ast);
+
+typedef void (*zend_ast_apply_func)(zend_ast **ast_ptr TSRMLS_DC);
+ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn TSRMLS_DC);
+
+static inline zend_bool zend_ast_is_list(zend_ast *ast) {
+ return (ast->kind >> ZEND_AST_IS_LIST_SHIFT) & 1;
+}
+static inline zend_ast_list *zend_ast_get_list(zend_ast *ast) {
+ ZEND_ASSERT(zend_ast_is_list(ast));
+ return (zend_ast_list *) ast;
+}
+
+static inline zval *zend_ast_get_zval(zend_ast *ast) {
+ ZEND_ASSERT(ast->kind == ZEND_AST_ZVAL);
+ return &((zend_ast_zval *) ast)->val;
+}
+static inline zend_string *zend_ast_get_str(zend_ast *ast) {
+ return Z_STR_P(zend_ast_get_zval(ast));
+}
+
+static inline uint32_t zend_ast_get_num_children(zend_ast *ast) {
+ ZEND_ASSERT(!zend_ast_is_list(ast));
+ return ast->kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
+}
+static inline uint32_t zend_ast_get_lineno(zend_ast *ast) {
+ if (ast->kind == ZEND_AST_ZVAL) {
+ zval *zv = zend_ast_get_zval(ast);
+ return zv->u2.lineno;
+ } else {
+ return ast->lineno;
+ }
+}
+
+static inline zend_ast *zend_ast_create_zval(zval *zv) {
+ return zend_ast_create_zval_ex(zv, 0);
+}
+static inline zend_ast *zend_ast_create_zval_from_str(zend_string *str) {
+ zval zv;
+ ZVAL_STR(&zv, str);
+ return zend_ast_create_zval(&zv);
+}
+static inline zend_ast *zend_ast_create_zval_from_long(zend_long lval) {
+ zval zv;
+ ZVAL_LONG(&zv, lval);
+ return zend_ast_create_zval(&zv);
+}
+
+static inline zend_ast *zend_ast_create_binary_op(uint32_t opcode, zend_ast *op0, zend_ast *op1) {
+ return zend_ast_create_ex(ZEND_AST_BINARY_OP, opcode, op0, op1);
+}
+static inline zend_ast *zend_ast_create_assign_op(uint32_t opcode, zend_ast *op0, zend_ast *op1) {
+ return zend_ast_create_ex(ZEND_AST_ASSIGN_OP, opcode, op0, op1);
+}
+static inline zend_ast *zend_ast_create_cast(uint32_t type, zend_ast *op0) {
+ return zend_ast_create_ex(ZEND_AST_CAST, type, op0);
+}
#endif
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 1e29ea4db1..1bb02ef2eb 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -78,6 +78,7 @@ static ZEND_FUNCTION(get_defined_functions);
static ZEND_FUNCTION(get_defined_vars);
static ZEND_FUNCTION(create_function);
static ZEND_FUNCTION(get_resource_type);
+static ZEND_FUNCTION(get_resources);
static ZEND_FUNCTION(get_loaded_extensions);
static ZEND_FUNCTION(extension_loaded);
static ZEND_FUNCTION(get_extension_funcs);
@@ -218,6 +219,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resource_type, 0, 0, 1)
ZEND_ARG_INFO(0, res)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resources, 0, 0, 0)
+ ZEND_ARG_INFO(0, type)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_get_loaded_extensions, 0, 0, 0)
ZEND_ARG_INFO(0, zend_extensions)
ZEND_END_ARG_INFO()
@@ -291,6 +296,7 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
ZEND_FE(get_defined_vars, arginfo_zend__void)
ZEND_FE(create_function, arginfo_create_function)
ZEND_FE(get_resource_type, arginfo_get_resource_type)
+ ZEND_FE(get_resources, arginfo_get_resources)
ZEND_FE(get_loaded_extensions, arginfo_get_loaded_extensions)
ZEND_FE(extension_loaded, arginfo_extension_loaded)
ZEND_FE(get_extension_funcs, arginfo_extension_loaded)
@@ -374,9 +380,9 @@ ZEND_FUNCTION(gc_enabled)
Activates the circular reference collector */
ZEND_FUNCTION(gc_enable)
{
- zend_string *key = STR_INIT("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
- zend_alter_ini_entry(key, "1", sizeof("1")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
- STR_RELEASE(key);
+ zend_string *key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
+ zend_alter_ini_entry_chars(key, "1", sizeof("1")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
+ zend_string_release(key);
}
/* }}} */
@@ -384,9 +390,9 @@ ZEND_FUNCTION(gc_enable)
Deactivates the circular reference collector */
ZEND_FUNCTION(gc_disable)
{
- zend_string *key = STR_INIT("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
- zend_alter_ini_entry(key, "0", sizeof("0")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
- STR_RELEASE(key);
+ zend_string *key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
+ zend_alter_ini_entry_chars(key, "0", sizeof("0")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
+ zend_string_release(key);
}
/* }}} */
@@ -409,9 +415,9 @@ ZEND_FUNCTION(func_num_args)
Get the $arg_num'th argument that was passed to the function */
ZEND_FUNCTION(func_get_arg)
{
- int arg_count, first_extra_arg;
+ uint32_t arg_count, first_extra_arg;
zval *arg;
- long requested_offset;
+ zend_long requested_offset;
zend_execute_data *ex;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &requested_offset) == FAILURE) {
@@ -432,7 +438,7 @@ ZEND_FUNCTION(func_get_arg)
arg_count = ex->num_args;
if (requested_offset >= arg_count) {
- zend_error(E_WARNING, "func_get_arg(): Argument %ld not passed to function", requested_offset);
+ zend_error(E_WARNING, "func_get_arg(): Argument " ZEND_LONG_FMT " not passed to function", requested_offset);
RETURN_FALSE;
}
@@ -454,8 +460,8 @@ ZEND_FUNCTION(func_get_arg)
ZEND_FUNCTION(func_get_args)
{
zval *p;
- int arg_count, first_extra_arg;
- int i;
+ uint32_t arg_count, first_extra_arg;
+ uint32_t i;
zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
if (ex->frame_kind != VM_FRAME_NESTED_FUNCTION && ex->frame_kind != VM_FRAME_TOP_FUNCTION) {
@@ -513,7 +519,8 @@ ZEND_FUNCTION(func_get_args)
/* }}} */
/* {{{ proto int strlen(string str)
- Get string length */
+ Get string length
+ Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
ZEND_FUNCTION(strlen)
{
zend_string *s;
@@ -537,14 +544,13 @@ ZEND_FUNCTION(strlen)
Binary safe string comparison */
ZEND_FUNCTION(strcmp)
{
- char *s1, *s2;
- int s1_len, s2_len;
+ zend_string *s1, *s2;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &s1, &s1_len, &s2, &s2_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "SS", &s1, &s2) == FAILURE) {
return;
}
- RETURN_LONG(zend_binary_strcmp(s1, s1_len, s2, s2_len));
+ RETURN_LONG(zend_binary_strcmp(s1->val, s1->len, s2->val, s2->len));
}
/* }}} */
@@ -553,11 +559,10 @@ ZEND_FUNCTION(strcmp)
Binary safe string comparison */
ZEND_FUNCTION(strncmp)
{
- char *s1, *s2;
- int s1_len, s2_len;
- long len;
+ zend_string *s1, *s2;
+ zend_long len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &s1, &s1_len, &s2, &s2_len, &len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "SSl", &s1, &s2, &len) == FAILURE) {
return;
}
@@ -566,7 +571,7 @@ ZEND_FUNCTION(strncmp)
RETURN_FALSE;
}
- RETURN_LONG(zend_binary_strncmp(s1, s1_len, s2, s2_len, len));
+ RETURN_LONG(zend_binary_strncmp(s1->val, s1->len, s2->val, s2->len, len));
}
/* }}} */
@@ -575,14 +580,13 @@ ZEND_FUNCTION(strncmp)
Binary safe case-insensitive string comparison */
ZEND_FUNCTION(strcasecmp)
{
- char *s1, *s2;
- int s1_len, s2_len;
+ zend_string *s1, *s2;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &s1, &s1_len, &s2, &s2_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "SS", &s1, &s2) == FAILURE) {
return;
}
- RETURN_LONG(zend_binary_strcasecmp(s1, s1_len, s2, s2_len));
+ RETURN_LONG(zend_binary_strcasecmp(s1->val, s1->len, s2->val, s2->len));
}
/* }}} */
@@ -591,11 +595,10 @@ ZEND_FUNCTION(strcasecmp)
Binary safe string comparison */
ZEND_FUNCTION(strncasecmp)
{
- char *s1, *s2;
- int s1_len, s2_len;
- long len;
+ zend_string *s1, *s2;
+ zend_long len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &s1, &s1_len, &s2, &s2_len, &len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "SSl", &s1, &s2, &len) == FAILURE) {
return;
}
@@ -604,7 +607,7 @@ ZEND_FUNCTION(strncasecmp)
RETURN_FALSE;
}
- RETURN_LONG(zend_binary_strncasecmp(s1, s1_len, s2, s2_len, len));
+ RETURN_LONG(zend_binary_strncasecmp(s1->val, s1->len, s2->val, s2->len, len));
}
/* }}} */
@@ -614,7 +617,7 @@ ZEND_FUNCTION(strncasecmp)
ZEND_FUNCTION(each)
{
zval *array, *entry, tmp;
- ulong num_key;
+ zend_ulong num_key;
HashTable *target_hash;
zend_string *key;
@@ -657,7 +660,7 @@ ZEND_FUNCTION(each)
/* add the key elements */
if (zend_hash_get_current_key(target_hash, &key, &num_key, 0) == HASH_KEY_IS_STRING) {
- ZVAL_STR(&tmp, STR_COPY(key));
+ ZVAL_STR(&tmp, zend_string_copy(key));
if (Z_REFCOUNTED(tmp)) Z_ADDREF(tmp);
} else {
ZVAL_LONG(&tmp, num_key);
@@ -673,19 +676,18 @@ ZEND_FUNCTION(each)
Return the current error_reporting level, and if an argument was passed - change to the new level */
ZEND_FUNCTION(error_reporting)
{
- char *err;
- int err_len;
+ zend_string *err;
int old_error_reporting;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &err, &err_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|S", &err) == FAILURE) {
return;
}
old_error_reporting = EG(error_reporting);
if(ZEND_NUM_ARGS() != 0) {
- zend_string *key = STR_INIT("error_reporting", sizeof("error_reporting")-1, 0);
- zend_alter_ini_entry(key, err, err_len, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
- STR_RELEASE(key);
+ zend_string *key = zend_string_init("error_reporting", sizeof("error_reporting")-1, 0);
+ zend_alter_ini_entry(key, err, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
+ zend_string_release(key);
}
RETVAL_LONG(old_error_reporting);
@@ -762,7 +764,7 @@ repeat:
ZVAL_DUP(&c.value, val);
zval_ptr_dtor(&val_free);
c.flags = case_sensitive; /* non persistent */
- c.name = STR_COPY(name);
+ c.name = zend_string_copy(name);
c.module_number = PHP_USER_CONSTANT;
if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
RETURN_TRUE;
@@ -774,7 +776,8 @@ repeat:
/* {{{ proto bool defined(string constant_name)
- Check whether a constant exists */
+ Check whether a constant exists
+ Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
ZEND_FUNCTION(defined)
{
zend_string *name;
@@ -810,7 +813,7 @@ ZEND_FUNCTION(get_class)
if (!obj) {
if (EG(scope)) {
- RETURN_STR(STR_COPY(EG(scope)->name));
+ RETURN_STR(zend_string_copy(EG(scope)->name));
} else {
zend_error(E_WARNING, "get_class() called without object from outside a class");
RETURN_FALSE;
@@ -831,7 +834,7 @@ ZEND_FUNCTION(get_called_class)
}
if (EG(current_execute_data)->called_scope) {
- RETURN_STR(STR_COPY(EG(current_execute_data)->called_scope->name));
+ RETURN_STR(zend_string_copy(EG(current_execute_data)->called_scope->name));
} else if (!EG(scope)) {
zend_error(E_WARNING, "get_called_class() called from outside a class");
}
@@ -855,7 +858,7 @@ ZEND_FUNCTION(get_parent_class)
if (!ZEND_NUM_ARGS()) {
ce = EG(scope);
if (ce && ce->parent) {
- RETURN_STR(STR_COPY(ce->parent->name));
+ RETURN_STR(zend_string_copy(ce->parent->name));
} else {
RETURN_FALSE;
}
@@ -873,7 +876,7 @@ ZEND_FUNCTION(get_parent_class)
}
if (ce && ce->parent) {
- RETURN_STR(STR_COPY(ce->parent->name));
+ RETURN_STR(zend_string_copy(ce->parent->name));
} else {
RETURN_FALSE;
}
@@ -1033,8 +1036,6 @@ ZEND_FUNCTION(get_object_vars)
zval *value;
HashTable *properties;
zend_string *key;
- const char *prop_name, *class_name;
- uint prop_len;
zend_object *zobj;
#ifndef FAST_ZPP
@@ -1059,7 +1060,7 @@ ZEND_FUNCTION(get_object_vars)
zobj = Z_OBJ_P(obj);
- array_init(return_value);
+ array_init_size(return_value, zend_hash_num_elements(properties));
ZEND_HASH_FOREACH_STR_KEY_VAL_IND(properties, key, value) {
if (key) {
@@ -1067,7 +1068,9 @@ ZEND_FUNCTION(get_object_vars)
/* Not separating references */
if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
if (key->val[0] == 0) {
- zend_unmangle_property_name_ex(key->val, key->len, &class_name, &prop_name, (int*) &prop_len);
+ const char *prop_name, *class_name;
+ size_t prop_len;
+ zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len);
zend_hash_str_add_new(Z_ARRVAL_P(return_value), prop_name, prop_len, value);
} else {
zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
@@ -1078,7 +1081,7 @@ ZEND_FUNCTION(get_object_vars)
}
/* }}} */
-static int same_name(const char *key, const char *name, zend_uint name_len)
+static int same_name(const char *key, const char *name, uint32_t name_len)
{
char *lcname = zend_str_tolower_dup(name, name_len);
int ret = memcmp(lcname, key, name_len) == 0;
@@ -1128,7 +1131,7 @@ ZEND_FUNCTION(get_class_methods)
/* Do not display old-style inherited constructors */
if (!key) {
- ZVAL_STR(&method_name, STR_COPY(mptr->common.function_name));
+ ZVAL_STR(&method_name, zend_string_copy(mptr->common.function_name));
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
} else if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 ||
mptr->common.scope == ce ||
@@ -1138,10 +1141,10 @@ ZEND_FUNCTION(get_class_methods)
*mptr->op_array.refcount > 1 &&
(len != key->len ||
!same_name(key->val, mptr->common.function_name->val, len))) {
- ZVAL_STR(&method_name, STR_COPY(zend_find_alias_name(mptr->common.scope, key)));
+ ZVAL_STR(&method_name, zend_string_copy(zend_find_alias_name(mptr->common.scope, key)));
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
} else {
- ZVAL_STR(&method_name, STR_COPY(mptr->common.function_name));
+ ZVAL_STR(&method_name, zend_string_copy(mptr->common.function_name));
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
}
}
@@ -1180,10 +1183,10 @@ ZEND_FUNCTION(method_exists)
RETURN_FALSE;
}
- lcname = STR_ALLOC(method_name->len, 0);
+ lcname = zend_string_alloc(method_name->len, 0);
zend_str_tolower_copy(lcname->val, method_name->val, method_name->len);
if (zend_hash_exists(&ce->function_table, lcname)) {
- STR_FREE(lcname);
+ zend_string_free(lcname);
RETURN_TRUE;
} else {
union _zend_function *func = NULL;
@@ -1196,12 +1199,11 @@ ZEND_FUNCTION(method_exists)
&& (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0
) {
/* Returns true to the fake Closure's __invoke */
- RETVAL_BOOL((func->common.scope == zend_ce_closure
- && (method_name->len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
- && memcmp(lcname->val, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0) ? 1 : 0);
+ RETVAL_BOOL(func->common.scope == zend_ce_closure
+ && zend_string_equals_literal(method_name, ZEND_INVOKE_FUNC_NAME));
- STR_FREE(lcname);
- STR_RELEASE(func->common.function_name);
+ zend_string_free(lcname);
+ zend_string_release(func->common.function_name);
efree(func);
return;
}
@@ -1285,14 +1287,14 @@ ZEND_FUNCTION(class_exists)
if (!autoload) {
if (class_name->val[0] == '\\') {
/* Ignore leading "\" */
- lc_name = STR_ALLOC(class_name->len - 1, 0);
+ lc_name = zend_string_alloc(class_name->len - 1, 0);
zend_str_tolower_copy(lc_name->val, class_name->val + 1, class_name->len - 1);
} else {
- lc_name = STR_ALLOC(class_name->len, 0);
+ lc_name = zend_string_alloc(class_name->len, 0);
zend_str_tolower_copy(lc_name->val, class_name->val, class_name->len);
}
ce = zend_hash_find_ptr(EG(class_table), lc_name);
- STR_FREE(lc_name);
+ zend_string_free(lc_name);
RETURN_BOOL(ce && !((ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT)) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS));
}
@@ -1328,14 +1330,14 @@ ZEND_FUNCTION(interface_exists)
if (!autoload) {
if (iface_name->val[0] == '\\') {
/* Ignore leading "\" */
- lc_name = STR_ALLOC(iface_name->len - 1, 0);
+ lc_name = zend_string_alloc(iface_name->len - 1, 0);
zend_str_tolower_copy(lc_name->val, iface_name->val + 1, iface_name->len - 1);
} else {
- lc_name = STR_ALLOC(iface_name->len, 0);
+ lc_name = zend_string_alloc(iface_name->len, 0);
zend_str_tolower_copy(lc_name->val, iface_name->val, iface_name->len);
}
ce = zend_hash_find_ptr(EG(class_table), lc_name);
- STR_FREE(lc_name);
+ zend_string_free(lc_name);
RETURN_BOOL(ce && ce->ce_flags & ZEND_ACC_INTERFACE);
}
@@ -1371,14 +1373,14 @@ ZEND_FUNCTION(trait_exists)
if (!autoload) {
if (trait_name->val[0] == '\\') {
/* Ignore leading "\" */
- lc_name = STR_ALLOC(trait_name->len - 1, 0);
+ lc_name = zend_string_alloc(trait_name->len - 1, 0);
zend_str_tolower_copy(lc_name->val, trait_name->val + 1, trait_name->len - 1);
} else {
- lc_name = STR_ALLOC(trait_name->len, 0);
+ lc_name = zend_string_alloc(trait_name->len, 0);
zend_str_tolower_copy(lc_name->val, trait_name->val, trait_name->len);
}
ce = zend_hash_find_ptr(EG(class_table), lc_name);
- STR_FREE(lc_name);
+ zend_string_free(lc_name);
RETURN_BOOL(ce && ((ce->ce_flags & ZEND_ACC_TRAIT) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS));
}
@@ -1397,7 +1399,7 @@ ZEND_FUNCTION(trait_exists)
ZEND_FUNCTION(function_exists)
{
char *name;
- int name_len;
+ size_t name_len;
zend_function *func;
zend_string *lcname;
@@ -1413,15 +1415,15 @@ ZEND_FUNCTION(function_exists)
if (name[0] == '\\') {
/* Ignore leading "\" */
- lcname = STR_ALLOC(name_len - 1, 0);
+ lcname = zend_string_alloc(name_len - 1, 0);
zend_str_tolower_copy(lcname->val, name + 1, name_len - 1);
} else {
- lcname = STR_ALLOC(name_len, 0);
+ lcname = zend_string_alloc(name_len, 0);
zend_str_tolower_copy(lcname->val, name, name_len);
}
func = zend_hash_find_ptr(EG(function_table), lcname);
- STR_FREE(lcname);
+ zend_string_free(lcname);
/*
* A bit of a hack, but not a bad one: we see if the handler of the function
@@ -1439,7 +1441,7 @@ ZEND_FUNCTION(class_alias)
zend_string *class_name;
char *alias_name;
zend_class_entry *ce;
- int alias_name_len;
+ size_t alias_name_len;
zend_bool autoload = 1;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ss|b", &class_name, &alias_name, &alias_name_len, &autoload) == FAILURE) {
@@ -1472,7 +1474,7 @@ ZEND_FUNCTION(class_alias)
Cause an intentional memory leak, for testing/debugging purposes */
ZEND_FUNCTION(leak)
{
- long leakbytes=3;
+ zend_long leakbytes=3;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &leakbytes) == FAILURE) {
return;
@@ -1529,7 +1531,7 @@ ZEND_FUNCTION(get_included_files)
array_init(return_value);
ZEND_HASH_FOREACH_STR_KEY(&EG(included_files), entry) {
if (entry) {
- add_next_index_str(return_value, STR_COPY(entry));
+ add_next_index_str(return_value, zend_string_copy(entry));
}
} ZEND_HASH_FOREACH_END();
}
@@ -1540,9 +1542,9 @@ ZEND_FUNCTION(get_included_files)
Generates a user-level error/warning/notice message */
ZEND_FUNCTION(trigger_error)
{
- long error_type = E_USER_NOTICE;
+ zend_long error_type = E_USER_NOTICE;
char *message;
- int message_len;
+ size_t message_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &message, &message_len, &error_type) == FAILURE) {
return;
@@ -1572,7 +1574,7 @@ ZEND_FUNCTION(set_error_handler)
{
zval *error_handler;
zend_string *error_handler_name = NULL;
- long error_type = E_ALL;
+ zend_long error_type = E_ALL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &error_handler, &error_type) == FAILURE) {
return;
@@ -1582,10 +1584,10 @@ ZEND_FUNCTION(set_error_handler)
if (!zend_is_callable(error_handler, 0, &error_handler_name TSRMLS_CC)) {
zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
get_active_function_name(TSRMLS_C), error_handler_name?error_handler_name->val:"unknown");
- STR_RELEASE(error_handler_name);
+ zend_string_release(error_handler_name);
return;
}
- STR_RELEASE(error_handler_name);
+ zend_string_release(error_handler_name);
}
if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
@@ -1648,10 +1650,10 @@ ZEND_FUNCTION(set_exception_handler)
if (!zend_is_callable(exception_handler, 0, &exception_handler_name TSRMLS_CC)) {
zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
get_active_function_name(TSRMLS_C), exception_handler_name?exception_handler_name->val:"unknown");
- STR_RELEASE(exception_handler_name);
+ zend_string_release(exception_handler_name);
return;
}
- STR_RELEASE(exception_handler_name);
+ zend_string_release(exception_handler_name);
}
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
@@ -1692,18 +1694,18 @@ static int copy_class_or_interface_name(zval *el TSRMLS_DC, int num_args, va_lis
{
zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
zval *array = va_arg(args, zval *);
- zend_uint mask = va_arg(args, zend_uint);
- zend_uint comply = va_arg(args, zend_uint);
- zend_uint comply_mask = (comply)? mask:0;
+ uint32_t mask = va_arg(args, uint32_t);
+ uint32_t comply = va_arg(args, uint32_t);
+ uint32_t comply_mask = (comply)? mask:0;
if ((hash_key->key && hash_key->key->val[0] != 0)
&& (comply_mask == (ce->ce_flags & mask))) {
if (ce->refcount > 1 &&
- (ce->name->len != hash_key->key->len - 1 ||
+ (ce->name->len != hash_key->key->len ||
!same_name(hash_key->key->val, ce->name->val, ce->name->len))) {
- add_next_index_str(array, STR_COPY(hash_key->key));
+ add_next_index_str(array, zend_string_copy(hash_key->key));
} else {
- add_next_index_str(array, STR_COPY(ce->name));
+ add_next_index_str(array, zend_string_copy(ce->name));
}
}
return ZEND_HASH_APPLY_KEEP;
@@ -1713,8 +1715,8 @@ static int copy_class_or_interface_name(zval *el TSRMLS_DC, int num_args, va_lis
Returns an array of all declared traits. */
ZEND_FUNCTION(get_declared_traits)
{
- zend_uint mask = ZEND_ACC_TRAIT;
- zend_uint comply = 1;
+ uint32_t mask = ZEND_ACC_TRAIT;
+ uint32_t comply = 1;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1730,8 +1732,8 @@ ZEND_FUNCTION(get_declared_traits)
Returns an array of all declared classes. */
ZEND_FUNCTION(get_declared_classes)
{
- zend_uint mask = ZEND_ACC_INTERFACE | (ZEND_ACC_TRAIT & ~ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
- zend_uint comply = 0;
+ uint32_t mask = ZEND_ACC_INTERFACE | (ZEND_ACC_TRAIT & ~ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
+ uint32_t comply = 0;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1746,8 +1748,8 @@ ZEND_FUNCTION(get_declared_classes)
Returns an array of all declared interfaces. */
ZEND_FUNCTION(get_declared_interfaces)
{
- zend_uint mask = ZEND_ACC_INTERFACE;
- zend_uint comply = 1;
+ uint32_t mask = ZEND_ACC_INTERFACE;
+ uint32_t comply = 1;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1770,9 +1772,9 @@ static int copy_function_name(zval *zv TSRMLS_DC, int num_args, va_list args, ze
}
if (func->type == ZEND_INTERNAL_FUNCTION) {
- add_next_index_str(internal_ar, STR_COPY(hash_key->key));
+ add_next_index_str(internal_ar, zend_string_copy(hash_key->key));
} else if (func->type == ZEND_USER_FUNCTION) {
- add_next_index_str(user_ar, STR_COPY(hash_key->key));
+ add_next_index_str(user_ar, zend_string_copy(hash_key->key));
}
return 0;
@@ -1835,7 +1837,7 @@ ZEND_FUNCTION(create_function)
{
zend_string *function_name;
char *eval_code, *function_args, *function_code;
- int eval_code_length, function_args_len, function_code_len;
+ size_t eval_code_length, function_args_len, function_code_len;
int retval;
char *eval_name;
@@ -1880,7 +1882,7 @@ ZEND_FUNCTION(create_function)
}
(*func->refcount)++;
- function_name = STR_ALLOC(sizeof("0lambda_")+MAX_LENGTH_OF_LONG, 0);
+ function_name = zend_string_alloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG, 0);
function_name->val[0] = '\0';
do {
@@ -1911,7 +1913,7 @@ ZEND_FUNCTION(zend_test_func)
#ifdef ZTS
ZEND_FUNCTION(zend_thread_id)
{
- RETURN_LONG((long)tsrm_thread_id());
+ RETURN_LONG((zend_long)tsrm_thread_id());
}
#endif
#endif
@@ -1936,6 +1938,53 @@ ZEND_FUNCTION(get_resource_type)
}
/* }}} */
+/* {{{ proto array get_resources([string resouce_type])
+ Get an array with all active resources */
+ZEND_FUNCTION(get_resources)
+{
+ zend_string *type = NULL;
+ zend_string *key;
+ zend_ulong index;
+ zval *val;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|S", &type) == FAILURE) {
+ return;
+ }
+
+ if (!type) {
+ array_init(return_value);
+ ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
+ if (!key) {
+ Z_ADDREF_P(val);
+ zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
+ }
+ } ZEND_HASH_FOREACH_END();
+ } else if (zend_string_equals_literal(type, "Unknown")) {
+ array_init(return_value);
+ ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
+ if (!key && Z_RES_TYPE_P(val) <= 0) {
+ Z_ADDREF_P(val);
+ zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
+ }
+ } ZEND_HASH_FOREACH_END();
+ } else {
+ int id = zend_fetch_list_dtor_id(type->val);
+
+ if (id <= 0) {
+ zend_error(E_WARNING, "get_resources(): Unknown resource type '%s'", type->val);
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
+ if (!key && Z_RES_TYPE_P(val) == id) {
+ Z_ADDREF_P(val);
+ zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+}
+/* }}} */
static int add_extension_info(zval *item, void *arg TSRMLS_DC)
{
@@ -2055,15 +2104,15 @@ ZEND_FUNCTION(get_defined_constants)
static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array TSRMLS_DC)
{
- int num_args = call->num_args;
+ uint32_t num_args = call->num_args;
array_init_size(arg_array, num_args);
if (num_args) {
- int i = 0;
+ uint32_t i = 0;
zval *p = ZEND_CALL_ARG(call, 1);
if (call->func->type == ZEND_USER_FUNCTION) {
- int first_extra_arg = call->func->op_array.num_args;
+ uint32_t first_extra_arg = call->func->op_array.num_args;
if (call->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
first_extra_arg--;
@@ -2115,8 +2164,8 @@ ZEND_FUNCTION(debug_print_backtrace)
const char *include_filename = NULL;
zval arg_array;
int indent = 0;
- long options = 0;
- long limit = 0;
+ zend_long options = 0;
+ zend_long limit = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &options, &limit) == FAILURE) {
return;
@@ -2374,7 +2423,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
break;
}
if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
- add_assoc_str_ex(&stack_frame, "file", sizeof("file")-1, STR_COPY(prev->func->op_array.filename));
+ add_assoc_str_ex(&stack_frame, "file", sizeof("file")-1, zend_string_copy(prev->func->op_array.filename));
add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, prev->opline->lineno);
break;
}
@@ -2412,10 +2461,10 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
if (object) {
if (func->common.scope) {
- add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(func->common.scope->name));
+ add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(func->common.scope->name));
} else {
class_name = zend_get_object_classname(object TSRMLS_CC);
- add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(class_name));
+ add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(class_name));
}
if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
@@ -2427,7 +2476,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "->");
} else if (func->common.scope) {
- add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(func->common.scope->name));
+ add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(func->common.scope->name));
add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "::");
}
@@ -2503,8 +2552,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
Return backtrace as array */
ZEND_FUNCTION(debug_backtrace)
{
- long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
- long limit = 0;
+ zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
+ zend_long limit = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &options, &limit) == FAILURE) {
return;
@@ -2519,21 +2568,21 @@ ZEND_FUNCTION(debug_backtrace)
ZEND_FUNCTION(extension_loaded)
{
char *extension_name;
- int extension_name_len;
+ size_t extension_name_len;
zend_string *lcname;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &extension_name, &extension_name_len) == FAILURE) {
return;
}
- lcname = STR_ALLOC(extension_name_len, 0);
+ lcname = zend_string_alloc(extension_name_len, 0);
zend_str_tolower_copy(lcname->val, extension_name, extension_name_len);
if (zend_hash_exists(&module_registry, lcname)) {
RETVAL_TRUE;
} else {
RETVAL_FALSE;
}
- STR_FREE(lcname);
+ zend_string_free(lcname);
}
/* }}} */
@@ -2544,7 +2593,8 @@ ZEND_FUNCTION(get_extension_funcs)
{
char *extension_name;
zend_string *lcname;
- int extension_name_len, array;
+ size_t extension_name_len;
+ int array;
zend_module_entry *module;
zend_function *zif;
@@ -2552,13 +2602,13 @@ ZEND_FUNCTION(get_extension_funcs)
return;
}
if (strncasecmp(extension_name, "zend", sizeof("zend"))) {
- lcname = STR_ALLOC(extension_name_len, 0);
+ lcname = zend_string_alloc(extension_name_len, 0);
zend_str_tolower_copy(lcname->val, extension_name, extension_name_len);
} else {
- lcname = STR_INIT("core", sizeof("core")-1, 0);
+ lcname = zend_string_init("core", sizeof("core")-1, 0);
}
module = zend_hash_find_ptr(&module_registry, lcname);
- STR_FREE(lcname);
+ zend_string_free(lcname);
if (!module) {
RETURN_FALSE;
}
@@ -2578,7 +2628,7 @@ ZEND_FUNCTION(get_extension_funcs)
array_init(return_value);
array = 1;
}
- add_next_index_str(return_value, STR_COPY(zif->common.function_name));
+ add_next_index_str(return_value, zend_string_copy(zif->common.function_name));
}
} ZEND_HASH_FOREACH_END();
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index c10c1a4327..c8497a4f2d 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -61,11 +61,66 @@ ZEND_METHOD(Closure, __invoke) /* {{{ */
efree(arguments);
/* destruct the function also, then - we have allocated it in get_method */
- STR_RELEASE(func->internal_function.function_name);
+ zend_string_release(func->internal_function.function_name);
efree(func);
}
/* }}} */
+/* {{{ proto mixed Closure::call(object $to [, mixed $parameter] [, mixed $...] )
+ Call closure, binding to a given object with its class as the scope */
+ZEND_METHOD(Closure, call)
+{
+ zval *zclosure, *newthis, closure_result;
+ zend_closure *closure;
+ zend_fcall_info fci;
+ zend_fcall_info_cache fci_cache;
+ zval *my_params;
+ int my_param_count = 0;
+ zend_function my_function;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o*", &newthis, &my_params, &my_param_count) == FAILURE) {
+ return;
+ }
+
+ zclosure = getThis();
+ closure = (zend_closure *)Z_OBJ_P(zclosure);
+
+ if (closure->func.common.fn_flags & ZEND_ACC_STATIC) {
+ zend_error(E_WARNING, "Cannot bind an instance to a static closure");
+ return;
+ }
+
+ if (closure->func.type == ZEND_INTERNAL_FUNCTION) {
+ /* verify that we aren't binding internal function to a wrong object */
+ if ((closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0 &&
+ !instanceof_function(Z_OBJCE_P(newthis), closure->func.common.scope TSRMLS_CC)) {
+ zend_error(E_WARNING, "Cannot bind function %s::%s to object of class %s", closure->func.common.scope->name->val, closure->func.common.function_name->val, Z_OBJCE_P(newthis)->name->val);
+ return;
+ }
+ }
+
+ /* This should never happen as closures will always be callable */
+ if (zend_fcall_info_init(zclosure, 0, &fci, &fci_cache, NULL, NULL TSRMLS_CC) != SUCCESS) {
+ ZEND_ASSERT(0);
+ }
+
+ fci.retval = &closure_result;
+ fci.params = my_params;
+ fci.param_count = my_param_count;
+ fci.object = fci_cache.object = Z_OBJ_P(newthis);
+ fci_cache.initialized = 1;
+
+ my_function = *fci_cache.function_handler;
+ /* use scope of passed object */
+ my_function.common.scope = Z_OBJCE_P(newthis);
+ fci_cache.function_handler = &my_function;
+
+ if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) {
+ ZVAL_COPY_VALUE(return_value, &closure_result);
+ }
+}
+/* }}} */
+
/* {{{ proto Closure Closure::bind(Closure $old, object $to [, mixed $scope = "static" ] )
Create a closure from another one and bind to another object and scope */
ZEND_METHOD(Closure, bind)
@@ -91,15 +146,14 @@ ZEND_METHOD(Closure, bind)
ce = NULL;
} else {
zend_string *class_name = zval_get_string(scope_arg);
- if ((class_name->len == sizeof("static") - 1) &&
- (memcmp("static", class_name->val, sizeof("static") - 1) == 0)) {
+ if (zend_string_equals_literal(class_name, "static")) {
ce = closure->func.common.scope;
} else if ((ce = zend_lookup_class_ex(class_name, NULL, 1 TSRMLS_CC)) == NULL) {
zend_error(E_WARNING, "Class '%s' not found", class_name->val);
- STR_RELEASE(class_name);
+ zend_string_release(class_name);
RETURN_NULL();
}
- STR_RELEASE(class_name);
+ zend_string_release(class_name);
}
} else { /* scope argument not given; do not change the scope by default */
ce = closure->func.common.scope;
@@ -133,7 +187,7 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object TSRML
invoke->internal_function.handler = ZEND_MN(Closure___invoke);
invoke->internal_function.module = 0;
invoke->internal_function.scope = zend_ce_closure;
- invoke->internal_function.function_name = STR_INIT(ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1, 0);
+ invoke->internal_function.function_name = zend_string_init(ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1, 0);
return invoke;
}
/* }}} */
@@ -156,15 +210,13 @@ static zend_function *zend_closure_get_method(zend_object **object, zend_string
{
zend_string *lc_name;
- lc_name = STR_ALLOC(method->len, 0);
+ lc_name = zend_string_alloc(method->len, 0);
zend_str_tolower_copy(lc_name->val, method->val, method->len);
- if ((method->len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) &&
- memcmp(lc_name->val, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
- ) {
- STR_FREE(lc_name);
+ if (zend_string_equals_literal(method, ZEND_INVOKE_FUNC_NAME)) {
+ zend_string_free(lc_name);
return zend_get_closure_invoke_method(*object TSRMLS_CC);
}
- STR_FREE(lc_name);
+ zend_string_free(lc_name);
return std_object_handlers.get_method(object, method, key TSRMLS_CC);
}
/* }}} */
@@ -308,7 +360,7 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_
}
if (arg_info) {
- zend_uint i, required = closure->func.common.required_num_args;
+ uint32_t i, required = closure->func.common.required_num_args;
array_init(&val);
@@ -326,7 +378,7 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_
}
ZVAL_STR(&info, zend_strpprintf(0, "%s", i >= required ? "<optional>" : "<required>"));
zend_hash_update(Z_ARRVAL(val), name, &info);
- STR_RELEASE(name);
+ zend_string_release(name);
arg_info++;
}
zend_hash_str_update(closure->debug_info, "parameter", sizeof("parameter")-1, &val);
@@ -373,10 +425,16 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_bind, 0, 0, 2)
ZEND_ARG_INFO(0, newscope)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_call, 0, 0, 1)
+ ZEND_ARG_INFO(0, newthis)
+ ZEND_ARG_VARIADIC_INFO(0, parameters)
+ZEND_END_ARG_INFO()
+
static const zend_function_entry closure_functions[] = {
ZEND_ME(Closure, __construct, NULL, ZEND_ACC_PRIVATE)
ZEND_ME(Closure, bind, arginfo_closure_bind, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_MALIAS(Closure, bindTo, bind, arginfo_closure_bindto, ZEND_ACC_PUBLIC)
+ ZEND_ME(Closure, call, arginfo_closure_call, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 35761ecec0..5beacab0b6 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -14,6 +14,7 @@
+----------------------------------------------------------------------+
| Authors: Andi Gutmans <andi@zend.com> |
| Zeev Suraski <zeev@zend.com> |
+ | Nikita Popov <nikic@php.net> |
+----------------------------------------------------------------------+
*/
@@ -51,43 +52,21 @@
(target)->u.constant = CONSTANT(src.constant); \
} else { \
(target)->u.op = src; \
- (target)->EA = 0; \
} \
} while (0)
-#define COPY_NODE(target, src) do { \
- target ## _type = src ## _type; \
- target = src; \
- } while (0)
-
-#define GET_CACHE_SLOT(literal) do { \
- Z_CACHE_SLOT(CG(active_op_array)->literals[literal]) = CG(active_op_array)->last_cache_slot++; \
- if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
- CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
- CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
- } \
- } while (0)
+static inline void zend_alloc_cache_slot(uint32_t literal TSRMLS_DC) {
+ zend_op_array *op_array = CG(active_op_array);
+ Z_CACHE_SLOT(op_array->literals[literal]) = op_array->last_cache_slot++;
+}
#define POLYMORPHIC_CACHE_SLOT_SIZE 2
-#define GET_POLYMORPHIC_CACHE_SLOT(literal) do { \
- Z_CACHE_SLOT(CG(active_op_array)->literals[literal]) = CG(active_op_array)->last_cache_slot; \
- CG(active_op_array)->last_cache_slot += POLYMORPHIC_CACHE_SLOT_SIZE; \
- if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
- CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
- CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
- CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 2] = NULL; \
- } \
- } while (0)
-
-#define FREE_POLYMORPHIC_CACHE_SLOT(literal) do { \
- if (Z_CACHE_SLOT(CG(active_op_array)->literals[literal]) != -1 && \
- Z_CACHE_SLOT(CG(active_op_array)->literals[literal]) == \
- CG(active_op_array)->last_cache_slot - POLYMORPHIC_CACHE_SLOT_SIZE) { \
- Z_CACHE_SLOT(CG(active_op_array)->literals[literal]) = -1; \
- CG(active_op_array)->last_cache_slot -= POLYMORPHIC_CACHE_SLOT_SIZE; \
- } \
- } while (0)
+static inline void zend_alloc_polymorphic_cache_slot(uint32_t literal TSRMLS_DC) {
+ zend_op_array *op_array = CG(active_op_array);
+ Z_CACHE_SLOT(op_array->literals[literal]) = op_array->last_cache_slot;
+ op_array->last_cache_slot += POLYMORPHIC_CACHE_SLOT_SIZE;
+}
ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
@@ -97,22 +76,15 @@ ZEND_API zend_compiler_globals compiler_globals;
ZEND_API zend_executor_globals executor_globals;
#endif
-static void zend_push_function_call_entry(zend_function *fbc, zend_uint opline_num TSRMLS_DC) /* {{{ */
-{
- zend_function_call_entry fcall = { fbc, opline_num };
- zend_stack_push(&CG(function_call_stack), &fcall);
-}
-/* }}} */
-
static zend_property_info *zend_duplicate_property_info(zend_property_info *property_info TSRMLS_DC) /* {{{ */
{
zend_property_info* new_property_info;
new_property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
memcpy(new_property_info, property_info, sizeof(zend_property_info));
- STR_ADDREF(new_property_info->name);
+ zend_string_addref(new_property_info->name);
if (new_property_info->doc_comment) {
- STR_ADDREF(new_property_info->doc_comment);
+ zend_string_addref(new_property_info->doc_comment);
}
return new_property_info;
}
@@ -122,7 +94,7 @@ static zend_property_info *zend_duplicate_property_info_internal(zend_property_i
{
zend_property_info* new_property_info = pemalloc(sizeof(zend_property_info), 1);
memcpy(new_property_info, property_info, sizeof(zend_property_info));
- STR_ADDREF(new_property_info->name);
+ zend_string_addref(new_property_info->name);
return new_property_info;
}
/* }}} */
@@ -131,9 +103,9 @@ static void zend_destroy_property_info(zval *zv) /* {{{ */
{
zend_property_info *property_info = Z_PTR_P(zv);
- STR_RELEASE(property_info->name);
+ zend_string_release(property_info->name);
if (property_info->doc_comment) {
- STR_RELEASE(property_info->doc_comment);
+ zend_string_release(property_info->doc_comment);
}
}
/* }}} */
@@ -142,18 +114,32 @@ static void zend_destroy_property_info_internal(zval *zv) /* {{{ */
{
zend_property_info *property_info = Z_PTR_P(zv);
- STR_RELEASE(property_info->name);
+ zend_string_release(property_info->name);
free(property_info);
}
/* }}} */
-static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC) /* {{{ */
+static zend_string *zend_new_interned_string_safe(zend_string *str TSRMLS_DC) /* {{{ */ {
+ zend_string *interned_str;
+
+ zend_string_addref(str);
+ interned_str = zend_new_interned_string(str TSRMLS_CC);
+ if (str != interned_str) {
+ return interned_str;
+ } else {
+ zend_string_release(str);
+ return str;
+ }
+}
+/* }}} */
+
+static zend_string *zend_build_runtime_definition_key(zend_string *name, unsigned char *lex_pos TSRMLS_DC) /* {{{ */
{
+ zend_string *result;
char char_pos_buf[32];
- uint char_pos_len;
- const char *filename;
+ size_t char_pos_len = zend_sprintf(char_pos_buf, "%p", lex_pos);
- char_pos_len = zend_sprintf(char_pos_buf, "%p", LANG_SCNG(yy_text));
+ const char *filename;
if (CG(active_op_array)->filename) {
filename = CG(active_op_array)->filename->val;
} else {
@@ -161,11 +147,11 @@ static void build_runtime_defined_function_key(zval *result, const char *name, i
}
/* NULL, name length, filename length, last accepting char position length */
- ZVAL_NEW_STR(result, STR_ALLOC(1+name_length+strlen(filename)+char_pos_len, 0));
+ result = zend_string_alloc(1 + name->len + strlen(filename) + char_pos_len, 0);
- /* must be binary safe */
- Z_STRVAL_P(result)[0] = '\0';
- sprintf(Z_STRVAL_P(result)+1, "%s%s%s", name, filename, char_pos_buf);
+ result->val[0] = '\0';
+ sprintf(result->val + 1, "%s%s%s", name->val, filename, char_pos_buf);
+ return result;
}
/* }}} */
@@ -177,7 +163,7 @@ static void init_compiler_declarables(TSRMLS_D) /* {{{ */
void zend_init_compiler_context(TSRMLS_D) /* {{{ */
{
- CG(context).opcodes_size = (CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) ? INITIAL_INTERACTIVE_OP_ARRAY_SIZE : INITIAL_OP_ARRAY_SIZE;
+ CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
CG(context).vars_size = 0;
CG(context).literals_size = 0;
CG(context).current_brk_cont = -1;
@@ -189,19 +175,12 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */
void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
{
- zend_stack_init(&CG(bp_stack), sizeof(zend_llist));
- zend_stack_init(&CG(function_call_stack), sizeof(zend_function_call_entry));
- zend_stack_init(&CG(switch_cond_stack), sizeof(zend_switch_entry));
- zend_stack_init(&CG(foreach_copy_stack), sizeof(zend_op));
- zend_stack_init(&CG(object_stack), sizeof(znode));
- zend_stack_init(&CG(declare_stack), sizeof(zend_declarables));
+ zend_stack_init(&CG(loop_var_stack), sizeof(znode));
+ zend_stack_init(&CG(delayed_oplines_stack), sizeof(zend_op));
CG(active_class_entry) = NULL;
- zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
- zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
- zend_stack_init(&CG(list_stack), sizeof(zend_llist));
CG(in_compilation) = 0;
CG(start_lineno) = 0;
- ZVAL_UNDEF(&CG(current_namespace));
+ CG(current_namespace) = NULL;
CG(in_namespace) = 0;
CG(has_bracketed_namespaces) = 0;
CG(current_import) = NULL;
@@ -238,13 +217,8 @@ void init_compiler(TSRMLS_D) /* {{{ */
void shutdown_compiler(TSRMLS_D) /* {{{ */
{
- zend_stack_destroy(&CG(bp_stack));
- zend_stack_destroy(&CG(function_call_stack));
- zend_stack_destroy(&CG(switch_cond_stack));
- zend_stack_destroy(&CG(foreach_copy_stack));
- zend_stack_destroy(&CG(object_stack));
- zend_stack_destroy(&CG(declare_stack));
- zend_stack_destroy(&CG(list_stack));
+ zend_stack_destroy(&CG(loop_var_stack));
+ zend_stack_destroy(&CG(delayed_oplines_stack));
zend_hash_destroy(&CG(filenames_table));
zend_hash_destroy(&CG(const_filenames));
zend_stack_destroy(&CG(context_stack));
@@ -261,7 +235,7 @@ ZEND_API zend_string *zend_set_compiled_filename(zend_string *new_compiled_filen
CG(compiled_filename) = p;
return p;
}
- p = STR_COPY(new_compiled_filename);
+ p = zend_string_copy(new_compiled_filename);
zend_hash_update_ptr(&CG(filenames_table), new_compiled_filename, p);
CG(compiled_filename) = p;
return p;
@@ -292,22 +266,22 @@ ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
}
/* }}} */
-static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
+static uint32_t get_temporary_variable(zend_op_array *op_array) /* {{{ */
{
- return (zend_uint)op_array->T++;
+ return (uint32_t)op_array->T++;
}
/* }}} */
static int lookup_cv(zend_op_array *op_array, zend_string* name TSRMLS_DC) /* {{{ */{
int i = 0;
- ulong hash_value = STR_HASH_VAL(name);
+ zend_ulong hash_value = zend_string_hash_val(name);
while (i < op_array->last_var) {
if (op_array->vars[i]->val == name->val ||
(op_array->vars[i]->h == hash_value &&
op_array->vars[i]->len == name->len &&
memcmp(op_array->vars[i]->val, name->val, name->len) == 0)) {
- STR_RELEASE(name);
+ zend_string_release(name);
return (int)(zend_intptr_t)EX_VAR_NUM_2(NULL, i);
}
i++;
@@ -339,7 +313,7 @@ void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */
static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int literal_position TSRMLS_DC) /* {{{ */
{
if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) {
- STR_HASH_VAL(Z_STR_P(zv));
+ zend_string_hash_val(Z_STR_P(zv));
Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv) TSRMLS_CC);
if (IS_INTERNED(Z_STR_P(zv))) {
Z_TYPE_FLAGS_P(zv) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
@@ -383,7 +357,7 @@ static int zend_add_func_name_literal(zend_op_array *op_array, zval *zv TSRMLS_D
ret = zend_add_literal(op_array, zv TSRMLS_CC);
}
- lc_name = STR_ALLOC(Z_STRLEN_P(zv), 0);
+ lc_name = zend_string_alloc(Z_STRLEN_P(zv), 0);
zend_str_tolower_copy(lc_name->val, Z_STRVAL_P(zv), Z_STRLEN_P(zv));
ZVAL_NEW_STR(&c, lc_name);
zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
@@ -409,7 +383,7 @@ static int zend_add_ns_func_name_literal(zend_op_array *op_array, zval *zv TSRML
ret = zend_add_literal(op_array, zv TSRMLS_CC);
}
- lc_name = STR_ALLOC(Z_STRLEN_P(zv), 0);
+ lc_name = zend_string_alloc(Z_STRLEN_P(zv), 0);
zend_str_tolower_copy(lc_name->val, Z_STRVAL_P(zv), Z_STRLEN_P(zv));
ZVAL_NEW_STR(&c, lc_name);
zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
@@ -419,7 +393,7 @@ static int zend_add_ns_func_name_literal(zend_op_array *op_array, zval *zv TSRML
if (ns_separator != NULL) {
ns_separator += 1;
lc_len = Z_STRLEN_P(zv) - (ns_separator - Z_STRVAL_P(zv));
- lc_name = STR_ALLOC(lc_len, 0);
+ lc_name = zend_string_alloc(lc_len, 0);
zend_str_tolower_copy(lc_name->val, ns_separator, lc_len);
ZVAL_NEW_STR(&c, lc_name);
zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
@@ -429,32 +403,23 @@ static int zend_add_ns_func_name_literal(zend_op_array *op_array, zval *zv TSRML
}
/* }}} */
-static int zend_add_class_name_literal(zend_op_array *op_array, zval *zv TSRMLS_DC) /* {{{ */
-{
+static int zend_add_class_name_literal(zend_op_array *op_array, zend_string *name TSRMLS_DC) /* {{{ */ {
int ret;
zend_string *lc_name;
- zval c;
- if (op_array->last_literal > 0 &&
- &op_array->literals[op_array->last_literal - 1] == zv &&
- Z_CACHE_SLOT(op_array->literals[op_array->last_literal - 1]) == -1) {
- /* we already have function name as last literal (do nothing) */
- ret = op_array->last_literal - 1;
- } else {
- ret = zend_add_literal(op_array, zv TSRMLS_CC);
- }
+ zval zv;
+ ZVAL_STR(&zv, name);
- if (Z_STRVAL_P(zv)[0] == '\\') {
- lc_name = STR_ALLOC(Z_STRLEN_P(zv) - 1, 0);
- zend_str_tolower_copy(lc_name->val, Z_STRVAL_P(zv) + 1, Z_STRLEN_P(zv) - 1);
- } else {
- lc_name = STR_ALLOC(Z_STRLEN_P(zv), 0);
- zend_str_tolower_copy(lc_name->val, Z_STRVAL_P(zv), Z_STRLEN_P(zv));
- }
- ZVAL_NEW_STR(&c, lc_name);
- zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+ ret = zend_add_literal(op_array, &zv TSRMLS_CC);
+ name = Z_STR(zv); /* Load new name string in case it was interned */
- GET_CACHE_SLOT(ret);
+ lc_name = zend_string_alloc(name->len, 0);
+ zend_str_tolower_copy(lc_name->val, name->val, name->len);
+
+ ZVAL_NEW_STR(&zv, lc_name);
+ zend_add_literal(CG(active_op_array), &zv TSRMLS_CC);
+
+ zend_alloc_cache_slot(ret TSRMLS_CC);
return ret;
}
@@ -495,13 +460,13 @@ static int zend_add_const_name_literal(zend_op_array *op_array, zval *zv, int un
if (ns_len) {
/* lowercased namespace name & original constant name */
- tmp_name = STR_INIT(name, name_len, 0);
+ tmp_name = zend_string_init(name, name_len, 0);
zend_str_tolower(tmp_name->val, ns_len);
ZVAL_NEW_STR(&c, tmp_name);
zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
/* lowercased namespace name & lowercased constant name */
- tmp_name = STR_ALLOC(name_len, 0);
+ tmp_name = zend_string_alloc(name_len, 0);
zend_str_tolower_copy(tmp_name->val, name, name_len);
ZVAL_NEW_STR(&c, tmp_name);
zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
@@ -517,12 +482,12 @@ static int zend_add_const_name_literal(zend_op_array *op_array, zval *zv, int un
}
/* original constant name */
- tmp_name = STR_INIT(name, name_len, 0);
+ tmp_name = zend_string_init(name, name_len, 0);
ZVAL_NEW_STR(&c, tmp_name);
zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
/* lowercased constant name */
- tmp_name = STR_ALLOC(name_len, 0);
+ tmp_name = zend_string_alloc(name_len, 0);
zend_str_tolower_copy(tmp_name->val, name, name_len);
ZVAL_NEW_STR(&c, tmp_name);
zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
@@ -537,511 +502,19 @@ static int zend_add_const_name_literal(zend_op_array *op_array, zval *zv, int un
op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
} while (0)
-#define LITERAL_STRINGL(op, str, len) do { \
- zval _c; \
- ZVAL_STRINGL(&_c, str, len); \
- op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
- } while (0)
-
-#define LITERAL_LONG(op, val) do { \
- zval _c; \
- ZVAL_LONG(&_c, val); \
- op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
- } while (0)
-
-#define LITERAL_LONG_EX(op_array, op, val) do { \
- zval _c; \
- ZVAL_LONG(&_c, val); \
- op.constant = zend_add_literal(op_array, &_c TSRMLS_CC); \
- } while (0)
-
-#define LITERAL_NULL(op) do { \
- zval _c; \
- ZVAL_NULL(&_c); \
- op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
- } while (0)
-
-static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
-{
- zend_uint type = variable->EA;
-
- return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
-}
-/* }}} */
-
-void zend_do_binary_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = op;
- opline->result_type = IS_TMP_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, op1);
- SET_NODE(opline->op2, op2);
- GET_NODE(result, opline->result);
-}
-/* }}} */
-
-void zend_do_unary_op(zend_uchar op, znode *result, znode *op1 TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = op;
- opline->result_type = IS_TMP_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, op1);
- GET_NODE(result, opline->result);
- SET_UNUSED(opline->op2);
-}
-/* }}} */
-
-#define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(opline->result)); memset(&opline->op1,0,sizeof(opline->op1)); memset(&opline->op2,0,sizeof(opline->op2)); opline->result_type=opline->op1_type=opline->op2_type=IS_UNUSED; }
+#define MAKE_NOP(opline) do { \
+ opline->opcode = ZEND_NOP; \
+ memset(&opline->result, 0, sizeof(opline->result)); \
+ memset(&opline->op1, 0, sizeof(opline->op1)); \
+ memset(&opline->op2, 0, sizeof(opline->op2)); \
+ opline->result_type = opline->op1_type = opline->op2_type = IS_UNUSED; \
+} while (0)
-static void zend_do_op_data(zend_op *data_op, znode *value TSRMLS_DC) /* {{{ */
-{
- data_op->opcode = ZEND_OP_DATA;
- SET_NODE(data_op->op1, value);
- SET_UNUSED(data_op->op2);
+void zend_stop_lexing(TSRMLS_D) {
+ LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
}
-/* }}} */
-void zend_do_binary_assign_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
-{
- int last_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- if (last_op_number > 0) {
- zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
-
- switch (last_op->opcode) {
- case ZEND_FETCH_OBJ_RW:
- last_op->opcode = op;
- last_op->extended_value = ZEND_ASSIGN_OBJ;
-
- zend_do_op_data(opline, op2 TSRMLS_CC);
- SET_UNUSED(opline->result);
- GET_NODE(result, last_op->result);
- return;
- case ZEND_FETCH_DIM_RW:
- last_op->opcode = op;
- last_op->extended_value = ZEND_ASSIGN_DIM;
-
- zend_do_op_data(opline, op2 TSRMLS_CC);
- opline->op2.var = get_temporary_variable(CG(active_op_array));
- opline->op2_type = IS_VAR;
- SET_UNUSED(opline->result);
- GET_NODE(result,last_op->result);
- return;
- default:
- break;
- }
- }
-
- opline->opcode = op;
- SET_NODE(opline->op1, op1);
- SET_NODE(opline->op2, op2);
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, opline->result);
-}
-/* }}} */
-
-void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC) /* {{{ */
-{
- zend_op opline;
- zend_op *opline_ptr;
-
- if (varname->op_type == IS_CONST) {
- if (Z_TYPE(varname->u.constant) != IS_STRING) {
- convert_to_string(&varname->u.constant);
- }
-
- if (!zend_is_auto_global(Z_STR(varname->u.constant) TSRMLS_CC) &&
- !(Z_STRLEN(varname->u.constant) == (sizeof("this")-1) &&
- !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1)) &&
- (CG(active_op_array)->last == 0 ||
- CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
- result->op_type = IS_CV;
- result->u.op.var = lookup_cv(CG(active_op_array), Z_STR(varname->u.constant) TSRMLS_CC);
- Z_STR(varname->u.constant) = CG(active_op_array)->vars[EX_VAR_TO_NUM(result->u.op.var)];
- result->EA = 0;
- return;
- }
- }
-
- if (bp) {
- opline_ptr = &opline;
- init_op(opline_ptr TSRMLS_CC);
- } else {
- opline_ptr = get_next_op(CG(active_op_array) TSRMLS_CC);
- }
-
- opline_ptr->opcode = op;
- opline_ptr->result_type = IS_VAR;
- opline_ptr->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline_ptr->op1, varname);
- GET_NODE(result, opline_ptr->result);
- SET_UNUSED(opline_ptr->op2);
- opline_ptr->extended_value = ZEND_FETCH_LOCAL;
-
- if (varname->op_type == IS_CONST) {
- if (zend_is_auto_global(Z_STR(varname->u.constant) TSRMLS_CC)) {
- opline_ptr->extended_value = ZEND_FETCH_GLOBAL;
- }
- }
-
- if (bp) {
- zend_llist *fetch_list_ptr = zend_stack_top(&CG(bp_stack));
- zend_llist_add_element(fetch_list_ptr, opline_ptr);
- }
-}
-/* }}} */
-
-void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC) /* {{{ */
-{
- /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
- fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
-}
-/* }}} */
-
-void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
-{
- znode class_node;
- zend_llist *fetch_list_ptr;
- zend_llist_element *le;
- zend_op *opline_ptr;
- zend_op opline;
-
- if (class_name->op_type == IS_CONST &&
- ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
- zend_resolve_class_name(class_name TSRMLS_CC);
- class_node = *class_name;
- } else {
- zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
- }
- fetch_list_ptr = zend_stack_top(&CG(bp_stack));
- if (result->op_type == IS_CV) {
- init_op(&opline TSRMLS_CC);
-
- opline.opcode = ZEND_FETCH_W;
- opline.result_type = IS_VAR;
- opline.result.var = get_temporary_variable(CG(active_op_array));
- opline.op1_type = IS_CONST;
- LITERAL_STR(opline.op1, STR_COPY(CG(active_op_array)->vars[EX_VAR_TO_NUM(result->u.op.var)]));
- GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
- if (class_node.op_type == IS_CONST) {
- opline.op2_type = IS_CONST;
- opline.op2.constant =
- zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
- } else {
- SET_NODE(opline.op2, &class_node);
- }
- GET_NODE(result,opline.result);
- opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
- opline_ptr = &opline;
-
- zend_llist_add_element(fetch_list_ptr, &opline);
- } else {
- le = fetch_list_ptr->head;
-
- opline_ptr = (zend_op *)le->data;
- if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1_type == IS_CV) {
- init_op(&opline TSRMLS_CC);
- opline.opcode = ZEND_FETCH_W;
- opline.result_type = IS_VAR;
- opline.result.var = get_temporary_variable(CG(active_op_array));
- opline.op1_type = IS_CONST;
- LITERAL_STR(opline.op1, STR_COPY(CG(active_op_array)->vars[EX_VAR_TO_NUM(opline_ptr->op1.var)]));
- GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
- if (class_node.op_type == IS_CONST) {
- opline.op2_type = IS_CONST;
- opline.op2.constant =
- zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
- } else {
- SET_NODE(opline.op2, &class_node);
- }
- opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
- COPY_NODE(opline_ptr->op1, opline.result);
-
- zend_llist_prepend_element(fetch_list_ptr, &opline);
- } else {
- if (opline_ptr->op1_type == IS_CONST) {
- GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op1.constant);
- }
- if (class_node.op_type == IS_CONST) {
- opline_ptr->op2_type = IS_CONST;
- opline_ptr->op2.constant =
- zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
- } else {
- SET_NODE(opline_ptr->op2, &class_node);
- }
- opline_ptr->extended_value |= ZEND_FETCH_STATIC_MEMBER;
- }
- }
-}
-/* }}} */
-
-void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC) /* {{{ */
-{
- fetch_simple_variable(result, varname, 1 TSRMLS_CC);
-
- fetch_array_dim(result, result, first_dim TSRMLS_CC);
-}
-/* }}} */
-
-void fetch_array_dim(znode *result, znode *parent, znode *dim TSRMLS_DC) /* {{{ */
-{
- zend_op opline;
- zend_llist *fetch_list_ptr = zend_stack_top(&CG(bp_stack));
-
- if (zend_is_function_or_method_call(parent)) {
- init_op(&opline TSRMLS_CC);
- opline.opcode = ZEND_SEPARATE;
- SET_NODE(opline.op1, parent);
- SET_UNUSED(opline.op2);
- opline.result_type = IS_VAR;
- opline.result.var = opline.op1.var;
- zend_llist_add_element(fetch_list_ptr, &opline);
- }
-
- init_op(&opline TSRMLS_CC);
- opline.opcode = ZEND_FETCH_DIM_W; /* the backpatching routine assumes W */
- opline.result_type = IS_VAR;
- opline.result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline.op1, parent);
- SET_NODE(opline.op2, dim);
- if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
- ulong index;
-
- if (ZEND_HANDLE_NUMERIC(Z_STR(CONSTANT(opline.op2.constant)), index)) {
- zval_dtor(&CONSTANT(opline.op2.constant));
- ZVAL_LONG(&CONSTANT(opline.op2.constant), index);
- }
- }
-
- GET_NODE(result, opline.result);
-
- zend_llist_add_element(fetch_list_ptr, &opline);
-}
-/* }}} */
-
-void fetch_string_offset(znode *result, znode *parent, znode *offset TSRMLS_DC) /* {{{ */
-{
- fetch_array_dim(result, parent, offset TSRMLS_CC);
-}
-/* }}} */
-
-void zend_do_print(znode *result, znode *arg TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->result_type = IS_TMP_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- opline->opcode = ZEND_PRINT;
- SET_NODE(opline->op1, arg);
- SET_UNUSED(opline->op2);
- GET_NODE(result, opline->result);
-}
-/* }}} */
-
-void zend_do_echo(znode *arg TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_ECHO;
- SET_NODE(opline->op1, arg);
- SET_UNUSED(opline->op2);
-}
-/* }}} */
-
-void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC) /* {{{ */
-{
- char *method_type;
-
- if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
- Z_LVAL(modifiers->u.constant) |= ZEND_ACC_ABSTRACT;
- method_type = "Interface";
- } else {
- method_type = "Abstract";
- }
-
- if (Z_LVAL(modifiers->u.constant) & ZEND_ACC_ABSTRACT) {
- if(Z_LVAL(modifiers->u.constant) & ZEND_ACC_PRIVATE) {
- zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private", method_type, CG(active_class_entry)->name->val, Z_STRVAL(function_name->u.constant));
- }
- if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- } else {
- /* we had code in the function body */
- zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body", method_type, CG(active_class_entry)->name->val, Z_STRVAL(function_name->u.constant));
- }
- } else {
- if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body", CG(active_class_entry)->name->val, Z_STRVAL(function_name->u.constant));
- }
- }
-}
-/* }}} */
-
-static zend_bool opline_is_fetch_this(const zend_op *opline TSRMLS_DC) /* {{{ */
-{
- if ((opline->opcode == ZEND_FETCH_W) && (opline->op1_type == IS_CONST)
- && (Z_TYPE(CONSTANT(opline->op1.constant)) == IS_STRING)
- && ((opline->extended_value & ZEND_FETCH_STATIC_MEMBER) != ZEND_FETCH_STATIC_MEMBER)
- && (Z_STRHASH(CONSTANT(opline->op1.constant)) == THIS_HASHVAL)
- && (Z_STRLEN(CONSTANT(opline->op1.constant)) == (sizeof("this")-1))
- && !memcmp(Z_STRVAL(CONSTANT(opline->op1.constant)), "this", sizeof("this") - 1)) {
- return 1;
- } else {
- return 0;
- }
-}
-/* }}} */
-
-void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) /* {{{ */
-{
- int last_op_number;
- zend_op *opline;
-
- if (value->op_type == IS_CV) {
- zend_llist *fetch_list_ptr = zend_stack_top(&CG(bp_stack));
- if (fetch_list_ptr && fetch_list_ptr->head) {
- opline = (zend_op *)fetch_list_ptr->head->data;
-
- if (opline->opcode == ZEND_FETCH_DIM_W &&
- opline->op1_type == IS_CV &&
- opline->op1.var == value->u.op.var) {
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_FETCH_R;
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- opline->op1_type = IS_CONST;
- LITERAL_STR(opline->op1,
- STR_COPY(CG(active_op_array)->vars[EX_VAR_TO_NUM(value->u.op.var)]));
- SET_UNUSED(opline->op2);
- opline->extended_value = ZEND_FETCH_LOCAL;
- GET_NODE(value, opline->result);
- }
- }
- }
-
- zend_do_end_variable_parse(variable, BP_VAR_W, 0 TSRMLS_CC);
-
- last_op_number = get_next_op_number(CG(active_op_array));
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- if (variable->op_type == IS_CV) {
- if (variable->u.op.var == CG(active_op_array)->this_var) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
- }
- } else if (variable->op_type == IS_VAR) {
- int n = 0;
-
- while (last_op_number - n > 0) {
- zend_op *last_op;
-
- last_op = &CG(active_op_array)->opcodes[last_op_number-n-1];
-
- if (last_op->result_type == IS_VAR &&
- last_op->result.var == variable->u.op.var) {
- if (last_op->opcode == ZEND_FETCH_OBJ_W) {
- if (n > 0) {
- int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
- *opline = *last_op;
- MAKE_NOP(last_op);
- /* last_op = opline; */
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- /* get_next_op can realloc, we need to move last_op */
- last_op = &CG(active_op_array)->opcodes[opline_no];
- }
- last_op->opcode = ZEND_ASSIGN_OBJ;
- zend_do_op_data(opline, value TSRMLS_CC);
- SET_UNUSED(opline->result);
- GET_NODE(result, last_op->result);
- return;
- } else if (last_op->opcode == ZEND_FETCH_DIM_W) {
- if (n > 0) {
- int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
- *opline = *last_op;
- MAKE_NOP(last_op);
- /* last_op = opline; */
- /* TBFixed: this can realloc opcodes, leaving last_op pointing wrong */
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- /* get_next_op can realloc, we need to move last_op */
- last_op = &CG(active_op_array)->opcodes[opline_no];
- }
- last_op->opcode = ZEND_ASSIGN_DIM;
- zend_do_op_data(opline, value TSRMLS_CC);
- opline->op2.var = get_temporary_variable(CG(active_op_array));
- opline->op2_type = IS_VAR;
- SET_UNUSED(opline->result);
- GET_NODE(result, last_op->result);
- return;
- } else if (opline_is_fetch_this(last_op TSRMLS_CC)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
- } else {
- break;
- }
- }
- n++;
- }
- }
-
- opline->opcode = ZEND_ASSIGN;
- SET_NODE(opline->op1, variable);
- SET_NODE(opline->op2, value);
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, opline->result);
-}
-/* }}} */
-
-void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
-
- if (lvar->op_type == IS_CV) {
- if (lvar->u.op.var == CG(active_op_array)->this_var) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
- }
- } else if (lvar->op_type == IS_VAR) {
- int last_op_number = get_next_op_number(CG(active_op_array));
-
- if (last_op_number > 0) {
- opline = &CG(active_op_array)->opcodes[last_op_number-1];
- if (opline_is_fetch_this(opline TSRMLS_CC)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
- }
- }
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_ASSIGN_REF;
- if (zend_is_function_or_method_call(rvar)) {
- opline->extended_value = ZEND_RETURNS_FUNCTION;
- } else if (rvar->EA & ZEND_PARSED_NEW) {
- opline->extended_value = ZEND_RETURNS_NEW;
- } else {
- opline->extended_value = 0;
- }
- if (result) {
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, opline->result);
- } else {
- opline->result_type = IS_UNUSED | EXT_TYPE_UNUSED;
- }
- SET_NODE(opline->op1, lvar);
- SET_NODE(opline->op2, rvar);
-}
-/* }}} */
-
-static inline void do_begin_loop(TSRMLS_D) /* {{{ */
+static inline void zend_begin_loop(TSRMLS_D) /* {{{ */
{
zend_brk_cont_element *brk_cont_element;
int parent;
@@ -1054,7 +527,7 @@ static inline void do_begin_loop(TSRMLS_D) /* {{{ */
}
/* }}} */
-static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{ */
+static inline void zend_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{ */
{
if (!has_loop_var) {
/* The start fileld is used to free temporary variables in case of exceptions.
@@ -1068,355 +541,6 @@ static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{
}
/* }}} */
-void zend_do_while_cond(znode *expr, znode *close_bracket_token TSRMLS_DC) /* {{{ */
-{
- int while_cond_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMPZ;
- SET_NODE(opline->op1, expr);
- close_bracket_token->u.op.opline_num = while_cond_op_number;
- SET_UNUSED(opline->op2);
-
- do_begin_loop(TSRMLS_C);
- INC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- /* add unconditional jump */
- opline->opcode = ZEND_JMP;
- opline->op1.opline_num = while_token->u.op.opline_num;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
-
- /* update while's conditional jmp */
- CG(active_op_array)->opcodes[close_bracket_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
-
- do_end_loop(while_token->u.op.opline_num, 0 TSRMLS_CC);
-
- DEC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_for_cond(znode *expr, znode *second_semicolon_token TSRMLS_DC) /* {{{ */
-{
- int for_cond_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMPZNZ;
- SET_NODE(opline->op1, expr); /* the conditional expression */
- second_semicolon_token->u.op.opline_num = for_cond_op_number;
- SET_UNUSED(opline->op2);
-}
-/* }}} */
-
-void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMP;
- opline->op1.opline_num = cond_start->u.op.opline_num;
- CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
-
- do_begin_loop(TSRMLS_C);
-
- INC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMP;
- opline->op1.opline_num = second_semicolon_token->u.op.opline_num+1;
- CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
-
- do_end_loop(second_semicolon_token->u.op.opline_num+1, 0 TSRMLS_CC);
-
- DEC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_pre_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
-{
- int last_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline;
-
- if (last_op_number > 0) {
- zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
-
- if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
- last_op->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
- last_op->result_type = IS_VAR;
- last_op->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, last_op->result);
- return;
- }
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = op;
- SET_NODE(opline->op1, op1);
- SET_UNUSED(opline->op2);
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, opline->result);
-}
-/* }}} */
-
-void zend_do_post_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
-{
- int last_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline;
-
- if (last_op_number > 0) {
- zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
-
- if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
- last_op->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
- last_op->result_type = IS_TMP_VAR;
- last_op->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, last_op->result);
- return;
- }
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = op;
- SET_NODE(opline->op1, op1);
- SET_UNUSED(opline->op2);
- opline->result_type = IS_TMP_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, opline->result);
-}
-/* }}} */
-
-void zend_do_if_cond(znode *cond, znode *closing_bracket_token TSRMLS_DC) /* {{{ */
-{
- int if_cond_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMPZ;
- SET_NODE(opline->op1, cond);
- closing_bracket_token->u.op.opline_num = if_cond_op_number;
- SET_UNUSED(opline->op2);
- INC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC) /* {{{ */
-{
- int if_end_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- zend_llist *jmp_list_ptr;
-
- opline->opcode = ZEND_JMP;
- /* save for backpatching */
- if (initialize) {
- zend_llist jmp_list;
-
- zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
- zend_stack_push(&CG(bp_stack), (void *) &jmp_list);
- }
- jmp_list_ptr = zend_stack_top(&CG(bp_stack));
- zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
-
- CG(active_op_array)->opcodes[closing_bracket_token->u.op.opline_num].op2.opline_num = if_end_op_number+1;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
-}
-/* }}} */
-
-void zend_do_if_end(TSRMLS_D) /* {{{ */
-{
- int next_op_number = get_next_op_number(CG(active_op_array));
- zend_llist *jmp_list_ptr = zend_stack_top(&CG(bp_stack));
- zend_llist_element *le;
-
- for (le=jmp_list_ptr->head; le; le = le->next) {
- CG(active_op_array)->opcodes[*((int *) le->data)].op1.opline_num = next_op_number;
- }
- zend_llist_destroy(jmp_list_ptr);
- zend_stack_del_top(&CG(bp_stack));
- DEC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_check_writable_variable(const znode *variable) /* {{{ */
-{
- zend_uint type = variable->EA;
-
- if (type & ZEND_PARSED_METHOD_CALL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Can't use method return value in write context");
- }
- if (type == ZEND_PARSED_FUNCTION_CALL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Can't use function return value in write context");
- }
-}
-/* }}} */
-
-void zend_do_begin_variable_parse(TSRMLS_D) /* {{{ */
-{
- zend_llist fetch_list;
-
- zend_llist_init(&fetch_list, sizeof(zend_op), NULL, 0);
- zend_stack_push(&CG(bp_stack), (void *) &fetch_list);
-}
-/* }}} */
-
-void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC) /* {{{ */
-{
- zend_llist *fetch_list_ptr = zend_stack_top(&CG(bp_stack));
- zend_llist_element *le = fetch_list_ptr->head;
- zend_op *opline = NULL;
- zend_op *opline_ptr;
- zend_uint this_var = -1;
-
- /* TODO: $foo->x->y->z = 1 should fetch "x" and "y" for R or RW, not just W */
-
- if (le) {
- opline_ptr = (zend_op *)le->data;
- if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
- /* convert to FETCH_?(this) into IS_CV */
- if (CG(active_op_array)->last == 0 ||
- CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
-
- this_var = opline_ptr->result.var;
- if (CG(active_op_array)->this_var == -1) {
- CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STR(CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC);
- ZVAL_UNDEF(&CONSTANT(opline_ptr->op1.constant));
- } else {
- zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
- }
- le = le->next;
- if (variable->op_type == IS_VAR &&
- variable->u.op.var == this_var) {
- variable->op_type = IS_CV;
- variable->u.op.var = CG(active_op_array)->this_var;
- }
- } else if (CG(active_op_array)->this_var == -1) {
- CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), STR_INIT("this", sizeof("this")-1, 0) TSRMLS_CC);
- }
- }
-
- while (le) {
- opline_ptr = (zend_op *)le->data;
- if (opline_ptr->opcode == ZEND_SEPARATE) {
- if (type != BP_VAR_R && type != BP_VAR_IS) {
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- memcpy(opline, opline_ptr, sizeof(zend_op));
- }
- le = le->next;
- continue;
- }
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- memcpy(opline, opline_ptr, sizeof(zend_op));
- if (opline->op1_type == IS_VAR &&
- opline->op1.var == this_var) {
- opline->op1_type = IS_CV;
- opline->op1.var = CG(active_op_array)->this_var;
- }
- switch (type) {
- case BP_VAR_R:
- if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
- }
- opline->opcode -= 3;
- break;
- case BP_VAR_W:
- break;
- case BP_VAR_RW:
- opline->opcode += 3;
- break;
- case BP_VAR_IS:
- if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
- }
- opline->opcode += 6; /* 3+3 */
- break;
- case BP_VAR_FUNC_ARG:
- opline->opcode += 9; /* 3+3+3 */
- opline->extended_value |= arg_offset;
- break;
- case BP_VAR_UNSET:
- if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
- }
- opline->opcode += 12; /* 3+3+3+3 */
- break;
- }
- le = le->next;
- }
- if (opline && type == BP_VAR_W && arg_offset) {
- opline->extended_value |= ZEND_FETCH_MAKE_REF;
- }
- }
- zend_llist_destroy(fetch_list_ptr);
- zend_stack_del_top(&CG(bp_stack));
-}
-/* }}} */
-
-void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
-
- if (Z_STRLEN(op2->u.constant) > 1) {
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_ADD_STRING;
- } else if (Z_STRLEN(op2->u.constant) == 1) {
- int ch = *Z_STRVAL(op2->u.constant);
-
- /* Free memory and use ZEND_ADD_CHAR in case of 1 character strings */
- STR_FREE(Z_STR(op2->u.constant));
- ZVAL_LONG(&op2->u.constant, ch);
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_ADD_CHAR;
- } else { /* String can be empty after a variable at the end of a heredoc */
- STR_FREE(Z_STR(op2->u.constant));
- return;
- }
-
- if (op1) {
- SET_NODE(opline->op1, op1);
- SET_NODE(opline->result, op1);
- } else {
- SET_UNUSED(opline->op1);
- opline->result_type = IS_TMP_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- }
- SET_NODE(opline->op2, op2);
- GET_NODE(result, opline->result);
-}
-/* }}} */
-
-void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_ADD_VAR;
-
- if (op1) {
- SET_NODE(opline->op1, op1);
- SET_NODE(opline->result, op1);
- } else {
- SET_UNUSED(opline->op1);
- opline->result_type = IS_TMP_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- }
- SET_NODE(opline->op2, op2);
- GET_NODE(result, opline->result);
-}
-/* }}} */
-
void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
{
if (op1->op_type==IS_TMP_VAR) {
@@ -1436,7 +560,7 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
if (opline->opcode == ZEND_FETCH_R ||
opline->opcode == ZEND_FETCH_DIM_R ||
opline->opcode == ZEND_FETCH_OBJ_R ||
- opline->opcode == ZEND_QM_ASSIGN_VAR) {
+ opline->opcode == ZEND_QM_ASSIGN) {
/* It's very rare and useless case. It's better to use
additional FREE opcode and simplify the FETCH handlers
their selves */
@@ -1473,867 +597,194 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
}
}
} else if (op1->op_type == IS_CONST) {
- zval_dtor(&op1->u.constant);
+ /* Destroy value without using GC: When opcache moves arrays into SHM it will
+ * free the zend_array structure, so references to it from outside the op array
+ * become invalid. GC would cause such a reference in the root buffer. */
+ zval_ptr_dtor_nogc(&op1->u.constant);
}
}
/* }}} */
-int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier) /* {{{ */
+uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
{
- if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_PPP_MASK)
- && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_PPP_MASK)) {
+ uint32_t new_flags = flags | new_flag;
+ if ((flags & ZEND_ACC_PPP_MASK) && (new_flag & ZEND_ACC_PPP_MASK)) {
zend_error_noreturn(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
}
- if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_ABSTRACT)
- && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_ABSTRACT)) {
+ if ((flags & ZEND_ACC_ABSTRACT) && (new_flag & ZEND_ACC_ABSTRACT)) {
zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
}
- if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_STATIC)
- && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_STATIC)) {
+ if ((flags & ZEND_ACC_STATIC) && (new_flag & ZEND_ACC_STATIC)) {
zend_error_noreturn(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
}
- if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_FINAL)
- && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_FINAL)) {
+ if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
}
- if (((Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant)) & (ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL)) == (ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL)) {
+ if ((new_flags & ZEND_ACC_ABSTRACT) && (new_flags & ZEND_ACC_FINAL)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
}
- return (Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant));
-}
-/* }}} */
-
-void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */
-{
- zend_op_array op_array;
- zend_string *name = Z_STR(function_name->u.constant);
- int function_begin_line = function_token->u.op.opline_num;
- zend_uint fn_flags;
- zend_string *lcname;
- zend_bool orig_interactive;
- ALLOCA_FLAG(use_heap)
-
- if (is_method) {
- if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
- if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name->val, Z_STRVAL(function_name->u.constant));
- }
- Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
- }
- fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
- } else {
- fn_flags = 0;
- }
- if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_error(E_STRICT, "Static function %s%s%s() should not be abstract", is_method ? CG(active_class_entry)->name->val : "", is_method ? "::" : "", Z_STRVAL(function_name->u.constant));
- }
-
- function_token->u.op_array = CG(active_op_array);
-
- orig_interactive = CG(interactive);
- CG(interactive) = 0;
- init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
- CG(interactive) = orig_interactive;
-
- op_array.function_name = name;
- if (return_reference) {
- op_array.fn_flags |= ZEND_ACC_RETURN_REFERENCE;
- }
- op_array.fn_flags |= fn_flags;
-
- op_array.scope = is_method?CG(active_class_entry):NULL;
- op_array.prototype = NULL;
-
- op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
-
- if (is_method) {
- lcname = STR_ALLOC(name->len, 0);
- zend_str_tolower_copy(lcname->val, name->val, name->len);
- lcname = zend_new_interned_string(lcname TSRMLS_CC);
- CG(active_op_array) = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
- memcpy(CG(active_op_array), &op_array, sizeof(zend_op_array));
- if (zend_hash_add_ptr(&CG(active_class_entry)->function_table, lcname, CG(active_op_array)) == NULL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name->val, name->val);
- }
-
- zend_stack_push(&CG(context_stack), (void *) &CG(context));
- zend_init_compiler_context(TSRMLS_C);
-
- if (fn_flags & ZEND_ACC_ABSTRACT) {
- CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
- }
-
- if (!(fn_flags & ZEND_ACC_PPP_MASK)) {
- fn_flags |= ZEND_ACC_PUBLIC;
- }
-
- if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
- if ((name->len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
- }
- } else if ((name->len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
- if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
- zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
- }
- } else if ((name->len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
- }
- } else if ((name->len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
- }
- } else if ((name->len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
- }
- } else if ((name->len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
- }
- } else if ((name->len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
- }
- } else if ((name->len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static");
- }
-
- } else if ((name->len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __debugInfo() must have public visibility and cannot be static");
- }
- }
- } else {
- char *class_lcname;
-
- class_lcname = do_alloca(CG(active_class_entry)->name->len + 1, use_heap);
- zend_str_tolower_copy(class_lcname, CG(active_class_entry)->name->val, CG(active_class_entry)->name->len);
- /* Improve after RC: cache the lowercase class name */
-
- if ((CG(active_class_entry)->name->len == name->len) && ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) && (!memcmp(class_lcname, lcname->val, name->len))) {
- if (!CG(active_class_entry)->constructor) {
- CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
- }
- } else if ((name->len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1))) {
- if (CG(active_class_entry)->constructor) {
- zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name->val);
- }
- CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
- } else if ((name->len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1))) {
- CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
- } else if ((name->len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
- CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
- } else if ((name->len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
- }
- CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
- } else if ((name->len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
- if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
- zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
- }
- CG(active_class_entry)->__callstatic = (zend_function *) CG(active_op_array);
- } else if ((name->len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
- }
- CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
- } else if ((name->len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
- }
- CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
- } else if ((name->len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
- }
- CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
- } else if ((name->len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
- }
- CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
- } else if ((name->len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
- }
- CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
- } else if ((name->len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static");
- }
- } else if ((name->len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && (!memcmp(lcname->val, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __debugInfo() must have public visibility and cannot be static");
- }
- CG(active_class_entry)->__debugInfo = (zend_function *) CG(active_op_array);
- } else if (!(fn_flags & ZEND_ACC_STATIC)) {
- CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
- }
- free_alloca(class_lcname, use_heap);
- }
-
- STR_RELEASE(lcname);
- } else {
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- zval key;
- zval *ns_name;
-
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- /* Prefix function name with current namespace name */
- znode tmp;
-
- ZVAL_DUP(&tmp.u.constant, &CG(current_namespace));
- zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
- op_array.function_name = Z_STR(tmp.u.constant);
- lcname = STR_ALLOC(Z_STRLEN(tmp.u.constant), 0);
- zend_str_tolower_copy(lcname->val, Z_STRVAL(tmp.u.constant), Z_STRLEN(tmp.u.constant));
- } else {
- lcname = STR_ALLOC(name->len, 0);
- zend_str_tolower_copy(lcname->val, name->val, name->len);
- }
-
- /* Function name must not conflict with import names */
- if (CG(current_import_function) &&
- (ns_name = zend_hash_find(CG(current_import_function), lcname)) != NULL) {
-
- char *tmp = zend_str_tolower_dup(Z_STRVAL_P(ns_name), Z_STRLEN_P(ns_name));
-
- if (Z_STRLEN_P(ns_name) != Z_STRLEN(function_name->u.constant) ||
- memcmp(tmp, lcname->val, Z_STRLEN(function_name->u.constant))) {
- zend_error(E_COMPILE_ERROR, "Cannot declare function %s because the name is already in use", Z_STRVAL(function_name->u.constant));
- }
- efree(tmp);
- }
-
- opline->opcode = ZEND_DECLARE_FUNCTION;
- opline->op1_type = IS_CONST;
- build_runtime_defined_function_key(&key, lcname->val, lcname->len TSRMLS_CC);
- opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
- opline->op2_type = IS_CONST;
- LITERAL_STR(opline->op2, STR_COPY(lcname));
- opline->extended_value = ZEND_DECLARE_FUNCTION;
- CG(active_op_array) = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
- memcpy(CG(active_op_array), &op_array, sizeof(zend_op_array));
- zend_hash_update_ptr(CG(function_table), Z_STR(key), CG(active_op_array));
- zend_stack_push(&CG(context_stack), (void *) &CG(context));
- zend_init_compiler_context(TSRMLS_C);
- STR_RELEASE(lcname);
- }
-
- if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_EXT_NOP;
- opline->lineno = function_begin_line;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- }
-
- {
- /* Push a separator to the switch stack */
- zend_switch_entry switch_entry;
-
- switch_entry.cond.op_type = IS_UNUSED;
- switch_entry.default_case = 0;
- switch_entry.control_var = 0;
-
- zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry);
- }
-
- {
- /* Push a separator to the foreach stack */
- zend_op dummy_opline;
-
- dummy_opline.result_type = IS_UNUSED;
-
- zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline);
- }
-
- if (CG(doc_comment)) {
- CG(active_op_array)->doc_comment = CG(doc_comment);
- CG(doc_comment) = NULL;
- }
+ return new_flags;
}
/* }}} */
-void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC) /* {{{ */
+zend_string *zend_concat3(char *str1, size_t str1_len, char *str2, size_t str2_len, char *str3, size_t str3_len) /* {{{ */
{
- znode function_name;
- zend_op_array *current_op_array = CG(active_op_array);
- int current_op_number = get_next_op_number(CG(active_op_array));
- zend_op *current_op;
-
- function_name.op_type = IS_CONST;
- ZVAL_STRINGL(&function_name.u.constant, "{closure}", sizeof("{closure}")-1);
+ size_t len = str1_len + str2_len + str3_len;
+ zend_string *res = zend_string_alloc(len, 0);
- zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);
+ memcpy(res->val, str1, str1_len);
+ memcpy(res->val + str1_len, str2, str2_len);
+ memcpy(res->val + str1_len + str2_len, str3, str3_len);
+ res->val[len] = '\0';
- result->op_type = IS_TMP_VAR;
- result->u.op.var = get_temporary_variable(current_op_array);
-
- current_op = &current_op_array->opcodes[current_op_number];
- current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION;
- zend_del_literal(current_op_array, current_op->op2.constant);
- SET_UNUSED(current_op->op2);
- SET_NODE(current_op->result, result);
- if (is_static) {
- CG(active_op_array)->fn_flags |= ZEND_ACC_STATIC;
- }
- CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
+ return res;
}
-/* }}} */
-
-void zend_do_handle_exception(TSRMLS_D) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_HANDLE_EXCEPTION;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
+zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_t name2_len) {
+ return zend_concat3(name1, name1_len, "\\", 1, name2, name2_len);
}
-/* }}} */
-void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC) /* {{{ */
-{
- char lcname[16];
- int name_len;
-
- zend_do_extended_info(TSRMLS_C);
- zend_do_return(NULL, 0 TSRMLS_CC);
-
- pass_two(CG(active_op_array) TSRMLS_CC);
- 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);
+zend_string *zend_prefix_with_ns(zend_string *name TSRMLS_DC) {
+ if (CG(current_namespace)) {
+ zend_string *ns = CG(current_namespace);
+ return zend_concat_names(ns->val, ns->len, name->val, name->len);
} else {
- /* we don't care if the function name is longer, in fact lowercasing only
- * the beginning of the name speeds up the check process */
- name_len = CG(active_op_array)->function_name->len;
- zend_str_tolower_copy(lcname, CG(active_op_array)->function_name->val, MIN(name_len, sizeof(lcname)-1));
- lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
- if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1) {
- zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
- }
+ return zend_string_copy(name);
}
+}
- CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
- CG(active_op_array) = function_token->u.op_array;
-
-
- /* Pop the switch and foreach separators */
- zend_stack_del_top(&CG(switch_cond_stack));
- zend_stack_del_top(&CG(foreach_copy_stack));
+void *zend_hash_find_ptr_lc(HashTable *ht, char *str, size_t len) {
+ void *result;
+ zend_string *lcname = zend_string_alloc(len, 0);
+ zend_str_tolower_copy(lcname->val, str, len);
+ result = zend_hash_find_ptr(ht, lcname);
+ zend_string_free(lcname);
+ return result;
}
-/* }}} */
-void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization, znode *class_type, zend_uchar pass_by_reference, zend_bool is_variadic TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
- zend_arg_info *cur_arg_info;
- znode var;
+zend_string *zend_resolve_non_class_name(
+ zend_string *name, uint32_t type, zend_bool *is_fully_qualified,
+ zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC
+) {
+ char *compound;
+ *is_fully_qualified = 0;
- if (zend_is_auto_global(Z_STR(varname->u.constant) TSRMLS_CC)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s", Z_STRVAL(varname->u.constant));
- } else {
- var.op_type = IS_CV;
- var.u.op.var = lookup_cv(CG(active_op_array), Z_STR(varname->u.constant) TSRMLS_CC);
- Z_STR(varname->u.constant) = CG(active_op_array)->vars[EX_VAR_TO_NUM(var.u.op.var)];
- var.EA = 0;
- if (EX_VAR_TO_NUM(var.u.op.var) != CG(active_op_array)->num_args) {
- zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter $%s", Z_STRVAL(varname->u.constant));
- } else if (Z_STRHASH(varname->u.constant) == THIS_HASHVAL &&
- Z_STRLEN(varname->u.constant) == sizeof("this")-1 &&
- !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")-1)) {
- if (CG(active_op_array)->scope &&
- (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
- }
- CG(active_op_array)->this_var = var.u.op.var;
- }
+ if (name->val[0] == '\\') {
+ /* Remove \ prefix (only relevant if this is a string rather than a label) */
+ return zend_string_init(name->val + 1, name->len - 1, 0);
}
- if (CG(active_op_array)->fn_flags & ZEND_ACC_VARIADIC) {
- zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
+ if (type == ZEND_NAME_FQ) {
+ *is_fully_qualified = 1;
+ return zend_string_copy(name);
}
- if (is_variadic) {
- if (op == ZEND_RECV_INIT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Variadic parameter cannot have a default value");
- }
-
- op = ZEND_RECV_VARIADIC;
- CG(active_op_array)->fn_flags |= ZEND_ACC_VARIADIC;
+ if (type == ZEND_NAME_RELATIVE) {
+ *is_fully_qualified = 1;
+ return zend_prefix_with_ns(name TSRMLS_CC);
}
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- CG(active_op_array)->num_args++;
- opline->opcode = op;
- SET_NODE(opline->result, &var);
- opline->op1_type = IS_UNUSED;
- opline->op1.num = CG(active_op_array)->num_args;
- if (op == ZEND_RECV_INIT) {
- SET_NODE(opline->op2, initialization);
- } else {
- SET_UNUSED(opline->op2);
- if (!is_variadic) {
- CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
- }
- }
- CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
- cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
- cur_arg_info->name = estrndup(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant));
- cur_arg_info->name_len = Z_STRLEN(varname->u.constant);
- cur_arg_info->type_hint = 0;
- cur_arg_info->pass_by_reference = pass_by_reference;
- cur_arg_info->allow_null = 1;
- cur_arg_info->is_variadic = is_variadic;
- cur_arg_info->class_name = NULL;
- cur_arg_info->class_name_len = 0;
-
- if (class_type->op_type != IS_UNUSED) {
- cur_arg_info->allow_null = 0;
-
- if (Z_TYPE(class_type->u.constant) != IS_NULL) {
- if (Z_TYPE(class_type->u.constant) == IS_ARRAY) {
- cur_arg_info->type_hint = IS_ARRAY;
- if (op == ZEND_RECV_INIT) {
- if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
- cur_arg_info->allow_null = 1;
- } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY) {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
- }
- }
- } else if (Z_TYPE(class_type->u.constant) == IS_CALLABLE) {
- cur_arg_info->type_hint = IS_CALLABLE;
- if (op == ZEND_RECV_INIT) {
- if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
- cur_arg_info->allow_null = 1;
- } else {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with callable type hint can only be NULL");
- }
- }
- } else {
- cur_arg_info->type_hint = IS_OBJECT;
- if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
- zend_resolve_class_name(class_type TSRMLS_CC);
- }
- Z_STR(class_type->u.constant) = zend_new_interned_string(Z_STR(class_type->u.constant) TSRMLS_CC);
- if (IS_INTERNED(Z_STR(class_type->u.constant))) {
- Z_TYPE_FLAGS(class_type->u.constant) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
- }
-// TODO: for now we have to copy it ???
-#if 1
- cur_arg_info->class_name = estrndup(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant));
- cur_arg_info->class_name_len = Z_STRLEN(class_type->u.constant);
- STR_RELEASE(Z_STR(class_type->u.constant));
-#else
- cur_arg_info->class_name = Z_STRVAL(class_type->u.constant);
- cur_arg_info->class_name_len = Z_STRLEN(class_type->u.constant);
-#endif
- if (op == ZEND_RECV_INIT) {
- if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
- cur_arg_info->allow_null = 1;
- } else {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
- }
- }
- }
+ if (current_import_sub) {
+ /* If an unqualified name is a function/const alias, replace it. */
+ zend_string *import_name;
+ if (case_sensitive) {
+ import_name = zend_hash_find_ptr(current_import_sub, name);
+ } else {
+ import_name = zend_hash_find_ptr_lc(current_import_sub, name->val, name->len);
}
- }
- if (cur_arg_info->class_name || cur_arg_info->type_hint) {
- CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
+ if (import_name) {
+ *is_fully_qualified = 1;
+ return zend_string_copy(import_name);
+ }
}
-}
-/* }}} */
-
-int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
- zend_uint op_number;
- zend_function *function;
- zend_string *lcname;
- char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
-
- zend_resolve_function_name(function_name, &check_namespace TSRMLS_CC);
- if (check_namespace && Z_TYPE(CG(current_namespace)) != IS_UNDEF && !is_compound) {
- /* We assume we call function from the current namespace
- if it is not prefixed. */
-
- /* In run-time PHP will check for function with full name and
- internal function with short name */
- zend_do_begin_dynamic_function_call(function_name, 1 TSRMLS_CC);
- return 1;
+ compound = memchr(name->val, '\\', name->len);
+ if (compound) {
+ *is_fully_qualified = 1;
}
- lcname = STR_ALLOC(Z_STRLEN(function_name->u.constant), 0);
- zend_str_tolower_copy(lcname->val, Z_STRVAL(function_name->u.constant), Z_STRLEN(function_name->u.constant));
- if (((function = zend_hash_find_ptr(CG(function_table), lcname)) == NULL) ||
- ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
- (function->type == ZEND_INTERNAL_FUNCTION))) {
- zend_do_begin_dynamic_function_call(function_name, 0 TSRMLS_CC);
- efree(lcname);
- return 1; /* Dynamic */
- }
- STR_RELEASE(Z_STR(function_name->u.constant));
- Z_STR(function_name->u.constant) = lcname;
-
- op_number = get_next_op_number(CG(active_op_array));
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_INIT_FCALL;
- SET_UNUSED(opline->op1);
- SET_NODE(opline->op2, function_name);
- GET_CACHE_SLOT(opline->op2.constant);
-
- zend_push_function_call_entry(function, op_number TSRMLS_CC);
- zend_do_extended_fcall_begin(TSRMLS_C);
- return 0;
-}
-/* }}} */
-
-void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
-{
- zend_op *last_op;
- int last_op_number;
-
- zend_do_end_variable_parse(left_bracket, BP_VAR_R, 0 TSRMLS_CC);
- zend_do_begin_variable_parse(TSRMLS_C);
-
- last_op_number = get_next_op_number(CG(active_op_array))-1;
- last_op = &CG(active_op_array)->opcodes[last_op_number];
-
- if ((last_op->op2_type == IS_CONST) && (Z_TYPE(CONSTANT(last_op->op2.constant)) == IS_STRING) && (Z_STRLEN(CONSTANT(last_op->op2.constant)) == sizeof(ZEND_CLONE_FUNC_NAME)-1)
- && !zend_binary_strcasecmp(Z_STRVAL(CONSTANT(last_op->op2.constant)), Z_STRLEN(CONSTANT(last_op->op2.constant)), ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot call __clone() method on objects - use 'clone $obj' instead");
- }
+ if (compound && CG(current_import)) {
+ /* If the first part of a qualified name is an alias, substitute it. */
+ size_t len = compound - name->val;
+ zend_string *import_name = zend_hash_find_ptr_lc(CG(current_import), name->val, len);
- if (last_op->opcode == ZEND_FETCH_OBJ_R) {
- if (last_op->op2_type == IS_CONST) {
- zval name;
- name = CONSTANT(last_op->op2.constant);
- if (Z_TYPE(name) != IS_STRING) {
- zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
- }
- Z_STR(name) = STR_COPY(Z_STR(name));
- FREE_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
- last_op->op2.constant =
- zend_add_func_name_literal(CG(active_op_array), &name TSRMLS_CC);
- GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
- }
- last_op->opcode = ZEND_INIT_METHOD_CALL;
- last_op->result_type = IS_UNUSED;
- Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
- } else {
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_INIT_FCALL_BY_NAME;
- SET_UNUSED(opline->op1);
- if (left_bracket->op_type == IS_CONST) {
- opline->op2_type = IS_CONST;
- opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &left_bracket->u.constant TSRMLS_CC);
- GET_CACHE_SLOT(opline->op2.constant);
- } else {
- SET_NODE(opline->op2, left_bracket);
+ if (import_name) {
+ return zend_concat_names(
+ import_name->val, import_name->len, name->val + len + 1, name->len - len - 1);
}
}
- zend_push_function_call_entry(NULL, last_op_number TSRMLS_CC);
- zend_do_extended_fcall_begin(TSRMLS_C);
+ return zend_prefix_with_ns(name TSRMLS_CC);
}
/* }}} */
-void zend_do_clone(znode *result, znode *expr TSRMLS_DC) /* {{{ */
+zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified TSRMLS_DC) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_CLONE;
- SET_NODE(opline->op1, expr);
- SET_UNUSED(opline->op2);
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, opline->result);
+ return zend_resolve_non_class_name(
+ name, type, is_fully_qualified, 0, CG(current_import_function) TSRMLS_CC);
}
/* }}} */
-void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
-{
- zend_uint op_number;
- zend_op *opline;
-
- op_number = get_next_op_number(CG(active_op_array));
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- if (ns_call) {
- /* In run-time PHP will check for function with full name and
- internal function with short name */
- opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
- SET_UNUSED(opline->op1);
- opline->op2_type = IS_CONST;
- opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
- GET_CACHE_SLOT(opline->op2.constant);
- } else {
- opline->opcode = ZEND_INIT_FCALL_BY_NAME;
- SET_UNUSED(opline->op1);
- if (function_name->op_type == IS_CONST) {
- opline->op2_type = IS_CONST;
- opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
- GET_CACHE_SLOT(opline->op2.constant);
- } else {
- SET_NODE(opline->op2, function_name);
- }
- }
-
- zend_push_function_call_entry(NULL, op_number TSRMLS_CC);
- zend_do_extended_fcall_begin(TSRMLS_C);
+zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified TSRMLS_DC) /* {{{ */ {
+ return zend_resolve_non_class_name(
+ name, type, is_fully_qualified, 1, CG(current_import_const) TSRMLS_CC);
}
/* }}} */
-void zend_resolve_non_class_name(znode *element_name, zend_bool *check_namespace, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC) /* {{{ */
+zend_string *zend_resolve_class_name(zend_string *name, uint32_t type TSRMLS_DC) /* {{{ */
{
- znode tmp;
- int len;
- zval *ns;
- zend_string *lookup_name;
- char *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
+ char *compound;
- if (Z_STRVAL(element_name->u.constant)[0] == '\\') {
- /* name starts with \ so it is known and unambiguos, nothing to do here but shorten it */
- memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+1, Z_STRLEN(element_name->u.constant));
- --Z_STRLEN(element_name->u.constant);
- return;
+ if (type == ZEND_NAME_RELATIVE) {
+ return zend_prefix_with_ns(name TSRMLS_CC);
}
- if(!*check_namespace) {
- return;
- }
-
- if (current_import_sub) {
- len = Z_STRLEN(element_name->u.constant);
- if (case_sensitive) {
- lookup_name = STR_INIT(Z_STRVAL(element_name->u.constant), len, 0);
+ if (type == ZEND_NAME_FQ || name->val[0] == '\\') {
+ /* Remove \ prefix (only relevant if this is a string rather than a label) */
+ if (name->val[0] == '\\') {
+ name = zend_string_init(name->val + 1, name->len - 1, 0);
} else {
- lookup_name = STR_ALLOC(len, 0);
- zend_str_tolower_copy(lookup_name->val, Z_STRVAL(element_name->u.constant), len);
- }
- /* Check if function/const matches imported name */
- if ((ns = zend_hash_find(current_import_sub, lookup_name)) != NULL) {
- zval_dtor(&element_name->u.constant);
- ZVAL_DUP(&element_name->u.constant, ns);
- STR_FREE(lookup_name);
- *check_namespace = 0;
- return;
+ zend_string_addref(name);
}
- STR_FREE(lookup_name);
- }
-
- if (compound && CG(current_import)) {
- len = compound - Z_STRVAL(element_name->u.constant);
- /* namespace is always lowercase */
- lookup_name = STR_ALLOC(len, 0);
- zend_str_tolower_copy(lookup_name->val, Z_STRVAL(element_name->u.constant), len);
- /* Check if first part of compound name is an import name */
- if ((ns = zend_hash_find(CG(current_import), lookup_name)) != NULL) {
- /* Substitute import name */
- tmp.op_type = IS_CONST;
- ZVAL_DUP(&tmp.u.constant, ns);
- len += 1;
- Z_STRLEN(element_name->u.constant) -= len;
- memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+len, Z_STRLEN(element_name->u.constant)+1);
- zend_do_build_namespace_name(&tmp, &tmp, element_name TSRMLS_CC);
- *element_name = tmp;
- STR_FREE(lookup_name);
- *check_namespace = 0;
- return;
+ /* Ensure that \self, \parent and \static are not used */
+ if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", name->val);
}
- STR_FREE(lookup_name);
+ return name;
}
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- tmp = *element_name;
- Z_STR(tmp.u.constant) = STR_ALLOC(sizeof("\\")-1 + Z_STRLEN(element_name->u.constant) + Z_STRLEN(CG(current_namespace)), 0);
- Z_TYPE_FLAGS(tmp.u.constant) = IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE;
- memcpy(Z_STRVAL(tmp.u.constant), Z_STRVAL(CG(current_namespace)), Z_STRLEN(CG(current_namespace)));
- memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN(CG(current_namespace))]), "\\", sizeof("\\")-1);
- memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN(CG(current_namespace)) + sizeof("\\")-1]), Z_STRVAL(element_name->u.constant), Z_STRLEN(element_name->u.constant)+1);
- STR_RELEASE(Z_STR(element_name->u.constant));
- *element_name = tmp;
- }
-}
-/* }}} */
-
-void zend_resolve_function_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC) /* {{{ */
-{
- zend_resolve_non_class_name(element_name, check_namespace, 0, CG(current_import_function) TSRMLS_CC);
-}
-/* }}} */
-
-void zend_resolve_const_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC) /* {{{ */
-{
- zend_resolve_non_class_name(element_name, check_namespace, 1, CG(current_import_const) TSRMLS_CC);
-}
-/* }}} */
-
-void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC) /* {{{ */
-{
- char *lcname;
- int lctype;
- znode constant_name;
-
- lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
- lctype = zend_get_class_fetch_type(lcname, strlen(lcname));
- switch (lctype) {
- case ZEND_FETCH_CLASS_SELF:
- if (!CG(active_class_entry)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot access self::class when no class scope is active");
- }
- zval_dtor(&class_name->u.constant);
- class_name->op_type = IS_CONST;
- ZVAL_STR(&class_name->u.constant, STR_COPY(CG(active_class_entry)->name));
- *result = *class_name;
- break;
- case ZEND_FETCH_CLASS_STATIC:
- case ZEND_FETCH_CLASS_PARENT:
- if (is_static) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "%s::class cannot be used for compile-time class name resolution",
- lctype == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
- );
- }
- if (!CG(active_class_entry)) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "Cannot access %s::class when no class scope is active",
- lctype == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
- );
- }
- constant_name.op_type = IS_CONST;
- ZVAL_STRINGL(&constant_name.u.constant, "class", sizeof("class")-1);
- zend_do_fetch_constant(result, class_name, &constant_name, ZEND_RT, 1 TSRMLS_CC);
- break;
- case ZEND_FETCH_CLASS_DEFAULT:
- zend_resolve_class_name(class_name TSRMLS_CC);
- *result = *class_name;
- break;
- }
-
- efree(lcname);
-
-}
-/* }}} */
-
-void zend_resolve_class_name(znode *class_name TSRMLS_DC) /* {{{ */
-{
- char *compound;
- zend_string *lcname;
- zval *ns;
- znode tmp;
- int len;
-
- compound = memchr(Z_STRVAL(class_name->u.constant), '\\', Z_STRLEN(class_name->u.constant));
- if (compound) {
- /* This is a compound class name that contains namespace prefix */
- if (Z_STRVAL(class_name->u.constant)[0] == '\\') {
- /* The STRING name has "\" prefix */
- memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant));
- Z_STR(class_name->u.constant) = STR_REALLOC(
- Z_STR(class_name->u.constant),
- Z_STRLEN(class_name->u.constant) - 1, 0);
- Z_TYPE_FLAGS(class_name->u.constant) = IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE;
-
- if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
- zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", Z_STRVAL(class_name->u.constant));
+ if (CG(current_import)) {
+ compound = memchr(name->val, '\\', name->len);
+ if (compound) {
+ /* If the first part of a qualified name is an alias, substitute it. */
+ size_t len = compound - name->val;
+ zend_string *import_name = zend_hash_find_ptr_lc(CG(current_import), name->val, len);
+
+ if (import_name) {
+ return zend_concat_names(
+ import_name->val, import_name->len, name->val + len + 1, name->len - len - 1);
}
} else {
- if (CG(current_import)) {
- len = compound - Z_STRVAL(class_name->u.constant);
- lcname = STR_ALLOC(len, 0);
- zend_str_tolower_copy(lcname->val, Z_STRVAL(class_name->u.constant), len);
- /* Check if first part of compound name is an import name */
- if ((ns = zend_hash_find(CG(current_import), lcname)) != NULL) {
- /* Substitute import name */
- tmp.op_type = IS_CONST;
- ZVAL_DUP(&tmp.u.constant, ns);
- len += 1;
- Z_STRLEN(class_name->u.constant) -= len;
- memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+len, Z_STRLEN(class_name->u.constant)+1);
- zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
- *class_name = tmp;
- STR_FREE(lcname);
- return;
- }
- STR_FREE(lcname);
- }
- /* Here name is not prefixed with \ and not imported */
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- tmp.op_type = IS_CONST;
- ZVAL_DUP(&tmp.u.constant, &CG(current_namespace));
- zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
- *class_name = tmp;
- }
- }
- } else if (CG(current_import) || Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- /* this is a plain name (without \) */
- lcname = STR_ALLOC(Z_STRLEN(class_name->u.constant), 0);
- zend_str_tolower_copy(lcname->val, Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
+ /* If an unqualified name is an alias, replace it. */
+ zend_string *import_name
+ = zend_hash_find_ptr_lc(CG(current_import), name->val, name->len);
- if (CG(current_import) &&
- (ns = zend_hash_find(CG(current_import), lcname)) != NULL) {
- /* The given name is an import name. Substitute it. */
- zval_dtor(&class_name->u.constant);
- ZVAL_DUP(&class_name->u.constant, ns);
- } else if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- /* plain name, no import - prepend current namespace to it */
- tmp.op_type = IS_CONST;
- ZVAL_DUP(&tmp.u.constant, &CG(current_namespace));
- zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
- *class_name = tmp;
+ if (import_name) {
+ return zend_string_copy(import_name);
+ }
}
- STR_FREE(lcname);
}
+
+ /* If not fully qualified and not an alias, prepend the current namespace */
+ return zend_prefix_with_ns(name TSRMLS_CC);
}
/* }}} */
-void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
+zend_string *zend_resolve_class_name_ast(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- long fetch_class_op_number;
- zend_op *opline;
-
- fetch_class_op_number = get_next_op_number(CG(active_op_array));
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_FETCH_CLASS;
- SET_UNUSED(opline->op1);
- opline->extended_value = ZEND_FETCH_CLASS_DEFAULT;
- CG(catch_begin) = fetch_class_op_number;
- if (class_name->op_type == IS_CONST) {
- int fetch_type;
-
- fetch_type = zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
- switch (fetch_type) {
- case ZEND_FETCH_CLASS_SELF:
- case ZEND_FETCH_CLASS_PARENT:
- case ZEND_FETCH_CLASS_STATIC:
- SET_UNUSED(opline->op2);
- opline->extended_value = fetch_type;
- zval_dtor(&class_name->u.constant);
- break;
- default:
- zend_resolve_class_name(class_name TSRMLS_CC);
- opline->op2_type = IS_CONST;
- opline->op2.constant =
- zend_add_class_name_literal(CG(active_op_array), &class_name->u.constant TSRMLS_CC);
- break;
- }
- } else {
- SET_NODE(opline->op2, class_name);
- }
- opline->result.var = get_temporary_variable(CG(active_op_array));
- opline->result_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
- GET_NODE(result, opline->result);
- result->EA = opline->extended_value;
+ zend_string *name = zend_ast_get_str(ast);
+ return zend_resolve_class_name(name, ast->attr TSRMLS_CC);
}
/* }}} */
@@ -2343,31 +794,15 @@ static void ptr_dtor(zval *zv) /* {{{ */
}
/* }}} */
-void zend_do_label(znode *label TSRMLS_DC) /* {{{ */
-{
- zend_label dest;
-
- if (!CG(context).labels) {
- ALLOC_HASHTABLE(CG(context).labels);
- zend_hash_init(CG(context).labels, 8, NULL, ptr_dtor, 0);
- }
-
- dest.brk_cont = CG(context).current_brk_cont;
- dest.opline_num = get_next_op_number(CG(active_op_array));
-
- if (zend_hash_add_mem(CG(context).labels, Z_STR(label->u.constant), &dest, sizeof(zend_label)) == NULL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL(label->u.constant));
- }
-
- /* Done with label now */
- zval_dtor(&label->u.constant);
+static void str_dtor(zval *zv) /* {{{ */ {
+ zend_string_release(Z_STR_P(zv));
}
/* }}} */
void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC) /* {{{ */
{
zend_label *dest;
- long current, distance;
+ zend_long current, distance;
zval *label;
if (pass2) {
@@ -2385,7 +820,6 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2
zend_error_noreturn(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
} else {
/* Label is not defined. Delay to pass 2. */
- INC_BPC(op_array);
return;
}
}
@@ -2417,22 +851,6 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2
/* Set real break distance */
ZVAL_LONG(label, distance);
}
-
- if (pass2) {
- DEC_BPC(op_array);
- }
-}
-/* }}} */
-
-void zend_do_goto(znode *label TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_GOTO;
- opline->extended_value = CG(context).current_brk_cont;
- SET_UNUSED(opline->op1);
- SET_NODE(opline->op2, label);
- zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC);
}
/* }}} */
@@ -2451,982 +869,48 @@ void zend_release_labels(int temporary TSRMLS_DC) /* {{{ */
}
/* }}} */
-void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_class_member TSRMLS_DC) /* {{{ */
-{
- zend_uint length;
-
- if (!result) {
- result = prefix;
- } else {
- *result = *prefix;
- }
+static zend_bool zend_is_call(zend_ast *ast);
- if (is_class_member) {
- int old_len = Z_STRLEN(result->u.constant);
- length = sizeof("::")-1 + old_len + Z_STRLEN(name->u.constant);
- Z_STR(result->u.constant) = STR_REALLOC(Z_STR(result->u.constant), length, 0);
- Z_TYPE_FLAGS(result->u.constant) = IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE;
- memcpy(&Z_STRVAL(result->u.constant)[old_len], "::", sizeof("::")-1);
- memcpy(&Z_STRVAL(result->u.constant)[old_len + sizeof("::")-1], Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1);
- STR_RELEASE(Z_STR(name->u.constant));
- } else {
- int old_len = Z_STRLEN(result->u.constant);
- length = sizeof("\\")-1 + old_len + Z_STRLEN(name->u.constant);
- Z_STR(result->u.constant) = STR_REALLOC(Z_STR(result->u.constant), length, 0);
- Z_TYPE_FLAGS(result->u.constant) = IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE;
- memcpy(&Z_STRVAL(result->u.constant)[old_len], "\\", sizeof("\\")-1);
- memcpy(&Z_STRVAL(result->u.constant)[old_len + sizeof("\\")-1], Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1);
- STR_RELEASE(Z_STR(name->u.constant));
- }
-}
-/* }}} */
-
-int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
+static int generate_free_loop_var(znode *var TSRMLS_DC) /* {{{ */
{
- znode class_node;
- zend_uint op_number;
- zend_op *opline;
-
- if (method_name->op_type == IS_CONST) {
- char *lcname;
- if (Z_TYPE(method_name->u.constant) != IS_STRING) {
- zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
- }
- lcname = zend_str_tolower_dup(Z_STRVAL(method_name->u.constant), Z_STRLEN(method_name->u.constant));
- if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(method_name->u.constant) &&
- memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
- zval_dtor(&method_name->u.constant);
- method_name->op_type = IS_UNUSED;
- }
- efree(lcname);
- }
-
- if (class_name->op_type == IS_CONST &&
- ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
- zend_resolve_class_name(class_name TSRMLS_CC);
- class_node = *class_name;
- op_number = get_next_op_number(CG(active_op_array));
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- } else {
- zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
- op_number = get_next_op_number(CG(active_op_array));
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- }
- opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
- if (class_node.op_type == IS_CONST) {
- opline->op1_type = IS_CONST;
- opline->op1.constant =
- zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
- } else {
- SET_NODE(opline->op1, &class_node);
- }
- if (method_name->op_type == IS_CONST) {
- opline->op2_type = IS_CONST;
- opline->op2.constant =
- zend_add_func_name_literal(CG(active_op_array), &method_name->u.constant TSRMLS_CC);
- if (opline->op1_type == IS_CONST) {
- GET_CACHE_SLOT(opline->op2.constant);
- } else {
- GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
- }
- } else {
- SET_NODE(opline->op2, method_name);
- }
-
- zend_push_function_call_entry(NULL, op_number TSRMLS_CC);
- zend_do_extended_fcall_begin(TSRMLS_C);
- return 1; /* Dynamic */
-}
-/* }}} */
-
-static int zend_do_convert_call(zend_op *init_opline, zend_op *opline, long num_args, zend_function **func_ptr TSRMLS_DC) /* {{{ */
-{
- zval *function_name;
- zend_string *lcname;
- zend_function *function;
-
- *func_ptr = NULL;
- if (opline->op1_type == IS_CONST && Z_TYPE(CONSTANT(opline->op1.constant)) == IS_STRING) {
- function_name = &CONSTANT(opline->op1.constant);
- lcname = STR_ALLOC(Z_STRLEN_P(function_name), 0);
- zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name), Z_STRLEN_P(function_name));
- if (((function = zend_hash_find_ptr(CG(function_table), lcname)) == NULL) ||
- ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
- (function->type == ZEND_INTERNAL_FUNCTION))) {
- function = NULL;
- STR_RELEASE(lcname);
- opline->opcode = ZEND_INIT_USER_CALL;
- opline->extended_value = num_args;
- opline->op2_type = opline->op1_type;
- opline->op2 = opline->op1;
- opline->op1_type = IS_CONST;
- opline->op1 = init_opline->op2;
- SET_UNUSED(opline->result);
- MAKE_NOP(init_opline);
- return 1;
- } else {
- STR_RELEASE(Z_STR_P(function_name));
- Z_STR_P(function_name) = zend_new_interned_string(lcname TSRMLS_CC);
- opline->opcode = ZEND_INIT_FCALL;
- opline->extended_value = num_args;
- opline->op2_type = IS_CONST;
- opline->op2.constant = opline->op1.constant;
- GET_CACHE_SLOT(opline->op2.constant);
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->result);
- MAKE_NOP(init_opline);
- *func_ptr = function;
+ switch (var->op_type) {
+ case IS_UNUSED:
+ /* Stack separator on function boundary, stop applying */
return 1;
- }
- } else {
- opline->opcode = ZEND_INIT_USER_CALL;
- opline->extended_value = num_args;
- opline->op2_type = opline->op1_type;
- opline->op2 = opline->op1;
- opline->op1_type = IS_CONST;
- opline->op1 = init_opline->op2;
- SET_UNUSED(opline->result);
- MAKE_NOP(init_opline);
- return 1;
- }
- return 0;
-}
-/* }}} */
-
-static int zend_do_convert_call_user_func(zend_op *init_opline, zend_uint num_args TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = init_opline + 1;
- int level = 0;
- int converted = 0;
- zend_uint arg_num = 0;
- zend_function *func = NULL;
-
- while (1) {
- switch (opline->opcode) {
- case ZEND_SEND_VAL:
- case ZEND_SEND_VAL_EX:
- case ZEND_SEND_VAR:
- case ZEND_SEND_VAR_EX:
- case ZEND_SEND_VAR_NO_REF:
- case ZEND_SEND_REF:
- case ZEND_SEND_UNPACK:
- if (level == 0) {
- if (!converted) {
- if (opline->opcode == ZEND_SEND_UNPACK) {
- return 0;
- }
- if (!zend_do_convert_call(init_opline, opline, init_opline->extended_value - 1, &func TSRMLS_CC)) {
- return 0;
- }
- converted = 1;
- } else {
- /* Use ZEND_SEND_USER instruction for parameters that may pass by reference */
- if (opline->opcode != ZEND_SEND_VAL &&
- (func == NULL ||
- ARG_SHOULD_BE_SENT_BY_REF(func, opline->op2.num-1))) {
- opline->opcode = ZEND_SEND_USER;
- }
- opline->op2.num--;
- }
- if (++arg_num == num_args) {
- return 1;
- }
- }
- break;
- case ZEND_INIT_FCALL_BY_NAME:
- case ZEND_INIT_NS_FCALL_BY_NAME:
- case ZEND_NEW:
- case ZEND_INIT_METHOD_CALL:
- case ZEND_INIT_STATIC_METHOD_CALL:
- case ZEND_INIT_FCALL:
- level++;
- break;
- case ZEND_DO_FCALL:
- level--;
- break;
- }
- opline++;
- }
-}
-/* }}} */
-
-static int zend_do_convert_call_user_func_array(zend_op *init_opline TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = init_opline + 1;
- zend_op *send1 = NULL, *send2 = NULL;
- int level = 0;
- zend_function *func;
-
- do {
- switch (opline->opcode) {
- case ZEND_SEND_VAL:
- case ZEND_SEND_VAL_EX:
- case ZEND_SEND_VAR:
- case ZEND_SEND_VAR_EX:
- case ZEND_SEND_VAR_NO_REF:
- case ZEND_SEND_REF:
- case ZEND_SEND_UNPACK:
- if (level == 0) {
- if (opline->opcode == ZEND_SEND_UNPACK) {
- return 0;
- }
- if (send1 == NULL) {
- send1 = opline;
- } else {
- send2 = opline;
- }
- }
- break;
- case ZEND_INIT_FCALL_BY_NAME:
- case ZEND_INIT_NS_FCALL_BY_NAME:
- case ZEND_NEW:
- case ZEND_INIT_METHOD_CALL:
- case ZEND_INIT_STATIC_METHOD_CALL:
- case ZEND_INIT_FCALL:
- level++;
- break;
- case ZEND_DO_FCALL:
- level--;
- break;
- }
- opline++;
- } while (send2 == NULL);
-
- if (!zend_do_convert_call(init_opline, send1, 0, &func TSRMLS_CC)) {
- return 0;
- }
-
- send2->opcode = ZEND_SEND_ARRAY;
- send2->extended_value = 0;
- send2->op2.num--;
- return 1;
-}
-/* }}} */
-
-static int zend_do_convert_strlen(zend_op *init_opline, znode *result TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = init_opline + 1;
- zend_op *send = NULL;
- int level = 0;
-
- do {
- switch (opline->opcode) {
- case ZEND_SEND_VAL:
- case ZEND_SEND_VAL_EX:
- case ZEND_SEND_VAR:
- case ZEND_SEND_VAR_EX:
- case ZEND_SEND_VAR_NO_REF:
- case ZEND_SEND_REF:
- case ZEND_SEND_UNPACK:
- if (level == 0) {
- if (opline->opcode == ZEND_SEND_UNPACK) {
- return 0;
- }
- send = opline;
- }
- break;
- case ZEND_INIT_FCALL_BY_NAME:
- case ZEND_INIT_NS_FCALL_BY_NAME:
- case ZEND_NEW:
- case ZEND_INIT_METHOD_CALL:
- case ZEND_INIT_STATIC_METHOD_CALL:
- case ZEND_INIT_FCALL:
- level++;
- break;
- case ZEND_DO_FCALL:
- level--;
- break;
- }
- opline++;
- } while (send == NULL);
-
- MAKE_NOP(init_opline);
- send->opcode = ZEND_STRLEN;
- send->extended_value = 0;
- SET_UNUSED(send->op2);
- send->result.var = get_temporary_variable(CG(active_op_array));
- send->result_type = IS_TMP_VAR;
- GET_NODE(result, send->result);
- return 1;
-}
-/* }}} */
-
-static int zend_do_convert_type_check(zend_op *init_opline, znode *result, zend_uint type TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = init_opline + 1;
- zend_op *send = NULL;
- int level = 0;
-
- do {
- switch (opline->opcode) {
- case ZEND_SEND_VAL:
- case ZEND_SEND_VAL_EX:
- case ZEND_SEND_VAR:
- case ZEND_SEND_VAR_EX:
- case ZEND_SEND_VAR_NO_REF:
- case ZEND_SEND_REF:
- case ZEND_SEND_UNPACK:
- if (level == 0) {
- if (opline->opcode == ZEND_SEND_UNPACK) {
- return 0;
- }
- send = opline;
- }
- break;
- case ZEND_INIT_FCALL_BY_NAME:
- case ZEND_INIT_NS_FCALL_BY_NAME:
- case ZEND_NEW:
- case ZEND_INIT_METHOD_CALL:
- case ZEND_INIT_STATIC_METHOD_CALL:
- case ZEND_INIT_FCALL:
- level++;
- break;
- case ZEND_DO_FCALL:
- level--;
- break;
- }
- opline++;
- } while (send == NULL);
-
- MAKE_NOP(init_opline);
- send->opcode = ZEND_TYPE_CHECK;
- send->extended_value = type;
- SET_UNUSED(send->op2);
- send->result.var = get_temporary_variable(CG(active_op_array));
- send->result_type = IS_TMP_VAR;
- GET_NODE(result, send->result);
- return 1;
-}
-/* }}} */
-
-static int zend_do_convert_defined(zend_op *init_opline, znode *result TSRMLS_DC) /* {{{ */
-{
- zval c;
- zend_string *lc_name;
- zend_op *opline = init_opline + 1;
-
- if (opline->opcode != ZEND_SEND_VAL ||
- opline->op1_type != IS_CONST ||
- Z_TYPE(CONSTANT(opline->op1.constant)) != IS_STRING
- || zend_memrchr(Z_STRVAL(CONSTANT(opline->op1.constant)), '\\', Z_STRLEN(CONSTANT(opline->op1.constant))) != NULL
- || zend_memrchr(Z_STRVAL(CONSTANT(opline->op1.constant)), ':', Z_STRLEN(CONSTANT(opline->op1.constant))) != NULL) {
- return 0;
- }
-
- MAKE_NOP(init_opline);
- opline->opcode = ZEND_DEFINED;
- opline->extended_value = 0;
- GET_CACHE_SLOT(opline->op1.constant);
- /* lowcase constant name */
- lc_name = STR_ALLOC(Z_STRLEN(CONSTANT(opline->op1.constant)), 0);
- zend_str_tolower_copy(lc_name->val, Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
- ZVAL_NEW_STR(&c, lc_name);
- zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
- opline->result.var = get_temporary_variable(CG(active_op_array));
- opline->result_type = IS_TMP_VAR;
- GET_NODE(result, opline->result);
- return 1;
-}
-/* }}} */
-
-void zend_do_end_function_call(znode *function_name, znode *result, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
- zend_function_call_entry *fcall = zend_stack_top(&CG(function_call_stack));
-
- if (is_method && function_name && function_name->op_type == IS_UNUSED) {
- /* clone */
- if (fcall->arg_num != 0) {
- zend_error(E_WARNING, "Clone method does not require arguments");
- }
- opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
- } else {
- zend_uint call_flags = 0;
-
- opline = &CG(active_op_array)->opcodes[fcall->op_number];
- opline->extended_value = fcall->arg_num;
-
- if (opline->opcode == ZEND_NEW) {
- call_flags = ZEND_CALL_CTOR;
- } else {
- zend_function *func = fcall->fbc;
- if (func && func->type == ZEND_INTERNAL_FUNCTION) {
- /* Convert calls to some internal functions into built-ins */
- if (func->common.function_name->len == sizeof("call_user_func")-1 &&
- memcmp(func->common.function_name->val, "call_user_func", sizeof("call_user_func")-1) == 0) {
- if (fcall->arg_num > 0) {
- if (zend_do_convert_call_user_func(opline, fcall->arg_num TSRMLS_CC)) {
- fcall->arg_num--;
- }
- }
- } else if (func->common.function_name->len == sizeof("call_user_func_array")-1 &&
- memcmp(func->common.function_name->val, "call_user_func_array", sizeof("call_user_func_array")-1) == 0) {
- if (fcall->arg_num == 2) {
- if (zend_do_convert_call_user_func_array(opline TSRMLS_CC)) {
- fcall->arg_num = 0;
- }
- }
- } else if (func->common.function_name->len == sizeof("defined")-1 &&
- memcmp(func->common.function_name->val, "defined", sizeof("defined")-1) == 0) {
- if (fcall->arg_num == 1) {
- if (zend_do_convert_defined(opline, result TSRMLS_CC)) {
- zend_stack_del_top(&CG(function_call_stack));
- return;
- }
- }
- } else if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) == 0 &&
- func->common.function_name->len == sizeof("strlen")-1 &&
- memcmp(func->common.function_name->val, "strlen", sizeof("strlen")-1) == 0) {
- if (fcall->arg_num == 1) {
- if (zend_do_convert_strlen(opline, result TSRMLS_CC)) {
- zend_stack_del_top(&CG(function_call_stack));
- return;
- }
- }
- } else if (func->common.function_name->len == sizeof("is_null")-1 &&
- memcmp(func->common.function_name->val, "is_null", sizeof("is_null")-1) == 0) {
- if (fcall->arg_num == 1) {
- if (zend_do_convert_type_check(opline, result, IS_NULL TSRMLS_CC)) {
- zend_stack_del_top(&CG(function_call_stack));
- return;
- }
- }
- } else if (func->common.function_name->len == sizeof("is_bool")-1 &&
- memcmp(func->common.function_name->val, "is_bool", sizeof("is_bool")-1) == 0) {
- if (fcall->arg_num == 1) {
- if (zend_do_convert_type_check(opline, result, _IS_BOOL TSRMLS_CC)) {
- zend_stack_del_top(&CG(function_call_stack));
- return;
- }
- }
- } else if (func->common.function_name->len == sizeof("is_long")-1 &&
- memcmp(func->common.function_name->val, "is_long", sizeof("is_long")-1) == 0) {
- if (fcall->arg_num == 1) {
- if (zend_do_convert_type_check(opline, result, IS_LONG TSRMLS_CC)) {
- zend_stack_del_top(&CG(function_call_stack));
- return;
- }
- }
- } else if (func->common.function_name->len == sizeof("is_float")-1 &&
- memcmp(func->common.function_name->val, "is_float", sizeof("is_float")-1) == 0) {
- if (fcall->arg_num == 1) {
- if (zend_do_convert_type_check(opline, result, IS_DOUBLE TSRMLS_CC)) {
- zend_stack_del_top(&CG(function_call_stack));
- return;
- }
- }
- } else if (func->common.function_name->len == sizeof("is_string")-1 &&
- memcmp(func->common.function_name->val, "is_string", sizeof("is_string")-1) == 0) {
- if (fcall->arg_num == 1) {
- if (zend_do_convert_type_check(opline, result, IS_STRING TSRMLS_CC)) {
- zend_stack_del_top(&CG(function_call_stack));
- return;
- }
- }
- } else if (func->common.function_name->len == sizeof("is_array")-1 &&
- memcmp(func->common.function_name->val, "is_array", sizeof("is_array")-1) == 0) {
- if (fcall->arg_num == 1) {
- if (zend_do_convert_type_check(opline, result, IS_ARRAY TSRMLS_CC)) {
- zend_stack_del_top(&CG(function_call_stack));
- return;
- }
- }
- } else if (func->common.function_name->len == sizeof("is_object")-1 &&
- memcmp(func->common.function_name->val, "is_object", sizeof("is_object")-1) == 0) {
- if (fcall->arg_num == 1) {
- if (zend_do_convert_type_check(opline, result, IS_OBJECT TSRMLS_CC)) {
- zend_stack_del_top(&CG(function_call_stack));
- return;
- }
- }
- } else if (func->common.function_name->len == sizeof("is_resouce")-1 &&
- memcmp(func->common.function_name->val, "is_resource", sizeof("is_resource")-1) == 0) {
- if (fcall->arg_num == 1) {
- if (zend_do_convert_type_check(opline, result, IS_RESOURCE TSRMLS_CC)) {
- zend_stack_del_top(&CG(function_call_stack));
- return;
- }
- }
- }
- }
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_DO_FCALL;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- opline->op1.num = call_flags;
- }
-
- opline->result.var = get_temporary_variable(CG(active_op_array));
- opline->result_type = IS_VAR;
- GET_NODE(result, opline->result);
- opline->extended_value = fcall->arg_num;
-
- zend_stack_del_top(&CG(function_call_stack));
-}
-/* }}} */
-
-void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
- int original_op = op;
- zend_function_call_entry *fcall = zend_stack_top(&CG(function_call_stack));
- zend_function *function_ptr = fcall->fbc;
- int send_by_reference = 0;
- int send_function = 0;
-
- fcall->arg_num++;
-
- if (fcall->uses_argument_unpacking) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "Cannot use positional argument after argument unpacking");
- }
-
- if (op == ZEND_SEND_VAR && (param->op_type & (IS_CONST|IS_TMP_VAR))) {
- /* Function call was converted into builtin instruction */
- zend_llist *fetch_list_ptr = zend_stack_top(&CG(bp_stack));
- zend_llist_destroy(fetch_list_ptr);
- zend_stack_del_top(&CG(bp_stack));
- original_op = op = ZEND_SEND_VAL;
- }
-
- if (original_op == ZEND_SEND_REF) {
- if (function_ptr &&
- function_ptr->common.function_name &&
- function_ptr->common.type == ZEND_USER_FUNCTION &&
- !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "Call-time pass-by-reference has been removed; "
- "If you would like to pass argument by reference, modify the declaration of %s().",
- function_ptr->common.function_name->val);
- } else {
- zend_error_noreturn(E_COMPILE_ERROR, "Call-time pass-by-reference has been removed");
- }
- return;
- }
-
- if (function_ptr) {
- if (ARG_MAY_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
- if (op == ZEND_SEND_VAR && param->op_type & (IS_VAR|IS_CV)) {
- send_by_reference = ZEND_ARG_SEND_BY_REF;
- if (zend_is_function_or_method_call(param)) {
- /* Method call */
- op = ZEND_SEND_VAR_NO_REF;
- send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT;
- }
- } else {
- op = ZEND_SEND_VAL;
- }
- } else if (ARG_SHOULD_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
- send_by_reference = ZEND_ARG_SEND_BY_REF;
- }
- }
-
- if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
- /* Method call */
- op = ZEND_SEND_VAR_NO_REF;
- send_function = ZEND_ARG_SEND_FUNCTION;
- } else if (op == ZEND_SEND_VAL && (param->op_type & (IS_VAR|IS_CV))) {
- op = ZEND_SEND_VAR_NO_REF;
- }
-
- if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference==ZEND_ARG_SEND_BY_REF) {
- /* change to passing by reference */
- switch (param->op_type) {
- case IS_VAR:
- case IS_CV:
- op = ZEND_SEND_REF;
- break;
- default:
- zend_error_noreturn(E_COMPILE_ERROR, "Only variables can be passed by reference");
- break;
- }
- }
-
- if (original_op == ZEND_SEND_VAR) {
- switch (op) {
- case ZEND_SEND_VAR_NO_REF:
- zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
- break;
- case ZEND_SEND_VAR:
- if (function_ptr) {
- zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
- } else {
- zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, fcall->arg_num TSRMLS_CC);
- }
- break;
- case ZEND_SEND_REF:
- zend_do_end_variable_parse(param, BP_VAR_W, 0 TSRMLS_CC);
- break;
- }
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ case IS_VAR:
+ case IS_TMP_VAR:
+ {
+ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- if (op == ZEND_SEND_VAR_NO_REF) {
- if (function_ptr) {
- opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference | send_function;
- } else {
- opline->extended_value = send_function;
- }
- } else {
- if (!function_ptr) {
- switch (op) {
- case ZEND_SEND_VAL:
- op = ZEND_SEND_VAL_EX;
- break;
- case ZEND_SEND_VAR:
- op = ZEND_SEND_VAR_EX;
- break;
- }
+ opline->opcode = var->op_type == IS_TMP_VAR ? ZEND_FREE : ZEND_SWITCH_FREE;
+ SET_NODE(opline->op1, var);
+ SET_UNUSED(opline->op2);
}
}
- opline->opcode = op;
- SET_NODE(opline->op1, param);
- opline->op2.opline_num = fcall->arg_num;
- SET_UNUSED(opline->op2);
-}
-/* }}} */
-
-void zend_do_unpack_params(znode *params TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
- zend_function_call_entry *fcall = zend_stack_top(&CG(function_call_stack));
-
- fcall->uses_argument_unpacking = 1;
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_SEND_UNPACK;
- SET_NODE(opline->op1, params);
- SET_UNUSED(opline->op2);
- opline->op2.num = fcall->arg_num;
-}
-/* }}} */
-
-static int generate_free_switch_expr(zend_switch_entry *switch_entry TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
-
- if (switch_entry->cond.op_type != IS_VAR && switch_entry->cond.op_type != IS_TMP_VAR) {
- return (switch_entry->cond.op_type == IS_UNUSED);
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
- SET_NODE(opline->op1, &switch_entry->cond);
- SET_UNUSED(opline->op2);
return 0;
}
/* }}} */
-static int generate_free_foreach_copy(const zend_op *foreach_copy TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
-
- /* If we reach the separator then stop applying the stack */
- if (foreach_copy->result_type == IS_UNUSED) {
- return 1;
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = (foreach_copy->result_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
- COPY_NODE(opline->op1, foreach_copy->result);
- SET_UNUSED(opline->op2);
-
- return 0;
-}
-/* }}} */
-
-void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
- int start_op_number, end_op_number;
- zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
-
- /* The error for use of return inside a generator is thrown in pass_two. */
-
- if (do_end_vparse) {
- if (returns_reference && !zend_is_function_or_method_call(expr)) {
- zend_do_end_variable_parse(expr, BP_VAR_W, 1 TSRMLS_CC);
- } else {
- zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
- }
- }
-
- start_op_number = get_next_op_number(CG(active_op_array));
-
-#ifdef ZTS
- zend_stack_apply_with_argument(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_switch_expr TSRMLS_CC);
- zend_stack_apply_with_argument(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_foreach_copy TSRMLS_CC);
-#else
- zend_stack_apply(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_switch_expr);
- zend_stack_apply(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_foreach_copy);
-#endif
-
- end_op_number = get_next_op_number(CG(active_op_array));
- while (start_op_number < end_op_number) {
- CG(active_op_array)->opcodes[start_op_number].extended_value |= EXT_TYPE_FREE_ON_RETURN;
- start_op_number++;
- }
-
- if (CG(context).in_finally) {
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_DISCARD_EXCEPTION;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN;
-
- if (expr) {
- SET_NODE(opline->op1, expr);
-
- if (!do_end_vparse) {
- opline->extended_value = ZEND_RETURNS_VALUE;
- } else if (zend_is_function_or_method_call(expr)) {
- opline->extended_value = ZEND_RETURNS_FUNCTION;
- }
- } else {
- opline->op1_type = IS_CONST;
- LITERAL_NULL(opline->op1);
- }
-
- SET_UNUSED(opline->op2);
-}
-/* }}} */
-
-void zend_do_yield(znode *result, znode *value, znode *key, zend_bool is_variable TSRMLS_DC) /* {{{ */
+static uint32_t zend_add_try_element(uint32_t try_op TSRMLS_DC) /* {{{ */
{
- zend_op *opline;
+ zend_op_array *op_array = CG(active_op_array);
+ uint32_t try_catch_offset = op_array->last_try_catch++;
+ zend_try_catch_element *elem;
- if (!CG(active_op_array)->function_name) {
- zend_error_noreturn(E_COMPILE_ERROR, "The \"yield\" expression can only be used inside a function");
- }
+ op_array->try_catch_array = safe_erealloc(
+ op_array->try_catch_array, sizeof(zend_try_catch_element), op_array->last_try_catch, 0);
- CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
+ elem = &op_array->try_catch_array[try_catch_offset];
+ elem->try_op = try_op;
+ elem->catch_op = 0;
+ elem->finally_op = 0;
+ elem->finally_end = 0;
- if (is_variable) {
- if ((CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) && !zend_is_function_or_method_call(value)) {
- zend_do_end_variable_parse(value, BP_VAR_W, 1 TSRMLS_CC);
- } else {
- zend_do_end_variable_parse(value, BP_VAR_R, 0 TSRMLS_CC);
- }
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_YIELD;
-
- if (value) {
- SET_NODE(opline->op1, value);
-
- if (is_variable && zend_is_function_or_method_call(value)) {
- opline->extended_value = ZEND_RETURNS_FUNCTION;
- }
- } else {
- SET_UNUSED(opline->op1);
- }
-
- if (key) {
- SET_NODE(opline->op2, key);
- } else {
- SET_UNUSED(opline->op2);
- }
-
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, opline->result);
-}
-/* }}} */
-
-static int zend_add_try_element(zend_uint try_op TSRMLS_DC) /* {{{ */
-{
- int try_catch_offset = CG(active_op_array)->last_try_catch++;
-
- CG(active_op_array)->try_catch_array = erealloc(CG(active_op_array)->try_catch_array, sizeof(zend_try_catch_element)*CG(active_op_array)->last_try_catch);
- CG(active_op_array)->try_catch_array[try_catch_offset].try_op = try_op;
- CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = 0;
- CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = 0;
- CG(active_op_array)->try_catch_array[try_catch_offset].finally_end = 0;
return try_catch_offset;
}
/* }}} */
-static void zend_add_catch_element(int offset, zend_uint catch_op TSRMLS_DC) /* {{{ */
-{
- CG(active_op_array)->try_catch_array[offset].catch_op = catch_op;
-}
-/* }}} */
-
-void zend_do_first_catch(znode *open_parentheses TSRMLS_DC) /* {{{ */
-{
- open_parentheses->u.op.opline_num = get_next_op_number(CG(active_op_array));
-}
-/* }}} */
-
-void zend_initialize_try_catch_element(znode *catch_token TSRMLS_DC) /* {{{ */
-{
- int jmp_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- zend_llist jmp_list;
- zend_llist *jmp_list_ptr;
-
- opline->opcode = ZEND_JMP;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- /* save for backpatching */
-
- zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
- zend_stack_push(&CG(bp_stack), (void *) &jmp_list);
- jmp_list_ptr = zend_stack_top(&CG(bp_stack));
- zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
-
- catch_token->EA = get_next_op_number(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additional_catch TSRMLS_DC) /* {{{ */
-{
- CG(active_op_array)->last--;
- zend_do_if_end(TSRMLS_C);
- if (last_additional_catch->u.op.opline_num == -1) {
- CG(active_op_array)->opcodes[first_catch->u.op.opline_num].result.num = 1;
- CG(active_op_array)->opcodes[first_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
- } else {
- CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].result.num = 1;
- CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
- }
- DEC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */
-{
- try_token->u.op.opline_num = zend_add_try_element(get_next_op_number(CG(active_op_array)) TSRMLS_CC);
- INC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_finally(znode *finally_token TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- finally_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
- /* call the the "finally" block */
- opline->opcode = ZEND_FAST_CALL;
- SET_UNUSED(opline->op1);
- opline->op1.opline_num = finally_token->u.op.opline_num + 1;
- SET_UNUSED(opline->op2);
- /* jump to code after the "finally" block,
- * the actual jump address is going to be set in zend_do_end_finally()
- */
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_JMP;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
-
- CG(context).in_finally++;
-}
-/* }}} */
-
-void zend_do_begin_catch(znode *catch_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
-{
- long catch_op_number;
- zend_op *opline;
- znode catch_class;
-
- if (class_name->op_type == IS_CONST &&
- ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
- zend_resolve_class_name(class_name TSRMLS_CC);
- catch_class = *class_name;
- } else {
- zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
- }
-
- catch_op_number = get_next_op_number(CG(active_op_array));
- if (first_catch) {
- first_catch->u.op.opline_num = catch_op_number;
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_CATCH;
- opline->op1_type = IS_CONST;
- opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), &catch_class.u.constant TSRMLS_CC);
- opline->op2_type = IS_CV;
- opline->op2.var = lookup_cv(CG(active_op_array), Z_STR(catch_var->u.constant) TSRMLS_CC);
- Z_STR(catch_var->u.constant) = CG(active_op_array)->vars[EX_VAR_TO_NUM(opline->op2.var)];
- opline->result.num = 0; /* 1 means it's the last catch in the block */
-
- catch_token->u.op.opline_num = catch_op_number;
-}
-/* }}} */
-
-void zend_do_end_catch(znode *catch_token TSRMLS_DC) /* {{{ */
-{
- int jmp_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- zend_llist *jmp_list_ptr;
-
- opline->opcode = ZEND_JMP;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- /* save for backpatching */
-
- jmp_list_ptr = zend_stack_top(&CG(bp_stack));
- zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
-
- CG(active_op_array)->opcodes[catch_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_bind_catch(znode *try_token, znode *catch_token TSRMLS_DC) /* {{{ */ {
- if (catch_token->op_type != IS_UNUSED) {
- zend_add_catch_element(try_token->u.op.opline_num, catch_token->EA TSRMLS_CC);
- }
-}
-/* }}} */
-
-void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_token TSRMLS_DC) /* {{{ */
-{
- if (catch_token->op_type == IS_UNUSED && finally_token->op_type == IS_UNUSED) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
- }
- if (finally_token->op_type != IS_UNUSED) {
- zend_op *opline;
-
- CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_op = finally_token->u.op.opline_num + 1;
- CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_end = get_next_op_number(CG(active_op_array));
- CG(active_op_array)->has_finally_block = 1;
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_FAST_RET;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
-
- CG(active_op_array)->opcodes[finally_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
-
- CG(context).in_finally--;
- }
-}
-/* }}} */
-
-void zend_do_throw(znode *expr TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_THROW;
- SET_NODE(opline->op1, expr);
- SET_UNUSED(opline->op2);
-}
-/* }}} */
-
ZEND_API void function_add_ref(zend_function *function) /* {{{ */
{
if (function->type == ZEND_USER_FUNCTION) {
@@ -3442,7 +926,7 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
op_array->run_time_cache = NULL;
} else if (function->type == ZEND_INTERNAL_FUNCTION) {
if (function->common.function_name) {
- STR_ADDREF(function->common.function_name);
+ zend_string_addref(function->common.function_name);
}
}
}
@@ -3528,10 +1012,10 @@ static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC) /* {{{
zend_string *lc_class_name;
zend_string *lc_parent_class_name;
- lc_class_name = STR_ALLOC(ce->name->len, 0);
+ lc_class_name = zend_string_alloc(ce->name->len, 0);
zend_str_tolower_copy(lc_class_name->val, ce->name->val, ce->name->len);
if (!zend_hash_exists(&ce->function_table, lc_class_name)) {
- lc_parent_class_name = STR_ALLOC(ce->parent->name->len, 0);
+ lc_parent_class_name = zend_string_alloc(ce->parent->name->len, 0);
zend_str_tolower_copy(lc_parent_class_name->val, ce->parent->name->val, ce->parent->name->len);
if (!zend_hash_exists(&ce->function_table, lc_parent_class_name) &&
(function = zend_hash_find_ptr(&ce->parent->function_table, lc_parent_class_name)) != NULL) {
@@ -3543,15 +1027,15 @@ static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC) /* {{{
function_add_ref(new_function);
}
}
- STR_RELEASE(lc_parent_class_name);
+ zend_string_release(lc_parent_class_name);
}
- STR_FREE(lc_class_name);
+ zend_string_free(lc_class_name);
}
ce->constructor = ce->parent->constructor;
}
/* }}} */
-char *zend_visibility_string(zend_uint fn_flags) /* {{{ */
+char *zend_visibility_string(uint32_t fn_flags) /* {{{ */
{
if (fn_flags & ZEND_ACC_PRIVATE) {
return "private";
@@ -3588,7 +1072,7 @@ static zend_function *do_inherit_method(zend_function *old_function TSRMLS_DC) /
static zend_bool zend_do_perform_implementation_check(const zend_function *fe, const zend_function *proto TSRMLS_DC) /* {{{ */
{
- zend_uint i, num_args;
+ uint32_t i, num_args;
/* If it's a user function then arg_info == NULL means we don't have any parameters but
* we still need to do the arg number checks. We are only willing to ignore this for internal
@@ -3634,7 +1118,7 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
* go through all the parameters of the function and not just those present in the
* prototype. */
num_args = proto->common.num_args;
- if ((fe->common.fn_flags & ZEND_ACC_VARIADIC)
+ if ((proto->common.fn_flags & ZEND_ACC_VARIADIC)
&& fe->common.num_args > proto->common.num_args) {
num_args = fe->common.num_args;
}
@@ -3658,21 +1142,21 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
zend_string *fe_class_name, *proto_class_name;
if (!strcasecmp(fe_arg_info->class_name, "parent") && proto->common.scope) {
- fe_class_name = STR_COPY(proto->common.scope->name);
+ fe_class_name = zend_string_copy(proto->common.scope->name);
} else if (!strcasecmp(fe_arg_info->class_name, "self") && fe->common.scope) {
- fe_class_name = STR_COPY(fe->common.scope->name);
+ fe_class_name = zend_string_copy(fe->common.scope->name);
} else {
- fe_class_name = STR_INIT(
+ fe_class_name = zend_string_init(
fe_arg_info->class_name,
fe_arg_info->class_name_len, 0);
}
if (!strcasecmp(proto_arg_info->class_name, "parent") && proto->common.scope && proto->common.scope->parent) {
- proto_class_name = STR_COPY(proto->common.scope->parent->name);
+ proto_class_name = zend_string_copy(proto->common.scope->parent->name);
} else if (!strcasecmp(proto_arg_info->class_name, "self") && proto->common.scope) {
- proto_class_name = STR_COPY(proto->common.scope->name);
+ proto_class_name = zend_string_copy(proto->common.scope->name);
} else {
- proto_class_name = STR_INIT(
+ proto_class_name = zend_string_init(
proto_arg_info->class_name,
proto_arg_info->class_name_len, 0);
}
@@ -3681,8 +1165,8 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
const char *colon;
if (fe->common.type != ZEND_USER_FUNCTION) {
- STR_RELEASE(proto_class_name);
- STR_RELEASE(fe_class_name);
+ zend_string_release(proto_class_name);
+ zend_string_release(fe_class_name);
return 0;
} else if (strchr(proto_class_name->val, '\\') != NULL ||
(colon = zend_memrchr(fe_class_name->val, '\\', fe_class_name->len)) == NULL ||
@@ -3697,14 +1181,14 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
fe_ce->type == ZEND_INTERNAL_CLASS ||
proto_ce->type == ZEND_INTERNAL_CLASS ||
fe_ce != proto_ce) {
- STR_RELEASE(proto_class_name);
- STR_RELEASE(fe_class_name);
+ zend_string_release(proto_class_name);
+ zend_string_release(fe_class_name);
return 0;
}
}
}
- STR_RELEASE(proto_class_name);
- STR_RELEASE(fe_class_name);
+ zend_string_release(proto_class_name);
+ zend_string_release(fe_class_name);
}
if (fe_arg_info->type_hint != proto_arg_info->type_hint) {
/* Incompatible type hint */
@@ -3727,10 +1211,10 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
buf = erealloc(buf, length); \
}
-static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{{ */
+static char *zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{{ */
{
char *offset, *buf;
- zend_uint length = 1024;
+ uint32_t length = 1024;
offset = buf = (char *)emalloc(length * sizeof(char));
if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
@@ -3754,14 +1238,14 @@ static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{
*(offset++) = '(';
if (fptr->common.arg_info) {
- zend_uint i, required;
+ uint32_t i, required;
zend_arg_info *arg_info = fptr->common.arg_info;
required = fptr->common.required_num_args;
for (i = 0; i < fptr->common.num_args;) {
if (arg_info->class_name) {
const char *class_name;
- zend_uint class_name_len;
+ uint32_t class_name_len;
if (!strcasecmp(arg_info->class_name, "self") && fptr->common.scope ) {
class_name = fptr->common.scope->name->val;
class_name_len = fptr->common.scope->name->len;
@@ -3777,7 +1261,7 @@ static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{
offset += class_name_len;
*(offset++) = ' ';
} else if (arg_info->type_hint) {
- zend_uint type_name_len;
+ uint32_t type_name_len;
char *type_name = zend_get_type_by_const(arg_info->type_hint);
type_name_len = strlen(type_name);
REALLOC_BUF_IF_EXCEED(buf, offset, length, type_name_len);
@@ -3803,7 +1287,7 @@ static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{
memcpy(offset, arg_info->name, arg_info->name_len);
offset += arg_info->name_len;
} else {
- zend_uint idx = i;
+ uint32_t idx = i;
memcpy(offset, "param", 5);
offset += 5;
do {
@@ -3818,14 +1302,14 @@ static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{
if (fptr->type == ZEND_USER_FUNCTION) {
zend_op *precv = NULL;
{
- zend_uint idx = i;
+ uint32_t idx = i;
zend_op *op = ((zend_op_array *)fptr)->opcodes;
zend_op *end = op + ((zend_op_array *)fptr)->last;
++idx;
while (op < end) {
if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
- && op->op1.num == (long)idx)
+ && op->op1.num == (zend_ulong)idx)
{
precv = op;
}
@@ -3870,7 +1354,7 @@ static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{
REALLOC_BUF_IF_EXCEED(buf, offset, length, str->len);
memcpy(offset, str->val, str->len);
offset += str->len;
- STR_RELEASE(str);
+ zend_string_release(str);
}
}
} else {
@@ -3896,8 +1380,8 @@ static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{
static void do_inheritance_check_on_method(zend_function *child, zend_function *parent TSRMLS_DC) /* {{{ */
{
- zend_uint child_flags;
- zend_uint parent_flags = parent->common.fn_flags;
+ uint32_t child_flags;
+ uint32_t parent_flags = parent->common.fn_flags;
if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
&& parent->common.fn_flags & ZEND_ACC_ABSTRACT
@@ -3968,7 +1452,7 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, zend_string *key, zend_class_entry *child_ce) /* {{{ */
{
- zend_uint parent_flags = parent->common.fn_flags;
+ uint32_t parent_flags = parent->common.fn_flags;
zend_function *child;
TSRMLS_FETCH();
@@ -4047,7 +1531,7 @@ static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry
ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC) /* {{{ */
{
/* expects interface to be contained in ce's interface list already */
- zend_uint i, ce_num, if_num = iface->num_interfaces;
+ uint32_t i, ce_num, if_num = iface->num_interfaces;
zend_class_entry *entry;
if (if_num==0) {
@@ -4286,9 +1770,9 @@ static void do_inherit_iface_constant(zend_string *name, zval *zv, zend_class_en
ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
{
- zend_uint i, ignore = 0;
- zend_uint current_iface_num = ce->num_interfaces;
- zend_uint parent_iface_num = ce->parent ? ce->parent->num_interfaces : 0;
+ uint32_t i, ignore = 0;
+ uint32_t current_iface_num = ce->num_interfaces;
+ uint32_t parent_iface_num = ce->parent ? ce->parent->num_interfaces : 0;
zend_function *func;
zend_string *key;
zval *zv;
@@ -4339,9 +1823,9 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC) /* {{{ */
{
- zend_uint i, ignore = 0;
- zend_uint current_trait_num = ce->num_traits;
- zend_uint parent_trait_num = ce->parent ? ce->parent->num_traits : 0;
+ uint32_t i, ignore = 0;
+ uint32_t current_trait_num = ce->num_traits;
+ uint32_t parent_trait_num = ce->parent ? ce->parent->num_traits : 0;
for (i = 0; i < ce->num_traits; i++) {
if (ce->traits[i] == NULL) {
@@ -4368,8 +1852,8 @@ ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *tr
static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_function *other_fn TSRMLS_DC) /* {{{ */
{
- zend_uint fn_flags = fn->common.scope->ce_flags;
- zend_uint other_flags = other_fn->common.scope->ce_flags;
+ uint32_t fn_flags = fn->common.scope->ce_flags;
+ uint32_t other_flags = other_fn->common.scope->ce_flags;
return zend_do_perform_implementation_check(fn, other_fn TSRMLS_CC)
&& ((other_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) || zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC))
@@ -4406,7 +1890,7 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen
} else if (!strncmp(mname->val, ZEND_DEBUGINFO_FUNC_NAME, mname->len)) {
ce->__debugInfo = fe;
} else if (ce->name->len == mname->len) {
- zend_string *lowercase_name = STR_ALLOC(ce->name->len, 0);
+ zend_string *lowercase_name = zend_string_alloc(ce->name->len, 0);
zend_str_tolower_copy(lowercase_name->val, ce->name->val, ce->name->len);
lowercase_name = zend_new_interned_string(lowercase_name TSRMLS_CC);
if (!memcmp(mname->val, lowercase_name->val, mname->len)) {
@@ -4416,7 +1900,7 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen
ce->constructor = fe;
fe->common.fn_flags |= ZEND_ACC_CTOR;
}
- STR_RELEASE(lowercase_name);
+ zend_string_release(lowercase_name);
}
}
/* }}} */
@@ -4453,7 +1937,7 @@ static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_s
ALLOC_HASHTABLE(*overriden);
zend_hash_init_ex(*overriden, 8, NULL, ptr_dtor, 0, 0);
}
- fn = zend_hash_update_mem(*overriden, key, fn, sizeof(zend_function));
+ zend_hash_update_mem(*overriden, key, fn, sizeof(zend_function));
return;
} else if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
/* Make sure the trait method is compatible with previosly declared abstract method */
@@ -4535,10 +2019,10 @@ static int zend_traits_copy_functions(zend_string *fnname, zend_function *fn, ze
fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
}
- lcname = STR_ALLOC(alias->alias->len, 0);
+ lcname = zend_string_alloc(alias->alias->len, 0);
zend_str_tolower_copy(lcname->val, alias->alias->val, alias->alias->len);
zend_add_trait_method(ce, alias->alias->val, lcname, &fn_copy, overriden TSRMLS_CC);
- STR_RELEASE(lcname);
+ zend_string_release(lcname);
/* Record the trait from which this alias was resolved. */
if (!alias->trait_method->ce) {
@@ -4586,7 +2070,7 @@ static int zend_traits_copy_functions(zend_string *fnname, zend_function *fn, ze
static void zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC) /* {{{ */
{
- zend_uint i;
+ uint32_t i;
if ((trait->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) {
zend_error_noreturn(E_COMPILE_ERROR, "Class %s is not a trait, Only traits may be used in 'as' and 'insteadof' statements", trait->name->val);
@@ -4623,13 +2107,13 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /*
zend_check_trait_usage(ce, cur_precedence->trait_method->ce TSRMLS_CC);
/** Ensure that the prefered method is actually available. */
- lcname = STR_ALLOC(cur_method_ref->method_name->len, 0);
+ lcname = zend_string_alloc(cur_method_ref->method_name->len, 0);
zend_str_tolower_copy(lcname->val,
cur_method_ref->method_name->val,
cur_method_ref->method_name->len);
method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
lcname);
- STR_FREE(lcname);
+ zend_string_free(lcname);
if (!method_exists) {
zend_error_noreturn(E_COMPILE_ERROR,
"A precedence rule was defined for %s::%s but this method does not exist",
@@ -4663,7 +2147,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /*
cur_precedence->trait_method->ce->name->val);
}
- STR_RELEASE(class_name);
+ zend_string_release(class_name);
j++;
}
}
@@ -4683,13 +2167,13 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /*
zend_check_trait_usage(ce, cur_method_ref->ce TSRMLS_CC);
/** And, ensure that the referenced method is resolvable, too. */
- lcname = STR_ALLOC(cur_method_ref->method_name->len, 0);
+ lcname = zend_string_alloc(cur_method_ref->method_name->len, 0);
zend_str_tolower_copy(lcname->val,
cur_method_ref->method_name->val,
cur_method_ref->method_name->len);
method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
lcname);
- STR_FREE(lcname);
+ zend_string_free(lcname);
if (!method_exists) {
zend_error_noreturn(E_COMPILE_ERROR, "An alias was defined for %s::%s but this method does not exist", cur_method_ref->ce->name->val, cur_method_ref->method_name->val);
@@ -4713,16 +2197,16 @@ static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_tra
j = 0;
while (precedences[i]->exclude_from_classes[j].ce) {
if (precedences[i]->exclude_from_classes[j].ce == trait) {
- zend_string *lcname = STR_ALLOC(precedences[i]->trait_method->method_name->len, 0);
+ zend_string *lcname = zend_string_alloc(precedences[i]->trait_method->method_name->len, 0);
zend_str_tolower_copy(lcname->val,
precedences[i]->trait_method->method_name->val,
precedences[i]->trait_method->method_name->len);
if (zend_hash_add_empty_element(exclude_table, lcname) == NULL) {
- STR_RELEASE(lcname);
+ zend_string_release(lcname);
zend_error_noreturn(E_COMPILE_ERROR, "Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times", precedences[i]->trait_method->method_name->val, trait->name->val);
}
- STR_RELEASE(lcname);
+ zend_string_release(lcname);
}
++j;
}
@@ -4734,7 +2218,7 @@ static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_tra
static void zend_do_traits_method_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
{
- zend_uint i;
+ uint32_t i;
HashTable *overriden = NULL;
zend_string *key;
zend_function *fn;
@@ -4798,7 +2282,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {
const char* class_name_unused;
zend_bool not_compatible;
zval* prop_value;
- zend_uint flags;
+ uint32_t flags;
zend_string *doc_comment;
/* In the following steps the properties are inserted into the property table
@@ -4813,15 +2297,15 @@ static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {
*/
flags = property_info->flags;
if ((flags & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
- prop_name = STR_COPY(property_info->name);
+ prop_name = zend_string_copy(property_info->name);
} else {
const char *pname;
- int pname_len;
+ size_t pname_len;
/* for private and protected we need to unmangle the names */
- zend_unmangle_property_name_ex(property_info->name->val, property_info->name->len,
+ zend_unmangle_property_name_ex(property_info->name,
&class_name_unused, &pname, &pname_len);
- prop_name = STR_INIT(pname, pname_len, 0);
+ prop_name = zend_string_init(pname, pname_len, 0);
}
/* next: check for conflicts with current class */
@@ -4863,7 +2347,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {
property_info->ce->name->val,
prop_name->val,
ce->name->val);
- STR_RELEASE(prop_name);
+ zend_string_release(prop_name);
continue;
}
}
@@ -4877,11 +2361,11 @@ static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {
}
if (Z_REFCOUNTED_P(prop_value)) Z_ADDREF_P(prop_value);
- doc_comment = property_info->doc_comment ? STR_COPY(property_info->doc_comment) : NULL;
+ doc_comment = property_info->doc_comment ? zend_string_copy(property_info->doc_comment) : NULL;
zend_declare_property_ex(ce, prop_name,
prop_value, flags,
doc_comment TSRMLS_CC);
- STR_RELEASE(prop_name);
+ zend_string_release(prop_name);
} ZEND_HASH_FOREACH_END();
}
}
@@ -4914,19 +2398,19 @@ static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce
2) it is just a plain old inconsitency/typo/bug
as in the case where alias is set. */
- lc_method_name = STR_ALLOC(cur_alias->trait_method->method_name->len, 0);
+ lc_method_name = zend_string_alloc(cur_alias->trait_method->method_name->len, 0);
zend_str_tolower_copy(
lc_method_name->val,
cur_alias->trait_method->method_name->val,
cur_alias->trait_method->method_name->len);
if (zend_hash_exists(&ce->function_table,
lc_method_name)) {
- STR_FREE(lc_method_name);
+ zend_string_free(lc_method_name);
zend_error_noreturn(E_COMPILE_ERROR,
"The modifiers for the trait alias %s() need to be changed in the same statment in which the alias is defined. Error",
cur_alias->trait_method->method_name->val);
} else {
- STR_FREE(lc_method_name);
+ zend_string_free(lc_method_name);
zend_error_noreturn(E_COMPILE_ERROR,
"The modifiers of the trait method %s() are changed, but this method does not exist. Error",
cur_alias->trait_method->method_name->val);
@@ -4969,7 +2453,7 @@ ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC) /* {{{ */
}
/* }}} */
-ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
+ZEND_API int do_bind_function(const zend_op_array *op_array, const zend_op *opline, HashTable *function_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
{
zend_function *function, *new_function;
zval *op1, *op2;
@@ -4989,7 +2473,7 @@ ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, Ha
int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
zend_function *old_function;
- efree(new_function);
+ efree_size(new_function, sizeof(zend_op_array));
if ((old_function = zend_hash_find_ptr(function_table, Z_STR_P(op2))) != NULL
&& old_function->type == ZEND_USER_FUNCTION
&& old_function->op_array.last > 0) {
@@ -5009,67 +2493,6 @@ ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, Ha
}
/* }}} */
-void zend_prepare_reference(znode *result, znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
-{
- zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
- method_ref->ce = NULL;
-
- /* REM: There should not be a need for copying,
- zend_do_begin_class_declaration is also just using that string */
- if (class_name) {
- zend_resolve_class_name(class_name TSRMLS_CC);
- method_ref->class_name = Z_STR(class_name->u.constant);
- } else {
- method_ref->class_name = NULL;
- }
-
- method_ref->method_name = Z_STR(method_name->u.constant);
-
- result->u.op.ptr = method_ref;
- result->op_type = IS_TMP_VAR;
-}
-/* }}} */
-
-void zend_add_trait_alias(znode *method_reference, znode *modifiers, znode *alias TSRMLS_DC) /* {{{ */
-{
- zend_class_entry *ce = CG(active_class_entry);
- zend_trait_alias *trait_alias;
-
- if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_STATIC) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier");
- return;
- } else if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_ABSTRACT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier");
- return;
- } else if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_FINAL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier");
- return;
- }
-
- trait_alias = emalloc(sizeof(zend_trait_alias));
- trait_alias->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
- trait_alias->modifiers = Z_LVAL(modifiers->u.constant);
- if (alias) {
- trait_alias->alias = Z_STR(alias->u.constant);
- } else {
- trait_alias->alias = NULL;
- }
- zend_add_to_list(&ce->trait_aliases, trait_alias TSRMLS_CC);
-}
-/* }}} */
-
-void zend_add_trait_precedence(znode *method_reference, znode *trait_list TSRMLS_DC) /* {{{ */
-{
- zend_class_entry *ce = CG(active_class_entry);
- zend_trait_precedence *trait_precedence = emalloc(sizeof(zend_trait_precedence));
-
- trait_precedence->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
- trait_precedence->exclude_from_classes = trait_list->u.op.ptr;
-
- zend_add_to_list(&ce->trait_precedences, trait_precedence TSRMLS_CC);
-}
-/* }}} */
-
ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
{
zend_class_entry *ce;
@@ -5185,7 +2608,7 @@ void zend_do_early_binding(TSRMLS_D) /* {{{ */
((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
(ce->type == ZEND_INTERNAL_CLASS))) {
if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
- zend_uint *opline_num = &CG(active_op_array)->early_binding;
+ uint32_t *opline_num = &CG(active_op_array)->early_binding;
while (*opline_num != -1) {
opline_num = &CG(active_op_array)->opcodes[*opline_num].result.opline_num;
@@ -5230,7 +2653,7 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS
{
if (op_array->early_binding != -1) {
zend_bool orig_in_compilation = CG(in_compilation);
- zend_uint opline_num = op_array->early_binding;
+ uint32_t opline_num = op_array->early_binding;
zend_class_entry *ce;
CG(in_compilation) = 1;
@@ -5245,1315 +2668,1943 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS
}
/* }}} */
-void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
+ZEND_API zend_string *zend_mangle_property_name(const char *src1, size_t src1_length, const char *src2, size_t src2_length, int internal) /* {{{ */
{
- int next_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ size_t prop_name_length = 1 + src1_length + 1 + src2_length;
+ zend_string *prop_name = zend_string_alloc(prop_name_length, internal);
- opline->opcode = ZEND_JMPNZ_EX;
- if (expr1->op_type == IS_TMP_VAR) {
- SET_NODE(opline->result, expr1);
- } else {
- opline->result.var = get_temporary_variable(CG(active_op_array));
- opline->result_type = IS_TMP_VAR;
+ prop_name->val[0] = '\0';
+ memcpy(prop_name->val + 1, src1, src1_length+1);
+ memcpy(prop_name->val + 1 + src1_length + 1, src2, src2_length+1);
+ return prop_name;
+}
+/* }}} */
+
+static int zend_strnlen(const char* s, size_t maxlen) /* {{{ */
+{
+ size_t len = 0;
+ while (*s++ && maxlen--) len++;
+ return len;
+}
+/* }}} */
+
+ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char **class_name, const char **prop_name, size_t *prop_len) /* {{{ */
+{
+ size_t class_name_len;
+
+ *class_name = NULL;
+
+ if (name->val[0] != '\0') {
+ *prop_name = name->val;
+ if (prop_len) {
+ *prop_len = name->len;
+ }
+ return SUCCESS;
+ }
+ if (name->len < 3 || name->val[1] == '\0') {
+ zend_error(E_NOTICE, "Illegal member variable name");
+ *prop_name = name->val;
+ if (prop_len) {
+ *prop_len = name->len;
+ }
+ return FAILURE;
}
- SET_NODE(opline->op1, expr1);
- SET_UNUSED(opline->op2);
- op_token->u.op.opline_num = next_op_number;
+ class_name_len = zend_strnlen(name->val + 1, name->len - 2);
+ if (class_name_len >= name->len - 2 || name->val[class_name_len + 1] != '\0') {
+ zend_error(E_NOTICE, "Corrupt member variable name");
+ *prop_name = name->val;
+ if (prop_len) {
+ *prop_len = name->len;
+ }
+ return FAILURE;
+ }
- GET_NODE(expr1, opline->result);
+ *class_name = name->val + 1;
+ *prop_name = name->val + class_name_len + 2;
+ if (prop_len) {
+ *prop_len = name->len - class_name_len - 2;
+ }
+ return SUCCESS;
}
/* }}} */
-void zend_do_boolean_or_end(znode *result, znode *expr1, znode *expr2, const znode *op_token TSRMLS_DC) /* {{{ */
+static zend_constant *zend_get_ct_const(zend_string *name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_constant *c = NULL;
+ char *lookup_name;
- *result = *expr1; /* we saved the original result in expr1 */
- opline->opcode = ZEND_BOOL;
- SET_NODE(opline->result, result);
- SET_NODE(opline->op1, expr2);
- SET_UNUSED(opline->op2);
+ if (name->val[0] == '\\') {
+ c = zend_hash_str_find_ptr(EG(zend_constants), name->val + 1, name->len - 1);
+ if (!c) {
+ lookup_name = zend_str_tolower_dup(name->val + 1, name->len - 1);
+ c = zend_hash_str_find_ptr(EG(zend_constants), lookup_name, name->len - 1);
+ efree(lookup_name);
+
+ if (c && (c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
+ return c;
+ }
+ return NULL;
+ }
+ } else if ((c = zend_hash_find_ptr(EG(zend_constants), name)) == NULL) {
+ lookup_name = zend_str_tolower_dup(name->val, name->len);
+ c = zend_hash_str_find_ptr(EG(zend_constants), lookup_name, name->len);
+ efree(lookup_name);
- CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
+ if (c && (c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
+ return c;
+ }
+ return NULL;
+ }
+
+ if (c->flags & CONST_CT_SUBST) {
+ return c;
+ }
+ if (all_internal_constants_substitution &&
+ (c->flags & CONST_PERSISTENT) &&
+ !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
+ !Z_CONSTANT(c->value)) {
+ return c;
+ }
+ return NULL;
}
/* }}} */
-void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
+static int zend_constant_ct_subst(znode *result, zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
{
- int next_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_constant *c = zend_get_ct_const(Z_STR_P(const_name),
+ all_internal_constants_substitution TSRMLS_CC);
- opline->opcode = ZEND_JMPZ_EX;
- if (expr1->op_type == IS_TMP_VAR) {
- SET_NODE(opline->result, expr1);
- } else {
- opline->result.var = get_temporary_variable(CG(active_op_array));
- opline->result_type = IS_TMP_VAR;
+ if (c) {
+ result->op_type = IS_CONST;
+ ZVAL_DUP(&result->u.constant, &c->value);
+ return 1;
+ }
+ return 0;
+}
+/* }}} */
+
+void zend_init_list(void *result, void *item TSRMLS_DC) /* {{{ */
+{
+ void** list = emalloc(sizeof(void*) * 2);
+
+ list[0] = item;
+ list[1] = NULL;
+
+ *(void**)result = list;
+}
+/* }}} */
+
+void zend_add_to_list(void *result, void *item TSRMLS_DC) /* {{{ */
+{
+ void** list = *(void**)result;
+ size_t n = 0;
+
+ if (list) {
+ while (list[n]) {
+ n++;
+ }
+ }
+
+ list = erealloc(list, sizeof(void*) * (n+2));
+
+ list[n] = item;
+ list[n+1] = NULL;
+
+ *(void**)result = list;
+}
+/* }}} */
+
+void zend_do_extended_info(TSRMLS_D) /* {{{ */
+{
+ zend_op *opline;
+
+ if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
+ return;
}
- SET_NODE(opline->op1, expr1);
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+
+ opline->opcode = ZEND_EXT_STMT;
+ SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
+}
+/* }}} */
- op_token->u.op.opline_num = next_op_number;
+void zend_do_extended_fcall_begin(TSRMLS_D) /* {{{ */
+{
+ zend_op *opline;
- GET_NODE(expr1, opline->result);
+ if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
+ return;
+ }
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+
+ opline->opcode = ZEND_EXT_FCALL_BEGIN;
+ SET_UNUSED(opline->op1);
+ SET_UNUSED(opline->op2);
}
/* }}} */
-void zend_do_boolean_and_end(znode *result, znode *expr1, znode *expr2, const znode *op_token TSRMLS_DC) /* {{{ */
+void zend_do_extended_fcall_end(TSRMLS_D) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_op *opline;
+
+ if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
+ return;
+ }
- *result = *expr1; /* we saved the original result in expr1 */
- opline->opcode = ZEND_BOOL;
- SET_NODE(opline->result, result);
- SET_NODE(opline->op1, expr2);
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+
+ opline->opcode = ZEND_EXT_FCALL_END;
+ SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
+}
+/* }}} */
- CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
+zend_bool zend_is_auto_global(zend_string *name TSRMLS_DC) /* {{{ */
+{
+ zend_auto_global *auto_global;
+
+ if ((auto_global = zend_hash_find_ptr(CG(auto_globals), name)) != NULL) {
+ if (auto_global->armed) {
+ auto_global->armed = auto_global->auto_global_callback(auto_global->name TSRMLS_CC);
+ }
+ return 1;
+ }
+ return 0;
}
/* }}} */
-void zend_do_do_while_begin(TSRMLS_D) /* {{{ */
+int zend_register_auto_global(zend_string *name, zend_bool jit, zend_auto_global_callback auto_global_callback TSRMLS_DC) /* {{{ */
{
- do_begin_loop(TSRMLS_C);
- INC_BPC(CG(active_op_array));
+ zend_auto_global auto_global;
+ int retval;
+
+ auto_global.name = zend_new_interned_string(name TSRMLS_CC);
+ auto_global.auto_global_callback = auto_global_callback;
+ auto_global.jit = jit;
+
+ retval = zend_hash_add_mem(CG(auto_globals), name, &auto_global, sizeof(zend_auto_global)) != NULL ? SUCCESS : FAILURE;
+
+ zend_string_release(auto_global.name);
+ return retval;
}
/* }}} */
-void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, znode *expr TSRMLS_DC) /* {{{ */
+ZEND_API void zend_activate_auto_globals(TSRMLS_D) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_auto_global *auto_global;
- opline->opcode = ZEND_JMPNZ;
- SET_NODE(opline->op1, expr);
- opline->op2.opline_num = do_token->u.op.opline_num;
- SET_UNUSED(opline->op2);
+ ZEND_HASH_FOREACH_PTR(CG(auto_globals), auto_global) {
+ if (auto_global->jit) {
+ auto_global->armed = 1;
+ } else if (auto_global->auto_global_callback) {
+ auto_global->armed = auto_global->auto_global_callback(auto_global->name TSRMLS_CC);
+ } else {
+ auto_global->armed = 0;
+ }
+ } ZEND_HASH_FOREACH_END();
+}
+/* }}} */
+
+int zendlex(zend_parser_stack_elem *elem TSRMLS_DC) /* {{{ */
+{
+ zval zv;
+ int retval;
+
+ if (CG(increment_lineno)) {
+ CG(zend_lineno)++;
+ CG(increment_lineno) = 0;
+ }
- do_end_loop(expr_open_bracket->u.op.opline_num, 0 TSRMLS_CC);
+again:
+ ZVAL_UNDEF(&zv);
+ retval = lex_scan(&zv TSRMLS_CC);
+ switch (retval) {
+ case T_COMMENT:
+ case T_DOC_COMMENT:
+ case T_OPEN_TAG:
+ case T_WHITESPACE:
+ goto again;
- DEC_BPC(CG(active_op_array));
+ case T_CLOSE_TAG:
+ if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') {
+ CG(increment_lineno) = 1;
+ }
+ if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
+ goto again;
+ }
+ retval = ';'; /* implicit ; */
+ break;
+ case T_OPEN_TAG_WITH_ECHO:
+ retval = T_ECHO;
+ break;
+ }
+ if (Z_TYPE(zv) != IS_UNDEF) {
+ elem->ast = zend_ast_create_zval(&zv);
+ }
+
+ return retval;
}
/* }}} */
-void zend_do_brk_cont(zend_uchar op, znode *expr TSRMLS_DC) /* {{{ */
+ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
+ dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
- opline->opcode = op;
- opline->op1.opline_num = CG(context).current_brk_cont;
- SET_UNUSED(opline->op1);
- if (expr) {
- if (expr->op_type != IS_CONST) {
- zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand is no longer supported", op == ZEND_BRK ? "break" : "continue");
- } else if (Z_TYPE(expr->u.constant) != IS_LONG || Z_LVAL(expr->u.constant) < 1) {
- zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers", op == ZEND_BRK ? "break" : "continue");
+ ce->refcount = 1;
+ ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
+
+ ce->default_properties_table = NULL;
+ ce->default_static_members_table = NULL;
+ zend_hash_init_ex(&ce->properties_info, 8, NULL, (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
+ zend_hash_init_ex(&ce->constants_table, 8, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
+ zend_hash_init_ex(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
+
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+#ifdef ZTS
+ int n = zend_hash_num_elements(CG(class_table));
+
+ if (CG(static_members_table) && n >= CG(last_static_member)) {
+ /* Support for run-time declaration: dl() */
+ CG(last_static_member) = n+1;
+ CG(static_members_table) = realloc(CG(static_members_table), (n+1)*sizeof(zval*));
+ CG(static_members_table)[n] = NULL;
}
- SET_NODE(opline->op2, expr);
+ ce->static_members_table = (zval*)(zend_intptr_t)n;
+#else
+ ce->static_members_table = NULL;
+#endif
} else {
- LITERAL_LONG(opline->op2, 1);
- opline->op2_type = IS_CONST;
+ ce->static_members_table = ce->default_static_members_table;
+ ce->info.user.doc_comment = NULL;
+ }
+
+ ce->default_properties_count = 0;
+ ce->default_static_members_count = 0;
+
+ if (nullify_handlers) {
+ ce->constructor = NULL;
+ ce->destructor = NULL;
+ ce->clone = NULL;
+ ce->__get = NULL;
+ ce->__set = NULL;
+ ce->__unset = NULL;
+ ce->__isset = NULL;
+ ce->__call = NULL;
+ ce->__callstatic = NULL;
+ ce->__tostring = NULL;
+ ce->create_object = NULL;
+ ce->get_iterator = NULL;
+ ce->iterator_funcs.funcs = NULL;
+ ce->interface_gets_implemented = NULL;
+ ce->get_static_method = NULL;
+ ce->parent = NULL;
+ ce->num_interfaces = 0;
+ ce->interfaces = NULL;
+ ce->num_traits = 0;
+ ce->traits = NULL;
+ ce->trait_aliases = NULL;
+ ce->trait_precedences = NULL;
+ ce->serialize = NULL;
+ ce->unserialize = NULL;
+ ce->serialize_func = NULL;
+ ce->unserialize_func = NULL;
+ ce->__debugInfo = NULL;
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ ce->info.internal.module = NULL;
+ ce->info.internal.builtin_functions = NULL;
+ }
}
}
/* }}} */
-void zend_do_switch_cond(const znode *cond TSRMLS_DC) /* {{{ */
+uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
{
- zend_switch_entry switch_entry;
+ if (zend_string_equals_literal_ci(name, "self")) {
+ return ZEND_FETCH_CLASS_SELF;
+ } else if (zend_string_equals_literal_ci(name, "parent")) {
+ return ZEND_FETCH_CLASS_PARENT;
+ } else if (zend_string_equals_literal_ci(name, "static")) {
+ return ZEND_FETCH_CLASS_STATIC;
+ } else {
+ return ZEND_FETCH_CLASS_DEFAULT;
+ }
+}
+/* }}} */
- switch_entry.cond = *cond;
- switch_entry.default_case = -1;
- switch_entry.control_var = -1;
- zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry);
+ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var) /* {{{ */
+{
+ return op_array->vars[EX_VAR_TO_NUM(var)];
+}
+/* }}} */
+
+zend_ast *zend_ast_append_str(zend_ast *left_ast, zend_ast *right_ast) /* {{{ */
+{
+ zval *left_zv = zend_ast_get_zval(left_ast);
+ zend_string *left = Z_STR_P(left_zv);
+ zend_string *right = zend_ast_get_str(right_ast);
+
+ zend_string *result;
+ size_t left_len = left->len;
+ size_t len = left_len + right->len + 1; /* left\right */
- do_begin_loop(TSRMLS_C);
+ result = zend_string_realloc(left, len, 0);
+ result->val[left_len] = '\\';
+ memcpy(&result->val[left_len + 1], right->val, right->len);
+ result->val[len] = '\0';
+ zend_string_release(right);
- INC_BPC(CG(active_op_array));
+ ZVAL_STR(left_zv, result);
+ return left_ast;
}
/* }}} */
-void zend_do_switch_end(const znode *case_list TSRMLS_DC) /* {{{ */
+/* A hacky way that is used to store the doc comment for properties */
+zend_ast *zend_ast_append_doc_comment(zend_ast *list TSRMLS_DC) /* {{{ */
{
- zend_op *opline;
- zend_switch_entry *switch_entry_ptr = zend_stack_top(&CG(switch_cond_stack));
+ if (CG(doc_comment)) {
+ list = zend_ast_list_add(list, zend_ast_create_zval_from_str(CG(doc_comment)));
+ CG(doc_comment) = NULL;
+ }
- /* add code to jmp to default case */
- if (switch_entry_ptr->default_case != -1) {
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_JMP;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- opline->op1.opline_num = switch_entry_ptr->default_case;
+ return list;
+}
+/* }}} */
+
+void zend_verify_namespace(TSRMLS_D) /* {{{ */
+{
+ if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
}
+}
+/* }}} */
- if (case_list->op_type != IS_UNUSED) { /* non-empty switch */
- int next_op_number = get_next_op_number(CG(active_op_array));
+static void zend_reset_import_tables(TSRMLS_D) /* {{{ */
+{
+ if (CG(current_import)) {
+ zend_hash_destroy(CG(current_import));
+ efree(CG(current_import));
+ CG(current_import) = NULL;
+ }
- CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
+ if (CG(current_import_function)) {
+ zend_hash_destroy(CG(current_import_function));
+ efree(CG(current_import_function));
+ CG(current_import_function) = NULL;
}
- /* remember break/continue loop information */
- CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
- CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
+ if (CG(current_import_const)) {
+ zend_hash_destroy(CG(current_import_const));
+ efree(CG(current_import_const));
+ CG(current_import_const) = NULL;
+ }
+}
+/* }}} */
- if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
- /* emit free for the switch condition*/
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = (switch_entry_ptr->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
- SET_NODE(opline->op1, &switch_entry_ptr->cond);
- SET_UNUSED(opline->op2);
+static void zend_end_namespace(TSRMLS_D) /* {{{ */ {
+ CG(in_namespace) = 0;
+ zend_reset_import_tables(TSRMLS_C);
+ if (CG(current_namespace)) {
+ zend_string_release(CG(current_namespace));
+ CG(current_namespace) = NULL;
+ }
+}
+/* }}} */
+
+void zend_do_end_compilation(TSRMLS_D) /* {{{ */
+{
+ CG(has_bracketed_namespaces) = 0;
+ zend_end_namespace(TSRMLS_C);
+}
+/* }}} */
+
+/* {{{ zend_dirname
+ Returns directory name component of path */
+ZEND_API size_t zend_dirname(char *path, size_t len)
+{
+ register char *end = path + len - 1;
+ unsigned int len_adjust = 0;
+
+#ifdef PHP_WIN32
+ /* Note that on Win32 CWD is per drive (heritage from CP/M).
+ * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
+ */
+ if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
+ /* Skip over the drive spec (if any) so as not to change */
+ path += 2;
+ len_adjust += 2;
+ if (2 == len) {
+ /* Return "c:" on Win32 for dirname("c:").
+ * It would be more consistent to return "c:."
+ * but that would require making the string *longer*.
+ */
+ return len;
+ }
}
- if (switch_entry_ptr->cond.op_type == IS_CONST) {
- zval_dtor(&switch_entry_ptr->cond.u.constant);
+#elif defined(NETWARE)
+ /*
+ * Find the first occurrence of : from the left
+ * move the path pointer to the position just after :
+ * increment the len_adjust to the length of path till colon character(inclusive)
+ * If there is no character beyond : simple return len
+ */
+ char *colonpos = NULL;
+ colonpos = strchr(path, ':');
+ if (colonpos != NULL) {
+ len_adjust = ((colonpos - path) + 1);
+ path += len_adjust;
+ if (len_adjust == len) {
+ return len;
+ }
}
+#endif
- zend_stack_del_top(&CG(switch_cond_stack));
+ if (len == 0) {
+ /* Illegal use of this function */
+ return 0;
+ }
- DEC_BPC(CG(active_op_array));
+ /* Strip trailing slashes */
+ while (end >= path && IS_SLASH_P(end)) {
+ end--;
+ }
+ if (end < path) {
+ /* The path only contained slashes */
+ path[0] = DEFAULT_SLASH;
+ path[1] = '\0';
+ return 1 + len_adjust;
+ }
+
+ /* Strip filename */
+ while (end >= path && !IS_SLASH_P(end)) {
+ end--;
+ }
+ if (end < path) {
+ /* No slash found, therefore return '.' */
+#ifdef NETWARE
+ if (len_adjust == 0) {
+ path[0] = '.';
+ path[1] = '\0';
+ return 1; /* only one character */
+ } else {
+ path[0] = '\0';
+ return len_adjust;
+ }
+#else
+ path[0] = '.';
+ path[1] = '\0';
+ return 1 + len_adjust;
+#endif
+ }
+
+ /* Strip slashes which came before the file name */
+ while (end >= path && IS_SLASH_P(end)) {
+ end--;
+ }
+ if (end < path) {
+ path[0] = DEFAULT_SLASH;
+ path[1] = '\0';
+ return 1 + len_adjust;
+ }
+ *(end+1) = '\0';
+
+ return (size_t)(end + 1 - path) + len_adjust;
}
/* }}} */
-void zend_do_case_before_statement(const znode *case_list, znode *case_token, znode *case_expr TSRMLS_DC) /* {{{ */
+static inline zend_bool zend_string_equals_str_ci(zend_string *str1, zend_string *str2) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- int next_op_number;
- zend_switch_entry *switch_entry_ptr = zend_stack_top(&CG(switch_cond_stack));
- znode result;
+ return str1->len == str2->len
+ && !zend_binary_strcasecmp(str1->val, str1->len, str2->val, str2->len);
+}
+/* }}} */
- if (switch_entry_ptr->control_var == -1) {
- switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array));
+static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
+{
+ switch (type & BP_VAR_MASK) {
+ case BP_VAR_R:
+ return;
+ case BP_VAR_W:
+ opline->opcode += 3;
+ return;
+ case BP_VAR_REF:
+ opline->opcode += 3;
+ opline->extended_value |= ZEND_FETCH_MAKE_REF;
+ return;
+ case BP_VAR_RW:
+ opline->opcode += 6;
+ return;
+ case BP_VAR_IS:
+ opline->opcode += 9;
+ return;
+ case BP_VAR_FUNC_ARG:
+ opline->opcode += 12;
+ opline->extended_value |= type >> BP_VAR_SHIFT;
+ return;
+ case BP_VAR_UNSET:
+ opline->opcode += 15;
+ return;
+ EMPTY_SWITCH_DEFAULT_CASE()
}
- opline->opcode = ZEND_CASE;
- opline->result.var = switch_entry_ptr->control_var;
+}
+/* }}} */
+
+static inline void zend_make_var_result(znode *result, zend_op *opline TSRMLS_DC) /* {{{ */
+{
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, opline->result);
+}
+/* }}} */
+
+static inline void zend_make_tmp_result(znode *result, zend_op *opline TSRMLS_DC) /* {{{ */
+{
opline->result_type = IS_TMP_VAR;
- SET_NODE(opline->op1, &switch_entry_ptr->cond);
- SET_NODE(opline->op2, case_expr);
- if (opline->op1_type == IS_CONST) {
- zval_copy_ctor(&CONSTANT(opline->op1.constant));
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, opline->result);
+}
+/* }}} */
+
+static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
+{
+ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = opcode;
+
+ if (op1 == NULL) {
+ SET_UNUSED(opline->op1);
+ } else {
+ SET_NODE(opline->op1, op1);
}
- GET_NODE(&result, opline->result);
- next_op_number = get_next_op_number(CG(active_op_array));
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_JMPZ;
- SET_NODE(opline->op1, &result);
- SET_UNUSED(opline->op2);
- case_token->u.op.opline_num = next_op_number;
+ if (op2 == NULL) {
+ SET_UNUSED(opline->op2);
+ } else {
+ SET_NODE(opline->op2, op2);
+ }
- if (case_list->op_type==IS_UNUSED) {
- return;
+ if (result) {
+ zend_make_var_result(result, opline TSRMLS_CC);
}
- next_op_number = get_next_op_number(CG(active_op_array));
- CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
+ return opline;
}
/* }}} */
-void zend_do_case_after_statement(znode *result, const znode *case_token TSRMLS_DC) /* {{{ */
+static zend_op *zend_emit_op_tmp(znode *result, zend_uchar opcode, znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
{
- int next_op_number = get_next_op_number(CG(active_op_array));
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = opcode;
- opline->opcode = ZEND_JMP;
+ if (op1 == NULL) {
+ SET_UNUSED(opline->op1);
+ } else {
+ SET_NODE(opline->op1, op1);
+ }
+
+ if (op2 == NULL) {
+ SET_UNUSED(opline->op2);
+ } else {
+ SET_NODE(opline->op2, op2);
+ }
+
+ zend_make_tmp_result(result, opline TSRMLS_CC);
+
+ return opline;
+}
+/* }}} */
+
+static void zend_emit_tick(TSRMLS_D) /* {{{ */
+{
+ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+
+ opline->opcode = ZEND_TICKS;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
- result->u.op.opline_num = next_op_number;
+ opline->extended_value = Z_LVAL(CG(declarables).ticks);
+}
+/* }}} */
- switch (CG(active_op_array)->opcodes[case_token->u.op.opline_num].opcode) {
+static inline zend_op *zend_emit_op_data(znode *value TSRMLS_DC) /* {{{ */
+{
+ return zend_emit_op(NULL, ZEND_OP_DATA, value, NULL TSRMLS_CC);
+}
+/* }}} */
+
+static inline uint32_t zend_emit_jump(uint32_t opnum_target TSRMLS_DC) /* {{{ */
+{
+ uint32_t opnum = get_next_op_number(CG(active_op_array));
+ zend_op *opline = zend_emit_op(NULL, ZEND_JMP, NULL, NULL TSRMLS_CC);
+ opline->op1.opline_num = opnum_target;
+ return opnum;
+}
+/* }}} */
+
+static inline uint32_t zend_emit_cond_jump(zend_uchar opcode, znode *cond, uint32_t opnum_target TSRMLS_DC) /* {{{ */
+{
+ uint32_t opnum = get_next_op_number(CG(active_op_array));
+ zend_op *opline = zend_emit_op(NULL, opcode, cond, NULL TSRMLS_CC);
+ opline->op2.opline_num = opnum_target;
+ return opnum;
+}
+/* }}} */
+
+static inline void zend_update_jump_target(uint32_t opnum_jump, uint32_t opnum_target TSRMLS_DC) /* {{{ */
+{
+ zend_op *opline = &CG(active_op_array)->opcodes[opnum_jump];
+ switch (opline->opcode) {
case ZEND_JMP:
- CG(active_op_array)->opcodes[case_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
+ opline->op1.opline_num = opnum_target;
break;
case ZEND_JMPZ:
- CG(active_op_array)->opcodes[case_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
+ case ZEND_JMPNZ:
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+ opline->op2.opline_num = opnum_target;
break;
+ EMPTY_SWITCH_DEFAULT_CASE()
}
}
/* }}} */
-void zend_do_default_before_statement(const znode *case_list, znode *default_token TSRMLS_DC) /* {{{ */
+static inline void zend_update_jump_target_to_next(uint32_t opnum_jump TSRMLS_DC) /* {{{ */
{
- int next_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- zend_switch_entry *switch_entry_ptr = zend_stack_top(&CG(switch_cond_stack));
+ zend_update_jump_target(opnum_jump, get_next_op_number(CG(active_op_array)) TSRMLS_CC);
+}
+/* }}} */
- opline->opcode = ZEND_JMP;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- default_token->u.op.opline_num = next_op_number;
+static inline zend_op *zend_delayed_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
+{
+ zend_op tmp_opline;
+ init_op(&tmp_opline TSRMLS_CC);
+ tmp_opline.opcode = opcode;
+ SET_NODE(tmp_opline.op1, op1);
+ SET_NODE(tmp_opline.op2, op2);
+ if (result) {
+ zend_make_var_result(result, &tmp_opline TSRMLS_CC);
+ }
- next_op_number = get_next_op_number(CG(active_op_array));
- switch_entry_ptr->default_case = next_op_number;
+ zend_stack_push(&CG(delayed_oplines_stack), &tmp_opline);
+ return zend_stack_top(&CG(delayed_oplines_stack));
+}
+/* }}} */
- if (case_list->op_type==IS_UNUSED) {
- return;
- }
- CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
+static inline uint32_t zend_delayed_compile_begin(TSRMLS_D) /* {{{ */
+{
+ return zend_stack_count(&CG(delayed_oplines_stack));
}
/* }}} */
-void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC) /* {{{ */
+static zend_op *zend_delayed_compile_end(uint32_t offset TSRMLS_DC) /* {{{ */
{
- zend_op *opline;
- int doing_inheritance = 0;
- zend_class_entry *new_class_entry;
- zend_string *lcname;
- int error = 0;
- zval *ns_name, key;
+ zend_op *opline, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
+ uint32_t i, count = zend_stack_count(&CG(delayed_oplines_stack));
- if (CG(active_class_entry)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
- return;
+ ZEND_ASSERT(count > offset);
+ for (i = offset; i < count; ++i) {
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ memcpy(opline, &oplines[i], sizeof(zend_op));
}
+ CG(delayed_oplines_stack).top = offset;
+ return opline;
+}
+/* }}} */
- lcname = STR_ALLOC(Z_STRLEN(class_name->u.constant), 0);
- zend_str_tolower_copy(lcname->val, Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
+void zend_emit_final_return(zval *zv TSRMLS_DC) /* {{{ */
+{
+ znode zn;
+ zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
- if (!(strcmp(lcname->val, "self") && strcmp(lcname->val, "parent"))) {
- STR_FREE(lcname);
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", Z_STRVAL(class_name->u.constant));
+ zn.op_type = IS_CONST;
+ if (zv) {
+ ZVAL_COPY_VALUE(&zn.u.constant, zv);
+ } else {
+ ZVAL_NULL(&zn.u.constant);
}
- /* Class name must not conflict with import names */
- if (CG(current_import) &&
- (ns_name = zend_hash_find(CG(current_import), lcname)) != NULL) {
- error = 1;
- }
+ zend_emit_op(NULL, returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN, &zn, NULL TSRMLS_CC);
+}
+/* }}} */
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- /* Prefix class name with name of current namespace */
- znode tmp;
+static inline zend_bool zend_is_variable(zend_ast *ast) /* {{{ */
+{
+ return ast->kind == ZEND_AST_VAR || ast->kind == ZEND_AST_DIM
+ || ast->kind == ZEND_AST_PROP || ast->kind == ZEND_AST_STATIC_PROP
+ || ast->kind == ZEND_AST_CALL || ast->kind == ZEND_AST_METHOD_CALL
+ || ast->kind == ZEND_AST_STATIC_CALL;
+}
+/* }}} */
- tmp.op_type = IS_CONST;
- ZVAL_DUP(&tmp.u.constant, &CG(current_namespace));
- zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
- *class_name = tmp;
- STR_FREE(lcname);
- lcname = STR_ALLOC(Z_STRLEN(class_name->u.constant), 0);
- zend_str_tolower_copy(lcname->val, Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
- }
+static inline zend_bool zend_is_call(zend_ast *ast) /* {{{ */
+{
+ return ast->kind == ZEND_AST_CALL
+ || ast->kind == ZEND_AST_METHOD_CALL
+ || ast->kind == ZEND_AST_STATIC_CALL;
+}
+/* }}} */
- if (error) {
- char *tmp = zend_str_tolower_dup(Z_STRVAL_P(ns_name), Z_STRLEN_P(ns_name));
+static inline zend_bool zend_is_unticked_stmt(zend_ast *ast) /* {{{ */
+{
+ return ast->kind == ZEND_AST_STMT_LIST || ast->kind == ZEND_AST_LABEL;
+}
+/* }}} */
- if (Z_STRLEN_P(ns_name) != Z_STRLEN(class_name->u.constant) ||
- memcmp(tmp, lcname->val, Z_STRLEN(class_name->u.constant))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s because the name is already in use", Z_STRVAL(class_name->u.constant));
- }
- efree(tmp);
+static inline zend_bool zend_can_write_to_variable(zend_ast *ast) /* {{{ */
+{
+ while (ast->kind == ZEND_AST_DIM || ast->kind == ZEND_AST_PROP) {
+ ast = ast->child[0];
}
- new_class_entry = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
- new_class_entry->type = ZEND_USER_CLASS;
- new_class_entry->name = zend_new_interned_string(Z_STR(class_name->u.constant) TSRMLS_CC);
+ return zend_is_variable(ast);
+}
+/* }}} */
- zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
- new_class_entry->info.user.filename = zend_get_compiled_filename(TSRMLS_C);
- new_class_entry->info.user.line_start = class_token->u.op.opline_num;
- new_class_entry->ce_flags |= class_token->EA;
+static inline zend_bool zend_is_const_default_class_ref(zend_ast *name_ast) /* {{{ */
+{
+ zend_string *name;
- if (parent_class_name && parent_class_name->op_type != IS_UNUSED) {
- switch (parent_class_name->EA) {
- case ZEND_FETCH_CLASS_SELF:
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'self' as class name as it is reserved");
- break;
- case ZEND_FETCH_CLASS_PARENT:
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved");
- break;
- case ZEND_FETCH_CLASS_STATIC:
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as class name as it is reserved");
- break;
- default:
- break;
- }
- doing_inheritance = 1;
+ if (name_ast->kind != ZEND_AST_ZVAL) {
+ return 0;
}
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->op1_type = IS_CONST;
- build_runtime_defined_function_key(&key, lcname->val, lcname->len TSRMLS_CC);
- opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
+ /* Fully qualified names are always default refs */
+ if (!name_ast->attr) {
+ return 1;
+ }
- opline->op2_type = IS_CONST;
+ name = zend_ast_get_str(name_ast);
+ return ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(name);
+}
+/* }}} */
+
+static inline void zend_handle_numeric_op(znode *node TSRMLS_DC) /* {{{ */
+{
+ if (node->op_type == IS_CONST && Z_TYPE(node->u.constant) == IS_STRING) {
+ zend_ulong index;
- if (doing_inheritance) {
- /* Make sure a trait does not try to extend a class */
- if ((new_class_entry->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
- zend_error_noreturn(E_COMPILE_ERROR, "A trait (%s) cannot extend a class. Traits can only be composed from other traits with the 'use' keyword. Error", new_class_entry->name->val);
+ if (ZEND_HANDLE_NUMERIC(Z_STR(node->u.constant), index)) {
+ zval_ptr_dtor(&node->u.constant);
+ ZVAL_LONG(&node->u.constant, index);
}
+ }
+}
+/* }}} */
- opline->extended_value = parent_class_name->u.op.var;
- opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
+static inline void zend_set_class_name_op1(zend_op *opline, znode *class_node TSRMLS_DC) /* {{{ */
+{
+ if (class_node->op_type == IS_CONST) {
+ opline->op1_type = IS_CONST;
+ opline->op1.constant = zend_add_class_name_literal(
+ CG(active_op_array), Z_STR(class_node->u.constant) TSRMLS_CC);
} else {
- opline->opcode = ZEND_DECLARE_CLASS;
+ SET_NODE(opline->op1, class_node);
}
+}
+/* }}} */
- LITERAL_STR(opline->op2, lcname);
+static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast TSRMLS_DC) /* {{{ */
+{
+ zend_op *opline;
+ znode name_node;
+ zend_compile_expr(&name_node, name_ast TSRMLS_CC);
- zend_hash_update_ptr(CG(class_table), Z_STR(key), new_class_entry);
- CG(active_class_entry) = new_class_entry;
+ if (name_node.op_type == IS_CONST) {
+ zend_string *name = Z_STR(name_node.u.constant);
+ uint32_t fetch_type = zend_get_class_fetch_type(name);
- opline->result.var = get_temporary_variable(CG(active_op_array));
- opline->result_type = IS_VAR;
- GET_NODE(&CG(implementing_class), opline->result);
+ opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, NULL TSRMLS_CC);
+ opline->extended_value = fetch_type;
- if (CG(doc_comment)) {
- CG(active_class_entry)->info.user.doc_comment = CG(doc_comment);
- CG(doc_comment) = NULL;
+ if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
+ uint32_t type = name_ast->kind == ZEND_AST_ZVAL ? name_ast->attr : ZEND_NAME_FQ;
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
+ zend_resolve_class_name(name, type TSRMLS_CC) TSRMLS_CC);
+ }
+
+ zend_string_release(name);
+ } else {
+ opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node TSRMLS_CC);
+ opline->extended_value = ZEND_FETCH_CLASS_DEFAULT;
}
+
+ return opline;
}
/* }}} */
-static void do_verify_abstract_class(TSRMLS_D) /* {{{ */
+static int zend_try_compile_cv(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_ast *name_ast = ast->child[0];
+ if (name_ast->kind == ZEND_AST_ZVAL) {
+ zend_string *name = zval_get_string(zend_ast_get_zval(name_ast));
- opline->opcode = ZEND_VERIFY_ABSTRACT_CLASS;
- SET_NODE(opline->op1, &CG(implementing_class));
- SET_UNUSED(opline->op2);
+ if (zend_is_auto_global(name TSRMLS_CC)) {
+ zend_string_release(name);
+ return FAILURE;
+ }
+
+ result->op_type = IS_CV;
+ result->u.op.var = lookup_cv(CG(active_op_array), name TSRMLS_CC);
+
+ if (zend_string_equals_literal(name, "this")) {
+ CG(active_op_array)->this_var = result->u.op.var;
+ }
+ return SUCCESS;
+ }
+
+ return FAILURE;
}
/* }}} */
-void zend_do_end_class_declaration(const znode *class_token, const znode *parent_token TSRMLS_DC) /* {{{ */
+static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
{
- zend_class_entry *ce = CG(active_class_entry);
+ zend_ast *name_ast = ast->child[0];
+ znode name_node;
+ zend_op *opline;
- if (ce->constructor) {
- ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
- if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error_noreturn(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static", ce->name->val, ce->constructor->common.function_name->val);
- }
+ /* there is a chance someone is accessing $this */
+ if (ast->kind != ZEND_AST_ZVAL
+ && CG(active_op_array)->scope && CG(active_op_array)->this_var == -1
+ ) {
+ zend_string *key = zend_string_init("this", sizeof("this") - 1, 0);
+ CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), key TSRMLS_CC);
}
- if (ce->destructor) {
- ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
- if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error_noreturn(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static", ce->name->val, ce->destructor->common.function_name->val);
+
+ zend_compile_expr(&name_node, name_ast TSRMLS_CC);
+
+ opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL TSRMLS_CC);
+
+ opline->extended_value = ZEND_FETCH_LOCAL;
+ if (name_node.op_type == IS_CONST) {
+ if (zend_is_auto_global(Z_STR(name_node.u.constant) TSRMLS_CC)) {
+ opline->extended_value = ZEND_FETCH_GLOBAL;
}
}
- if (ce->clone) {
- ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
- if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error_noreturn(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static", ce->name->val, ce->clone->common.function_name->val);
+
+ return opline;
+}
+/* }}} */
+
+static void zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
+{
+ if (zend_try_compile_cv(result, ast TSRMLS_CC) == FAILURE) {
+ zend_op *opline = zend_compile_simple_var_no_cv(result, ast, type TSRMLS_CC);
+ zend_adjust_for_fetch_type(opline, type);
+ }
+}
+/* }}} */
+
+static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
+{
+ if (type != BP_VAR_R && type != BP_VAR_IS && zend_is_call(ast)) {
+ if (node->op_type == IS_VAR) {
+ zend_op *opline = zend_emit_op(NULL, ZEND_SEPARATE, node, NULL TSRMLS_CC);
+ opline->result_type = IS_VAR;
+ opline->result.var = opline->op1.var;
+ } else {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
}
}
+}
+/* }}} */
- ce->info.user.line_end = zend_get_compiled_lineno(TSRMLS_C);
+void zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC);
- /* Check for traits and proceed like with interfaces.
- * The only difference will be a combined handling of them in the end.
- * Thus, we need another opcode here. */
- if (ce->num_traits > 0) {
- zend_op *opline;
+static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
+{
+ zend_ast *var_ast = ast->child[0];
+ zend_ast *dim_ast = ast->child[1];
- ce->traits = NULL;
- ce->num_traits = 0;
- ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
+ znode var_node, dim_node;
- /* opcode generation: */
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_BIND_TRAITS;
- SET_NODE(opline->op1, &CG(implementing_class));
- }
+ zend_delayed_compile_var(&var_node, var_ast, type TSRMLS_CC);
+ zend_separate_if_call_and_write(&var_node, var_ast, type TSRMLS_CC);
- if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
- && (parent_token || (ce->num_interfaces > 0))) {
- zend_verify_abstract_class(ce TSRMLS_CC);
- if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
- do_verify_abstract_class(TSRMLS_C);
+ if (dim_ast == NULL) {
+ if (type == BP_VAR_R || type == BP_VAR_IS) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
}
+ if (type == BP_VAR_UNSET) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
+ }
+ dim_node.op_type = IS_UNUSED;
+ } else {
+ zend_compile_expr(&dim_node, dim_ast TSRMLS_CC);
+ zend_handle_numeric_op(&dim_node TSRMLS_CC);
}
- /* Inherit interfaces; reset number to zero, we need it for above check and
- * will restore it during actual implementation.
- * The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
- * zend_verify_abstract_class() */
- if (ce->num_interfaces > 0) {
- ce->interfaces = NULL;
- ce->num_interfaces = 0;
- ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
+
+ return zend_delayed_emit_op(result, ZEND_FETCH_DIM_R, &var_node, &dim_node TSRMLS_CC);
+}
+/* }}} */
+
+static inline zend_op *zend_compile_dim_common(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
+{
+ uint32_t offset = zend_delayed_compile_begin(TSRMLS_C);
+ zend_delayed_compile_dim(result, ast, type TSRMLS_CC);
+ return zend_delayed_compile_end(offset TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_dim(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
+{
+ zend_op *opline = zend_compile_dim_common(result, ast, type TSRMLS_CC);
+ zend_adjust_for_fetch_type(opline, type);
+}
+/* }}} */
+
+static zend_bool is_this_fetch(zend_ast *ast) /* {{{ */
+{
+ if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
+ zval *name = zend_ast_get_zval(ast->child[0]);
+ return Z_TYPE_P(name) == IS_STRING && zend_string_equals_literal(Z_STR_P(name), "this");
}
- CG(active_class_entry) = NULL;
+ return 0;
}
/* }}} */
-void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
+static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
{
+ zend_ast *obj_ast = ast->child[0];
+ zend_ast *prop_ast = ast->child[1];
+
+ znode obj_node, prop_node;
zend_op *opline;
- /* Traits can not implement interfaces */
- if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as interface on '%s' since it is a Trait",
- Z_STRVAL(interface_name->u.constant),
- CG(active_class_entry)->name->val);
+ if (is_this_fetch(obj_ast)) {
+ obj_node.op_type = IS_UNUSED;
+ } else {
+ zend_delayed_compile_var(&obj_node, obj_ast, type TSRMLS_CC);
+ zend_separate_if_call_and_write(&obj_node, obj_ast, type TSRMLS_CC);
}
+ zend_compile_expr(&prop_node, prop_ast TSRMLS_CC);
- switch (zend_get_class_fetch_type(Z_STRVAL(interface_name->u.constant), Z_STRLEN(interface_name->u.constant))) {
- case ZEND_FETCH_CLASS_SELF:
- case ZEND_FETCH_CLASS_PARENT:
- case ZEND_FETCH_CLASS_STATIC:
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as interface name as it is reserved", Z_STRVAL(interface_name->u.constant));
- break;
- default:
- break;
+ opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node TSRMLS_CC);
+ if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
+ zend_alloc_polymorphic_cache_slot(opline->op2.constant TSRMLS_CC);
}
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_ADD_INTERFACE;
- SET_NODE(opline->op1, &CG(implementing_class));
- zend_resolve_class_name(interface_name TSRMLS_CC);
- opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;
- opline->op2_type = IS_CONST;
- opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &interface_name->u.constant TSRMLS_CC);
- CG(active_class_entry)->num_interfaces++;
+ return opline;
}
/* }}} */
-void zend_do_use_trait(znode *trait_name TSRMLS_DC) /* {{{ */
+static zend_op *zend_compile_prop_common(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
{
+ uint32_t offset = zend_delayed_compile_begin(TSRMLS_C);
+ zend_delayed_compile_prop(result, ast, type TSRMLS_CC);
+ return zend_delayed_compile_end(offset TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_prop(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
+{
+ zend_op *opline = zend_compile_prop_common(result, ast, type TSRMLS_CC);
+ zend_adjust_for_fetch_type(opline, type);
+}
+/* }}} */
+
+zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
+{
+ zend_ast *class_ast = ast->child[0];
+ zend_ast *prop_ast = ast->child[1];
+
+ znode class_node, prop_node;
zend_op *opline;
- if ((CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "Cannot use traits inside of interfaces. %s is used in %s",
- Z_STRVAL(trait_name->u.constant), CG(active_class_entry)->name->val);
+ if (zend_is_const_default_class_ref(class_ast)) {
+ class_node.op_type = IS_CONST;
+ ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast TSRMLS_CC));
+ } else {
+ zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
}
+ zend_compile_expr(&prop_node, prop_ast TSRMLS_CC);
- switch (zend_get_class_fetch_type(Z_STRVAL(trait_name->u.constant), Z_STRLEN(trait_name->u.constant))) {
- case ZEND_FETCH_CLASS_SELF:
- case ZEND_FETCH_CLASS_PARENT:
- case ZEND_FETCH_CLASS_STATIC:
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as trait name as it is reserved", Z_STRVAL(trait_name->u.constant));
- break;
- default:
- break;
+ opline = zend_emit_op(result, ZEND_FETCH_R, &prop_node, NULL TSRMLS_CC);
+ if (opline->op1_type == IS_CONST) {
+ zend_alloc_polymorphic_cache_slot(opline->op1.constant TSRMLS_CC);
}
+ if (class_node.op_type == IS_CONST) {
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_class_name_literal(
+ CG(active_op_array), Z_STR(class_node.u.constant) TSRMLS_CC);
+ } else {
+ SET_NODE(opline->op2, &class_node);
+ }
+ opline->extended_value |= ZEND_FETCH_STATIC_MEMBER;
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_ADD_TRAIT;
- SET_NODE(opline->op1, &CG(implementing_class));
- zend_resolve_class_name(trait_name TSRMLS_CC);
- opline->extended_value = ZEND_FETCH_CLASS_TRAIT;
- opline->op2_type = IS_CONST;
- opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &trait_name->u.constant TSRMLS_CC);
- CG(active_class_entry)->num_traits++;
+ return opline;
}
/* }}} */
-ZEND_API zend_string *zend_mangle_property_name(const char *src1, int src1_length, const char *src2, int src2_length, int internal) /* {{{ */
+void zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
{
- zend_string *prop_name;
- int prop_name_length;
-
- prop_name_length = 1 + src1_length + 1 + src2_length;
- prop_name = STR_ALLOC(prop_name_length, internal);
- prop_name->val[0] = '\0';
- memcpy(prop_name->val + 1, src1, src1_length+1);
- memcpy(prop_name->val + 1 + src1_length + 1, src2, src2_length+1);
- return prop_name;
+ zend_op *opline = zend_compile_static_prop_common(result, ast, type TSRMLS_CC);
+ zend_adjust_for_fetch_type(opline, type);
}
/* }}} */
-static int zend_strnlen(const char* s, int maxlen) /* {{{ */
+static inline zend_uchar get_list_fetch_opcode(zend_uchar op_type) /* {{{ */
{
- int len = 0;
- while (*s++ && maxlen--) len++;
- return len;
+ switch (op_type) {
+ case IS_VAR:
+ case IS_CV:
+ return ZEND_FETCH_DIM_R;
+ case IS_TMP_VAR:
+ case IS_CONST:
+ return ZEND_FETCH_DIM_TMP_VAR;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
}
/* }}} */
-ZEND_API int zend_unmangle_property_name_ex(const char *mangled_property, int len, const char **class_name, const char **prop_name, int *prop_len) /* {{{ */
+static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node TSRMLS_DC) /* {{{ */
{
- int class_name_len;
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
- *class_name = NULL;
+ if (list->children == 1 && !list->child[0]) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
+ }
- if (mangled_property[0]!=0) {
- *prop_name = mangled_property;
- if (prop_len) {
- *prop_len = len;
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *var_ast = list->child[i];
+ znode fetch_result, dim_node, var_node, assign_result;
+ zend_op *opline;
+
+ if (var_ast == NULL) {
+ continue;
}
- return SUCCESS;
- }
- if (len < 3 || mangled_property[1]==0) {
- zend_error(E_NOTICE, "Illegal member variable name");
- *prop_name = mangled_property;
- if (prop_len) {
- *prop_len = len;
+
+ dim_node.op_type = IS_CONST;
+ ZVAL_LONG(&dim_node.u.constant, i);
+
+ if (expr_node->op_type == IS_CONST) {
+ Z_TRY_ADDREF(expr_node->u.constant);
}
- return FAILURE;
- }
- class_name_len = zend_strnlen(mangled_property + 1, --len - 1) + 1;
- if (class_name_len >= len || mangled_property[class_name_len]!=0) {
- zend_error(E_NOTICE, "Corrupt member variable name");
- *prop_name = mangled_property;
- if (prop_len) {
- *prop_len = len + 1;
+ opline = zend_emit_op(&fetch_result,
+ get_list_fetch_opcode(expr_node->op_type), expr_node, &dim_node TSRMLS_CC);
+ opline->extended_value |= ZEND_FETCH_ADD_LOCK;
+
+ if (var_ast->kind != ZEND_AST_LIST) {
+ if (is_this_fetch(var_ast)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
+ }
+ zend_compile_var(&var_node, var_ast, BP_VAR_W TSRMLS_CC);
+ zend_emit_op(&assign_result, ZEND_ASSIGN, &var_node, &fetch_result TSRMLS_CC);
+ zend_do_free(&assign_result TSRMLS_CC);
+ } else {
+ zend_compile_list_assign(&assign_result, var_ast, &fetch_result TSRMLS_CC);
+ zend_do_free(&assign_result TSRMLS_CC);
}
- return FAILURE;
- }
- *class_name = mangled_property + 1;
- *prop_name = (*class_name) + class_name_len;
- if (prop_len) {
- *prop_len = len - class_name_len;
}
- return SUCCESS;
+ *result = *expr_node;
}
/* }}} */
-void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC) /* {{{ */
+void zend_ensure_writable_variable(const zend_ast *ast) /* {{{ */
{
- zval property;
- zend_property_info *existing_property_info;
- zend_string *comment = NULL;
-
- if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
- zend_error_noreturn(E_COMPILE_ERROR, "Interfaces may not include member variables");
+ if (ast->kind == ZEND_AST_CALL) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Can't use function return value in write context");
}
+ if (ast->kind == ZEND_AST_METHOD_CALL || ast->kind == ZEND_AST_STATIC_CALL) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Can't use method return value in write context");
+ }
+}
+/* }}} */
- if (access_type & ZEND_ACC_ABSTRACT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract");
+/* Detects $a... = $a pattern */
+zend_bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast TSRMLS_DC) /* {{{ */
+{
+ if (expr_ast->kind != ZEND_AST_VAR || expr_ast->child[0]->kind != ZEND_AST_ZVAL) {
+ return 0;
}
- if (access_type & ZEND_ACC_FINAL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, the final modifier is allowed only for methods and classes",
- CG(active_class_entry)->name->val, Z_STRVAL(var_name->u.constant));
+ while (zend_is_variable(var_ast) && var_ast->kind != ZEND_AST_VAR) {
+ var_ast = var_ast->child[0];
}
- if ((existing_property_info = zend_hash_find_ptr(&CG(active_class_entry)->properties_info, Z_STR(var_name->u.constant))) != NULL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name->val, Z_STRVAL(var_name->u.constant));
+ if (var_ast->kind != ZEND_AST_VAR || var_ast->child[0]->kind != ZEND_AST_ZVAL) {
+ return 0;
}
- if (value) {
- ZVAL_COPY_VALUE(&property, &value->u.constant);
- } else {
- ZVAL_NULL(&property);
+ {
+ zend_string *name1 = zval_get_string(zend_ast_get_zval(var_ast->child[0]));
+ zend_string *name2 = zval_get_string(zend_ast_get_zval(expr_ast->child[0]));
+ zend_bool result = zend_string_equals(name1, name2);
+ zend_string_release(name1);
+ zend_string_release(name2);
+ return result;
}
+}
+/* }}} */
- if (CG(doc_comment)) {
- comment = CG(doc_comment);
- CG(doc_comment) = NULL;
+void zend_compile_assign(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *var_ast = ast->child[0];
+ zend_ast *expr_ast = ast->child[1];
+
+ znode var_node, expr_node;
+ zend_op *opline;
+ uint32_t offset;
+
+ if (is_this_fetch(var_ast)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
}
- Z_STR(var_name->u.constant) = zend_new_interned_string(Z_STR(var_name->u.constant) TSRMLS_CC);
- if (IS_INTERNED(Z_STR(var_name->u.constant))) {
- Z_TYPE_FLAGS(var_name->u.constant) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
+ zend_ensure_writable_variable(var_ast);
+
+ switch (var_ast->kind) {
+ case ZEND_AST_VAR:
+ case ZEND_AST_STATIC_PROP:
+ zend_compile_var(&var_node, var_ast, BP_VAR_W TSRMLS_CC);
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+ zend_emit_op(result, ZEND_ASSIGN, &var_node, &expr_node TSRMLS_CC);
+ return;
+ case ZEND_AST_DIM:
+ offset = zend_delayed_compile_begin(TSRMLS_C);
+ zend_delayed_compile_dim(result, var_ast, BP_VAR_W TSRMLS_CC);
+
+ if (zend_is_assign_to_self(var_ast, expr_ast TSRMLS_CC)) {
+ /* $a[0] = $a should evaluate the right $a first */
+ zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R TSRMLS_CC);
+ } else {
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+ }
+
+ opline = zend_delayed_compile_end(offset TSRMLS_CC);
+ opline->opcode = ZEND_ASSIGN_DIM;
+
+ opline = zend_emit_op_data(&expr_node TSRMLS_CC);
+ opline->op2.var = get_temporary_variable(CG(active_op_array));
+ opline->op2_type = IS_VAR;
+ return;
+ case ZEND_AST_PROP:
+ offset = zend_delayed_compile_begin(TSRMLS_C);
+ zend_delayed_compile_prop(result, var_ast, BP_VAR_W TSRMLS_CC);
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ opline = zend_delayed_compile_end(offset TSRMLS_CC);
+ opline->opcode = ZEND_ASSIGN_OBJ;
+
+ zend_emit_op_data(&expr_node TSRMLS_CC);
+ return;
+ case ZEND_AST_LIST:
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+ zend_compile_list_assign(result, var_ast, &expr_node TSRMLS_CC);
+ return;
+ EMPTY_SWITCH_DEFAULT_CASE();
}
- zend_declare_property_ex(CG(active_class_entry), Z_STR(var_name->u.constant), &property, access_type, comment TSRMLS_CC);
- STR_RELEASE(Z_STR(var_name->u.constant));
}
/* }}} */
-void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC) /* {{{ */
+static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node TSRMLS_DC) /* {{{ */
{
- if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants");
- return;
- }
+ znode dummy_node;
+ zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast,
+ zend_ast_create_znode(value_node));
+ zend_compile_assign(&dummy_node, assign_ast TSRMLS_CC);
+ zend_do_free(&dummy_node TSRMLS_CC);
+}
+/* }}} */
- Z_STR(var_name->u.constant) = zend_new_interned_string(Z_STR(var_name->u.constant) TSRMLS_CC);
- if (IS_INTERNED(Z_STR(var_name->u.constant))) {
- Z_TYPE_FLAGS(var_name->u.constant) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
+void zend_compile_assign_ref(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *target_ast = ast->child[0];
+ zend_ast *source_ast = ast->child[1];
+
+ znode target_node, source_node;
+ zend_op *opline;
+
+ if (is_this_fetch(target_ast)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
}
- if (Z_CONSTANT(value->u.constant)) {
- CG(active_class_entry)->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ zend_ensure_writable_variable(target_ast);
+
+ zend_compile_var(&target_node, target_ast, BP_VAR_W TSRMLS_CC);
+ zend_compile_var(&source_node, source_ast, BP_VAR_REF TSRMLS_CC);
+
+ opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node TSRMLS_CC);
+ if (!result) {
+ opline->result_type |= EXT_TYPE_UNUSED;
}
- if (zend_hash_add(&CG(active_class_entry)->constants_table, Z_STR(var_name->u.constant), &value->u.constant) == NULL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name->val, Z_STRVAL(var_name->u.constant));
+
+ if (zend_is_call(source_ast)) {
+ opline->extended_value = ZEND_RETURNS_FUNCTION;
+ } else if (source_ast->kind == ZEND_AST_NEW) {
+ zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated");
+ opline->extended_value = ZEND_RETURNS_NEW;
}
- FREE_PNODE(var_name);
+}
+/* }}} */
- if (CG(doc_comment)) {
- STR_RELEASE(CG(doc_comment));
- CG(doc_comment) = NULL;
+static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node TSRMLS_DC) /* {{{ */
+{
+ zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN_REF, var_ast,
+ zend_ast_create_znode(value_node));
+ zend_compile_assign_ref(NULL, assign_ast TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_compound_assign(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *var_ast = ast->child[0];
+ zend_ast *expr_ast = ast->child[1];
+ uint32_t opcode = ast->attr;
+
+ znode var_node, expr_node;
+ zend_op *opline;
+ uint32_t offset;
+
+ zend_ensure_writable_variable(var_ast);
+
+ switch (var_ast->kind) {
+ case ZEND_AST_VAR:
+ case ZEND_AST_STATIC_PROP:
+ zend_compile_var(&var_node, var_ast, BP_VAR_RW TSRMLS_CC);
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+ zend_emit_op(result, opcode, &var_node, &expr_node TSRMLS_CC);
+ return;
+ case ZEND_AST_DIM:
+ offset = zend_delayed_compile_begin(TSRMLS_C);
+ zend_delayed_compile_dim(result, var_ast, BP_VAR_RW TSRMLS_CC);
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ opline = zend_delayed_compile_end(offset TSRMLS_CC);
+ opline->opcode = opcode;
+ opline->extended_value = ZEND_ASSIGN_DIM;
+
+ opline = zend_emit_op_data(&expr_node TSRMLS_CC);
+ opline->op2.var = get_temporary_variable(CG(active_op_array));
+ opline->op2_type = IS_VAR;
+ return;
+ case ZEND_AST_PROP:
+ offset = zend_delayed_compile_begin(TSRMLS_C);
+ zend_delayed_compile_prop(result, var_ast, BP_VAR_RW TSRMLS_CC);
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ opline = zend_delayed_compile_end(offset TSRMLS_CC);
+ opline->opcode = opcode;
+ opline->extended_value = ZEND_ASSIGN_OBJ;
+
+ zend_emit_op_data(&expr_node TSRMLS_CC);
+ return;
+ EMPTY_SWITCH_DEFAULT_CASE()
}
}
/* }}} */
-void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS_DC) /* {{{ */
+uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc TSRMLS_DC) /* {{{ */
{
- zend_op opline;
- zend_llist *fetch_list_ptr = zend_stack_top(&CG(bp_stack));
+ /* TODO.AST &var error */
+ zend_ast_list *args = zend_ast_get_list(ast);
+ uint32_t i;
+ zend_bool uses_arg_unpack = 0;
+ uint32_t arg_count = 0; /* number of arguments not including unpacks */
+
+ for (i = 0; i < args->children; ++i) {
+ zend_ast *arg = args->child[i];
+ uint32_t arg_num = i + 1;
- if (object->op_type == IS_CV) {
- if (object->u.op.var == CG(active_op_array)->this_var) {
- object->op_type = IS_UNUSED; /* this means $this for objects */
+ znode arg_node;
+ zend_op *opline;
+ zend_uchar opcode;
+ zend_ulong flags = 0;
+
+ if (arg->kind == ZEND_AST_UNPACK) {
+ uses_arg_unpack = 1;
+ fbc = NULL;
+
+ zend_compile_expr(&arg_node, arg->child[0] TSRMLS_CC);
+ opline = zend_emit_op(NULL, ZEND_SEND_UNPACK, &arg_node, NULL TSRMLS_CC);
+ opline->op2.num = arg_count;
+ continue;
}
- } else if (fetch_list_ptr->count == 1) {
- zend_llist_element *le = fetch_list_ptr->head;
- zend_op *opline_ptr = (zend_op *) le->data;
- if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
- zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
- SET_UNUSED(opline_ptr->op1); /* this means $this for objects */
- SET_NODE(opline_ptr->op2, property);
- /* if it was usual fetch, we change it to object fetch */
- switch (opline_ptr->opcode) {
- case ZEND_FETCH_W:
- opline_ptr->opcode = ZEND_FETCH_OBJ_W;
- break;
- case ZEND_FETCH_R:
- opline_ptr->opcode = ZEND_FETCH_OBJ_R;
- break;
- case ZEND_FETCH_RW:
- opline_ptr->opcode = ZEND_FETCH_OBJ_RW;
- break;
- case ZEND_FETCH_IS:
- opline_ptr->opcode = ZEND_FETCH_OBJ_IS;
- break;
- case ZEND_FETCH_UNSET:
- opline_ptr->opcode = ZEND_FETCH_OBJ_UNSET;
- break;
- case ZEND_FETCH_FUNC_ARG:
- opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG;
- break;
+ if (uses_arg_unpack) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Cannot use positional argument after argument unpacking");
+ }
+
+ arg_count++;
+ if (zend_is_variable(arg)) {
+ if (zend_is_call(arg)) {
+ zend_compile_var(&arg_node, arg, BP_VAR_R TSRMLS_CC);
+ if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) {
+ /* Function call was converted into builtin instruction */
+ opcode = ZEND_SEND_VAL;
+ } else {
+ opcode = ZEND_SEND_VAR_NO_REF;
+ flags |= ZEND_ARG_SEND_FUNCTION;
+ if (fbc && ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
+ flags |= ZEND_ARG_SEND_BY_REF;
+ if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) {
+ flags |= ZEND_ARG_SEND_SILENT;
+ }
+ }
+ }
+ } else if (fbc) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
+ zend_compile_var(&arg_node, arg, BP_VAR_W TSRMLS_CC);
+ opcode = ZEND_SEND_REF;
+ } else {
+ zend_compile_var(&arg_node, arg, BP_VAR_R TSRMLS_CC);
+ opcode = ZEND_SEND_VAR;
+ }
+ } else {
+ zend_compile_var(&arg_node, arg,
+ BP_VAR_FUNC_ARG | (arg_num << BP_VAR_SHIFT) TSRMLS_CC);
+ opcode = ZEND_SEND_VAR_EX;
}
- if (opline_ptr->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline_ptr->op2.constant)) == IS_STRING) {
- GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op2.constant);
+ } else {
+ zend_compile_expr(&arg_node, arg TSRMLS_CC);
+ if (arg_node.op_type & (IS_VAR|IS_CV)) {
+ opcode = ZEND_SEND_VAR_NO_REF;
+ if (fbc && ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
+ flags |= ZEND_ARG_SEND_BY_REF;
+ }
+ } else {
+ if (fbc) {
+ opcode = ZEND_SEND_VAL;
+ if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Only variables can be passed by reference");
+ }
+ } else {
+ opcode = ZEND_SEND_VAL_EX;
+ }
}
- GET_NODE(result, opline_ptr->result);
- return;
}
- }
- if (zend_is_function_or_method_call(object)) {
- init_op(&opline TSRMLS_CC);
- opline.opcode = ZEND_SEPARATE;
- SET_NODE(opline.op1, object);
- SET_UNUSED(opline.op2);
- opline.result_type = IS_VAR;
- opline.result.var = opline.op1.var;
- zend_llist_add_element(fetch_list_ptr, &opline);
- }
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = opcode;
+ SET_NODE(opline->op1, &arg_node);
+ SET_UNUSED(opline->op2);
+ opline->op2.opline_num = arg_num;
- init_op(&opline TSRMLS_CC);
- opline.opcode = ZEND_FETCH_OBJ_W; /* the backpatching routine assumes W */
- opline.result_type = IS_VAR;
- opline.result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline.op1, object);
- SET_NODE(opline.op2, property);
- if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
- GET_POLYMORPHIC_CACHE_SLOT(opline.op2.constant);
+ if (opcode == ZEND_SEND_VAR_NO_REF) {
+ if (fbc) {
+ flags |= ZEND_ARG_COMPILE_TIME_BOUND;
+ }
+ opline->extended_value = flags;
+ } else if (fbc) {
+ opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
+ }
}
- GET_NODE(result, opline.result);
- zend_llist_add_element(fetch_list_ptr, &opline);
+ return arg_count;
}
/* }}} */
-void zend_do_halt_compiler_register(TSRMLS_D) /* {{{ */
+void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc TSRMLS_DC) /* {{{ */
{
- zend_string *name;
- zend_string *cfilename;
- char haltoff[] = "__COMPILER_HALT_OFFSET__";
+ zend_op *opline;
+ uint32_t opnum_init = get_next_op_number(CG(active_op_array)) - 1;
+ uint32_t arg_count;
+ uint32_t call_flags;
- if (CG(has_bracketed_namespaces) && CG(in_namespace)) {
- zend_error_noreturn(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope");
- }
+ zend_do_extended_fcall_begin(TSRMLS_C);
- cfilename = zend_get_compiled_filename(TSRMLS_C);
- name = zend_mangle_property_name(haltoff, sizeof(haltoff) - 1, cfilename->val, cfilename->len, 0);
- zend_register_long_constant(name->val, name->len, zend_get_scanned_file_offset(TSRMLS_C), CONST_CS, 0 TSRMLS_CC);
- STR_FREE(name);
+ arg_count = zend_compile_args(args_ast, fbc TSRMLS_CC);
- if (CG(in_namespace)) {
- zend_do_end_namespace(TSRMLS_C);
- }
+ opline = &CG(active_op_array)->opcodes[opnum_init];
+ opline->extended_value = arg_count;
+
+ call_flags = (opline->opcode == ZEND_NEW ? ZEND_CALL_CTOR : 0);
+ opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL TSRMLS_CC);
+ opline->op1.num = call_flags;
+
+ zend_do_extended_fcall_end(TSRMLS_C);
}
/* }}} */
-void zend_do_push_object(const znode *object TSRMLS_DC) /* {{{ */
+zend_bool zend_compile_function_name(znode *name_node, zend_ast *name_ast TSRMLS_DC) /* {{{ */
{
- zend_stack_push(&CG(object_stack), object);
+ zend_string *orig_name = zend_ast_get_str(name_ast);
+ zend_bool is_fully_qualified;
+
+ name_node->op_type = IS_CONST;
+ ZVAL_STR(&name_node->u.constant, zend_resolve_function_name(
+ orig_name, name_ast->attr, &is_fully_qualified TSRMLS_CC));
+
+ return !is_fully_qualified && CG(current_namespace);
}
/* }}} */
-void zend_do_pop_object(znode *object TSRMLS_DC) /* {{{ */
+void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast TSRMLS_DC) /* {{{ */
{
- if (object) {
- znode *tmp = zend_stack_top(&CG(object_stack));
- *object = *tmp;
- }
- zend_stack_del_top(&CG(object_stack));
+ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
+ SET_UNUSED(opline->op1);
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_ns_func_name_literal(
+ CG(active_op_array), &name_node->u.constant TSRMLS_CC);
+ zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC);
+
+ zend_compile_call_common(result, args_ast, NULL TSRMLS_CC);
}
/* }}} */
-void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /* {{{ */
+void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline;
+ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_INIT_FCALL_BY_NAME;
+ SET_UNUSED(opline->op1);
+ if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
+ opline->op2_type = IS_CONST;
+ opline->op2.constant
+ = zend_add_func_name_literal(CG(active_op_array), &name_node->u.constant TSRMLS_CC);
+ zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC);
+ } else {
+ SET_NODE(opline->op2, name_node);
+ }
- new_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_NEW;
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, class_type);
- SET_UNUSED(opline->op2);
+ zend_compile_call_common(result, args_ast, NULL TSRMLS_CC);
+}
+/* }}} */
- zend_push_function_call_entry(NULL, new_token->u.op.opline_num TSRMLS_CC);
+static zend_bool zend_args_contain_unpack(zend_ast_list *args) /* {{{ */
+{
+ uint32_t i;
+ for (i = 0; i < args->children; ++i) {
+ if (args->child[i]->kind == ZEND_AST_UNPACK) {
+ return 1;
+ }
+ }
+ return 0;
}
/* }}} */
-void zend_do_end_new_object(znode *result, const znode *new_token TSRMLS_DC) /* {{{ */
+int zend_compile_func_strlen(znode *result, zend_ast_list *args TSRMLS_DC) /* {{{ */
{
- znode ctor_result;
+ znode arg_node;
- zend_do_end_function_call(NULL, &ctor_result, 1, 0 TSRMLS_CC);
- zend_do_free(&ctor_result TSRMLS_CC);
+ if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN)
+ || args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK
+ ) {
+ return FAILURE;
+ }
- CG(active_op_array)->opcodes[new_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
- GET_NODE(result, CG(active_op_array)->opcodes[new_token->u.op.opline_num].result);
+ zend_compile_expr(&arg_node, args->child[0] TSRMLS_CC);
+ zend_emit_op_tmp(result, ZEND_STRLEN, &arg_node, NULL TSRMLS_CC);
+ return SUCCESS;
}
/* }}} */
-static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
+int zend_compile_func_typecheck(znode *result, zend_ast_list *args, uint32_t type TSRMLS_DC) /* {{{ */
{
- zend_constant *c = NULL;
- char *lookup_name;
+ znode arg_node;
+ zend_op *opline;
- if (Z_STRVAL_P(const_name)[0] == '\\') {
- if ((c = zend_hash_str_find_ptr(EG(zend_constants), Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name)-1)) == NULL) {
- lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name)-1);
- if ((c = zend_hash_str_find_ptr(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name)-1)) != NULL) {
- if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
- efree(lookup_name);
- return c;
- }
- }
- efree(lookup_name);
- return NULL;
- }
- } else if ((c = zend_hash_find_ptr(EG(zend_constants), Z_STR_P(const_name))) == NULL) {
- lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name), Z_STRLEN_P(const_name));
- if ((c = zend_hash_str_find_ptr(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name))) != NULL) {
- if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
- efree(lookup_name);
- return c;
- }
- }
- efree(lookup_name);
- return NULL;
- }
- if (c->flags & CONST_CT_SUBST) {
- return c;
- }
- if (all_internal_constants_substitution &&
- (c->flags & CONST_PERSISTENT) &&
- !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
- !Z_CONSTANT(c->value)) {
- return c;
+ if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
+ return FAILURE;
}
- return NULL;
+
+ zend_compile_expr(&arg_node, args->child[0] TSRMLS_CC);
+ opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL TSRMLS_CC);
+ opline->extended_value = type;
+ return SUCCESS;
}
/* }}} */
-static int zend_constant_ct_subst(znode *result, zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
+int zend_compile_func_defined(znode *result, zend_ast_list *args TSRMLS_DC) /* {{{ */
{
- zend_constant *c = zend_get_ct_const(const_name, all_internal_constants_substitution TSRMLS_CC);
+ zend_string *name;
+ zend_op *opline;
- if (c) {
- zval_dtor(const_name);
- result->op_type = IS_CONST;
- result->u.constant = c->value;
- zval_copy_ctor(&result->u.constant);
- return 1;
+ if (args->children != 1 || args->child[0]->kind != ZEND_AST_ZVAL) {
+ return FAILURE;
}
- return 0;
+
+ name = zval_get_string(zend_ast_get_zval(args->child[0]));
+ if (zend_memrchr(name->val, '\\', name->len) || zend_memrchr(name->val, ':', name->len)) {
+ zend_string_release(name);
+ return FAILURE;
+ }
+
+ opline = zend_emit_op_tmp(result, ZEND_DEFINED, NULL, NULL TSRMLS_CC);
+ opline->op1_type = IS_CONST;
+ LITERAL_STR(opline->op1, name);
+ zend_alloc_cache_slot(opline->op1.constant TSRMLS_CC);
+
+ /* Lowercase constant name in a separate literal */
+ {
+ zval c;
+ zend_string *lcname = zend_string_alloc(name->len, 0);
+ zend_str_tolower_copy(lcname->val, name->val, name->len);
+ ZVAL_NEW_STR(&c, lcname);
+ zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+ }
+ return SUCCESS;
}
/* }}} */
-void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC) /* {{{ */
+static int zend_try_compile_ct_bound_init_user_func(znode *result, zend_ast *name_ast, uint32_t num_args TSRMLS_DC) /* {{{ */
{
- znode tmp;
+ zend_string *name, *lcname;
+ zend_function *fbc;
zend_op *opline;
- int type;
- char *compound;
- ulong fetch_type = 0;
-
- if (constant_container) {
- switch (mode) {
- case ZEND_CT:
- /* this is a class constant */
- type = zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant));
-
- if (ZEND_FETCH_CLASS_STATIC == type) {
- zend_error(E_ERROR, "\"static::\" is not allowed in compile-time constants");
- } else if (ZEND_FETCH_CLASS_DEFAULT == type) {
- zend_resolve_class_name(constant_container TSRMLS_CC);
- }
- zend_do_build_full_name(NULL, constant_container, constant_name, 1 TSRMLS_CC);
- *result = *constant_container;
- Z_TYPE_INFO(result->u.constant) = IS_CONSTANT_EX;
- if (IS_INTERNED(Z_STR(result->u.constant))) {
- Z_TYPE_FLAGS(result->u.constant) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
- }
- Z_CONST_FLAGS(result->u.constant) = fetch_type;
- break;
- case ZEND_RT:
- if (constant_container->op_type == IS_CONST &&
- ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant))) {
- zend_resolve_class_name(constant_container TSRMLS_CC);
- } else {
- zend_do_fetch_class(&tmp, constant_container TSRMLS_CC);
- constant_container = &tmp;
- }
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_FETCH_CONSTANT;
- opline->result_type = IS_TMP_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- if (constant_container->op_type == IS_CONST) {
- opline->op1_type = IS_CONST;
- opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), &constant_container->u.constant TSRMLS_CC);
- } else {
- SET_NODE(opline->op1, constant_container);
- }
- SET_NODE(opline->op2, constant_name);
- if (opline->op1_type == IS_CONST) {
- GET_CACHE_SLOT(opline->op2.constant);
- } else {
- GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
- }
- GET_NODE(result, opline->result);
- break;
- }
- return;
- }
- /* namespace constant */
- /* only one that did not contain \ from the start can be converted to string if unknown */
- switch (mode) {
- case ZEND_CT:
- compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
- /* this is a namespace constant, or an unprefixed constant */
- if (zend_constant_ct_subst(result, &constant_name->u.constant, 0 TSRMLS_CC)) {
- break;
- }
+ if (name_ast->kind != ZEND_AST_CONST || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
+ return FAILURE;
+ }
- zend_resolve_const_name(constant_name, &check_namespace TSRMLS_CC);
+ name = zend_ast_get_str(name_ast);
+ lcname = zend_string_alloc(name->len, 0);
+ zend_str_tolower_copy(lcname->val, name->val, name->len);
- if(!compound) {
- fetch_type |= IS_CONSTANT_UNQUALIFIED;
- }
+ fbc = zend_hash_find_ptr(CG(function_table), lcname);
+ if (!fbc || (fbc->type == ZEND_INTERNAL_FUNCTION &&
+ (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
+ ) {
+ zend_string_free(lcname);
+ return FAILURE;
+ }
- *result = *constant_name;
- Z_TYPE_INFO(result->u.constant) = IS_CONSTANT_EX;
- if (IS_INTERNED(Z_STR(result->u.constant))) {
- Z_TYPE_FLAGS(result->u.constant) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
- }
- Z_CONST_FLAGS(result->u.constant) = fetch_type;
- break;
- case ZEND_RT:
- compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
+ opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, NULL TSRMLS_CC);
+ opline->op2_type = IS_CONST;
+ LITERAL_STR(opline->op2, lcname);
+ opline->extended_value = num_args;
- zend_resolve_const_name(constant_name, &check_namespace TSRMLS_CC);
+ return SUCCESS;
+}
+/* }}} */
- if(zend_constant_ct_subst(result, &constant_name->u.constant, 1 TSRMLS_CC)) {
- break;
- }
+static void zend_compile_init_user_func(znode *result, zend_ast *name_ast, uint32_t num_args, zend_string *orig_func_name TSRMLS_DC) /* {{{ */
+{
+ zend_op *opline;
+ znode name_node;
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_FETCH_CONSTANT;
- opline->result_type = IS_TMP_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, opline->result);
- SET_UNUSED(opline->op1);
- opline->op2_type = IS_CONST;
- if (compound) {
- /* the name is unambiguous */
- opline->extended_value = 0;
- opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
- } else {
- opline->extended_value = IS_CONSTANT_UNQUALIFIED;
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- opline->extended_value |= IS_CONSTANT_IN_NAMESPACE;
- opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 1 TSRMLS_CC);
- } else {
- opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
- }
- }
- GET_CACHE_SLOT(opline->op2.constant);
- break;
+ if (zend_try_compile_ct_bound_init_user_func(result, name_ast, num_args TSRMLS_CC) == SUCCESS) {
+ return;
}
+
+ zend_compile_expr(&name_node, name_ast TSRMLS_CC);
+
+ opline = zend_emit_op(NULL, ZEND_INIT_USER_CALL, NULL, &name_node TSRMLS_CC);
+ opline->op1_type = IS_CONST;
+ LITERAL_STR(opline->op1, zend_string_copy(orig_func_name));
+ opline->extended_value = num_args;
}
/* }}} */
-void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC) /* {{{ */
+/* cufa = call_user_func_array */
+int zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname TSRMLS_DC) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ znode arg_node;
- opline->opcode = ZEND_INIT_FCALL;
- opline->extended_value = 1;
- SET_UNUSED(opline->op1);
- opline->op2_type = IS_CONST;
- LITERAL_STR(opline->op2, STR_INIT("shell_exec", sizeof("shell_exec")-1, 0));
- GET_CACHE_SLOT(opline->op2.constant);
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- switch (cmd->op_type) {
- case IS_CONST:
- case IS_TMP_VAR:
- opline->opcode = ZEND_SEND_VAL;
- break;
- default:
- opline->opcode = ZEND_SEND_VAR;
- break;
+ if (args->children != 2 || zend_args_contain_unpack(args)) {
+ return FAILURE;
}
- SET_NODE(opline->op1, cmd);
- opline->op2.opline_num = 1;
- SET_UNUSED(opline->op2);
- /* FIXME: exception support not added to this op2 */
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_DO_FCALL;
- opline->extended_value = 1;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- opline->result_type = IS_VAR;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- GET_NODE(result, opline->result);
+ zend_compile_init_user_func(NULL, args->child[0], 1, lcname TSRMLS_CC);
+ zend_compile_expr(&arg_node, args->child[1] TSRMLS_CC);
+ zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL TSRMLS_CC);
+ zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL TSRMLS_CC);
+
+ return SUCCESS;
}
/* }}} */
-void zend_do_init_array(znode *result, znode *expr, znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
+/* cuf = call_user_func */
+int zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcname TSRMLS_DC) /* {{{ */
{
- int op_num = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ uint32_t i;
- result->u.op.opline_num = op_num;
+ if (args->children < 1 || zend_args_contain_unpack(args)) {
+ return FAILURE;
+ }
- opline->opcode = ZEND_INIT_ARRAY;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- opline->result_type = IS_TMP_VAR;
- opline->extended_value = is_ref; /* extval = size << 2 | not_packed << 1 | is_ref */
-
- if (expr) {
- opline->extended_value += 1 << ZEND_ARRAY_SIZE_SHIFT; /* increment size */
- SET_NODE(opline->op1, expr);
- if (offset) {
- SET_NODE(opline->op2, offset);
- if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
- ulong index;
-
- opline->extended_value |= ZEND_ARRAY_NOT_PACKED;
- if (ZEND_HANDLE_NUMERIC(Z_STR(CONSTANT(opline->op2.constant)), index)) {
- zval_dtor(&CONSTANT(opline->op2.constant));
- ZVAL_LONG(&CONSTANT(opline->op2.constant), index);
- }
+ zend_compile_init_user_func(NULL, args->child[0], args->children - 1, lcname TSRMLS_CC);
+ for (i = 1; i < args->children; ++i) {
+ zend_ast *arg_ast = args->child[i];
+ znode arg_node;
+ zend_op *opline;
+ zend_bool send_user = 0;
+
+ if (zend_is_variable(arg_ast) && !zend_is_call(arg_ast)) {
+ zend_compile_var(&arg_node, arg_ast, BP_VAR_FUNC_ARG | (i << BP_VAR_SHIFT) TSRMLS_CC);
+ send_user = 1;
+ } else {
+ zend_compile_expr(&arg_node, arg_ast TSRMLS_CC);
+ if (arg_node.op_type & (IS_VAR|IS_CV)) {
+ send_user = 1;
}
+ }
+
+ if (send_user) {
+ opline = zend_emit_op(NULL, ZEND_SEND_USER, &arg_node, NULL TSRMLS_CC);
} else {
- SET_UNUSED(opline->op2);
+ opline = zend_emit_op(NULL, ZEND_SEND_VAL, &arg_node, NULL TSRMLS_CC);
}
- } else {
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
+
+ opline->op2.opline_num = i;
}
+ zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL TSRMLS_CC);
+
+ return SUCCESS;
}
/* }}} */
-void zend_do_add_array_element(znode *result, znode *expr, znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- zend_op *init_opline = &CG(active_op_array)->opcodes[result->u.op.opline_num];
- init_opline->extended_value += 1 << ZEND_ARRAY_SIZE_SHIFT; /* increment size */
-
- opline->opcode = ZEND_ADD_ARRAY_ELEMENT;
- COPY_NODE(opline->result, init_opline->result);
- SET_NODE(opline->op1, expr);
- if (offset) {
- SET_NODE(opline->op2, offset);
- if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
- ulong index;
-
- init_opline->extended_value |= ZEND_ARRAY_NOT_PACKED;
- if (ZEND_HANDLE_NUMERIC(Z_STR(CONSTANT(opline->op2.constant)), index)) {
- zval_dtor(&CONSTANT(opline->op2.constant));
- ZVAL_LONG(&CONSTANT(opline->op2.constant), index);
- }
- }
+int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args TSRMLS_DC) /* {{{ */
+{
+ if (zend_string_equals_literal(lcname, "strlen")) {
+ return zend_compile_func_strlen(result, args TSRMLS_CC);
+ } else if (zend_string_equals_literal(lcname, "is_null")) {
+ return zend_compile_func_typecheck(result, args, IS_NULL TSRMLS_CC);
+ } else if (zend_string_equals_literal(lcname, "is_bool")) {
+ return zend_compile_func_typecheck(result, args, _IS_BOOL TSRMLS_CC);
+ } else if (zend_string_equals_literal(lcname, "is_long")
+ || zend_string_equals_literal(lcname, "is_int")
+ || zend_string_equals_literal(lcname, "is_integer")
+ ) {
+ return zend_compile_func_typecheck(result, args, IS_LONG TSRMLS_CC);
+ } else if (zend_string_equals_literal(lcname, "is_float")
+ || zend_string_equals_literal(lcname, "is_double")
+ || zend_string_equals_literal(lcname, "is_real")
+ ) {
+ return zend_compile_func_typecheck(result, args, IS_DOUBLE TSRMLS_CC);
+ } else if (zend_string_equals_literal(lcname, "is_string")) {
+ return zend_compile_func_typecheck(result, args, IS_STRING TSRMLS_CC);
+ } else if (zend_string_equals_literal(lcname, "is_array")) {
+ return zend_compile_func_typecheck(result, args, IS_ARRAY TSRMLS_CC);
+ } else if (zend_string_equals_literal(lcname, "is_object")) {
+ return zend_compile_func_typecheck(result, args, IS_OBJECT TSRMLS_CC);
+ } else if (zend_string_equals_literal(lcname, "is_resource")) {
+ return zend_compile_func_typecheck(result, args, IS_RESOURCE TSRMLS_CC);
+ } else if (zend_string_equals_literal(lcname, "defined")) {
+ return zend_compile_func_defined(result, args TSRMLS_CC);
+ } else if (zend_string_equals_literal(lcname, "call_user_func_array")) {
+ return zend_compile_func_cufa(result, args, lcname TSRMLS_CC);
+ } else if (zend_string_equals_literal(lcname, "call_user_func")) {
+ return zend_compile_func_cuf(result, args, lcname TSRMLS_CC);
} else {
- SET_UNUSED(opline->op2);
+ return FAILURE;
}
- opline->extended_value = is_ref;
}
/* }}} */
-void zend_do_end_array(znode *result, const znode *array_node TSRMLS_DC) /* {{{ */
+void zend_compile_call(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
{
- int next_op_num = get_next_op_number(CG(active_op_array));
- zend_op *init_opline = &CG(active_op_array)->opcodes[array_node->u.op.opline_num];
- zend_op *opline;
- int i;
- int constant_array = 0;
- zval array;
-
- /* check if constructed array consists only from constants */
- if ((init_opline->op1_type & (IS_UNUSED | IS_CONST)) &&
- (init_opline->op2_type & (IS_UNUSED | IS_CONST))) {
- if (next_op_num == array_node->u.op.opline_num + 1) {
- constant_array = 1;
- } else if ((init_opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT) == next_op_num - array_node->u.op.opline_num) {
- opline = init_opline + 1;
- i = next_op_num - array_node->u.op.opline_num - 1;
- while (i > 0) {
- if (opline->opcode != ZEND_ADD_ARRAY_ELEMENT ||
- opline->op1_type != IS_CONST ||
- !(opline->op2_type & (IS_UNUSED | IS_CONST))) {
- break;
- }
- opline++;
- i--;
- }
- if (i == 0) {
- constant_array = 1;
- }
- }
+ zend_ast *name_ast = ast->child[0];
+ zend_ast *args_ast = ast->child[1];
+
+ znode name_node;
+
+ if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
+ zend_compile_expr(&name_node, name_ast TSRMLS_CC);
+ zend_compile_dynamic_call(result, &name_node, args_ast TSRMLS_CC);
+ return;
}
-
- if (constant_array) {
- /* try to construct constant array */
- zend_uint size;
- long num;
- zend_string *str;
-
- if (init_opline->op1_type != IS_UNUSED) {
- size = init_opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
- } else {
- size = 0;
+
+ {
+ zend_bool runtime_resolution = zend_compile_function_name(&name_node, name_ast TSRMLS_CC);
+ if (runtime_resolution) {
+ zend_compile_ns_call(result, &name_node, args_ast TSRMLS_CC);
+ return;
}
- ZVAL_NEW_ARR(&array);
- zend_hash_init(Z_ARRVAL(array), size, NULL, ZVAL_PTR_DTOR, 0);
+ }
- if (init_opline->op1_type != IS_UNUSED) {
- /* Explicitly initialize array as not-packed if flag is set */
- if (init_opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
- zend_hash_real_init(Z_ARRVAL(array), 0);
- }
+ {
+ zval *name = &name_node.u.constant;
+ zend_string *lcname = zend_string_alloc(Z_STRLEN_P(name), 0);
+ zend_function *fbc;
+ zend_op *opline;
- opline = init_opline;
- i = next_op_num - array_node->u.op.opline_num;
- while (i > 0 && constant_array) {
- if (opline->op2_type == IS_CONST) {
- switch (Z_TYPE(CONSTANT(opline->op2.constant))) {
- case IS_LONG:
- num = Z_LVAL(CONSTANT(opline->op2.constant));
-num_index:
- zend_hash_index_update(Z_ARRVAL(array), num, &CONSTANT(opline->op1.constant));
- if (Z_REFCOUNTED(CONSTANT(opline->op1.constant))) Z_ADDREF(CONSTANT(opline->op1.constant));
- break;
- case IS_STRING:
- str = Z_STR(CONSTANT(opline->op2.constant));
-str_index:
- zend_hash_update(Z_ARRVAL(array), str, &CONSTANT(opline->op1.constant));
- if (Z_REFCOUNTED(CONSTANT(opline->op1.constant))) Z_ADDREF(CONSTANT(opline->op1.constant));
- break;
- case IS_DOUBLE:
- num = zend_dval_to_lval(Z_DVAL(CONSTANT(opline->op2.constant)));
- goto num_index;
- case IS_FALSE:
- num = 0;
- goto num_index;
- case IS_TRUE:
- num = 1;
- goto num_index;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- default:
- constant_array = 0;
- break;
- }
- } else {
- zend_hash_next_index_insert(Z_ARRVAL(array), &CONSTANT(opline->op1.constant));
- if (Z_REFCOUNTED(CONSTANT(opline->op1.constant))) Z_ADDREF(CONSTANT(opline->op1.constant));
- }
- opline++;
- i--;
- }
- if (!constant_array) {
- zval_dtor(&array);
- }
+ zend_str_tolower_copy(lcname->val, Z_STRVAL_P(name), Z_STRLEN_P(name));
+
+ fbc = zend_hash_find_ptr(CG(function_table), lcname);
+ if (!fbc || (fbc->type == ZEND_INTERNAL_FUNCTION &&
+ (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
+ ) {
+ zend_string_release(lcname);
+ zend_compile_dynamic_call(result, &name_node, args_ast TSRMLS_CC);
+ return;
}
- }
- if (constant_array) {
- /* remove run-time array construction and use constant array instead */
- opline = &CG(active_op_array)->opcodes[next_op_num-1];
- while (1) {
- if (opline->op2_type == IS_CONST) {
- zend_del_literal(CG(active_op_array), opline->op2.constant);
- }
- if (opline->op1_type == IS_CONST) {
- if (Z_TYPE(CONSTANT(opline->op1.constant)) == IS_ARRAY &&
- Z_REFCOUNTED(CONSTANT(opline->op1.constant)) &&
- Z_REFCOUNT(CONSTANT(opline->op1.constant)) == 2) {
- /* don't delete nested arrays */
- Z_DELREF(CONSTANT(opline->op1.constant));
- ZVAL_UNDEF(&CONSTANT(opline->op1.constant));
- }
- zend_del_literal(CG(active_op_array), opline->op1.constant);
- }
- if (opline == init_opline) {
- break;
- }
- opline--;
+ if (zend_try_compile_special_func(result, lcname,
+ zend_ast_get_list(args_ast) TSRMLS_CC) == SUCCESS
+ ) {
+ zend_string_release(lcname);
+ zval_ptr_dtor(&name_node.u.constant);
+ return;
}
- CG(active_op_array)->last = array_node->u.op.opline_num;
- result->op_type = IS_CONST;
- ZVAL_COPY_VALUE(&result->u.constant, &array);
- } else {
- GET_NODE(result, init_opline->result);
+ zval_ptr_dtor(&name_node.u.constant);
+ ZVAL_NEW_STR(&name_node.u.constant, lcname);
+
+ opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node TSRMLS_CC);
+ zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC);
+
+ zend_compile_call_common(result, args_ast, fbc TSRMLS_CC);
}
- result->EA = 0;
}
/* }}} */
-void zend_do_add_list_element(const znode *element TSRMLS_DC) /* {{{ */
+void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
{
- list_llist_element lle;
+ zend_ast *obj_ast = ast->child[0];
+ zend_ast *method_ast = ast->child[1];
+ zend_ast *args_ast = ast->child[2];
- if (element) {
- zend_check_writable_variable(element);
+ znode obj_node, method_node;
+ zend_op *opline;
- lle.var = *element;
- zend_llist_copy(&lle.dimensions, &CG(dimension_llist));
- zend_llist_prepend_element(&CG(list_llist), &lle);
+ if (is_this_fetch(obj_ast)) {
+ obj_node.op_type = IS_UNUSED;
+ } else {
+ zend_compile_expr(&obj_node, obj_ast TSRMLS_CC);
}
- (*((int *)CG(dimension_llist).tail->data))++;
-}
-/* }}} */
-void zend_do_new_list_begin(TSRMLS_D) /* {{{ */
-{
- int current_dimension = 0;
- zend_llist_add_element(&CG(dimension_llist), &current_dimension);
-}
-/* }}} */
+ zend_compile_expr(&method_node, method_ast TSRMLS_CC);
+ opline = zend_emit_op(NULL, ZEND_INIT_METHOD_CALL, &obj_node, NULL TSRMLS_CC);
+
+ if (method_node.op_type == IS_CONST) {
+ if (Z_TYPE(method_node.u.constant) != IS_STRING) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
+ }
-void zend_do_new_list_end(TSRMLS_D) /* {{{ */
-{
- zend_llist_remove_tail(&CG(dimension_llist));
- (*((int *)CG(dimension_llist).tail->data))++;
+ opline->op2_type = IS_CONST;
+ opline->op2.constant =
+ zend_add_func_name_literal(CG(active_op_array), &method_node.u.constant TSRMLS_CC);
+ zend_alloc_polymorphic_cache_slot(opline->op2.constant TSRMLS_CC);
+ } else {
+ SET_NODE(opline->op2, &method_node);
+ }
+
+ zend_compile_call_common(result, args_ast, NULL TSRMLS_CC);
}
/* }}} */
-void zend_do_list_init(TSRMLS_D) /* {{{ */
+zend_bool zend_is_constructor(zend_string *name) /* {{{ */
{
- zend_stack_push(&CG(list_stack), &CG(list_llist));
- zend_stack_push(&CG(list_stack), &CG(dimension_llist));
- zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
- zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
- zend_do_new_list_begin(TSRMLS_C);
+ return zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME);
}
/* }}} */
-void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) /* {{{ */
+void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
{
- zend_llist_element *le;
- zend_llist_element *dimension;
+ zend_ast *class_ast = ast->child[0];
+ zend_ast *method_ast = ast->child[1];
+ zend_ast *args_ast = ast->child[2];
+
+ znode class_node, method_node;
zend_op *opline;
- znode last_container;
+ zend_ulong extended_value = 0;
- le = CG(list_llist).head;
- while (le) {
- zend_llist *tmp_dimension_llist = &((list_llist_element *)le->data)->dimensions;
- dimension = tmp_dimension_llist->head;
- while (dimension) {
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- if (dimension == tmp_dimension_llist->head) { /* first */
- last_container = *expr;
- switch (expr->op_type) {
- case IS_VAR:
- case IS_CV:
- opline->opcode = ZEND_FETCH_DIM_R;
- break;
- case IS_TMP_VAR:
- opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
- break;
- case IS_CONST: /* fetch_dim_tmp_var will handle this bogus fetch */
- zval_copy_ctor(&expr->u.constant);
- opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
- break;
- }
- opline->extended_value |= ZEND_FETCH_ADD_LOCK;
- } else {
- opline->opcode = ZEND_FETCH_DIM_R;
- }
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, &last_container);
- opline->op2_type = IS_CONST;
- LITERAL_LONG(opline->op2, *((int *) dimension->data));
- GET_NODE(&last_container, opline->result);
- dimension = dimension->next;
+ if (zend_is_const_default_class_ref(class_ast)) {
+ class_node.op_type = IS_CONST;
+ ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast TSRMLS_CC));
+ } else {
+ opline = zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
+ extended_value = opline->extended_value;
+ }
+
+ zend_compile_expr(&method_node, method_ast TSRMLS_CC);
+ if (method_node.op_type == IS_CONST) {
+ zval *name = &method_node.u.constant;
+ if (Z_TYPE_P(name) != IS_STRING) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
+ }
+ if (zend_is_constructor(Z_STR_P(name))) {
+ zval_ptr_dtor(name);
+ method_node.op_type = IS_UNUSED;
}
- ((list_llist_element *) le->data)->value = last_container;
- zend_llist_destroy(&((list_llist_element *) le->data)->dimensions);
- zend_do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value TSRMLS_CC);
- zend_do_free(result TSRMLS_CC);
- le = le->next;
}
- zend_llist_destroy(&CG(dimension_llist));
- zend_llist_destroy(&CG(list_llist));
- *result = *expr;
- {
- zend_llist *p;
- /* restore previous lists */
- p = zend_stack_top(&CG(list_stack));
- CG(dimension_llist) = *p;
- zend_stack_del_top(&CG(list_stack));
- p = zend_stack_top(&CG(list_stack));
- CG(list_llist) = *p;
- zend_stack_del_top(&CG(list_stack));
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
+ opline->extended_value = extended_value;
+
+ zend_set_class_name_op1(opline, &class_node TSRMLS_CC);
+
+ if (method_node.op_type == IS_CONST) {
+ opline->op2_type = IS_CONST;
+ opline->op2.constant =
+ zend_add_func_name_literal(CG(active_op_array), &method_node.u.constant TSRMLS_CC);
+ if (opline->op1_type == IS_CONST) {
+ zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC);
+ } else {
+ zend_alloc_polymorphic_cache_slot(opline->op2.constant TSRMLS_CC);
+ }
+ } else {
+ SET_NODE(opline->op2, &method_node);
}
+
+ zend_compile_call_common(result, args_ast, NULL TSRMLS_CC);
}
/* }}} */
-void zend_init_list(void *result, void *item TSRMLS_DC) /* {{{ */
+void zend_compile_new(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- void** list = emalloc(sizeof(void*) * 2);
+ zend_ast *class_ast = ast->child[0];
+ zend_ast *args_ast = ast->child[1];
- list[0] = item;
- list[1] = NULL;
+ znode class_node, ctor_result;
+ zend_op *opline;
+ uint32_t opnum;
- *(void**)result = list;
+ zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
+
+ opnum = get_next_op_number(CG(active_op_array));
+ zend_emit_op(result, ZEND_NEW, &class_node, NULL TSRMLS_CC);
+
+ zend_compile_call_common(&ctor_result, args_ast, NULL TSRMLS_CC);
+ zend_do_free(&ctor_result TSRMLS_CC);
+
+ /* New jumps over ctor call if ctor does not exist */
+ opline = &CG(active_op_array)->opcodes[opnum];
+ opline->op2.opline_num = get_next_op_number(CG(active_op_array));
}
/* }}} */
-void zend_add_to_list(void *result, void *item TSRMLS_DC) /* {{{ */
+void zend_compile_clone(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- void** list = *(void**)result;
- size_t n = 0;
+ zend_ast *obj_ast = ast->child[0];
- if (list) {
- while (list[n]) {
- n++;
+ znode obj_node;
+ zend_compile_expr(&obj_node, obj_ast TSRMLS_CC);
+
+ zend_emit_op(result, ZEND_CLONE, &obj_node, NULL TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_global_var(zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *var_ast = ast->child[0];
+ zend_ast *name_ast = var_ast->child[0];
+
+ znode name_node, result;
+
+ zend_compile_expr(&name_node, name_ast TSRMLS_CC);
+ if (name_node.op_type == IS_CONST) {
+ if (Z_TYPE(name_node.u.constant) != IS_STRING) {
+ convert_to_string(&name_node.u.constant);
}
}
- list = erealloc(list, sizeof(void*) * (n+2));
+ if (zend_try_compile_cv(&result, var_ast TSRMLS_CC) == SUCCESS) {
+ zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node TSRMLS_CC);
+ } else {
+ zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL TSRMLS_CC);
- list[n] = item;
- list[n+1] = NULL;
+ // TODO.AST Avoid double fetch
+ //opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
- *(void**)result = list;
+ zend_emit_assign_ref_znode(var_ast, &result TSRMLS_CC);
+ }
}
/* }}} */
-void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
+static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_bool by_ref TSRMLS_DC) /* {{{ */
{
- zval tmp;
+ znode var_node, result;
zend_op *opline;
- znode lval;
- znode result;
- if (static_assignment) {
- ZVAL_COPY_VALUE(&tmp, &static_assignment->u.constant);
- } else {
- ZVAL_NULL(&tmp);
- Z_CONST_FLAGS(tmp) = 0;
- }
+ zend_compile_expr(&var_node, var_ast TSRMLS_CC);
+
if (!CG(active_op_array)->static_variables) {
if (CG(active_op_array)->scope) {
CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
@@ -6561,1400 +4612,3330 @@ void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int
ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
zend_hash_init(CG(active_op_array)->static_variables, 8, NULL, ZVAL_PTR_DTOR, 0);
}
- zend_hash_update(CG(active_op_array)->static_variables, Z_STR(varname->u.constant), &tmp);
- if (varname->op_type == IS_CONST) {
- if (Z_TYPE(varname->u.constant) != IS_STRING) {
- convert_to_string(&varname->u.constant);
- }
- }
+ zend_hash_update(CG(active_op_array)->static_variables, Z_STR(var_node.u.constant), value);
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = (fetch_type == ZEND_FETCH_LEXICAL) ? ZEND_FETCH_R : ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, varname);
- SET_UNUSED(opline->op2);
+ opline = zend_emit_op(&result, by_ref ? ZEND_FETCH_W : ZEND_FETCH_R, &var_node, NULL TSRMLS_CC);
opline->extended_value = ZEND_FETCH_STATIC;
- GET_NODE(&result, opline->result);
- if (varname->op_type == IS_CONST) {
- zval_copy_ctor(&varname->u.constant);
+ if (by_ref) {
+ zend_ast *fetch_ast = zend_ast_create(ZEND_AST_VAR, var_ast);
+ zend_emit_assign_ref_znode(fetch_ast, &result TSRMLS_CC);
+ } else {
+ zend_ast *fetch_ast = zend_ast_create(ZEND_AST_VAR, var_ast);
+ zend_emit_assign_znode(fetch_ast, &result TSRMLS_CC);
}
- fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
+}
+/* }}} */
- if (fetch_type == ZEND_FETCH_LEXICAL) {
- znode dummy;
+void zend_compile_static_var(zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *var_ast = ast->child[0];
+ zend_ast *value_ast = ast->child[1];
+ zval value_zv;
- zend_do_begin_variable_parse(TSRMLS_C);
- zend_do_assign(&dummy, &lval, &result TSRMLS_CC);
- zend_do_free(&dummy TSRMLS_CC);
+ if (value_ast) {
+ zend_const_expr_to_zval(&value_zv, value_ast TSRMLS_CC);
} else {
- zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
+ ZVAL_NULL(&value_zv);
}
- CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED;
+
+ zend_compile_static_var_common(var_ast, &value_zv, 1 TSRMLS_CC);
}
/* }}} */
-void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC) /* {{{ */
+void zend_compile_unset(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- znode value;
+ zend_ast *var_ast = ast->child[0];
- if (Z_STRLEN(varname->u.constant) == sizeof("this") - 1 &&
- memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1) == 0) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
- return;
+ znode var_node;
+ zend_op *opline;
+ switch (var_ast->kind) {
+ case ZEND_AST_VAR:
+ if (zend_try_compile_cv(&var_node, var_ast TSRMLS_CC) == SUCCESS) {
+ opline = zend_emit_op(NULL, ZEND_UNSET_VAR, &var_node, NULL TSRMLS_CC);
+ opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
+ } else {
+ opline = zend_compile_simple_var_no_cv(NULL, var_ast, BP_VAR_UNSET TSRMLS_CC);
+ opline->opcode = ZEND_UNSET_VAR;
+ }
+ return;
+ case ZEND_AST_DIM:
+ opline = zend_compile_dim_common(NULL, var_ast, BP_VAR_UNSET TSRMLS_CC);
+ opline->opcode = ZEND_UNSET_DIM;
+ return;
+ case ZEND_AST_PROP:
+ opline = zend_compile_prop_common(NULL, var_ast, BP_VAR_UNSET TSRMLS_CC);
+ opline->opcode = ZEND_UNSET_OBJ;
+ return;
+ case ZEND_AST_STATIC_PROP:
+ opline = zend_compile_static_prop_common(NULL, var_ast, BP_VAR_UNSET TSRMLS_CC);
+ opline->opcode = ZEND_UNSET_VAR;
+ return;
+ EMPTY_SWITCH_DEFAULT_CASE()
}
+}
+/* }}} */
+
+static void zend_free_foreach_and_switch_variables(TSRMLS_D) /* {{{ */
+{
+ uint32_t opnum_start, opnum_end, i;
- value.op_type = IS_CONST;
- ZVAL_NULL(&value.u.constant);
- Z_CONST_FLAGS(value.u.constant) = is_ref ? IS_LEXICAL_REF : IS_LEXICAL_VAR;
- zend_do_fetch_static_variable(varname, &value, is_ref ? ZEND_FETCH_STATIC : ZEND_FETCH_LEXICAL TSRMLS_CC);
+ opnum_start = get_next_op_number(CG(active_op_array));
+
+#ifdef ZTS
+ zend_stack_apply_with_argument(&CG(loop_var_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_loop_var TSRMLS_CC);
+#else
+ zend_stack_apply(&CG(loop_var_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_loop_var);
+#endif
+
+ opnum_end = get_next_op_number(CG(active_op_array));
+
+ for (i = opnum_start; i < opnum_end; ++i) {
+ CG(active_op_array)->opcodes[i].extended_value |= EXT_TYPE_FREE_ON_RETURN;
+ }
}
/* }}} */
-void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
+void zend_compile_return(zend_ast *ast TSRMLS_DC) /* {{{ */
{
+ zend_ast *expr_ast = ast->child[0];
+ zend_bool by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+
+ znode expr_node;
zend_op *opline;
- znode lval;
- znode result;
- if (varname->op_type == IS_CONST) {
- if (Z_TYPE(varname->u.constant) != IS_STRING) {
- convert_to_string(&varname->u.constant);
- }
+ if (!expr_ast) {
+ expr_node.op_type = IS_CONST;
+ ZVAL_NULL(&expr_node.u.constant);
+ } else if (by_ref && zend_is_variable(expr_ast) && !zend_is_call(expr_ast)) {
+ zend_compile_var(&expr_node, expr_ast, BP_VAR_REF TSRMLS_CC);
+ } else {
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
}
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_free_foreach_and_switch_variables(TSRMLS_C);
- if (varname->op_type == IS_CONST &&
- !zend_is_auto_global(Z_STR(varname->u.constant) TSRMLS_CC) &&
- !(Z_STRLEN(varname->u.constant) == (sizeof("this")-1) &&
- !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1))) {
- opline->opcode = ZEND_BIND_GLOBAL;
- SET_NODE(opline->op2, varname);
- opline->op1_type = IS_CV;
- zval_copy_ctor(&varname->u.constant);
- opline->op1.var = lookup_cv(CG(active_op_array), Z_STR(varname->u.constant) TSRMLS_CC);
- } else {
- opline->opcode = ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, varname);
- SET_UNUSED(opline->op2);
- opline->extended_value = fetch_type;
- GET_NODE(&result, opline->result);
+ if (CG(context).in_finally) {
+ zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL TSRMLS_CC);
+ }
- if (varname->op_type == IS_CONST) {
- zval_copy_ctor(&varname->u.constant);
- }
- fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
+ opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
+ &expr_node, NULL TSRMLS_CC);
- zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
- CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED;
+ if (expr_ast) {
+ if (zend_is_call(expr_ast)) {
+ opline->extended_value = ZEND_RETURNS_FUNCTION;
+ } else if (!zend_is_variable(expr_ast)) {
+ opline->extended_value = ZEND_RETURNS_VALUE;
+ }
}
}
/* }}} */
-void zend_do_cast(znode *result, znode *expr, int type TSRMLS_DC) /* {{{ */
+void zend_compile_echo(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_ast *expr_ast = ast->child[0];
- opline->opcode = ZEND_CAST;
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, expr);
- SET_UNUSED(opline->op2);
- opline->extended_value = type;
- GET_NODE(result, opline->result);
+ znode expr_node;
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL TSRMLS_CC);
}
/* }}} */
-void zend_do_include_or_eval(int type, znode *result, znode *op1 TSRMLS_DC) /* {{{ */
+void zend_compile_throw(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_do_extended_fcall_begin(TSRMLS_C);
- {
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_ast *expr_ast = ast->child[0];
- opline->opcode = ZEND_INCLUDE_OR_EVAL;
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, op1);
- SET_UNUSED(opline->op2);
- opline->extended_value = type;
- GET_NODE(result, opline->result);
+ znode expr_node;
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ zend_emit_op(NULL, ZEND_THROW, &expr_node, NULL TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_break_continue(zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *depth_ast = ast->child[0];
+
+ znode depth_node;
+ zend_op *opline;
+
+ ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE);
+
+ if (depth_ast) {
+ if (depth_ast->kind != ZEND_AST_ZVAL) {
+ zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand "
+ "is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue");
+ }
+
+ zend_compile_expr(&depth_node, depth_ast TSRMLS_CC);
+
+ if (Z_TYPE(depth_node.u.constant) != IS_LONG || Z_LVAL(depth_node.u.constant) < 1) {
+ zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers",
+ ast->kind == ZEND_AST_BREAK ? "break" : "continue");
+ }
+ } else {
+ depth_node.op_type = IS_CONST;
+ ZVAL_LONG(&depth_node.u.constant, 1);
}
- zend_do_extended_fcall_end(TSRMLS_C);
+
+ opline = zend_emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT,
+ NULL, &depth_node TSRMLS_CC);
+ opline->op1.opline_num = CG(context).current_brk_cont;
}
/* }}} */
-void zend_do_indirect_references(znode *result, const znode *num_references, znode *variable TSRMLS_DC) /* {{{ */
+void zend_compile_goto(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- int i;
+ zend_ast *label_ast = ast->child[0];
+ znode label_node;
+ zend_op *opline;
- zend_do_end_variable_parse(variable, BP_VAR_R, 0 TSRMLS_CC);
- for (i=1; i<Z_LVAL(num_references->u.constant); i++) {
- fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
- *variable = *result;
+ zend_compile_expr(&label_node, label_ast TSRMLS_CC);
+ opline = zend_emit_op(NULL, ZEND_GOTO, NULL, &label_node TSRMLS_CC);
+ opline->extended_value = CG(context).current_brk_cont;
+ zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_label(zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zval *label = zend_ast_get_zval(ast->child[0]);
+ zend_label dest;
+
+ ZEND_ASSERT(Z_TYPE_P(label) == IS_STRING);
+
+ if (!CG(context).labels) {
+ ALLOC_HASHTABLE(CG(context).labels);
+ zend_hash_init(CG(context).labels, 8, NULL, ptr_dtor, 0);
}
- zend_do_begin_variable_parse(TSRMLS_C);
- fetch_simple_variable(result, variable, 1 TSRMLS_CC);
- /* there is a chance someone is accessing $this */
- if (CG(active_op_array)->scope && CG(active_op_array)->this_var == -1) {
- zend_string *key = STR_INIT("this", sizeof("this")-1, 0);
- CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), key TSRMLS_CC);
+
+ dest.brk_cont = CG(context).current_brk_cont;
+ dest.opline_num = get_next_op_number(CG(active_op_array));
+
+ if (!zend_hash_add_mem(CG(context).labels, Z_STR_P(label), &dest, sizeof(zend_label))) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL_P(label));
}
}
/* }}} */
-void zend_do_unset(znode *variable TSRMLS_DC) /* {{{ */
+void zend_compile_while(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *last_op;
+ zend_ast *cond_ast = ast->child[0];
+ zend_ast *stmt_ast = ast->child[1];
- zend_check_writable_variable(variable);
+ znode cond_node;
+ uint32_t opnum_start, opnum_jmpz;
- if (variable->op_type == IS_CV) {
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_UNSET_VAR;
- SET_NODE(opline->op1, variable);
- SET_UNUSED(opline->op2);
- SET_UNUSED(opline->result);
- opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
- } else {
- last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
+ opnum_start = get_next_op_number(CG(active_op_array));
+ zend_compile_expr(&cond_node, cond_ast TSRMLS_CC);
- switch (last_op->opcode) {
- case ZEND_FETCH_UNSET:
- last_op->opcode = ZEND_UNSET_VAR;
- SET_UNUSED(last_op->result);
- break;
- case ZEND_FETCH_DIM_UNSET:
- last_op->opcode = ZEND_UNSET_DIM;
- SET_UNUSED(last_op->result);
- break;
- case ZEND_FETCH_OBJ_UNSET:
- last_op->opcode = ZEND_UNSET_OBJ;
- SET_UNUSED(last_op->result);
- break;
+ opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0 TSRMLS_CC);
+ zend_begin_loop(TSRMLS_C);
- }
- }
+ zend_compile_stmt(stmt_ast TSRMLS_CC);
+
+ zend_emit_jump(opnum_start TSRMLS_CC);
+
+ zend_update_jump_target_to_next(opnum_jmpz TSRMLS_CC);
+
+ zend_end_loop(opnum_start, 0 TSRMLS_CC);
}
/* }}} */
-void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC) /* {{{ */
+void zend_compile_do_while(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *last_op;
+ zend_ast *stmt_ast = ast->child[0];
+ zend_ast *cond_ast = ast->child[1];
- zend_do_end_variable_parse(variable, BP_VAR_IS, 0 TSRMLS_CC);
+ znode cond_node;
+ uint32_t opnum_start, opnum_cond;
- if (zend_is_function_or_method_call(variable)) {
- if (type == ZEND_ISEMPTY) {
- /* empty(func()) can be transformed to !func() */
- zend_do_unary_op(ZEND_BOOL_NOT, result, variable TSRMLS_CC);
- } else {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use isset() on the result of a function call (you can use \"null !== func()\" instead)");
- }
+ zend_begin_loop(TSRMLS_C);
- return;
- }
+ opnum_start = get_next_op_number(CG(active_op_array));
+ zend_compile_stmt(stmt_ast TSRMLS_CC);
- if (variable->op_type == IS_CV) {
- last_op = get_next_op(CG(active_op_array) TSRMLS_CC);
- last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
- SET_NODE(last_op->op1, variable);
- SET_UNUSED(last_op->op2);
- last_op->result.var = get_temporary_variable(CG(active_op_array));
- last_op->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
- } else {
- last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
+ opnum_cond = get_next_op_number(CG(active_op_array));
+ zend_compile_expr(&cond_node, cond_ast TSRMLS_CC);
- switch (last_op->opcode) {
- case ZEND_FETCH_IS:
- last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
- break;
- case ZEND_FETCH_DIM_IS:
- last_op->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
- break;
- case ZEND_FETCH_OBJ_IS:
- last_op->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
- break;
- }
- }
- last_op->result_type = IS_TMP_VAR;
- last_op->extended_value |= type;
+ zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start TSRMLS_CC);
- GET_NODE(result, last_op->result);
+ zend_end_loop(opnum_cond, 0 TSRMLS_CC);
}
/* }}} */
-void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC) /* {{{ */
+void zend_compile_expr_list(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- int last_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline;
+ zend_ast_list *list;
+ uint32_t i;
- if (last_op_number > 0) {
- opline = &CG(active_op_array)->opcodes[last_op_number-1];
- if (opline->opcode == ZEND_FETCH_CLASS) {
- opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
- }
+ result->op_type = IS_CONST;
+ ZVAL_TRUE(&result->u.constant);
+
+ if (!ast) {
+ return;
}
- if (expr->op_type == IS_CONST) {
- zend_error_noreturn(E_COMPILE_ERROR, "instanceof expects an object instance, constant given");
+ list = zend_ast_get_list(ast);
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *expr_ast = list->child[i];
+
+ zend_do_free(result TSRMLS_CC);
+ zend_compile_expr(result, expr_ast TSRMLS_CC);
}
+}
+/* }}} */
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_INSTANCEOF;
- opline->result_type = IS_TMP_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, expr);
+void zend_compile_for(zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *init_ast = ast->child[0];
+ zend_ast *cond_ast = ast->child[1];
+ zend_ast *loop_ast = ast->child[2];
+ zend_ast *stmt_ast = ast->child[3];
- SET_NODE(opline->op2, class_znode);
+ znode result;
+ uint32_t opnum_cond, opnum_jmpz, opnum_loop;
- GET_NODE(result, opline->result);
+ zend_compile_expr_list(&result, init_ast TSRMLS_CC);
+ zend_do_free(&result TSRMLS_CC);
+
+ opnum_cond = get_next_op_number(CG(active_op_array));
+ zend_compile_expr_list(&result, cond_ast TSRMLS_CC);
+ zend_do_extended_info(TSRMLS_C);
+
+ opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &result, 0 TSRMLS_CC);
+ zend_begin_loop(TSRMLS_C);
+
+ zend_compile_stmt(stmt_ast TSRMLS_CC);
+
+ opnum_loop = get_next_op_number(CG(active_op_array));
+ zend_compile_expr_list(&result, loop_ast TSRMLS_CC);
+ zend_do_free(&result TSRMLS_CC);
+
+ zend_emit_jump(opnum_cond TSRMLS_CC);
+
+ zend_update_jump_target_to_next(opnum_jmpz TSRMLS_CC);
+
+ zend_end_loop(opnum_loop, 0 TSRMLS_CC);
}
/* }}} */
-void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, znode *as_token, int variable TSRMLS_DC) /* {{{ */
+void zend_compile_foreach(zend_ast *ast TSRMLS_DC) /* {{{ */
{
+ zend_ast *expr_ast = ast->child[0];
+ zend_ast *value_ast = ast->child[1];
+ zend_ast *key_ast = ast->child[2];
+ zend_ast *stmt_ast = ast->child[3];
+ zend_bool by_ref = value_ast->kind == ZEND_AST_REF;
+ zend_bool is_variable = zend_is_variable(expr_ast) && !zend_is_call(expr_ast)
+ && zend_can_write_to_variable(expr_ast);
+
+ znode expr_node, reset_node, value_node, key_node, dummy_node;
zend_op *opline;
- zend_bool is_variable;
- zend_op dummy_opline;
+ uint32_t opnum_reset, opnum_fetch;
- if (variable) {
- if (zend_is_function_or_method_call(array)) {
- is_variable = 0;
- } else {
- is_variable = 1;
+ if (key_ast) {
+ if (key_ast->kind == ZEND_AST_REF) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
+ }
+ if (key_ast->kind == ZEND_AST_LIST) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
}
- /* save the location of FETCH_W instruction(s) */
- open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
- zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
- } else {
- is_variable = 0;
- open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
}
- /* save the location of FE_RESET */
- foreach_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
+ if (by_ref) {
+ value_ast = value_ast->child[0];
+ }
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ if (by_ref && is_variable) {
+ zend_compile_var(&expr_node, expr_ast, BP_VAR_W TSRMLS_CC);
+ } else {
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+ }
- /* Preform array reset */
- opline->opcode = ZEND_FE_RESET;
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, array);
- SET_UNUSED(opline->op2);
- opline->extended_value = is_variable ? ZEND_FE_RESET_VARIABLE : 0;
+ opnum_reset = get_next_op_number(CG(active_op_array));
+ opline = zend_emit_op(&reset_node, ZEND_FE_RESET, &expr_node, NULL TSRMLS_CC);
+ if (by_ref && is_variable) {
+ opline->extended_value = ZEND_FE_RESET_VARIABLE | ZEND_FE_RESET_REFERENCE; // ???
+ }
- COPY_NODE(dummy_opline.result, opline->result);
- zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline);
+ zend_stack_push(&CG(loop_var_stack), &reset_node);
- /* save the location of FE_FETCH */
- as_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
+ opnum_fetch = get_next_op_number(CG(active_op_array));
+ opline = zend_emit_op(&value_node, ZEND_FE_FETCH, &reset_node, NULL TSRMLS_CC);
+ if (by_ref) {
+ opline->extended_value |= ZEND_FE_FETCH_BYREF;
+ }
+ if (key_ast) {
+ opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
+ }
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_FE_FETCH;
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- COPY_NODE(opline->op1, dummy_opline.result);
- opline->extended_value = 0;
- SET_UNUSED(opline->op2);
+ opline = zend_emit_op(NULL, ZEND_OP_DATA, NULL, NULL TSRMLS_CC);
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_OP_DATA;
/* Allocate enough space to keep HashPointer on VM stack */
opline->op1_type = IS_TMP_VAR;
opline->op1.var = get_temporary_variable(CG(active_op_array));
if (sizeof(HashPointer) > sizeof(zval)) {
- /* Make shure 1 zval is enough for HashPointer (2 must be enough) */
+ /* Make sure 1 zval is enough for HashPointer (2 must be enough) */
get_temporary_variable(CG(active_op_array));
}
- SET_UNUSED(opline->op2);
- SET_UNUSED(opline->result);
+
+ if (key_ast) {
+ zend_make_tmp_result(&key_node, opline TSRMLS_CC);
+ }
+
+ if (value_ast->attr == ZEND_AST_LIST) {
+ zend_compile_list_assign(&dummy_node, value_ast, &value_node TSRMLS_CC);
+ zend_do_free(&dummy_node TSRMLS_CC);
+ } else if (by_ref) {
+ zend_emit_assign_ref_znode(value_ast, &value_node TSRMLS_CC);
+ } else {
+ zend_emit_assign_znode(value_ast, &value_node TSRMLS_CC);
+ }
+
+ if (key_ast) {
+ zend_emit_assign_znode(key_ast, &key_node TSRMLS_CC);
+ }
+
+ zend_begin_loop(TSRMLS_C);
+
+ zend_compile_stmt(stmt_ast TSRMLS_CC);
+
+ zend_emit_jump(opnum_fetch TSRMLS_CC);
+
+ opline = &CG(active_op_array)->opcodes[opnum_reset];
+ opline->op2.opline_num = get_next_op_number(CG(active_op_array));
+
+ opline = &CG(active_op_array)->opcodes[opnum_fetch];
+ opline->op2.opline_num = get_next_op_number(CG(active_op_array));
+
+ zend_end_loop(opnum_fetch, 1 TSRMLS_CC);
+
+ generate_free_loop_var(&reset_node TSRMLS_CC);
+ zend_stack_del_top(&CG(loop_var_stack));
}
/* }}} */
-void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token, const znode *as_token, znode *value, znode *key TSRMLS_DC) /* {{{ */
+void zend_compile_if(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline;
- znode dummy, value_node;
- zend_bool assign_by_ref=0;
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
+ uint32_t *jmp_opnums;
+
+ if (list->children > 1) {
+ jmp_opnums = safe_emalloc(sizeof(uint32_t), list->children - 1, 0);
+ }
- opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num];
- if (key->op_type != IS_UNUSED) {
- znode *tmp;
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *elem_ast = list->child[i];
+ zend_ast *cond_ast = elem_ast->child[0];
+ zend_ast *stmt_ast = elem_ast->child[1];
- /* switch between the key and value... */
- tmp = key;
- key = value;
- value = tmp;
+ znode cond_node;
+ uint32_t opnum_jmpz;
+ if (cond_ast) {
+ zend_compile_expr(&cond_node, cond_ast TSRMLS_CC);
+ opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0 TSRMLS_CC);
+ }
- /* Mark extended_value in case both key and value are being used */
- opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
- }
+ zend_compile_stmt(stmt_ast TSRMLS_CC);
- if ((key->op_type != IS_UNUSED)) {
- if (key->EA & ZEND_PARSED_REFERENCE_VARIABLE) {
- zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
+ if (i != list->children - 1) {
+ jmp_opnums[i] = zend_emit_jump(0 TSRMLS_CC);
}
- if (key->EA & ZEND_PARSED_LIST_EXPR) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
+
+ if (cond_ast) {
+ zend_update_jump_target_to_next(opnum_jmpz TSRMLS_CC);
}
}
- if (value->EA & ZEND_PARSED_REFERENCE_VARIABLE) {
- assign_by_ref = 1;
-
- /* Mark extended_value for assign-by-reference */
- opline->extended_value |= ZEND_FE_FETCH_BYREF;
- CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE;
- } else {
- zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.op.opline_num];
- zend_op *end = &CG(active_op_array)->opcodes[open_brackets_token->u.op.opline_num];
-
- /* Change "write context" into "read context" */
- fetch->extended_value = 0; /* reset ZEND_FE_RESET_VARIABLE */
- while (fetch != end) {
- --fetch;
- if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2_type == IS_UNUSED) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
- }
- if (fetch->opcode == ZEND_SEPARATE) {
- MAKE_NOP(fetch);
- } else {
- fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
- }
+ if (list->children > 1) {
+ for (i = 0; i < list->children - 1; ++i) {
+ zend_update_jump_target_to_next(jmp_opnums[i] TSRMLS_CC);
}
+ efree(jmp_opnums);
}
+}
+/* }}} */
- GET_NODE(&value_node, opline->result);
+void zend_compile_switch(zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *expr_ast = ast->child[0];
+ zend_ast_list *cases = zend_ast_get_list(ast->child[1]);
+
+ uint32_t i;
+ zend_bool has_default_case = 0;
+
+ znode expr_node, case_node;
+ zend_op *opline;
+ uint32_t *jmpnz_opnums = safe_emalloc(sizeof(uint32_t), cases->children, 0);
+ uint32_t opnum_default_jmp;
- if (value->EA & ZEND_PARSED_LIST_EXPR) {
- if (!CG(list_llist).head) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ zend_stack_push(&CG(loop_var_stack), &expr_node);
+
+ zend_begin_loop(TSRMLS_C);
+
+ case_node.op_type = IS_TMP_VAR;
+ case_node.u.op.var = get_temporary_variable(CG(active_op_array));
+
+ for (i = 0; i < cases->children; ++i) {
+ zend_ast *case_ast = cases->child[i];
+ zend_ast *cond_ast = case_ast->child[0];
+ znode cond_node;
+
+ if (!cond_ast) {
+ has_default_case = 1;
+ continue;
}
- zend_do_list_end(&dummy, &value_node TSRMLS_CC);
- zend_do_free(&dummy TSRMLS_CC);
- } else {
- if (assign_by_ref) {
- zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
- /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
- zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
+
+ zend_compile_expr(&cond_node, cond_ast TSRMLS_CC);
+
+ opline = zend_emit_op(NULL, ZEND_CASE, &expr_node, &cond_node TSRMLS_CC);
+ SET_NODE(opline->result, &case_node);
+ if (opline->op1_type == IS_CONST) {
+ zval_copy_ctor(&CONSTANT(opline->op1.constant));
+ }
+
+ jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0 TSRMLS_CC);
+ }
+
+ opnum_default_jmp = zend_emit_jump(0 TSRMLS_CC);
+
+ for (i = 0; i < cases->children; ++i) {
+ zend_ast *case_ast = cases->child[i];
+ zend_ast *cond_ast = case_ast->child[0];
+ zend_ast *stmt_ast = case_ast->child[1];
+
+ if (cond_ast) {
+ zend_update_jump_target_to_next(jmpnz_opnums[i] TSRMLS_CC);
} else {
- zend_do_assign(&dummy, value, &value_node TSRMLS_CC);
- zend_do_free(&dummy TSRMLS_CC);
+ zend_update_jump_target_to_next(opnum_default_jmp TSRMLS_CC);
}
+
+ zend_compile_stmt(stmt_ast TSRMLS_CC);
}
- if (key->op_type != IS_UNUSED) {
- znode key_node;
+ if (!has_default_case) {
+ zend_update_jump_target_to_next(opnum_default_jmp TSRMLS_CC);
+ }
- opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num+1];
- opline->result_type = IS_TMP_VAR;
- opline->result.opline_num = get_temporary_variable(CG(active_op_array));
- GET_NODE(&key_node, opline->result);
+ zend_end_loop(get_next_op_number(CG(active_op_array)), 1 TSRMLS_CC);
- zend_do_assign(&dummy, key, &key_node TSRMLS_CC);
- zend_do_free(&dummy TSRMLS_CC);
+ if (expr_node.op_type == IS_VAR || expr_node.op_type == IS_TMP_VAR) {
+ zend_emit_op(NULL, expr_node.op_type == IS_TMP_VAR ? ZEND_FREE : ZEND_SWITCH_FREE,
+ &expr_node, NULL TSRMLS_CC);
+ } else if (expr_node.op_type == IS_CONST) {
+ zval_dtor(&expr_node.u.constant);
}
- do_begin_loop(TSRMLS_C);
- INC_BPC(CG(active_op_array));
+ zend_stack_del_top(&CG(loop_var_stack));
+ efree(jmpnz_opnums);
}
/* }}} */
-void zend_do_foreach_end(const znode *foreach_token, const znode *as_token TSRMLS_DC) /* {{{ */
+void zend_compile_try(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *container_ptr;
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_ast *try_ast = ast->child[0];
+ zend_ast_list *catches = zend_ast_get_list(ast->child[1]);
+ zend_ast *finally_ast = ast->child[2];
- opline->opcode = ZEND_JMP;
- opline->op1.opline_num = as_token->u.op.opline_num;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
+ uint32_t i;
+ zend_op *opline;
+ uint32_t try_catch_offset = zend_add_try_element(
+ get_next_op_number(CG(active_op_array)) TSRMLS_CC);
+ uint32_t *jmp_opnums = safe_emalloc(sizeof(uint32_t), catches->children, 0);
- CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array)); /* FE_RESET */
- CG(active_op_array)->opcodes[as_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array)); /* FE_FETCH */
+ if (catches->children == 0 && !finally_ast) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
+ }
+
+ zend_compile_stmt(try_ast TSRMLS_CC);
+
+ if (catches->children != 0) {
+ jmp_opnums[0] = zend_emit_jump(0 TSRMLS_CC);
+ }
+
+ for (i = 0; i < catches->children; ++i) {
+ zend_ast *catch_ast = catches->child[i];
+ zend_ast *class_ast = catch_ast->child[0];
+ zend_ast *var_ast = catch_ast->child[1];
+ zend_ast *stmt_ast = catch_ast->child[2];
+ zval *var_name = zend_ast_get_zval(var_ast);
+ zend_bool is_last_catch = (i + 1 == catches->children);
+
+ uint32_t opnum_catch;
+
+ if (!zend_is_const_default_class_ref(class_ast)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
+ }
+
+ opnum_catch = get_next_op_number(CG(active_op_array));
+ if (i == 0) {
+ CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = opnum_catch;
+ }
+
+ CG(zend_lineno) = catch_ast->lineno;
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_CATCH;
+ opline->op1_type = IS_CONST;
+ opline->op1.constant = zend_add_class_name_literal(CG(active_op_array),
+ zend_resolve_class_name_ast(class_ast TSRMLS_CC) TSRMLS_CC);
+
+ opline->op2_type = IS_CV;
+ opline->op2.var = lookup_cv(CG(active_op_array), zend_string_copy(Z_STR_P(var_name)) TSRMLS_CC);
+ opline->result.num = is_last_catch;
+
+ zend_compile_stmt(stmt_ast TSRMLS_CC);
+
+ if (!is_last_catch) {
+ jmp_opnums[i + 1] = zend_emit_jump(0 TSRMLS_CC);
+ }
+
+ opline = &CG(active_op_array)->opcodes[opnum_catch];
+ opline->extended_value = get_next_op_number(CG(active_op_array));
+ }
+
+ for (i = 0; i < catches->children; ++i) {
+ zend_update_jump_target_to_next(jmp_opnums[i] TSRMLS_CC);
+ }
+
+ if (finally_ast) {
+ uint32_t opnum_jmp = get_next_op_number(CG(active_op_array)) + 1;
+
+ opline = zend_emit_op(NULL, ZEND_FAST_CALL, NULL, NULL TSRMLS_CC);
+ opline->op1.opline_num = opnum_jmp + 1;
+
+ zend_emit_op(NULL, ZEND_JMP, NULL, NULL TSRMLS_CC);
+
+ CG(context).in_finally++;
+ zend_compile_stmt(finally_ast TSRMLS_CC);
+ CG(context).in_finally--;
+
+ CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = opnum_jmp + 1;
+ CG(active_op_array)->try_catch_array[try_catch_offset].finally_end
+ = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_FINALLY_BLOCK;
- do_end_loop(as_token->u.op.opline_num, 1 TSRMLS_CC);
+ zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL TSRMLS_CC);
- container_ptr = zend_stack_top(&CG(foreach_copy_stack));
- generate_free_foreach_copy(container_ptr TSRMLS_CC);
- zend_stack_del_top(&CG(foreach_copy_stack));
+ zend_update_jump_target_to_next(opnum_jmp TSRMLS_CC);
+ }
- DEC_BPC(CG(active_op_array));
+ efree(jmp_opnums);
}
/* }}} */
-void zend_do_declare_begin(TSRMLS_D) /* {{{ */
+/* Encoding declarations must already be handled during parsing */
+void zend_handle_encoding_declaration(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_stack_push(&CG(declare_stack), &CG(declarables));
+ zend_ast_list *declares = zend_ast_get_list(ast);
+ uint32_t i;
+ for (i = 0; i < declares->children; ++i) {
+ zend_ast *declare_ast = declares->child[i];
+ zend_ast *name_ast = declare_ast->child[0];
+ zend_ast *value_ast = declare_ast->child[1];
+ zend_string *name = zend_ast_get_str(name_ast);
+
+ if (zend_string_equals_literal_ci(name, "encoding")) {
+ if (value_ast->kind != ZEND_AST_ZVAL) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Encoding must be a literal");
+ }
+
+ if (CG(multibyte)) {
+ zend_string *encoding_name = zval_get_string(zend_ast_get_zval(value_ast));
+
+ const zend_encoding *new_encoding, *old_encoding;
+ zend_encoding_filter old_input_filter;
+
+ CG(encoding_declared) = 1;
+
+ new_encoding = zend_multibyte_fetch_encoding(encoding_name->val TSRMLS_CC);
+ if (!new_encoding) {
+ zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", encoding_name->val);
+ } else {
+ old_input_filter = LANG_SCNG(input_filter);
+ old_encoding = LANG_SCNG(script_encoding);
+ zend_multibyte_set_filter(new_encoding TSRMLS_CC);
+
+ /* need to re-scan if input filter changed */
+ if (old_input_filter != LANG_SCNG(input_filter) ||
+ (old_input_filter && new_encoding != old_encoding)) {
+ zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
+ }
+ }
+
+ zend_string_release(encoding_name);
+ } else {
+ zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because "
+ "Zend multibyte feature is turned off by settings");
+ }
+ }
+ }
}
/* }}} */
-void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC) /* {{{ */
+void zend_compile_declare(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- if (!zend_binary_strcasecmp(Z_STRVAL(var->u.constant), Z_STRLEN(var->u.constant), "ticks", sizeof("ticks")-1)) {
- convert_to_long(&val->u.constant);
- CG(declarables).ticks = val->u.constant;
- } else if (!zend_binary_strcasecmp(Z_STRVAL(var->u.constant), Z_STRLEN(var->u.constant), "encoding", sizeof("encoding")-1)) {
- if (Z_TYPE(val->u.constant) == IS_CONSTANT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use constants as encoding");
- }
+ zend_ast_list *declares = zend_ast_get_list(ast->child[0]);
+ zend_ast *stmt_ast = ast->child[1];
+ zend_declarables orig_declarables = CG(declarables);
+ uint32_t i;
- /*
- * Check that the pragma comes before any opcodes. If the compilation
- * got as far as this, the previous portion of the script must have been
- * parseable according to the .ini script_encoding setting. We still
- * want to tell them to put declare() at the top.
- */
- {
- int num = CG(active_op_array)->last;
- /* ignore ZEND_EXT_STMT and ZEND_TICKS */
+ for (i = 0; i < declares->children; ++i) {
+ zend_ast *declare_ast = declares->child[i];
+ zend_ast *name_ast = declare_ast->child[0];
+ zend_ast *value_ast = declare_ast->child[1];
+
+ zend_string *name = zend_ast_get_str(name_ast);
+ if (zend_string_equals_literal_ci(name, "ticks")) {
+ zval value_zv;
+ zend_const_expr_to_zval(&value_zv, value_ast TSRMLS_CC);
+ convert_to_long(&value_zv);
+ ZVAL_COPY_VALUE(&CG(declarables).ticks, &value_zv);
+ zval_dtor(&value_zv);
+ } else if (zend_string_equals_literal_ci(name, "encoding")) {
+ /* Encoding declaration was already handled during parsing. Here we
+ * only check that it is the first statement in the file. */
+ uint32_t num = CG(active_op_array)->last;
while (num > 0 &&
- (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
- CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
+ (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
+ CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
--num;
}
if (num > 0) {
- zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be the very first statement in the script");
+ zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
+ "the very first statement in the script");
}
+ } else {
+ zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", name->val);
}
+ }
- if (CG(multibyte)) {
- const zend_encoding *new_encoding, *old_encoding;
- zend_encoding_filter old_input_filter;
-
- CG(encoding_declared) = 1;
+ if (stmt_ast) {
+ zend_compile_stmt(stmt_ast TSRMLS_CC);
- convert_to_string(&val->u.constant);
- new_encoding = zend_multibyte_fetch_encoding(Z_STRVAL(val->u.constant) TSRMLS_CC);
- if (!new_encoding) {
- zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", Z_STRVAL(val->u.constant));
- } else {
- old_input_filter = LANG_SCNG(input_filter);
- old_encoding = LANG_SCNG(script_encoding);
- zend_multibyte_set_filter(new_encoding TSRMLS_CC);
-
- /* need to re-scan if input filter changed */
- if (old_input_filter != LANG_SCNG(input_filter) ||
- (old_input_filter && new_encoding != old_encoding)) {
- zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
- }
- }
- } else {
- zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because Zend multibyte feature is turned off by settings");
- }
- zval_dtor(&val->u.constant);
- } else {
- zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", Z_STRVAL(var->u.constant));
- zval_dtor(&val->u.constant);
+ CG(declarables) = orig_declarables;
}
- zval_dtor(&var->u.constant);
}
/* }}} */
-void zend_do_declare_end(const znode *declare_token TSRMLS_DC) /* {{{ */
+void zend_compile_stmt_list(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_declarables *declarables = zend_stack_top(&CG(declare_stack));
- /* We should restore if there was more than (current - start) - (ticks?1:0) opcodes */
- if ((get_next_op_number(CG(active_op_array)) - declare_token->u.op.opline_num) - ((Z_LVAL(CG(declarables).ticks))?1:0)) {
- CG(declarables) = *declarables;
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
+ for (i = 0; i < list->children; ++i) {
+ zend_compile_stmt(list->child[i] TSRMLS_CC);
}
}
/* }}} */
-void zend_do_exit(znode *result, znode *message TSRMLS_DC) /* {{{ */
+void zend_compile_params(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
+ zend_op_array *op_array = CG(active_op_array);
+ zend_arg_info *arg_infos;
- opline->opcode = ZEND_EXIT;
- SET_NODE(opline->op1, message);
- SET_UNUSED(opline->op2);
+ if (list->children == 0) {
+ return;
+ }
+
+ arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children, 0);
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *param_ast = list->child[i];
+ zend_ast *type_ast = param_ast->child[0];
+ zend_ast *var_ast = param_ast->child[1];
+ zend_ast *default_ast = param_ast->child[2];
+ zend_string *name = zend_ast_get_str(var_ast);
+ zend_bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
+ zend_bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
+
+ znode var_node, default_node;
+ zend_uchar opcode;
+ zend_op *opline;
+ zend_arg_info *arg_info;
- result->op_type = IS_CONST;
- ZVAL_BOOL(&result->u.constant, 1);
-}
-/* }}} */
+ if (zend_is_auto_global(name TSRMLS_CC)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s",
+ name->val);
+ }
-void zend_do_begin_silence(znode *strudel_token TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ var_node.op_type = IS_CV;
+ var_node.u.op.var = lookup_cv(CG(active_op_array), zend_string_copy(name) TSRMLS_CC);
- opline->opcode = ZEND_BEGIN_SILENCE;
- opline->result_type = IS_TMP_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- GET_NODE(strudel_token, opline->result);
-}
-/* }}} */
+ if (EX_VAR_TO_NUM(var_node.u.op.var) != i) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter $%s",
+ name->val);
+ } else if (zend_string_equals_literal(name, "this")) {
+ if (op_array->scope && (op_array->fn_flags & ZEND_ACC_STATIC) == 0) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
+ }
+ op_array->this_var = var_node.u.op.var;
+ }
-void zend_do_end_silence(znode *strudel_token TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
+ }
- opline->opcode = ZEND_END_SILENCE;
- SET_NODE(opline->op1, strudel_token);
- SET_UNUSED(opline->op2);
+ if (is_variadic) {
+ opcode = ZEND_RECV_VARIADIC;
+ default_node.op_type = IS_UNUSED;
+ op_array->fn_flags |= ZEND_ACC_VARIADIC;
+
+ if (default_ast) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Variadic parameter cannot have a default value");
+ }
+ } else if (default_ast) {
+ opcode = ZEND_RECV_INIT;
+ default_node.op_type = IS_CONST;
+ zend_const_expr_to_zval(&default_node.u.constant, default_ast TSRMLS_CC);
+ } else {
+ opcode = ZEND_RECV;
+ default_node.op_type = IS_UNUSED;
+ op_array->required_num_args = i + 1;
+ }
+
+ opline = zend_emit_op(NULL, opcode, NULL, &default_node TSRMLS_CC);
+ SET_NODE(opline->result, &var_node);
+ opline->op1.num = i + 1;
+
+ arg_info = &arg_infos[i];
+ arg_info->name = estrndup(name->val, name->len);
+ arg_info->name_len = name->len;
+ arg_info->pass_by_reference = is_ref;
+ arg_info->is_variadic = is_variadic;
+ arg_info->type_hint = 0;
+ arg_info->allow_null = 1;
+ arg_info->class_name = NULL;
+ arg_info->class_name_len = 0;
+
+ if (type_ast) {
+ zend_bool has_null_default = default_ast
+ && (Z_TYPE(default_node.u.constant) == IS_NULL
+ || (Z_TYPE(default_node.u.constant) == IS_CONSTANT
+ && strcasecmp(Z_STRVAL(default_node.u.constant), "NULL") == 0)
+ || Z_TYPE(default_node.u.constant) == IS_CONSTANT_AST); // ???
+
+ op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
+ arg_info->allow_null = has_null_default;
+
+ if (type_ast->kind == ZEND_AST_TYPE) {
+ arg_info->type_hint = type_ast->attr;
+ if (arg_info->type_hint == IS_ARRAY) {
+ if (default_ast && !has_null_default
+ && Z_TYPE(default_node.u.constant) != IS_ARRAY
+ ) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
+ "with array type hint can only be an array or NULL");
+ }
+ } else if (arg_info->type_hint == IS_CALLABLE && default_ast) {
+ if (!has_null_default) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
+ "with callable type hint can only be NULL");
+ }
+ }
+ } else {
+ zend_string *class_name = zend_ast_get_str(type_ast);
+
+ if (zend_is_const_default_class_ref(type_ast)) {
+ class_name = zend_resolve_class_name_ast(type_ast TSRMLS_CC);
+ } else {
+ zend_string_addref(class_name);
+ }
+
+ arg_info->type_hint = IS_OBJECT;
+ arg_info->class_name = estrndup(class_name->val, class_name->len);
+ arg_info->class_name_len = class_name->len;
+
+ zend_string_release(class_name);
+
+ if (default_ast && !has_null_default) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
+ "with a class type hint can only be NULL");
+ }
+ }
+ }
+ }
+
+ /* These are assigned at the end to avoid unitialized memory in case of an error */
+ op_array->num_args = list->children;
+ op_array->arg_info = arg_infos;
}
/* }}} */
-void zend_do_jmp_set(znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC) /* {{{ */
+void zend_compile_closure_uses(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- int op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
- if (value->op_type == IS_VAR || value->op_type == IS_CV) {
- opline->opcode = ZEND_JMP_SET_VAR;
- opline->result_type = IS_VAR;
- } else {
- opline->opcode = ZEND_JMP_SET;
- opline->result_type = IS_TMP_VAR;
- }
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, value);
- SET_UNUSED(opline->op2);
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *var_ast = list->child[i];
+ zend_string *name = zend_ast_get_str(var_ast);
+ zend_bool by_ref = var_ast->attr;
+ zval zv;
- GET_NODE(colon_token, opline->result);
+ if (zend_string_equals_literal(name, "this")) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
+ }
- jmp_token->u.op.opline_num = op_number;
+ ZVAL_NULL(&zv);
+ Z_CONST_FLAGS(zv) = by_ref ? IS_LEXICAL_REF : IS_LEXICAL_VAR;
- INC_BPC(CG(active_op_array));
+ zend_compile_static_var_common(var_ast, &zv, by_ref TSRMLS_CC);
+ }
}
/* }}} */
-void zend_do_jmp_set_else(znode *result, znode *false_value, const znode *jmp_token, znode *colon_token TSRMLS_DC) /* {{{ */
+void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_bool has_body TSRMLS_DC) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_class_entry *ce = CG(active_class_entry);
+ zend_bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0;
+ zend_bool in_trait = ZEND_CE_IS_TRAIT(ce);
+ zend_bool is_public = (op_array->fn_flags & ZEND_ACC_PUBLIC) != 0;
+ zend_bool is_static = (op_array->fn_flags & ZEND_ACC_STATIC) != 0;
- SET_NODE(opline->result, colon_token);
- if (colon_token->op_type == IS_TMP_VAR) {
- if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
- CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].opcode = ZEND_JMP_SET_VAR;
- CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].result_type = IS_VAR;
- opline->opcode = ZEND_QM_ASSIGN_VAR;
- opline->result_type = IS_VAR;
- } else {
- opline->opcode = ZEND_QM_ASSIGN;
+ zend_string *lcname;
+
+ if (in_interface) {
+ if ((op_array->fn_flags & ZEND_ACC_PPP_MASK) != ZEND_ACC_PUBLIC) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method "
+ "%s::%s() must be omitted", ce->name->val, name->val);
}
- } else {
- opline->opcode = ZEND_QM_ASSIGN_VAR;
+ op_array->fn_flags |= ZEND_ACC_ABSTRACT;
+ } else if (is_static && (op_array->fn_flags & ZEND_ACC_ABSTRACT)) {
+ zend_error(E_STRICT, "Static function %s::%s() should not be abstract",
+ ce->name->val, name->val);
}
- opline->extended_value = 0;
- SET_NODE(opline->op1, false_value);
- SET_UNUSED(opline->op2);
- GET_NODE(result, opline->result);
+ if (op_array->fn_flags & ZEND_ACC_ABSTRACT) {
+ //zend_op *opline;
+
+ if (op_array->fn_flags & ZEND_ACC_PRIVATE) {
+ zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private",
+ in_interface ? "Interface" : "Abstract", ce->name->val, name->val);
+ }
+
+ if (has_body) {
+ zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body",
+ in_interface ? "Interface" : "Abstract", ce->name->val, name->val);
+ }
+
+ ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
- CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
+ /*opline = get_next_op(op_array TSRMLS_CC);
+ opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
+ SET_UNUSED(opline->op1);
+ SET_UNUSED(opline->op2);*/
+ } else if (!has_body) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body",
+ ce->name->val, name->val);
+ }
+
+ op_array->scope = ce;
+ op_array->function_name = zend_string_copy(name);
+
+ lcname = zend_string_alloc(name->len, 0);
+ zend_str_tolower_copy(lcname->val, name->val, name->len);
+ lcname = zend_new_interned_string(lcname TSRMLS_CC);
+
+ if (zend_hash_add_ptr(&ce->function_table, lcname, op_array) == NULL) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()",
+ ce->name->val, name->val);
+ }
+
+ if (in_interface) {
+ if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __call() must have "
+ "public visibility and cannot be static");
+ }
+ } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
+ if (!is_public || !is_static) {
+ zend_error(E_WARNING, "The magic method __callStatic() must have "
+ "public visibility and be static");
+ }
+ } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __get() must have "
+ "public visibility and cannot be static");
+ }
+ } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __set() must have "
+ "public visibility and cannot be static");
+ }
+ } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __unset() must have "
+ "public visibility and cannot be static");
+ }
+ } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __isset() must have "
+ "public visibility and cannot be static");
+ }
+ } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __toString() must have "
+ "public visibility and cannot be static");
+ }
+ } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __invoke() must have "
+ "public visibility and cannot be static");
+ }
+ } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __debugInfo() must have "
+ "public visibility and cannot be static");
+ }
+ }
+ } else {
+ if (!in_trait && zend_string_equals_str_ci(lcname, ce->name)) {
+ if (!ce->constructor) {
+ ce->constructor = (zend_function *) op_array;
+ }
+ } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
+ if (CG(active_class_entry)->constructor) {
+ zend_error(E_STRICT, "Redefining already defined constructor for class %s",
+ ce->name->val);
+ }
+ ce->constructor = (zend_function *) op_array;
+ } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
+ ce->destructor = (zend_function *) op_array;
+ } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
+ ce->clone = (zend_function *) op_array;
+ } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __call() must have "
+ "public visibility and cannot be static");
+ }
+ ce->__call = (zend_function *) op_array;
+ } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
+ if (!is_public || !is_static) {
+ zend_error(E_WARNING, "The magic method __callStatic() must have "
+ "public visibility and be static");
+ }
+ ce->__callstatic = (zend_function *) op_array;
+ } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __get() must have "
+ "public visibility and cannot be static");
+ }
+ ce->__get = (zend_function *) op_array;
+ } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __set() must have "
+ "public visibility and cannot be static");
+ }
+ ce->__set = (zend_function *) op_array;
+ } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __unset() must have "
+ "public visibility and cannot be static");
+ }
+ ce->__unset = (zend_function *) op_array;
+ } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __isset() must have "
+ "public visibility and cannot be static");
+ }
+ ce->__isset = (zend_function *) op_array;
+ } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __toString() must have "
+ "public visibility and cannot be static");
+ }
+ ce->__tostring = (zend_function *) op_array;
+ } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __invoke() must have "
+ "public visibility and cannot be static");
+ }
+ } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
+ if (!is_public || is_static) {
+ zend_error(E_WARNING, "The magic method __debugInfo() must have "
+ "public visibility and cannot be static");
+ }
+ ce->__debugInfo = (zend_function *) op_array;
+ } else if (!is_static) {
+ op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC;
+ }
+ }
- DEC_BPC(CG(active_op_array));
+ zend_string_release(lcname);
}
/* }}} */
-void zend_do_begin_qm_op(znode *cond, znode *qm_token TSRMLS_DC) /* {{{ */
+static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl TSRMLS_DC) /* {{{ */
{
- int jmpz_op_number = get_next_op_number(CG(active_op_array));
+ zend_ast *params_ast = decl->child[0];
+ zend_string *name = decl->name, *lcname;
zend_op *opline;
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ op_array->function_name = name = zend_prefix_with_ns(name TSRMLS_CC);
- opline->opcode = ZEND_JMPZ;
- SET_NODE(opline->op1, cond);
- SET_UNUSED(opline->op2);
- opline->op2.opline_num = jmpz_op_number;
- GET_NODE(qm_token, opline->op2);
+ lcname = zend_string_alloc(name->len, 0);
+ zend_str_tolower_copy(lcname->val, name->val, name->len);
- INC_BPC(CG(active_op_array));
+ if (CG(current_import_function)) {
+ zend_string *import_name = zend_hash_find_ptr(CG(current_import_function), lcname);
+ if (import_name && !zend_string_equals_str_ci(lcname, import_name)) {
+ zend_error(E_COMPILE_ERROR, "Cannot declare function %s "
+ "because the name is already in use", name->val);
+ }
+ }
+
+ if (zend_string_equals_literal(lcname, ZEND_AUTOLOAD_FUNC_NAME)
+ && zend_ast_get_list(params_ast)->children != 1
+ ) {
+ zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument",
+ ZEND_AUTOLOAD_FUNC_NAME);
+ }
+
+ if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
+ opline = zend_emit_op_tmp(result, ZEND_DECLARE_LAMBDA_FUNCTION, NULL, NULL TSRMLS_CC);
+ } else {
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_DECLARE_FUNCTION;
+ opline->op2_type = IS_CONST;
+ LITERAL_STR(opline->op2, zend_string_copy(lcname));
+ }
+
+ {
+ zend_string *key = zend_build_runtime_definition_key(lcname, decl->lex_pos TSRMLS_CC);
+
+ opline->op1_type = IS_CONST;
+ LITERAL_STR(opline->op1, key);
+
+ zend_hash_update_ptr(CG(function_table), key, op_array);
+ }
+
+ zend_string_release(lcname);
}
/* }}} */
-void zend_do_qm_true(znode *true_value, znode *qm_token, znode *colon_token TSRMLS_DC) /* {{{ */
+void zend_compile_func_decl(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_ast_decl *decl = (zend_ast_decl *) ast;
+ zend_ast *params_ast = decl->child[0];
+ zend_ast *uses_ast = decl->child[1];
+ zend_ast *stmt_ast = decl->child[2];
+ zend_bool is_method = decl->kind == ZEND_AST_METHOD;
- CG(active_op_array)->opcodes[qm_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */
+ zend_op_array *orig_op_array = CG(active_op_array);
+ zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
- if (true_value->op_type == IS_VAR || true_value->op_type == IS_CV) {
- opline->opcode = ZEND_QM_ASSIGN_VAR;
- opline->result_type = IS_VAR;
+ // TODO.AST interactive (not just here - also bpc etc!)
+
+ init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
+
+ op_array->fn_flags |= decl->flags;
+ op_array->line_start = decl->start_lineno;
+ op_array->line_end = decl->end_lineno;
+ if (decl->doc_comment) {
+ op_array->doc_comment = zend_string_copy(decl->doc_comment);
+ }
+ if (decl->kind == ZEND_AST_CLOSURE) {
+ op_array->fn_flags |= ZEND_ACC_CLOSURE;
+ }
+
+ if (is_method) {
+ zend_bool has_body = stmt_ast != NULL;
+ zend_begin_method_decl(op_array, decl->name, has_body TSRMLS_CC);
} else {
- opline->opcode = ZEND_QM_ASSIGN;
- opline->result_type = IS_TMP_VAR;
+ zend_begin_func_decl(result, op_array, decl TSRMLS_CC);
}
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, true_value);
- SET_UNUSED(opline->op2);
- GET_NODE(qm_token, opline->result);
- colon_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
+ CG(active_op_array) = op_array;
+ zend_stack_push(&CG(context_stack), (void *) &CG(context));
+ zend_init_compiler_context(TSRMLS_C);
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_JMP;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
+ if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
+ zend_op *opline_ext = zend_emit_op(NULL, ZEND_EXT_NOP, NULL, NULL TSRMLS_CC);
+ opline_ext->lineno = decl->start_lineno;
+ }
+
+ {
+ /* Push a separator to the loop variable stack */
+ znode dummy_var;
+ dummy_var.op_type = IS_UNUSED;
+
+ zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var);
+ }
+
+ zend_compile_params(params_ast TSRMLS_CC);
+ if (uses_ast) {
+ zend_compile_closure_uses(uses_ast TSRMLS_CC);
+ }
+ zend_compile_stmt(stmt_ast TSRMLS_CC);
+
+ if (is_method) {
+ zend_check_magic_method_implementation(
+ CG(active_class_entry), (zend_function *) op_array, E_COMPILE_ERROR TSRMLS_CC);
+ }
+
+ zend_do_extended_info(TSRMLS_C);
+ zend_emit_final_return(NULL TSRMLS_CC);
+
+ pass_two(CG(active_op_array) TSRMLS_CC);
+ zend_release_labels(0 TSRMLS_CC);
+
+ /* Pop the loop variable stack separator */
+ zend_stack_del_top(&CG(loop_var_stack));
+
+ CG(active_op_array) = orig_op_array;
}
/* }}} */
-void zend_do_qm_false(znode *result, znode *false_value, znode *qm_token, const znode *colon_token TSRMLS_DC) /* {{{ */
+void zend_compile_prop_decl(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t flags = list->attr;
+ zend_class_entry *ce = CG(active_class_entry);
+ uint32_t i, children = list->children;
+ zend_string *doc_comment = NULL;
- SET_NODE(opline->result, qm_token);
- if (qm_token->op_type == IS_TMP_VAR) {
- if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
- CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].opcode = ZEND_QM_ASSIGN_VAR;
- CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].result_type = IS_VAR;
- opline->opcode = ZEND_QM_ASSIGN_VAR;
- opline->result_type = IS_VAR;
- } else {
- opline->opcode = ZEND_QM_ASSIGN;
- }
- } else {
- opline->opcode = ZEND_QM_ASSIGN_VAR;
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Interfaces may not include member variables");
}
- SET_NODE(opline->op1, false_value);
- SET_UNUSED(opline->op2);
- CG(active_op_array)->opcodes[colon_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
+ if (flags & ZEND_ACC_ABSTRACT) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract");
+ }
- GET_NODE(result, opline->result);
+ /* Doc comment has been appended as last element in property list */
+ if (list->child[children - 1]->kind == ZEND_AST_ZVAL) {
+ doc_comment = zend_string_copy(zend_ast_get_str(list->child[children - 1]));
+ children -= 1;
+ }
+
+ for (i = 0; i < children; ++i) {
+ zend_ast *prop_ast = list->child[i];
+ zend_ast *name_ast = prop_ast->child[0];
+ zend_ast *value_ast = prop_ast->child[1];
+ zend_string *name = zend_ast_get_str(name_ast);
+ zval value_zv;
- DEC_BPC(CG(active_op_array));
+ if (flags & ZEND_ACC_FINAL) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, "
+ "the final modifier is allowed only for methods and classes",
+ ce->name->val, name->val);
+ }
+
+ if (zend_hash_exists(&ce->properties_info, name)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s",
+ ce->name->val, name->val);
+ }
+
+ if (value_ast) {
+ zend_const_expr_to_zval(&value_zv, value_ast TSRMLS_CC);
+ } else {
+ ZVAL_NULL(&value_zv);
+ }
+
+ name = zend_new_interned_string_safe(name TSRMLS_CC);
+ zend_declare_property_ex(ce, name, &value_zv, flags, doc_comment TSRMLS_CC);
+
+ /* Doc comment is only assigned to first property */
+ doc_comment = NULL;
+ }
}
/* }}} */
-void zend_do_extended_info(TSRMLS_D) /* {{{ */
+void zend_compile_class_const_decl(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline;
+ zend_ast_list *list = zend_ast_get_list(ast);
+ zend_class_entry *ce = CG(active_class_entry);
+ uint32_t i;
- if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
- return;
- }
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *const_ast = list->child[i];
+ zend_ast *name_ast = const_ast->child[0];
+ zend_ast *value_ast = const_ast->child[1];
+ zend_string *name = zend_ast_get_str(name_ast);
+ zval value_zv;
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ if (ZEND_CE_IS_TRAIT(ce)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants");
+ return;
+ }
- opline->opcode = ZEND_EXT_STMT;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
+ zend_const_expr_to_zval(&value_zv, value_ast TSRMLS_CC);
+
+ name = zend_new_interned_string_safe(name TSRMLS_CC);
+ if (zend_hash_add(&ce->constants_table, name, &value_zv) == NULL) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s",
+ ce->name->val, name->val);
+ }
+
+ if (Z_CONSTANT(value_zv)) {
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ }
+ }
}
/* }}} */
-void zend_do_extended_fcall_begin(TSRMLS_D) /* {{{ */
+static zend_trait_method_reference *zend_compile_method_ref(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline;
+ zend_ast *class_ast = ast->child[0];
+ zend_ast *method_ast = ast->child[1];
- if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
- return;
- }
+ zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
+ method_ref->ce = NULL;
+ method_ref->method_name = zend_string_copy(zend_ast_get_str(method_ast));
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ if (class_ast) {
+ method_ref->class_name = zend_resolve_class_name_ast(class_ast TSRMLS_CC);
+ } else {
+ method_ref->class_name = NULL;
+ }
- opline->opcode = ZEND_EXT_FCALL_BEGIN;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
+ return method_ref;
}
/* }}} */
-void zend_do_extended_fcall_end(TSRMLS_D) /* {{{ */
+static zend_string **zend_compile_name_list(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline;
+ zend_ast_list *list = zend_ast_get_list(ast);
+ zend_string **names = safe_emalloc(sizeof(zend_string *), list->children + 1, 0);
+ uint32_t i;
- if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
- return;
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *name_ast = list->child[i];
+ names[i] = zend_resolve_class_name_ast(name_ast TSRMLS_CC);
}
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ names[list->children] = NULL;
- opline->opcode = ZEND_EXT_FCALL_END;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
+ return names;
}
/* }}} */
-void zend_do_ticks(TSRMLS_D) /* {{{ */
+static void zend_compile_trait_precedence(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_ast *method_ref_ast = ast->child[0];
+ zend_ast *insteadof_ast = ast->child[1];
+
+ zend_trait_precedence *precedence = emalloc(sizeof(zend_trait_precedence));
+ precedence->trait_method = zend_compile_method_ref(method_ref_ast TSRMLS_CC);
+ precedence->exclude_from_classes
+ = (void *) zend_compile_name_list(insteadof_ast TSRMLS_CC);
- opline->opcode = ZEND_TICKS;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- opline->extended_value = Z_LVAL(CG(declarables).ticks);
+ zend_add_to_list(&CG(active_class_entry)->trait_precedences, precedence TSRMLS_CC);
}
/* }}} */
-zend_bool zend_is_auto_global(zend_string *name TSRMLS_DC) /* {{{ */
+static void zend_compile_trait_alias(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_auto_global *auto_global;
+ zend_ast *method_ref_ast = ast->child[0];
+ zend_ast *alias_ast = ast->child[1];
+ uint32_t modifiers = ast->attr;
- if ((auto_global = zend_hash_find_ptr(CG(auto_globals), name)) != NULL) {
- if (auto_global->armed) {
- auto_global->armed = auto_global->auto_global_callback(auto_global->name TSRMLS_CC);
- }
- return 1;
+ zend_trait_alias *alias;
+
+ if (modifiers == ZEND_ACC_STATIC) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier");
+ } else if (modifiers == ZEND_ACC_ABSTRACT) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier");
+ } else if (modifiers == ZEND_ACC_FINAL) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier");
}
- return 0;
+
+ alias = emalloc(sizeof(zend_trait_alias));
+ alias->trait_method = zend_compile_method_ref(method_ref_ast TSRMLS_CC);
+ alias->modifiers = modifiers;
+
+ if (alias_ast) {
+ alias->alias = zend_string_copy(zend_ast_get_str(alias_ast));
+ } else {
+ alias->alias = NULL;
+ }
+
+ zend_add_to_list(&CG(active_class_entry)->trait_aliases, alias TSRMLS_CC);
}
/* }}} */
-int zend_register_auto_global(zend_string *name, zend_bool jit, zend_auto_global_callback auto_global_callback TSRMLS_DC) /* {{{ */
+void zend_compile_use_trait(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_auto_global auto_global;
- int retval;
+ zend_ast_list *traits = zend_ast_get_list(ast->child[0]);
+ zend_ast_list *adaptations = ast->child[1] ? zend_ast_get_list(ast->child[1]) : NULL;
+ zend_class_entry *ce = CG(active_class_entry);
+ zend_op *opline;
+ uint32_t i;
- auto_global.name = zend_new_interned_string(name TSRMLS_CC);
- auto_global.auto_global_callback = auto_global_callback;
- auto_global.jit = jit;
+ for (i = 0; i < traits->children; ++i) {
+ zend_ast *trait_ast = traits->child[i];
+ zend_string *name = zend_ast_get_str(trait_ast);
- retval = zend_hash_add_mem(CG(auto_globals), name, &auto_global, sizeof(zend_auto_global)) != NULL ? SUCCESS : FAILURE;
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use traits inside of interfaces. "
+ "%s is used in %s", name->val, ce->name->val);
+ }
- STR_RELEASE(auto_global.name);
- return retval;
+ switch (zend_get_class_fetch_type(name)) {
+ case ZEND_FETCH_CLASS_SELF:
+ case ZEND_FETCH_CLASS_PARENT:
+ case ZEND_FETCH_CLASS_STATIC:
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as trait name "
+ "as it is reserved", name->val);
+ break;
+ }
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_ADD_TRAIT;
+ SET_NODE(opline->op1, &CG(implementing_class));
+ opline->extended_value = ZEND_FETCH_CLASS_TRAIT;
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
+ zend_resolve_class_name_ast(trait_ast TSRMLS_CC) TSRMLS_CC);
+
+ ce->num_traits++;
+ }
+
+ if (!adaptations) {
+ return;
+ }
+
+ for (i = 0; i < adaptations->children; ++i) {
+ zend_ast *adaptation_ast = adaptations->child[i];
+ switch (adaptation_ast->kind) {
+ case ZEND_AST_TRAIT_PRECEDENCE:
+ zend_compile_trait_precedence(adaptation_ast TSRMLS_CC);
+ break;
+ case ZEND_AST_TRAIT_ALIAS:
+ zend_compile_trait_alias(adaptation_ast TSRMLS_CC);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
}
/* }}} */
-ZEND_API void zend_activate_auto_globals(TSRMLS_D) /* {{{ */
+void zend_compile_implements(znode *class_node, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_auto_global *auto_global;
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *class_ast = list->child[i];
+ zend_string *name = zend_ast_get_str(class_ast);
- ZEND_HASH_FOREACH_PTR(CG(auto_globals), auto_global) {
- if (auto_global->jit) {
- auto_global->armed = 1;
- } else if (auto_global->auto_global_callback) {
- auto_global->armed = auto_global->auto_global_callback(auto_global->name TSRMLS_CC);
- } else {
- auto_global->armed = 0;
+ zend_op *opline;
+
+ /* Traits can not implement interfaces */
+ if (ZEND_CE_IS_TRAIT(CG(active_class_entry))) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as interface on '%s' "
+ "since it is a Trait", name->val, CG(active_class_entry)->name->val);
}
- } ZEND_HASH_FOREACH_END();
+
+ if (!zend_is_const_default_class_ref(class_ast)) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Cannot use '%s' as interface name as it is reserved", name->val);
+ }
+
+ opline = zend_emit_op(NULL, ZEND_ADD_INTERFACE, class_node, NULL TSRMLS_CC);
+ opline->extended_value = ZEND_FETCH_CLASS_INTERFACE;
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
+ zend_resolve_class_name_ast(class_ast TSRMLS_CC) TSRMLS_CC);
+
+ CG(active_class_entry)->num_interfaces++;
+ }
}
/* }}} */
-int zendlex(znode *zendlval TSRMLS_DC) /* {{{ */
+void zend_compile_class_decl(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- int retval;
+ zend_ast_decl *decl = (zend_ast_decl *) ast;
+ zend_ast *extends_ast = decl->child[0];
+ zend_ast *implements_ast = decl->child[1];
+ zend_ast *stmt_ast = decl->child[2];
- if (CG(increment_lineno)) {
- CG(zend_lineno)++;
- CG(increment_lineno) = 0;
+ zend_string *name = decl->name, *lcname, *import_name = NULL;
+ zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
+ zend_op *opline;
+ znode declare_node, extends_node;
+
+ if (CG(active_class_entry)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
+ return;
}
-again:
- Z_TYPE_INFO(zendlval->u.constant) = IS_LONG;
- retval = lex_scan(&zendlval->u.constant TSRMLS_CC);
- switch (retval) {
- case T_COMMENT:
- case T_DOC_COMMENT:
- case T_OPEN_TAG:
- case T_WHITESPACE:
- goto again;
+ if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved",
+ name->val);
+ }
- case T_CLOSE_TAG:
- if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') {
- CG(increment_lineno) = 1;
- }
- if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
- goto again;
- }
- retval = ';'; /* implicit ; */
- break;
- case T_OPEN_TAG_WITH_ECHO:
- retval = T_ECHO;
- break;
+ lcname = zend_string_alloc(name->len, 0);
+ zend_str_tolower_copy(lcname->val, name->val, name->len);
+
+ if (CG(current_import)) {
+ import_name = zend_hash_find_ptr(CG(current_import), lcname);
}
- zendlval->op_type = IS_CONST;
- return retval;
-}
-/* }}} */
+ if (CG(current_namespace)) {
+ name = zend_prefix_with_ns(name TSRMLS_CC);
-ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC) /* {{{ */
-{
- zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
- dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
+ zend_string_release(lcname);
+ lcname = zend_string_alloc(name->len, 0);
+ zend_str_tolower_copy(lcname->val, name->val, name->len);
+ } else {
+ zend_string_addref(name);
+ }
- ce->refcount = 1;
- ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
+ if (import_name && !zend_string_equals_str_ci(lcname, import_name)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s "
+ "because the name is already in use", name->val);
+ }
- ce->default_properties_table = NULL;
- ce->default_static_members_table = NULL;
- zend_hash_init_ex(&ce->properties_info, 8, NULL, (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
- zend_hash_init_ex(&ce->constants_table, 8, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
- zend_hash_init_ex(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
+ name = zend_new_interned_string(name TSRMLS_CC);
+ lcname = zend_new_interned_string(lcname TSRMLS_CC);
- if (ce->type == ZEND_INTERNAL_CLASS) {
-#ifdef ZTS
- int n = zend_hash_num_elements(CG(class_table));
+ ce->type = ZEND_USER_CLASS;
+ ce->name = name;
+ zend_initialize_class_data(ce, 1 TSRMLS_CC);
- if (CG(static_members_table) && n >= CG(last_static_member)) {
- /* Support for run-time declaration: dl() */
- CG(last_static_member) = n+1;
- CG(static_members_table) = realloc(CG(static_members_table), (n+1)*sizeof(zval*));
- CG(static_members_table)[n] = NULL;
+ ce->ce_flags |= decl->flags;
+ ce->info.user.filename = zend_get_compiled_filename(TSRMLS_C);
+ ce->info.user.line_start = decl->start_lineno;
+ ce->info.user.line_end = decl->end_lineno;
+ if (decl->doc_comment) {
+ ce->info.user.doc_comment = zend_string_copy(decl->doc_comment);
+ }
+
+ if (extends_ast) {
+ if (ZEND_CE_IS_TRAIT(ce)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "A trait (%s) cannot extend a class. "
+ "Traits can only be composed from other traits with the 'use' keyword. Error",
+ name->val);
}
- ce->static_members_table = (zval*)(zend_intptr_t)n;
-#else
- ce->static_members_table = NULL;
-#endif
+
+ if (!zend_is_const_default_class_ref(extends_ast)) {
+ zend_string *extends_name = zend_ast_get_str(extends_ast);
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Cannot use '%s' as class name as it is reserved", extends_name->val);
+ }
+
+ zend_compile_class_ref(&extends_node, extends_ast TSRMLS_CC);
+ }
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zend_make_var_result(&declare_node, opline TSRMLS_CC);
+
+ // TODO.AST drop this
+ GET_NODE(&CG(implementing_class), opline->result);
+
+ opline->op2_type = IS_CONST;
+ LITERAL_STR(opline->op2, lcname);
+
+ if (extends_ast) {
+ opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
+ opline->extended_value = extends_node.u.op.var;
} else {
- ce->static_members_table = ce->default_static_members_table;
- ce->info.user.doc_comment = NULL;
+ opline->opcode = ZEND_DECLARE_CLASS;
}
- ce->default_properties_count = 0;
- ce->default_static_members_count = 0;
+ {
+ zend_string *key = zend_build_runtime_definition_key(lcname, decl->lex_pos TSRMLS_CC);
- if (nullify_handlers) {
- ce->constructor = NULL;
- ce->destructor = NULL;
- ce->clone = NULL;
- ce->__get = NULL;
- ce->__set = NULL;
- ce->__unset = NULL;
- ce->__isset = NULL;
- ce->__call = NULL;
- ce->__callstatic = NULL;
- ce->__tostring = NULL;
- ce->create_object = NULL;
- ce->get_iterator = NULL;
- ce->iterator_funcs.funcs = NULL;
- ce->interface_gets_implemented = NULL;
- ce->get_static_method = NULL;
- ce->parent = NULL;
- ce->num_interfaces = 0;
- ce->interfaces = NULL;
- ce->num_traits = 0;
+ opline->op1_type = IS_CONST;
+ LITERAL_STR(opline->op1, key);
+
+ zend_hash_update_ptr(CG(class_table), key, ce);
+ }
+
+ CG(active_class_entry) = ce;
+
+ if (implements_ast) {
+ zend_compile_implements(&declare_node, implements_ast TSRMLS_CC);
+ }
+
+ zend_compile_stmt(stmt_ast TSRMLS_CC);
+
+ if (ce->constructor) {
+ ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
+ if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static",
+ ce->name->val, ce->constructor->common.function_name->val);
+ }
+ }
+ if (ce->destructor) {
+ ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
+ if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static",
+ ce->name->val, ce->destructor->common.function_name->val);
+ }
+ }
+ if (ce->clone) {
+ ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
+ if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static",
+ ce->name->val, ce->clone->common.function_name->val);
+ }
+ }
+
+ /* Check for traits and proceed like with interfaces.
+ * The only difference will be a combined handling of them in the end.
+ * Thus, we need another opcode here. */
+ if (ce->num_traits > 0) {
ce->traits = NULL;
- ce->trait_aliases = NULL;
- ce->trait_precedences = NULL;
- ce->serialize = NULL;
- ce->unserialize = NULL;
- ce->serialize_func = NULL;
- ce->unserialize_func = NULL;
- ce->__debugInfo = NULL;
- if (ce->type == ZEND_INTERNAL_CLASS) {
- ce->info.internal.module = NULL;
- ce->info.internal.builtin_functions = NULL;
+ ce->num_traits = 0;
+ ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
+
+ zend_emit_op(NULL, ZEND_BIND_TRAITS, &declare_node, NULL TSRMLS_CC);
+ }
+
+ if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
+ && (extends_ast || ce->num_interfaces > 0)
+ ) {
+ zend_verify_abstract_class(ce TSRMLS_CC);
+ if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
+ zend_emit_op(NULL, ZEND_VERIFY_ABSTRACT_CLASS, &declare_node, NULL TSRMLS_CC);
}
}
+
+ /* Inherit interfaces; reset number to zero, we need it for above check and
+ * will restore it during actual implementation.
+ * The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
+ * zend_verify_abstract_class() */
+ if (ce->num_interfaces > 0) {
+ ce->interfaces = NULL;
+ ce->num_interfaces = 0;
+ ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
+ }
+
+ CG(active_class_entry) = NULL;
+}
+/* }}} */
+
+static HashTable *zend_get_import_ht(uint32_t type TSRMLS_DC) /* {{{ */
+{
+ switch (type) {
+ case T_CLASS:
+ if (!CG(current_import)) {
+ CG(current_import) = emalloc(sizeof(HashTable));
+ zend_hash_init(CG(current_import), 8, NULL, str_dtor, 0);
+ }
+ return CG(current_import);
+ case T_FUNCTION:
+ if (!CG(current_import_function)) {
+ CG(current_import_function) = emalloc(sizeof(HashTable));
+ zend_hash_init(CG(current_import_function), 8, NULL, str_dtor, 0);
+ }
+ return CG(current_import_function);
+ case T_CONST:
+ if (!CG(current_import_const)) {
+ CG(current_import_const) = emalloc(sizeof(HashTable));
+ zend_hash_init(CG(current_import_const), 8, NULL, str_dtor, 0);
+ }
+ return CG(current_import_const);
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
}
/* }}} */
-int zend_get_class_fetch_type(const char *class_name, uint class_name_len) /* {{{ */
+static char *zend_get_use_type_str(uint32_t type) /* {{{ */
{
- if ((class_name_len == sizeof("self")-1) &&
- !strncasecmp(class_name, "self", sizeof("self")-1)) {
- return ZEND_FETCH_CLASS_SELF;
- } else if ((class_name_len == sizeof("parent")-1) &&
- !strncasecmp(class_name, "parent", sizeof("parent")-1)) {
- return ZEND_FETCH_CLASS_PARENT;
- } else if ((class_name_len == sizeof("static")-1) &&
- !strncasecmp(class_name, "static", sizeof("static")-1)) {
- return ZEND_FETCH_CLASS_STATIC;
- } else {
- return ZEND_FETCH_CLASS_DEFAULT;
+ switch (type) {
+ case T_CLASS:
+ return "";
+ case T_FUNCTION:
+ return " function";
+ case T_CONST:
+ return " const";
+ EMPTY_SWITCH_DEFAULT_CASE()
}
}
/* }}} */
-ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var) /* {{{ */
+static void zend_check_already_in_use(uint32_t type, zend_string *old_name, zend_string *new_name, zend_string *check_name) /* {{{ */
{
- return op_array->vars[EX_VAR_TO_NUM(var)];
+ if (zend_string_equals_str_ci(old_name, check_name)) {
+ return;
+ }
+
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
+ "is already in use", zend_get_use_type_str(type), old_name->val, new_name->val);
}
/* }}} */
-void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC) /* {{{ */
+void zend_compile_use(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- if (prefix) {
- *result = *prefix;
- if (Z_TYPE(result->u.constant) == IS_STRING &&
- Z_STRLEN(result->u.constant) == 0) {
- /* namespace\ */
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- znode tmp;
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
+ zend_string *current_ns = CG(current_namespace);
+ uint32_t type = ast->attr;
+ HashTable *current_import = zend_get_import_ht(type TSRMLS_CC);
+ zend_bool case_sensitive = type == T_CONST;
+
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *use_ast = list->child[i];
+ zend_ast *old_name_ast = use_ast->child[0];
+ zend_ast *new_name_ast = use_ast->child[1];
+ zend_string *old_name = zend_ast_get_str(old_name_ast);
+ zend_string *new_name, *lookup_name;
+
+ if (new_name_ast) {
+ new_name = zend_string_copy(zend_ast_get_str(new_name_ast));
+ } else {
+ /* The form "use A\B" is eqivalent to "use A\B as B" */
+ const char *p = zend_memrchr(old_name->val, '\\', old_name->len);
+ if (p) {
+ new_name = zend_string_init(p + 1, old_name->len - (p - old_name->val + 1), 0);
+ } else {
+ new_name = zend_string_copy(old_name);
- zval_dtor(&result->u.constant);
- tmp.op_type = IS_CONST;
- ZVAL_DUP(&tmp.u.constant, &CG(current_namespace));
- zend_do_build_namespace_name(result, NULL, &tmp TSRMLS_CC);
+ if (!current_ns) {
+ if (type == T_CLASS && zend_string_equals_literal(new_name, "strict")) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "You seem to be trying to use a different language...");
+ }
+
+ zend_error(E_WARNING, "The use statement with non-compound name '%s' "
+ "has no effect", new_name->val);
+ }
}
}
- } else {
- result->op_type = IS_CONST;
- ZVAL_EMPTY_STRING(&result->u.constant);
+
+ if (case_sensitive) {
+ lookup_name = zend_string_copy(new_name);
+ } else {
+ lookup_name = zend_string_alloc(new_name->len, 0);
+ zend_str_tolower_copy(lookup_name->val, new_name->val, new_name->len);
+ }
+
+ if (type == T_CLASS && (zend_string_equals_literal(lookup_name, "self")
+ || zend_string_equals_literal(lookup_name, "parent"))
+ ) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' "
+ "is a special class name", old_name->val, new_name->val, new_name->val);
+ }
+
+ if (current_ns) {
+ zend_string *ns_name = zend_string_alloc(current_ns->len + 1 + new_name->len, 0);
+ zend_str_tolower_copy(ns_name->val, current_ns->val, current_ns->len);
+ ns_name->val[current_ns->len] = '\\';
+ memcpy(ns_name->val + current_ns->len + 1, lookup_name->val, lookup_name->len);
+
+ if (zend_hash_exists(CG(class_table), ns_name)) {
+ zend_check_already_in_use(type, old_name, new_name, ns_name);
+ }
+
+ zend_string_free(ns_name);
+ } else {
+ switch (type) {
+ case T_CLASS:
+ {
+ zend_class_entry *ce = zend_hash_find_ptr(CG(class_table), lookup_name);
+ if (ce && ce->type == ZEND_USER_CLASS
+ && ce->info.user.filename == CG(compiled_filename)
+ ) {
+ zend_check_already_in_use(type, old_name, new_name, lookup_name);
+ }
+ break;
+ }
+ case T_FUNCTION:
+ {
+ zend_function *fn = zend_hash_find_ptr(CG(function_table), lookup_name);
+ if (fn && fn->type == ZEND_USER_FUNCTION
+ && fn->op_array.filename == CG(compiled_filename)
+ ) {
+ zend_check_already_in_use(type, old_name, new_name, lookup_name);
+ }
+ break;
+ }
+ case T_CONST:
+ {
+ zend_string *filename = zend_hash_find_ptr(&CG(const_filenames), lookup_name);
+ if (filename && filename == CG(compiled_filename)) {
+ zend_check_already_in_use(type, old_name, new_name, lookup_name);
+ }
+ break;
+ }
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+
+ zend_string_addref(old_name);
+ if (!zend_hash_add_ptr(current_import, lookup_name, old_name)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
+ "is already in use", zend_get_use_type_str(type), old_name->val, new_name->val);
+ }
+
+ zend_string_release(lookup_name);
+ zend_string_release(new_name);
}
- /* prefix = result */
- zend_do_build_full_name(NULL, result, name, 0 TSRMLS_CC);
}
/* }}} */
-void zend_do_begin_namespace(znode *name, zend_bool with_bracket TSRMLS_DC) /* {{{ */
+void zend_compile_const_decl(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- char *lcname;
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *const_ast = list->child[i];
+ zend_ast *name_ast = const_ast->child[0];
+ zend_ast *value_ast = const_ast->child[1];
+ zend_string *name = zend_ast_get_str(name_ast);
+
+ zend_string *import_name;
+ znode name_node, value_node;
+ zval *value_zv = &value_node.u.constant;
+
+ value_node.op_type = IS_CONST;
+ zend_const_expr_to_zval(value_zv, value_ast TSRMLS_CC);
+
+ if (zend_get_ct_const(name, 0 TSRMLS_CC)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", name->val);
+ }
+
+ name = zend_prefix_with_ns(name TSRMLS_CC);
+
+ if (CG(current_import_const)
+ && (import_name = zend_hash_find_ptr(CG(current_import_const), name))
+ ) {
+ if (!zend_string_equals(import_name, name)) {
+ zend_error(E_COMPILE_ERROR, "Cannot declare const %s because "
+ "the name is already in use", name->val);
+ }
+ }
+
+ name_node.op_type = IS_CONST;
+ ZVAL_STR(&name_node.u.constant, name);
+
+ zend_emit_op(NULL, ZEND_DECLARE_CONST, &name_node, &value_node TSRMLS_CC);
+
+ zend_hash_add_ptr(&CG(const_filenames), name, CG(compiled_filename));
+ }
+}
+/* }}}*/
+
+void zend_compile_namespace(zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *name_ast = ast->child[0];
+ zend_ast *stmt_ast = ast->child[1];
+ zend_string *name;
+ zend_bool with_bracket = stmt_ast != NULL;
/* handle mixed syntax declaration or nested namespaces */
if (!CG(has_bracketed_namespaces)) {
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
+ if (CG(current_namespace)) {
/* previous namespace declarations were unbracketed */
if (with_bracket) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
+ "with unbracketed namespace declarations");
}
}
} else {
/* previous namespace declarations were bracketed */
if (!with_bracket) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
- } else if (Z_TYPE(CG(current_namespace)) != IS_UNDEF || CG(in_namespace)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
+ "with unbracketed namespace declarations");
+ } else if (CG(current_namespace) || CG(in_namespace)) {
zend_error_noreturn(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
}
}
- if (((!with_bracket && Z_TYPE(CG(current_namespace)) == IS_UNDEF) || (with_bracket && !CG(has_bracketed_namespaces))) && CG(active_op_array)->last > 0) {
+ if (((!with_bracket && !CG(current_namespace))
+ || (with_bracket && !CG(has_bracketed_namespaces))) && CG(active_op_array)->last > 0
+ ) {
/* ignore ZEND_EXT_STMT and ZEND_TICKS */
- int num = CG(active_op_array)->last;
+ uint32_t num = CG(active_op_array)->last;
while (num > 0 &&
(CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
--num;
}
if (num > 0) {
- zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script");
+ zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be "
+ "the very first statement in the script");
}
}
+ if (CG(current_namespace)) {
+ zend_string_release(CG(current_namespace));
+ }
+
+ if (name_ast) {
+ name = zend_ast_get_str(name_ast);
+
+ if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", name->val);
+ }
+
+ CG(current_namespace) = zend_string_copy(name);
+ } else {
+ CG(current_namespace) = NULL;
+ }
+
+ zend_reset_import_tables(TSRMLS_C);
+
CG(in_namespace) = 1;
if (with_bracket) {
CG(has_bracketed_namespaces) = 1;
}
- if (name) {
- lcname = zend_str_tolower_dup(Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant));
- if (((Z_STRLEN(name->u.constant) == sizeof("self")-1) &&
- !memcmp(lcname, "self", sizeof("self")-1)) ||
- ((Z_STRLEN(name->u.constant) == sizeof("parent")-1) &&
- !memcmp(lcname, "parent", sizeof("parent")-1))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant));
+ if (stmt_ast) {
+ zend_compile_top_stmt(stmt_ast TSRMLS_CC);
+ zend_end_namespace(TSRMLS_C);
+ }
+}
+/* }}} */
+
+void zend_compile_halt_compiler(zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *offset_ast = ast->child[0];
+ zend_long offset = Z_LVAL_P(zend_ast_get_zval(offset_ast));
+
+ zend_string *filename, *name;
+ const char const_name[] = "__COMPILER_HALT_OFFSET__";
+
+ if (CG(has_bracketed_namespaces) && CG(in_namespace)) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "__HALT_COMPILER() can only be used from the outermost scope");
+ }
+
+ filename = zend_get_compiled_filename(TSRMLS_C);
+ name = zend_mangle_property_name(const_name, sizeof(const_name) - 1,
+ filename->val, filename->len, 0);
+
+ zend_register_long_constant(name->val, name->len, offset, CONST_CS, 0 TSRMLS_CC);
+ zend_string_release(name);
+}
+/* }}} */
+
+static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_op_array *op_array = CG(active_op_array);
+ zend_class_entry *ce = CG(active_class_entry);
+
+ switch (ast->attr) {
+ case T_LINE:
+ ZVAL_LONG(zv, CG(zend_lineno));
+ break;
+ case T_FILE:
+ ZVAL_STR(zv, zend_string_copy(CG(compiled_filename)));
+ break;
+ case T_DIR:
+ {
+ zend_string *filename = CG(compiled_filename);
+ zend_string *dirname = zend_string_init(filename->val, filename->len, 0);
+ zend_dirname(dirname->val, dirname->len);
+
+ if (strcmp(dirname->val, ".") == 0) {
+ dirname = zend_string_realloc(dirname, MAXPATHLEN, 0);
+#if HAVE_GETCWD
+ VCWD_GETCWD(dirname->val, MAXPATHLEN);
+#elif HAVE_GETWD
+ VCWD_GETWD(dirname->val);
+#endif
+ }
+
+ dirname->len = strlen(dirname->val);
+ ZVAL_STR(zv, dirname);
+ break;
}
- efree(lcname);
+ case T_FUNC_C:
+ if (op_array && op_array->function_name) {
+ ZVAL_STR(zv, zend_string_copy(op_array->function_name));
+ } else {
+ ZVAL_EMPTY_STRING(zv);
+ }
+ break;
+ case T_METHOD_C:
+ if (ce) {
+ if (op_array && op_array->function_name) {
+ ZVAL_STR(zv, zend_concat3(ce->name->val, ce->name->len, "::", 2,
+ op_array->function_name->val, op_array->function_name->len));
+ } else {
+ ZVAL_STR(zv, zend_string_copy(ce->name));
+ }
+ } else if (op_array && op_array->function_name) {
+ ZVAL_STR(zv, zend_string_copy(op_array->function_name));
+ } else {
+ ZVAL_EMPTY_STRING(zv);
+ }
+ break;
+ case T_CLASS_C:
+ if (ce) {
+ if (ZEND_CE_IS_TRAIT(ce)) {
+ return 0;
+ } else {
+ ZVAL_STR(zv, zend_string_copy(ce->name));
+ }
+ } else {
+ ZVAL_EMPTY_STRING(zv);
+ }
+ break;
+ case T_TRAIT_C:
+ if (ce && ZEND_CE_IS_TRAIT(ce)) {
+ ZVAL_STR(zv, zend_string_copy(ce->name));
+ } else {
+ ZVAL_EMPTY_STRING(zv);
+ }
+ break;
+ case T_NS_C:
+ if (CG(current_namespace)) {
+ ZVAL_STR(zv, zend_string_copy(CG(current_namespace)));
+ } else {
+ ZVAL_EMPTY_STRING(zv);
+ }
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- zval_dtor(&CG(current_namespace));
+ return 1;
+}
+/* }}} */
+
+static inline void zend_ct_eval_binary_op(zval *result, uint32_t opcode, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+{
+ binary_op_type fn = get_binary_op(opcode);
+ fn(result, op1, op2 TSRMLS_CC);
+}
+/* }}} */
+
+static inline void zend_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op TSRMLS_DC) /* {{{ */
+{
+ binary_op_type fn = kind == ZEND_AST_UNARY_PLUS
+ ? add_function : sub_function;
+
+ zval left;
+ ZVAL_LONG(&left, 0);
+ fn(result, &left, op TSRMLS_CC);
+}
+/* }}} */
+
+static inline void zend_ct_eval_greater(zval *result, zend_ast_kind kind, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+{
+ binary_op_type fn = kind == ZEND_AST_GREATER
+ ? is_smaller_function : is_smaller_or_equal_function;
+ fn(result, op2, op1 TSRMLS_CC);
+}
+/* }}} */
+
+static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
+
+ /* First ensure that *all* child nodes are constant and by-val */
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *elem_ast = list->child[i];
+ zend_bool by_ref = elem_ast->attr;
+ zend_eval_const_expr(&elem_ast->child[0] TSRMLS_CC);
+ zend_eval_const_expr(&elem_ast->child[1] TSRMLS_CC);
+
+ if (by_ref || elem_ast->child[0]->kind != ZEND_AST_ZVAL
+ || (elem_ast->child[1] && elem_ast->child[1]->kind != ZEND_AST_ZVAL)
+ ) {
+ return 0;
}
- ZVAL_COPY_VALUE(&CG(current_namespace), &name->u.constant);
- } else {
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- zval_dtor(&CG(current_namespace));
- ZVAL_UNDEF(&CG(current_namespace));
+ }
+
+ array_init_size(result, list->children);
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *elem_ast = list->child[i];
+ zend_ast *value_ast = elem_ast->child[0];
+ zend_ast *key_ast = elem_ast->child[1];
+
+ zval *value = zend_ast_get_zval(value_ast);
+ if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
+
+ if (key_ast) {
+ zval *key = zend_ast_get_zval(key_ast);
+ switch (Z_TYPE_P(key)) {
+ case IS_LONG:
+ zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(key), value);
+ break;
+ case IS_STRING:
+ zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(key), value);
+ break;
+ case IS_DOUBLE:
+ zend_hash_index_update(Z_ARRVAL_P(result),
+ zend_dval_to_lval(Z_DVAL_P(key)), value);
+ break;
+ case IS_FALSE:
+ zend_hash_index_update(Z_ARRVAL_P(result), 0, value);
+ break;
+ case IS_TRUE:
+ zend_hash_index_update(Z_ARRVAL_P(result), 1, value);
+ break;
+ case IS_NULL:
+ zend_hash_update(Z_ARRVAL_P(result), STR_EMPTY_ALLOC(), value);
+ break;
+ default:
+ zend_error(E_COMPILE_ERROR, "Illegal offset type");
+ break;
+ }
+ } else {
+ zend_hash_next_index_insert(Z_ARRVAL_P(result), value);
}
}
- if (CG(current_import)) {
- zend_hash_destroy(CG(current_import));
- efree(CG(current_import));
- CG(current_import) = NULL;
+ return 1;
+}
+/* }}} */
+
+void zend_compile_binary_op(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *left_ast = ast->child[0];
+ zend_ast *right_ast = ast->child[1];
+ uint32_t opcode = ast->attr;
+
+ znode left_node, right_node;
+ zend_compile_expr(&left_node, left_ast TSRMLS_CC);
+ zend_compile_expr(&right_node, right_ast TSRMLS_CC);
+
+ if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
+ result->op_type = IS_CONST;
+ zend_ct_eval_binary_op(&result->u.constant, opcode,
+ &left_node.u.constant, &right_node.u.constant TSRMLS_CC);
+ zval_ptr_dtor(&left_node.u.constant);
+ zval_ptr_dtor(&right_node.u.constant);
+ return;
}
- if (CG(current_import_function)) {
- zend_hash_destroy(CG(current_import_function));
- efree(CG(current_import_function));
- CG(current_import_function) = NULL;
+ zend_emit_op_tmp(result, opcode, &left_node, &right_node TSRMLS_CC);
+}
+/* }}} */
+
+/* We do not use zend_compile_binary_op for this because we want to retain the left-to-right
+ * evaluation order. */
+void zend_compile_greater(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *left_ast = ast->child[0];
+ zend_ast *right_ast = ast->child[1];
+ znode left_node, right_node;
+
+ ZEND_ASSERT(ast->kind == ZEND_AST_GREATER || ast->kind == ZEND_AST_GREATER_EQUAL);
+
+ zend_compile_expr(&left_node, left_ast TSRMLS_CC);
+ zend_compile_expr(&right_node, right_ast TSRMLS_CC);
+
+ if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
+ result->op_type = IS_CONST;
+ zend_ct_eval_greater(&result->u.constant, ast->kind,
+ &left_node.u.constant, &right_node.u.constant TSRMLS_CC);
+ zval_ptr_dtor(&left_node.u.constant);
+ zval_ptr_dtor(&right_node.u.constant);
+ return;
}
- if (CG(current_import_const)) {
- zend_hash_destroy(CG(current_import_const));
- efree(CG(current_import_const));
- CG(current_import_const) = NULL;
+ zend_emit_op_tmp(result,
+ ast->kind == ZEND_AST_GREATER ? ZEND_IS_SMALLER : ZEND_IS_SMALLER_OR_EQUAL,
+ &right_node, &left_node TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_unary_op(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *expr_ast = ast->child[0];
+ uint32_t opcode = ast->attr;
+
+ znode expr_node;
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ zend_emit_op_tmp(result, opcode, &expr_node, NULL TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_unary_pm(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *expr_ast = ast->child[0];
+ znode zero_node, expr_node;
+
+ ZEND_ASSERT(ast->kind == ZEND_AST_UNARY_PLUS || ast->kind == ZEND_AST_UNARY_MINUS);
+
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ if (expr_node.op_type == IS_CONST) {
+ result->op_type = IS_CONST;
+ zend_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant TSRMLS_CC);
+ zval_ptr_dtor(&expr_node.u.constant);
+ return;
}
- if (CG(doc_comment)) {
- STR_RELEASE(CG(doc_comment));
- CG(doc_comment) = NULL;
+ zero_node.op_type = IS_CONST;
+ ZVAL_LONG(&zero_node.u.constant, 0);
+
+ zend_emit_op_tmp(result, ast->kind == ZEND_AST_UNARY_PLUS ? ZEND_ADD : ZEND_SUB,
+ &zero_node, &expr_node TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_short_circuiting(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *left_ast = ast->child[0];
+ zend_ast *right_ast = ast->child[1];
+
+ znode left_node, right_node;
+ zend_op *opline_jmpz, *opline_bool;
+ uint32_t opnum_jmpz;
+
+ ZEND_ASSERT(ast->kind == ZEND_AST_AND || ast->kind == ZEND_AST_OR);
+
+ zend_compile_expr(&left_node, left_ast TSRMLS_CC);
+
+ opnum_jmpz = get_next_op_number(CG(active_op_array));
+ opline_jmpz = zend_emit_op(NULL, ast->kind == ZEND_AST_AND ? ZEND_JMPZ_EX : ZEND_JMPNZ_EX,
+ &left_node, NULL TSRMLS_CC);
+
+ if (left_node.op_type == IS_TMP_VAR) {
+ SET_NODE(opline_jmpz->result, &left_node);
+ } else {
+ opline_jmpz->result.var = get_temporary_variable(CG(active_op_array));
+ opline_jmpz->result_type = IS_TMP_VAR;
}
+ GET_NODE(result, opline_jmpz->result);
+
+ zend_compile_expr(&right_node, right_ast TSRMLS_CC);
+
+ opline_bool = zend_emit_op(NULL, ZEND_BOOL, &right_node, NULL TSRMLS_CC);
+ SET_NODE(opline_bool->result, result);
+
+ zend_update_jump_target_to_next(opnum_jmpz TSRMLS_CC);
}
/* }}} */
-void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{{ */
+void zend_compile_post_incdec(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_string *lcname;
- zval *name, ns, tmp;
- zend_bool warn = 0;
- zend_class_entry *ce;
+ zend_ast *var_ast = ast->child[0];
+ ZEND_ASSERT(ast->kind == ZEND_AST_POST_INC || ast->kind == ZEND_AST_POST_DEC);
- if (!CG(current_import)) {
- CG(current_import) = emalloc(sizeof(HashTable));
- zend_hash_init(CG(current_import), 8, NULL, ZVAL_PTR_DTOR, 0);
+ if (var_ast->kind == ZEND_AST_PROP) {
+ zend_op *opline = zend_compile_prop_common(NULL, var_ast, BP_VAR_RW TSRMLS_CC);
+ opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ;
+ zend_make_tmp_result(result, opline TSRMLS_CC);
+ } else {
+ znode var_node;
+ zend_compile_var(&var_node, var_ast, BP_VAR_RW TSRMLS_CC);
+ zend_emit_op_tmp(result, ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC : ZEND_POST_DEC,
+ &var_node, NULL TSRMLS_CC);
}
+}
+/* }}} */
+
+void zend_compile_pre_incdec(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *var_ast = ast->child[0];
+ ZEND_ASSERT(ast->kind == ZEND_AST_PRE_INC || ast->kind == ZEND_AST_PRE_DEC);
- ZVAL_ZVAL(&ns, &ns_name->u.constant, 0, 0);
- if (new_name) {
- name = &new_name->u.constant;
+ if (var_ast->kind == ZEND_AST_PROP) {
+ zend_op *opline = zend_compile_prop_common(result, var_ast, BP_VAR_RW TSRMLS_CC);
+ opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ;
} else {
- const char *p;
-
- /* The form "use A\B" is eqivalent to "use A\B as B".
- So we extract the last part of compound name to use as a new_name */
- name = &tmp;
- p = zend_memrchr(Z_STRVAL(ns), '\\', Z_STRLEN(ns));
- if (p) {
- ZVAL_STRING(name, p+1);
- } else {
- ZVAL_ZVAL(name, &ns, 1, 0);
- warn = !is_global && Z_TYPE(CG(current_namespace)) == IS_UNDEF;
- }
+ znode var_node;
+ zend_compile_var(&var_node, var_ast, BP_VAR_RW TSRMLS_CC);
+ zend_emit_op(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC,
+ &var_node, NULL TSRMLS_CC);
}
+}
+/* }}} */
+
+void zend_compile_cast(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *expr_ast = ast->child[0];
+ znode expr_node;
+ zend_op *opline;
+
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ opline = zend_emit_op(result, ZEND_CAST, &expr_node, NULL TSRMLS_CC);
+ opline->extended_value = ast->attr;
+}
+/* }}} */
+
+static void zend_compile_shorthand_conditional(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *cond_ast = ast->child[0];
+ zend_ast *false_ast = ast->child[2];
+
+ znode cond_node, false_node;
+ zend_op *opline_jmp_set, *opline_qm_assign;
+ uint32_t opnum_jmp_set;
- lcname = STR_ALLOC(Z_STRLEN_P(name), 0);
- zend_str_tolower_copy(lcname->val, Z_STRVAL_P(name), Z_STRLEN_P(name));
+ ZEND_ASSERT(ast->child[1] == NULL);
- if (((Z_STRLEN_P(name) == sizeof("self")-1) &&
- !memcmp(lcname->val, "self", sizeof("self")-1)) ||
- ((Z_STRLEN_P(name) == sizeof("parent")-1) &&
- !memcmp(lcname->val, "parent", sizeof("parent")-1))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL(ns), Z_STRVAL_P(name), Z_STRVAL_P(name));
+ zend_compile_expr(&cond_node, cond_ast TSRMLS_CC);
+
+ opnum_jmp_set = get_next_op_number(CG(active_op_array));
+ zend_emit_op(result, ZEND_JMP_SET, &cond_node, NULL TSRMLS_CC);
+
+ zend_compile_expr(&false_node, false_ast TSRMLS_CC);
+
+ opline_jmp_set = &CG(active_op_array)->opcodes[opnum_jmp_set];
+ opline_jmp_set->op2.opline_num = get_next_op_number(CG(active_op_array)) + 1;
+ opline_qm_assign = zend_emit_op(NULL, ZEND_QM_ASSIGN, &false_node, NULL TSRMLS_CC);
+ SET_NODE(opline_qm_assign->result, result);
+}
+/* }}} */
+
+void zend_compile_conditional(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *cond_ast = ast->child[0];
+ zend_ast *true_ast = ast->child[1];
+ zend_ast *false_ast = ast->child[2];
+
+ znode cond_node, true_node, false_node;
+ zend_op *opline_qm_assign1, *opline_qm_assign2;
+ uint32_t opnum_jmpz, opnum_jmp, opnum_qm_assign1;
+
+ if (!true_ast) {
+ zend_compile_shorthand_conditional(result, ast TSRMLS_CC);
+ return;
}
+
+ zend_compile_expr(&cond_node, cond_ast TSRMLS_CC);
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- /* Prefix import name with current namespace name to avoid conflicts with classes */
- zend_string *c_ns_name = STR_ALLOC(Z_STRLEN(CG(current_namespace)) + 1 + Z_STRLEN_P(name), 0);
+ opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0 TSRMLS_CC);
- zend_str_tolower_copy(c_ns_name->val, Z_STRVAL(CG(current_namespace)), Z_STRLEN(CG(current_namespace)));
- c_ns_name->val[Z_STRLEN(CG(current_namespace))] = '\\';
- memcpy(c_ns_name->val+Z_STRLEN(CG(current_namespace))+1, lcname->val, Z_STRLEN_P(name)+1);
- if (zend_hash_exists(CG(class_table), c_ns_name)) {
- char *tmp2 = zend_str_tolower_dup(Z_STRVAL(ns), Z_STRLEN(ns));
+ zend_compile_expr(&true_node, true_ast TSRMLS_CC);
- if (Z_STRLEN(ns) != Z_STRLEN(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
- memcmp(tmp2, c_ns_name->val, Z_STRLEN(ns))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL(ns), Z_STRVAL_P(name));
- }
- efree(tmp2);
- }
- STR_FREE(c_ns_name);
- } else if ((ce = zend_hash_find_ptr(CG(class_table), lcname)) != NULL &&
- ce->type == ZEND_USER_CLASS &&
- ce->info.user.filename == CG(compiled_filename)) {
- char *c_tmp = zend_str_tolower_dup(Z_STRVAL(ns), Z_STRLEN(ns));
+ opnum_qm_assign1 = get_next_op_number(CG(active_op_array));
+ zend_emit_op(result, ZEND_QM_ASSIGN, &true_node, NULL TSRMLS_CC);
- if (Z_STRLEN(ns) != Z_STRLEN_P(name) ||
- memcmp(c_tmp, lcname->val, Z_STRLEN(ns))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL(ns), Z_STRVAL_P(name));
- }
- efree(c_tmp);
+ opnum_jmp = zend_emit_jump(0 TSRMLS_CC);
+
+ zend_update_jump_target_to_next(opnum_jmpz TSRMLS_CC);
+
+ zend_compile_expr(&false_node, false_ast TSRMLS_CC);
+
+ opline_qm_assign1 = &CG(active_op_array)->opcodes[opnum_qm_assign1];
+ opline_qm_assign2 = zend_emit_op(NULL, opline_qm_assign1->opcode, &false_node, NULL TSRMLS_CC);
+ SET_NODE(opline_qm_assign2->result, result);
+
+ zend_update_jump_target_to_next(opnum_jmp TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_print(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *expr_ast = ast->child[0];
+
+ znode expr_node;
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ zend_emit_op_tmp(result, ZEND_PRINT, &expr_node, NULL TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_exit(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *expr_ast = ast->child[0];
+
+ if (expr_ast) {
+ znode expr_node;
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+ zend_emit_op(NULL, ZEND_EXIT, &expr_node, NULL TSRMLS_CC);
+ } else {
+ zend_emit_op(NULL, ZEND_EXIT, NULL, NULL TSRMLS_CC);
+ }
+
+ result->op_type = IS_CONST;
+ ZVAL_BOOL(&result->u.constant, 1);
+}
+/* }}} */
+
+void zend_compile_yield(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *value_ast = ast->child[0];
+ zend_ast *key_ast = ast->child[1];
+
+ znode value_node, key_node;
+ znode *value_node_ptr = NULL, *key_node_ptr = NULL;
+ zend_op *opline;
+ zend_bool returns_by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+
+ if (!CG(active_op_array)->function_name) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "The \"yield\" expression can only be used inside a function");
}
- if (zend_hash_add(CG(current_import), lcname, &ns) == NULL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL(ns), Z_STRVAL_P(name));
+ CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
+
+ if (key_ast) {
+ zend_compile_expr(&key_node, key_ast TSRMLS_CC);
+ key_node_ptr = &key_node;
}
- if (warn) {
- if (!strcmp(Z_STRVAL_P(name), "strict")) {
- zend_error_noreturn(E_COMPILE_ERROR, "You seem to be trying to use a different language...");
+
+ if (value_ast) {
+ if (returns_by_ref && zend_is_variable(value_ast) && !zend_is_call(value_ast)) {
+ zend_compile_var(&value_node, value_ast, BP_VAR_REF TSRMLS_CC);
+ } else {
+ zend_compile_expr(&value_node, value_ast TSRMLS_CC);
}
- zend_error(E_WARNING, "The use statement with non-compound name '%s' has no effect", Z_STRVAL_P(name));
+ value_node_ptr = &value_node;
+ }
+
+ opline = zend_emit_op(result, ZEND_YIELD, value_node_ptr, key_node_ptr TSRMLS_CC);
+
+ if (value_ast && returns_by_ref && zend_is_call(value_ast)) {
+ opline->extended_value = ZEND_RETURNS_FUNCTION;
}
- STR_RELEASE(lcname);
- zval_dtor(name);
}
/* }}} */
-void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, int is_function, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC) /* {{{ */
+void zend_compile_instanceof(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_string *lookup_name;
- zval *name, ns, tmp;
- zend_bool warn = 0;
+ zend_ast *obj_ast = ast->child[0];
+ zend_ast *class_ast = ast->child[1];
- ZVAL_ZVAL(&ns, &ns_name->u.constant, 0, 0);
- if (new_name) {
- name = &new_name->u.constant;
- } else {
- const char *p;
-
- /* The form "use A\B" is eqivalent to "use A\B as B".
- So we extract the last part of compound name to use as a new_name */
- name = &tmp;
- p = zend_memrchr(Z_STRVAL(ns), '\\', Z_STRLEN(ns));
- if (p) {
- ZVAL_STRING(name, p+1);
+ znode obj_node, class_node;
+ zend_op *opline;
+
+ zend_compile_expr(&obj_node, obj_ast TSRMLS_CC);
+ if (obj_node.op_type == IS_CONST) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "instanceof expects an object instance, constant given");
+ }
+
+ opline = zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
+ opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
+
+ zend_emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, &class_node TSRMLS_CC);
+}
+/* }}} */
+
+void zend_compile_include_or_eval(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *expr_ast = ast->child[0];
+ znode expr_node;
+ zend_op *opline;
+
+ zend_do_extended_fcall_begin(TSRMLS_C);
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ opline = zend_emit_op(result, ZEND_INCLUDE_OR_EVAL, &expr_node, NULL TSRMLS_CC);
+ opline->extended_value = ast->attr;
+
+ zend_do_extended_fcall_end(TSRMLS_C);
+}
+/* }}} */
+
+void zend_compile_isset_or_empty(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *var_ast = ast->child[0];
+
+ znode var_node;
+ zend_op *opline;
+
+ ZEND_ASSERT(ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY);
+
+ if (!zend_is_variable(var_ast) || zend_is_call(var_ast)) {
+ if (ast->kind == ZEND_AST_EMPTY) {
+ /* empty(expr) can be transformed to !expr */
+ zend_ast *not_ast = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, var_ast);
+ zend_compile_expr(result, not_ast TSRMLS_CC);
+ return;
} else {
- ZVAL_ZVAL(name, &ns, 1, 0);
- warn = !is_global && Z_TYPE(CG(current_namespace)) == IS_UNDEF;
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Cannot use isset() on the result of an expression "
+ "(you can use \"null !== expression\" instead)");
}
}
- if (case_sensitive) {
- lookup_name = STR_COPY(Z_STR_P(name));
+ switch (var_ast->kind) {
+ case ZEND_AST_VAR:
+ if (zend_try_compile_cv(&var_node, var_ast TSRMLS_CC) == SUCCESS) {
+ opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_VAR, &var_node, NULL TSRMLS_CC);
+ opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
+ } else {
+ opline = zend_compile_simple_var_no_cv(result, var_ast, BP_VAR_IS TSRMLS_CC);
+ opline->opcode = ZEND_ISSET_ISEMPTY_VAR;
+ }
+ break;
+ case ZEND_AST_DIM:
+ opline = zend_compile_dim_common(result, var_ast, BP_VAR_IS TSRMLS_CC);
+ opline->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
+ break;
+ case ZEND_AST_PROP:
+ opline = zend_compile_prop_common(result, var_ast, BP_VAR_IS TSRMLS_CC);
+ opline->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
+ break;
+ case ZEND_AST_STATIC_PROP:
+ opline = zend_compile_static_prop_common(result, var_ast, BP_VAR_IS TSRMLS_CC);
+ opline->opcode = ZEND_ISSET_ISEMPTY_VAR;
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+
+ result->op_type = opline->result_type = IS_TMP_VAR;
+ opline->extended_value |= ast->kind == ZEND_AST_ISSET ? ZEND_ISSET : ZEND_ISEMPTY;
+}
+/* }}} */
+
+void zend_compile_silence(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *expr_ast = ast->child[0];
+ znode silence_node;
+ uint32_t opline_num;
+ zend_op *begin_silence, *end_silence;
+
+ opline_num = get_next_op_number(CG(active_op_array));
+ begin_silence = zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL TSRMLS_CC);
+ /* pair BEGIN_SILENCE and END_SILENCE opcodes */
+ begin_silence->op2.num = opline_num;
+
+ if (expr_ast->kind == ZEND_AST_VAR) {
+ /* For @$var we need to force a FETCH instruction, otherwise the CV access will
+ * happen outside the silenced section. */
+ zend_compile_simple_var_no_cv(result, expr_ast, BP_VAR_R TSRMLS_CC);
} else {
- lookup_name = STR_ALLOC(Z_STRLEN_P(name), 0);
- zend_str_tolower_copy(lookup_name->val, Z_STRVAL_P(name), Z_STRLEN_P(name));
+ zend_compile_expr(result, expr_ast TSRMLS_CC);
}
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- /* Prefix import name with current namespace name to avoid conflicts with functions/consts */
- zend_string *c_ns_name = STR_ALLOC(Z_STRLEN(CG(current_namespace)) + 1 + Z_STRLEN_P(name), 0);
+ end_silence = zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL TSRMLS_CC);
+ /* pair BEGIN_SILENCE and END_SILENCE opcodes */
+ end_silence->op2.num = opline_num;
+}
+/* }}} */
- zend_str_tolower_copy(c_ns_name->val, Z_STRVAL(CG(current_namespace)), Z_STRLEN(CG(current_namespace)));
- c_ns_name->val[Z_STRLEN(CG(current_namespace))] = '\\';
- memcpy(c_ns_name->val+Z_STRLEN(CG(current_namespace))+1, lookup_name, Z_STRLEN_P(name)+1);
- if (zend_hash_exists(lookup_table, c_ns_name)) {
- char *tmp2 = zend_str_tolower_dup(Z_STRVAL(ns), Z_STRLEN(ns));
+void zend_compile_shell_exec(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *expr_ast = ast->child[0];
- if (Z_STRLEN(ns) != Z_STRLEN(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
- memcmp(tmp2, c_ns_name->val, Z_STRLEN(ns))) {
- zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", is_function ? "function" : "const", Z_STRVAL(ns), Z_STRVAL_P(name));
- }
- efree(tmp2);
- }
- STR_FREE(c_ns_name);
- } else if (is_function) {
- zend_function *function;
+ zval fn_name;
+ zend_ast *name_ast, *args_ast, *call_ast;
- if ((function = zend_hash_find_ptr(lookup_table, lookup_name)) != NULL && function->type == ZEND_USER_FUNCTION && strcmp(function->op_array.filename->val, CG(compiled_filename)->val) == 0) {
- char *c_tmp = zend_str_tolower_dup(Z_STRVAL(ns), Z_STRLEN(ns));
+ ZVAL_STRING(&fn_name, "shell_exec");
+ name_ast = zend_ast_create_zval(&fn_name);
+ args_ast = zend_ast_create_list(1, ZEND_AST_ARG_LIST, expr_ast);
+ call_ast = zend_ast_create(ZEND_AST_CALL, name_ast, args_ast);
- if (Z_STRLEN(ns) != Z_STRLEN_P(name) ||
- memcmp(c_tmp, lookup_name->val, Z_STRLEN(ns))) {
- zend_error(E_COMPILE_ERROR, "Cannot use function %s as %s because the name is already in use", Z_STRVAL(ns), Z_STRVAL_P(name));
- }
- efree(c_tmp);
+ zend_compile_expr(result, call_ast TSRMLS_CC);
+
+ zval_ptr_dtor(&fn_name);
+}
+/* }}} */
+
+void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast_list *list = zend_ast_get_list(ast);
+ zend_op *opline;
+ uint32_t i, opnum_init;
+ zend_bool packed = 1;
+
+ if (zend_try_ct_eval_array(&result->u.constant, ast TSRMLS_CC)) {
+ result->op_type = IS_CONST;
+ return;
+ }
+
+ opnum_init = get_next_op_number(CG(active_op_array));
+
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *elem_ast = list->child[i];
+ zend_ast *value_ast = elem_ast->child[0];
+ zend_ast *key_ast = elem_ast->child[1];
+ zend_bool by_ref = elem_ast->attr;
+
+ znode value_node, key_node, *key_node_ptr = NULL;
+
+ if (key_ast) {
+ zend_compile_expr(&key_node, key_ast TSRMLS_CC);
+ zend_handle_numeric_op(&key_node TSRMLS_CC);
+ key_node_ptr = &key_node;
}
- } else {
- zend_string *filename;
- if ((filename = zend_hash_find_ptr(lookup_table, lookup_name)) != NULL && strcmp(filename->val, CG(compiled_filename)->val) == 0) {
- char *c_tmp = zend_str_tolower_dup(Z_STRVAL(ns), Z_STRLEN(ns));
+ if (by_ref) {
+ zend_ensure_writable_variable(value_ast);
+ zend_compile_var(&value_node, value_ast, BP_VAR_W TSRMLS_CC);
+ } else {
+ zend_compile_expr(&value_node, value_ast TSRMLS_CC);
+ }
- if (Z_STRLEN(ns) != Z_STRLEN_P(name) ||
- memcmp(c_tmp, lookup_name->val, Z_STRLEN(ns))) {
- zend_error(E_COMPILE_ERROR, "Cannot use const %s as %s because the name is already in use", Z_STRVAL(ns), Z_STRVAL_P(name));
- }
- efree(c_tmp);
+ if (i == 0) {
+ opline = zend_emit_op_tmp(result, ZEND_INIT_ARRAY, &value_node, key_node_ptr TSRMLS_CC);
+ opline->extended_value = list->children << ZEND_ARRAY_SIZE_SHIFT;
+ } else {
+ opline = zend_emit_op(NULL, ZEND_ADD_ARRAY_ELEMENT,
+ &value_node, key_node_ptr TSRMLS_CC);
+ SET_NODE(opline->result, result);
+ }
+ opline->extended_value |= by_ref;
+
+ if (key_ast && key_node.op_type == IS_CONST && Z_TYPE(key_node.u.constant) == IS_STRING) {
+ packed = 0;
}
}
- if (zend_hash_add(current_import_sub, lookup_name, &ns) == NULL) {
- zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", is_function ? "function" : "const", Z_STRVAL(ns), Z_STRVAL_P(name));
+ /* Handle empty array */
+ if (!list->children) {
+ zend_emit_op_tmp(result, ZEND_INIT_ARRAY, NULL, NULL TSRMLS_CC);
}
- if (warn) {
- zend_error(E_WARNING, "The use %s statement with non-compound name '%s' has no effect", is_function ? "function" : "const", Z_STRVAL_P(name));
+
+ /* Add a flag to INIT_ARRAY if we know this array cannot be packed */
+ if (!packed) {
+ opline = &CG(active_op_array)->opcodes[opnum_init];
+ opline->extended_value |= ZEND_ARRAY_NOT_PACKED;
}
- STR_RELEASE(lookup_name);
- zval_dtor(name);
}
/* }}} */
-void zend_do_use_function(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{{ */
+void zend_compile_const(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- if (!CG(current_import_function)) {
- CG(current_import_function) = emalloc(sizeof(HashTable));
- zend_hash_init(CG(current_import_function), 8, NULL, ZVAL_PTR_DTOR, 0);
+ zend_ast *name_ast = ast->child[0];
+ zend_string *orig_name = zend_ast_get_str(name_ast);
+ zend_bool is_fully_qualified;
+
+ zval resolved_name;
+ zend_op *opline;
+
+ ZVAL_STR(&resolved_name, zend_resolve_const_name(
+ orig_name, name_ast->attr, &is_fully_qualified TSRMLS_CC));
+
+ if (zend_constant_ct_subst(result, &resolved_name, 1 TSRMLS_CC)) {
+ zval_dtor(&resolved_name);
+ return;
}
- zend_do_use_non_class(ns_name, new_name, is_global, 1, 0, CG(current_import_function), CG(function_table) TSRMLS_CC);
+ opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL TSRMLS_CC);
+ opline->op2_type = IS_CONST;
+
+ if (is_fully_qualified) {
+ opline->op2.constant = zend_add_const_name_literal(
+ CG(active_op_array), &resolved_name, 0 TSRMLS_CC);
+ } else {
+ opline->extended_value = IS_CONSTANT_UNQUALIFIED;
+ if (CG(current_namespace)) {
+ opline->extended_value |= IS_CONSTANT_IN_NAMESPACE;
+ opline->op2.constant = zend_add_const_name_literal(
+ CG(active_op_array), &resolved_name, 1 TSRMLS_CC);
+ } else {
+ opline->op2.constant = zend_add_const_name_literal(
+ CG(active_op_array), &resolved_name, 0 TSRMLS_CC);
+ }
+ }
+ zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC);
}
/* }}} */
-void zend_do_use_const(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{{ */
+void zend_compile_class_const(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- if (!CG(current_import_const)) {
- CG(current_import_const) = emalloc(sizeof(HashTable));
- zend_hash_init(CG(current_import_const), 8, NULL, ZVAL_PTR_DTOR, 0);
+ zend_ast *class_ast = ast->child[0];
+ zend_ast *const_ast = ast->child[1];
+
+ znode class_node, const_node;
+ zend_op *opline;
+
+ if (zend_is_const_default_class_ref(class_ast)) {
+ class_node.op_type = IS_CONST;
+ ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast TSRMLS_CC));
+ } else {
+ zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
}
- zend_do_use_non_class(ns_name, new_name, is_global, 0, 1, CG(current_import_const), &CG(const_filenames) TSRMLS_CC);
+ zend_compile_expr(&const_node, const_ast TSRMLS_CC);
+
+ opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, &const_node TSRMLS_CC);
+
+ zend_set_class_name_op1(opline, &class_node TSRMLS_CC);
+
+ if (opline->op1_type == IS_CONST) {
+ zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC);
+ } else {
+ zend_alloc_polymorphic_cache_slot(opline->op2.constant TSRMLS_CC);
+ }
}
/* }}} */
-void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
+void zend_compile_resolve_class_name(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_op *opline;
- zval *ns_name;
+ zend_ast *name_ast = ast->child[0];
+ uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
- if (zend_get_ct_const(&name->u.constant, 0 TSRMLS_CC)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", Z_STRVAL(name->u.constant));
- }
+ switch (fetch_type) {
+ case ZEND_FETCH_CLASS_SELF:
+ if (!CG(active_class_entry)) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Cannot access self::class when no class scope is active");
+ }
+ result->op_type = IS_CONST;
+ ZVAL_STR(&result->u.constant, zend_string_copy(CG(active_class_entry)->name));
+ break;
+ case ZEND_FETCH_CLASS_STATIC:
+ case ZEND_FETCH_CLASS_PARENT:
+ if (!CG(active_class_entry)) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Cannot access %s::class when no class scope is active",
+ fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent");
+ } else {
+ zval class_str_zv;
+ zend_ast *class_str_ast, *class_const_ast;
+
+ ZVAL_STRING(&class_str_zv, "class");
+ class_str_ast = zend_ast_create_zval(&class_str_zv);
+ class_const_ast = zend_ast_create(
+ ZEND_AST_CLASS_CONST, name_ast, class_str_ast);
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- /* Prefix constant name with name of current namespace, lowercased */
- znode tmp;
+ zend_compile_expr(result, class_const_ast TSRMLS_CC);
- tmp.op_type = IS_CONST;
- ZVAL_NEW_STR(&tmp.u.constant, STR_ALLOC(Z_STRLEN(CG(current_namespace)), 0));
- zend_str_tolower_copy(Z_STRVAL(tmp.u.constant), Z_STRVAL(CG(current_namespace)), Z_STRLEN(CG(current_namespace)));
- zend_do_build_namespace_name(&tmp, &tmp, name TSRMLS_CC);
- *name = tmp;
+ zval_ptr_dtor(&class_str_zv);
+ }
+ break;
+ case ZEND_FETCH_CLASS_DEFAULT:
+ result->op_type = IS_CONST;
+ ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast TSRMLS_CC));
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
}
+}
+/* }}} */
+
+void zend_compile_encaps_list(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
+
+ ZEND_ASSERT(list->children > 0);
+
+ result->op_type = IS_TMP_VAR;
+ result->u.op.var = get_temporary_variable(CG(active_op_array));
+
+ for (i = 0; i < list->children; ++i) {
+ zend_ast *elem_ast = list->child[i];
+ znode elem_node;
+ zend_op *opline;
- /* Constant name must not conflict with import names */
- if (CG(current_import_const) &&
- (ns_name = zend_hash_find(CG(current_import_const), Z_STR(name->u.constant))) != NULL) {
+ zend_compile_expr(&elem_node, elem_ast TSRMLS_CC);
- char *tmp = estrndup(Z_STRVAL_P(ns_name), Z_STRLEN_P(ns_name));
+ if (elem_ast->kind == ZEND_AST_ZVAL) {
+ zval *zv = &elem_node.u.constant;
+ ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
- if (Z_STRLEN_P(ns_name) != Z_STRLEN(name->u.constant) ||
- memcmp(tmp, Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant))) {
- zend_error(E_COMPILE_ERROR, "Cannot declare const %s because the name is already in use", Z_STRVAL(name->u.constant));
+ if (Z_STRLEN_P(zv) > 1) {
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_ADD_STRING;
+ } else if (Z_STRLEN_P(zv) == 1) {
+ char ch = *Z_STRVAL_P(zv);
+ zend_string_release(Z_STR_P(zv));
+ ZVAL_LONG(zv, ch);
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_ADD_CHAR;
+ } else {
+ /* String can be empty after a variable at the end of a heredoc */
+ zend_string_release(Z_STR_P(zv));
+ continue;
+ }
+ } else {
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_ADD_VAR;
+ ZEND_ASSERT(elem_node.op_type != IS_CONST);
}
- efree(tmp);
+
+ if (i == 0) {
+ SET_UNUSED(opline->op1);
+ } else {
+ SET_NODE(opline->op1, result);
+ }
+ SET_NODE(opline->op2, &elem_node);
+ SET_NODE(opline->result, result);
}
+}
+/* }}} */
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_DECLARE_CONST;
- SET_UNUSED(opline->result);
- SET_NODE(opline->op1, name);
- SET_NODE(opline->op2, value);
+void zend_compile_magic_const(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_class_entry *ce = CG(active_class_entry);
+
+ if (zend_try_ct_eval_magic_const(&result->u.constant, ast TSRMLS_CC)) {
+ result->op_type = IS_CONST;
+ return;
+ }
+
+ ZEND_ASSERT(ast->attr == T_CLASS_C && ce && ZEND_CE_IS_TRAIT(ce));
- zend_hash_add_ptr(&CG(const_filenames), Z_STR(name->u.constant), CG(compiled_filename));
+ {
+ zend_ast *const_ast = zend_ast_create(ZEND_AST_CONST,
+ zend_ast_create_zval_from_str(zend_string_init("__CLASS__", sizeof("__CLASS__") - 1, 0)));
+ zend_compile_const(result, const_ast TSRMLS_CC);
+ zend_ast_destroy(const_ast);
+ }
}
/* }}} */
-void zend_verify_namespace(TSRMLS_D) /* {{{ */
+zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
{
- if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
- zend_error_noreturn(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
- }
+ return kind == ZEND_AST_ZVAL || kind == ZEND_AST_BINARY_OP
+ || kind == ZEND_AST_GREATER || kind == ZEND_AST_GREATER_EQUAL
+ || kind == ZEND_AST_AND || kind == ZEND_AST_OR
+ || kind == ZEND_AST_UNARY_OP
+ || kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS
+ || kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_DIM
+ || kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM
+ || kind == ZEND_AST_CONST || kind == ZEND_AST_CLASS_CONST
+ || kind == ZEND_AST_RESOLVE_CLASS_NAME || kind == ZEND_AST_MAGIC_CONST;
}
/* }}} */
-void zend_do_end_namespace(TSRMLS_D) /* {{{ */
+void zend_compile_const_expr_class_const(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */
{
- CG(in_namespace) = 0;
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- zval_dtor(&CG(current_namespace));
- ZVAL_UNDEF(&CG(current_namespace));
+ zend_ast *ast = *ast_ptr;
+ zend_ast *class_ast = ast->child[0];
+ zend_ast *const_ast = ast->child[1];
+ zend_string *class_name = zend_ast_get_str(class_ast);
+ zend_string *const_name = zend_ast_get_str(const_ast);
+ zval result;
+ int fetch_type;
+
+ if (class_ast->kind != ZEND_AST_ZVAL) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Dynamic class names are not allowed in compile-time class constant references");
}
- if (CG(current_import)) {
- zend_hash_destroy(CG(current_import));
- efree(CG(current_import));
- CG(current_import) = NULL;
+
+ fetch_type = zend_get_class_fetch_type(class_name);
+
+ if (ZEND_FETCH_CLASS_STATIC == fetch_type) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "\"static::\" is not allowed in compile-time constants");
}
- if (CG(current_import_function)) {
- zend_hash_destroy(CG(current_import_function));
- efree(CG(current_import_function));
- CG(current_import_function) = NULL;
+
+ if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
+ class_name = zend_resolve_class_name_ast(class_ast TSRMLS_CC);
+ } else {
+ zend_string_addref(class_name);
}
- if (CG(current_import_const)) {
- zend_hash_destroy(CG(current_import_const));
- efree(CG(current_import_const));
- CG(current_import_const) = NULL;
+
+ Z_STR(result) = zend_concat3(
+ class_name->val, class_name->len, "::", 2, const_name->val, const_name->len);
+
+ Z_TYPE_INFO(result) = IS_CONSTANT_EX;
+ if (IS_INTERNED(Z_STR(result))) {
+ Z_TYPE_FLAGS(result) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
}
+ Z_CONST_FLAGS(result) = fetch_type;
+
+ zend_ast_destroy(ast);
+ zend_string_release(class_name);
+
+ *ast_ptr = zend_ast_create_zval(&result);
}
/* }}} */
-void zend_do_end_compilation(TSRMLS_D) /* {{{ */
+void zend_compile_const_expr_const(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */
{
- CG(has_bracketed_namespaces) = 0;
- zend_do_end_namespace(TSRMLS_C);
+ zend_ast *ast = *ast_ptr;
+ zend_ast *name_ast = ast->child[0];
+ zval *orig_name = zend_ast_get_zval(name_ast);
+ zend_bool is_fully_qualified;
+
+ znode result;
+ zval resolved_name;
+
+ if (zend_constant_ct_subst(&result, orig_name, 0 TSRMLS_CC)) {
+ zend_ast_destroy(ast);
+ *ast_ptr = zend_ast_create_zval(&result.u.constant);
+ return;
+ }
+
+ ZVAL_STR(&resolved_name, zend_resolve_const_name(
+ Z_STR_P(orig_name), name_ast->attr, &is_fully_qualified TSRMLS_CC));
+
+ Z_TYPE_INFO(resolved_name) = IS_CONSTANT_EX;
+ if (!is_fully_qualified) {
+ Z_CONST_FLAGS(resolved_name) = IS_CONSTANT_UNQUALIFIED;
+ }
+
+ zend_ast_destroy(ast);
+ *ast_ptr = zend_ast_create_zval(&resolved_name);
}
/* }}} */
-void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+void zend_compile_const_expr_resolve_class_name(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */
{
- if (ast->kind == ZEND_CONST) {
- ZVAL_COPY_VALUE(&result->u.constant, &ast->u.val);
- efree(ast);
- } else if (zend_ast_is_ct_constant(ast)) {
- zend_ast_evaluate(&result->u.constant, ast, NULL TSRMLS_CC);
+ zend_ast *ast = *ast_ptr;
+ zend_ast *name_ast = ast->child[0];
+ uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
+ zval result;
+
+ switch (fetch_type) {
+ case ZEND_FETCH_CLASS_SELF:
+ if (!CG(active_class_entry)) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Cannot access self::class when no class scope is active");
+ }
+ ZVAL_STR(&result, zend_string_copy(CG(active_class_entry)->name));
+ break;
+ case ZEND_FETCH_CLASS_STATIC:
+ case ZEND_FETCH_CLASS_PARENT:
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "%s::class cannot be used for compile-time class name resolution",
+ fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
+ );
+ break;
+ case ZEND_FETCH_CLASS_DEFAULT:
+ ZVAL_STR(&result, zend_resolve_class_name_ast(name_ast TSRMLS_CC));
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+
+ zend_ast_destroy(ast);
+ *ast_ptr = zend_ast_create_zval(&result);
+}
+/* }}} */
+
+void zend_compile_const_expr_magic_const(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */
+{
+ zend_ast *ast = *ast_ptr;
+ zend_class_entry *ce = CG(active_class_entry);
+
+ /* Other cases already resolved by constant folding */
+ ZEND_ASSERT(ast->attr == T_CLASS_C && ce && ZEND_CE_IS_TRAIT(ce));
+
+ {
+ zval const_zv;
+ ZVAL_STRING(&const_zv, "__CLASS__");
+ Z_TYPE_INFO(const_zv) = IS_CONSTANT_EX;
+
zend_ast_destroy(ast);
+ *ast_ptr = zend_ast_create_zval(&const_zv);
+ }
+}
+/* }}} */
+
+void zend_compile_const_expr(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */
+{
+ zend_ast *ast = *ast_ptr;
+ if (ast == NULL || ast->kind == ZEND_AST_ZVAL) {
+ return;
+ }
+
+ if (!zend_is_allowed_in_const_expr(ast->kind)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
+ }
+
+ switch (ast->kind) {
+ case ZEND_AST_CLASS_CONST:
+ zend_compile_const_expr_class_const(ast_ptr TSRMLS_CC);
+ break;
+ case ZEND_AST_CONST:
+ zend_compile_const_expr_const(ast_ptr TSRMLS_CC);
+ break;
+ case ZEND_AST_RESOLVE_CLASS_NAME:
+ zend_compile_const_expr_resolve_class_name(ast_ptr TSRMLS_CC);
+ break;
+ case ZEND_AST_MAGIC_CONST:
+ zend_compile_const_expr_magic_const(ast_ptr TSRMLS_CC);
+ break;
+ default:
+ zend_ast_apply(ast, zend_compile_const_expr TSRMLS_CC);
+ break;
+ }
+}
+/* }}} */
+
+void zend_const_expr_to_zval(zval *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *orig_ast = ast;
+ zend_eval_const_expr(&ast TSRMLS_CC);
+ zend_compile_const_expr(&ast TSRMLS_CC);
+ if (ast->kind == ZEND_AST_ZVAL) {
+ ZVAL_COPY_VALUE(result, zend_ast_get_zval(ast));
+
+ /* Kill this branch of the original AST, as it was already destroyed.
+ * It would be nice to find a better solution to this problem in the
+ * future. */
+ orig_ast->kind = 0;
} else {
- ZVAL_NEW_AST(&result->u.constant, ast);
+ ZVAL_NEW_AST(result, zend_ast_copy(ast));
}
}
/* }}} */
-/* {{{ zend_dirname
- Returns directory name component of path */
-ZEND_API size_t zend_dirname(char *path, size_t len)
+/* Same as compile_stmt, but with early binding */
+void zend_compile_top_stmt(zend_ast *ast TSRMLS_DC) /* {{{ */
{
- register char *end = path + len - 1;
- unsigned int len_adjust = 0;
+ if (!ast) {
+ return;
+ }
-#ifdef PHP_WIN32
- /* Note that on Win32 CWD is per drive (heritage from CP/M).
- * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
- */
- if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
- /* Skip over the drive spec (if any) so as not to change */
- path += 2;
- len_adjust += 2;
- if (2 == len) {
- /* Return "c:" on Win32 for dirname("c:").
- * It would be more consistent to return "c:."
- * but that would require making the string *longer*.
- */
- return len;
+ if (ast->kind == ZEND_AST_STMT_LIST) {
+ zend_ast_list *list = zend_ast_get_list(ast);
+ uint32_t i;
+ for (i = 0; i < list->children; ++i) {
+ zend_compile_top_stmt(list->child[i] TSRMLS_CC);
}
+ return;
}
-#elif defined(NETWARE)
- /*
- * Find the first occurrence of : from the left
- * move the path pointer to the position just after :
- * increment the len_adjust to the length of path till colon character(inclusive)
- * If there is no character beyond : simple return len
- */
- char *colonpos = NULL;
- colonpos = strchr(path, ':');
- if (colonpos != NULL) {
- len_adjust = ((colonpos - path) + 1);
- path += len_adjust;
- if (len_adjust == len) {
- return len;
- }
+
+ zend_compile_stmt(ast TSRMLS_CC);
+
+ if (ast->kind != ZEND_AST_NAMESPACE && ast->kind != ZEND_AST_HALT_COMPILER) {
+ zend_verify_namespace(TSRMLS_C);
}
-#endif
+ if (ast->kind == ZEND_AST_FUNC_DECL || ast->kind == ZEND_AST_CLASS) {
+ CG(zend_lineno) = ((zend_ast_decl *) ast)->end_lineno;
+ zend_do_early_binding(TSRMLS_C);
+ }
+}
+/* }}} */
- if (len == 0) {
- /* Illegal use of this function */
- return 0;
+void zend_compile_stmt(zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ if (!ast) {
+ return;
}
- /* Strip trailing slashes */
- while (end >= path && IS_SLASH_P(end)) {
- end--;
+ CG(zend_lineno) = ast->lineno;
+
+ switch (ast->kind) {
+ case ZEND_AST_STMT_LIST:
+ zend_compile_stmt_list(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_GLOBAL:
+ zend_compile_global_var(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_STATIC:
+ zend_compile_static_var(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_UNSET:
+ zend_compile_unset(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_RETURN:
+ zend_compile_return(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_ECHO:
+ zend_compile_echo(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_THROW:
+ zend_compile_throw(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_BREAK:
+ case ZEND_AST_CONTINUE:
+ zend_compile_break_continue(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_GOTO:
+ zend_compile_goto(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_LABEL:
+ zend_compile_label(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_WHILE:
+ zend_compile_while(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_DO_WHILE:
+ zend_compile_do_while(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_FOR:
+ zend_compile_for(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_FOREACH:
+ zend_compile_foreach(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_IF:
+ zend_compile_if(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_SWITCH:
+ zend_compile_switch(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_TRY:
+ zend_compile_try(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_DECLARE:
+ zend_compile_declare(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_FUNC_DECL:
+ case ZEND_AST_METHOD:
+ zend_compile_func_decl(NULL, ast TSRMLS_CC);
+ break;
+ case ZEND_AST_PROP_DECL:
+ zend_compile_prop_decl(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_CLASS_CONST_DECL:
+ zend_compile_class_const_decl(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_USE_TRAIT:
+ zend_compile_use_trait(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_CLASS:
+ zend_compile_class_decl(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_USE:
+ zend_compile_use(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_CONST_DECL:
+ zend_compile_const_decl(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_NAMESPACE:
+ zend_compile_namespace(ast TSRMLS_CC);
+ break;
+ case ZEND_AST_HALT_COMPILER:
+ zend_compile_halt_compiler(ast TSRMLS_CC);
+ break;
+ default:
+ {
+ znode result;
+ zend_compile_expr(&result, ast TSRMLS_CC);
+ zend_do_free(&result TSRMLS_CC);
+ }
}
- if (end < path) {
- /* The path only contained slashes */
- path[0] = DEFAULT_SLASH;
- path[1] = '\0';
- return 1 + len_adjust;
+
+ if (Z_LVAL(CG(declarables).ticks) && !zend_is_unticked_stmt(ast)) {
+ zend_emit_tick(TSRMLS_C);
}
+}
+/* }}} */
- /* Strip filename */
- while (end >= path && !IS_SLASH_P(end)) {
- end--;
+void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ /* CG(zend_lineno) = ast->lineno; */
+ CG(zend_lineno) = zend_ast_get_lineno(ast);
+
+ switch (ast->kind) {
+ case ZEND_AST_ZVAL:
+ ZVAL_COPY(&result->u.constant, zend_ast_get_zval(ast));
+ result->op_type = IS_CONST;
+ return;
+ case ZEND_AST_ZNODE:
+ *result = *zend_ast_get_znode(ast);
+ return;
+ case ZEND_AST_VAR:
+ case ZEND_AST_DIM:
+ case ZEND_AST_PROP:
+ case ZEND_AST_STATIC_PROP:
+ case ZEND_AST_CALL:
+ case ZEND_AST_METHOD_CALL:
+ case ZEND_AST_STATIC_CALL:
+ zend_compile_var(result, ast, BP_VAR_R TSRMLS_CC);
+ return;
+ case ZEND_AST_ASSIGN:
+ zend_compile_assign(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_ASSIGN_REF:
+ zend_compile_assign_ref(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_NEW:
+ zend_compile_new(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_CLONE:
+ zend_compile_clone(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_ASSIGN_OP:
+ zend_compile_compound_assign(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_BINARY_OP:
+ zend_compile_binary_op(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_GREATER:
+ case ZEND_AST_GREATER_EQUAL:
+ zend_compile_greater(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_UNARY_OP:
+ zend_compile_unary_op(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_UNARY_PLUS:
+ case ZEND_AST_UNARY_MINUS:
+ zend_compile_unary_pm(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_AND:
+ case ZEND_AST_OR:
+ zend_compile_short_circuiting(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_POST_INC:
+ case ZEND_AST_POST_DEC:
+ zend_compile_post_incdec(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_PRE_INC:
+ case ZEND_AST_PRE_DEC:
+ zend_compile_pre_incdec(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_CAST:
+ zend_compile_cast(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_CONDITIONAL:
+ zend_compile_conditional(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_PRINT:
+ zend_compile_print(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_EXIT:
+ zend_compile_exit(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_YIELD:
+ zend_compile_yield(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_INSTANCEOF:
+ zend_compile_instanceof(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_INCLUDE_OR_EVAL:
+ zend_compile_include_or_eval(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_ISSET:
+ case ZEND_AST_EMPTY:
+ zend_compile_isset_or_empty(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_SILENCE:
+ zend_compile_silence(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_SHELL_EXEC:
+ zend_compile_shell_exec(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_ARRAY:
+ zend_compile_array(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_CONST:
+ zend_compile_const(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_CLASS_CONST:
+ zend_compile_class_const(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_RESOLVE_CLASS_NAME:
+ zend_compile_resolve_class_name(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_ENCAPS_LIST:
+ zend_compile_encaps_list(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_MAGIC_CONST:
+ zend_compile_magic_const(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_CLOSURE:
+ zend_compile_func_decl(result, ast TSRMLS_CC);
+ return;
+ default:
+ ZEND_ASSERT(0 /* not supported */);
}
- if (end < path) {
- /* No slash found, therefore return '.' */
-#ifdef NETWARE
- if (len_adjust == 0) {
- path[0] = '.';
- path[1] = '\0';
- return 1; /* only one character */
- } else {
- path[0] = '\0';
- return len_adjust;
- }
-#else
- path[0] = '.';
- path[1] = '\0';
- return 1 + len_adjust;
-#endif
+}
+/* }}} */
+
+void zend_compile_var(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
+{
+ switch (ast->kind) {
+ case ZEND_AST_VAR:
+ zend_compile_simple_var(result, ast, type TSRMLS_CC);
+ return;
+ case ZEND_AST_DIM:
+ zend_compile_dim(result, ast, type TSRMLS_CC);
+ return;
+ case ZEND_AST_PROP:
+ zend_compile_prop(result, ast, type TSRMLS_CC);
+ return;
+ case ZEND_AST_STATIC_PROP:
+ zend_compile_static_prop(result, ast, type TSRMLS_CC);
+ return;
+ case ZEND_AST_CALL:
+ zend_compile_call(result, ast, type TSRMLS_CC);
+ return;
+ case ZEND_AST_METHOD_CALL:
+ zend_compile_method_call(result, ast, type TSRMLS_CC);
+ return;
+ case ZEND_AST_STATIC_CALL:
+ zend_compile_static_call(result, ast, type TSRMLS_CC);
+ return;
+ case ZEND_AST_ZNODE:
+ *result = *zend_ast_get_znode(ast);
+ return;
+ default:
+ if (type == BP_VAR_W || type == BP_VAR_REF
+ || type == BP_VAR_RW || type == BP_VAR_UNSET
+ ) {
+ /* For BC reasons =& new Foo is allowed */
+ if (type != BP_VAR_REF || ast->kind != ZEND_AST_NEW) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Cannot use temporary expression in write context");
+ }
+ }
+
+ zend_compile_expr(result, ast TSRMLS_CC);
+ return;
}
+}
+/* }}} */
- /* Strip slashes which came before the file name */
- while (end >= path && IS_SLASH_P(end)) {
- end--;
+void zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type TSRMLS_DC) /* {{{ */
+{
+ zend_op *opline;
+ switch (ast->kind) {
+ case ZEND_AST_DIM:
+ opline = zend_delayed_compile_dim(result, ast, type TSRMLS_CC);
+ zend_adjust_for_fetch_type(opline, type);
+ return;
+ case ZEND_AST_PROP:
+ opline = zend_delayed_compile_prop(result, ast, type TSRMLS_CC);
+ zend_adjust_for_fetch_type(opline, type);
+ return;
+ default:
+ zend_compile_var(result, ast, type TSRMLS_CC);
+ return;
}
- if (end < path) {
- path[0] = DEFAULT_SLASH;
- path[1] = '\0';
- return 1 + len_adjust;
+}
+/* }}} */
+
+void zend_eval_const_expr(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */
+{
+ zend_ast *ast = *ast_ptr;
+ zval result;
+
+ if (!ast) {
+ return;
}
- *(end+1) = '\0';
- return (size_t)(end + 1 - path) + len_adjust;
+ switch (ast->kind) {
+ case ZEND_AST_BINARY_OP:
+ zend_eval_const_expr(&ast->child[0] TSRMLS_CC);
+ zend_eval_const_expr(&ast->child[1] TSRMLS_CC);
+ if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
+ return;
+ }
+
+ zend_ct_eval_binary_op(&result, ast->attr,
+ zend_ast_get_zval(ast->child[0]), zend_ast_get_zval(ast->child[1]) TSRMLS_CC);
+ break;
+ case ZEND_AST_GREATER:
+ case ZEND_AST_GREATER_EQUAL:
+ zend_eval_const_expr(&ast->child[0] TSRMLS_CC);
+ zend_eval_const_expr(&ast->child[1] TSRMLS_CC);
+ if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
+ return;
+ }
+
+ zend_ct_eval_greater(&result, ast->kind,
+ zend_ast_get_zval(ast->child[0]), zend_ast_get_zval(ast->child[1]) TSRMLS_CC);
+ break;
+ case ZEND_AST_UNARY_PLUS:
+ case ZEND_AST_UNARY_MINUS:
+ zend_eval_const_expr(&ast->child[0] TSRMLS_CC);
+ if (ast->child[0]->kind != ZEND_AST_ZVAL) {
+ return;
+ }
+
+ zend_ct_eval_unary_pm(&result, ast->kind,
+ zend_ast_get_zval(ast->child[0]) TSRMLS_CC);
+ break;
+ case ZEND_AST_ARRAY:
+ if (!zend_try_ct_eval_array(&result, ast TSRMLS_CC)) {
+ return;
+ }
+ break;
+ case ZEND_AST_MAGIC_CONST:
+ if (!zend_try_ct_eval_magic_const(&result, ast TSRMLS_CC)) {
+ return;
+ }
+ break;
+ case ZEND_AST_CONST: {
+ znode result_node;
+
+ if (!zend_constant_ct_subst(&result_node, zend_ast_get_zval(ast->child[0]), 0 TSRMLS_CC)) {
+ return;
+ }
+ zend_ast_destroy(ast);
+ *ast_ptr = zend_ast_create_zval(&result_node.u.constant);
+ return;
+ }
+ default:
+ return;
+ }
+
+ zend_ast_destroy(ast);
+ *ast_ptr = zend_ast_create_zval(&result);
}
/* }}} */
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index fa333545f4..8cbe465c14 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -33,28 +33,20 @@
#define DEBUG_ZEND 0
-#define FREE_PNODE(znode) zval_dtor(&znode->u.constant);
-
#define SET_UNUSED(op) op ## _type = IS_UNUSED
-#define INC_BPC(op_array) if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { (CG(context).backpatch_count++); }
-#define DEC_BPC(op_array) if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { (CG(context).backpatch_count--); }
-#define HANDLE_INTERACTIVE() if (CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) { execute_new_code(TSRMLS_C); }
-#define DO_TICKS() if (Z_LVAL(CG(declarables).ticks)) { zend_do_ticks(TSRMLS_C); }
-
-#define RESET_DOC_COMMENT() \
- { \
- if (CG(doc_comment)) { \
- STR_RELEASE(CG(doc_comment)); \
- CG(doc_comment) = NULL; \
- } \
- }
+#define RESET_DOC_COMMENT() do { \
+ if (CG(doc_comment)) { \
+ zend_string_release(CG(doc_comment)); \
+ CG(doc_comment) = NULL; \
+ } \
+} while (0)
typedef struct _zend_op_array zend_op_array;
typedef struct _zend_op zend_op;
typedef struct _zend_compiler_context {
- zend_uint opcodes_size;
+ uint32_t opcodes_size;
int vars_size;
int literals_size;
int current_brk_cont;
@@ -64,11 +56,11 @@ typedef struct _zend_compiler_context {
} zend_compiler_context;
typedef union _znode_op {
- zend_uint constant;
- zend_uint var;
- zend_uint num;
+ uint32_t constant;
+ uint32_t var;
+ uint32_t num;
zend_ulong hash;
- zend_uint opline_num; /* Needs to be signed */
+ uint32_t opline_num; /* Needs to be signed */
zend_op *jmp_addr;
zval *zv;
void *ptr; /* Used for passing pointers from the compile to execution phase, currently used for traits */
@@ -79,12 +71,35 @@ typedef struct _znode { /* used only during compilation */
union {
znode_op op;
zval constant; /* replaced by literal/zv */
- zend_op_array *op_array;
- zend_ast *ast;
} u;
- zend_uint EA; /* extended attributes */
} znode;
+/* Temporarily defined here, to avoid header ordering issues */
+typedef struct _zend_ast_znode {
+ zend_ast_kind kind;
+ zend_ast_attr attr;
+ uint32_t lineno;
+ znode node;
+} zend_ast_znode;
+ZEND_API zend_ast *zend_ast_create_znode(znode *node);
+
+static inline znode *zend_ast_get_znode(zend_ast *ast) {
+ return &((zend_ast_znode *) ast)->node;
+}
+
+typedef union _zend_parser_stack_elem {
+ zend_ast *ast;
+ zend_string *str;
+ zend_ulong num;
+} zend_parser_stack_elem;
+
+void zend_compile_top_stmt(zend_ast *ast TSRMLS_DC);
+void zend_compile_stmt(zend_ast *ast TSRMLS_DC);
+void zend_compile_expr(znode *node, zend_ast *ast TSRMLS_DC);
+void zend_compile_var(znode *node, zend_ast *ast, uint32_t type TSRMLS_DC);
+void zend_eval_const_expr(zend_ast **ast_ptr TSRMLS_DC);
+void zend_const_expr_to_zval(zval *result, zend_ast *ast TSRMLS_DC);
+
typedef struct _zend_execute_data zend_execute_data;
#define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data TSRMLS_DC
@@ -100,7 +115,7 @@ struct _zend_op {
znode_op op1;
znode_op op2;
znode_op result;
- ulong extended_value;
+ zend_ulong extended_value;
uint lineno;
zend_uchar opcode;
zend_uchar op1_type;
@@ -118,18 +133,22 @@ typedef struct _zend_brk_cont_element {
typedef struct _zend_label {
int brk_cont;
- zend_uint opline_num;
+ uint32_t opline_num;
} zend_label;
typedef struct _zend_try_catch_element {
- zend_uint try_op;
- zend_uint catch_op; /* ketchup! */
- zend_uint finally_op;
- zend_uint finally_end;
+ uint32_t try_op;
+ uint32_t catch_op; /* ketchup! */
+ uint32_t finally_op;
+ uint32_t finally_end;
} zend_try_catch_element;
-#if SIZEOF_LONG == 8
-#define THIS_HASHVAL 6385726429UL
+#if SIZEOF_ZEND_LONG == 8
+# ifdef _WIN32
+# define THIS_HASHVAL 6385726429Ui64
+# else
+# define THIS_HASHVAL 6385726429ULL
+# endif
#else
#define THIS_HASHVAL 2090759133UL
#endif
@@ -149,9 +168,6 @@ typedef struct _zend_try_catch_element {
#define ZEND_ACC_INTERFACE 0x80
#define ZEND_ACC_TRAIT 0x120
-/* op_array flags */
-#define ZEND_ACC_INTERACTIVE 0x10
-
/* method flags (visibility) */
/* The order of those must be kept - public < protected < private */
#define ZEND_ACC_PUBLIC 0x100
@@ -204,23 +220,26 @@ typedef struct _zend_try_catch_element {
/* function has arguments with type hinting */
#define ZEND_ACC_HAS_TYPE_HINTS 0x10000000
-char *zend_visibility_string(zend_uint fn_flags);
+/* op_array has finally blocks */
+#define ZEND_ACC_HAS_FINALLY_BLOCK 0x20000000
+#define ZEND_CE_IS_TRAIT(ce) (((ce)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT)
+
+char *zend_visibility_string(uint32_t fn_flags);
typedef struct _zend_property_info {
- zend_uint flags;
- zend_string *name;
- ulong h;
+ uint32_t flags;
int offset;
+ zend_string *name;
zend_string *doc_comment;
zend_class_entry *ce;
} zend_property_info;
typedef struct _zend_arg_info {
const char *name; // TODO: convert into zend_string ???
- zend_uint name_len;
+ uint32_t name_len;
const char *class_name; // TODO: convert into zend_string ???
- zend_uint class_name_len;
+ uint32_t class_name_len;
zend_uchar type_hint;
zend_uchar pass_by_reference;
zend_bool allow_null;
@@ -233,9 +252,9 @@ typedef struct _zend_arg_info {
*/
typedef struct _zend_internal_function_info {
const char *_name;
- zend_uint _name_len;
+ uint32_t _name_len;
const char *_class_name;
- zend_uint required_num_args;
+ uint32_t required_num_args;
zend_uchar _type_hint;
zend_bool return_reference;
zend_bool _allow_null;
@@ -245,48 +264,45 @@ typedef struct _zend_internal_function_info {
struct _zend_op_array {
/* Common elements */
zend_uchar type;
+ uint32_t fn_flags;
zend_string *function_name;
zend_class_entry *scope;
- zend_uint fn_flags;
zend_function *prototype;
- zend_uint num_args;
- zend_uint required_num_args;
+ uint32_t num_args;
+ uint32_t required_num_args;
zend_arg_info *arg_info;
/* END of common elements */
- zend_uint *refcount;
+ uint32_t *refcount;
+
+ uint32_t this_var;
+ uint32_t last;
zend_op *opcodes;
- zend_uint last;
- zend_string **vars;
int last_var;
+ uint32_t T;
+ zend_string **vars;
- zend_uint T;
-
- zend_brk_cont_element *brk_cont_array;
int last_brk_cont;
-
- zend_try_catch_element *try_catch_array;
int last_try_catch;
- zend_bool has_finally_block;
+ zend_brk_cont_element *brk_cont_array;
+ zend_try_catch_element *try_catch_array;
/* static variables support */
HashTable *static_variables;
- zend_uint this_var;
-
zend_string *filename;
- zend_uint line_start;
- zend_uint line_end;
+ uint32_t line_start;
+ uint32_t line_end;
zend_string *doc_comment;
- zend_uint early_binding; /* the linked list of delayed declarations */
+ uint32_t early_binding; /* the linked list of delayed declarations */
- zval *literals;
int last_literal;
+ zval *literals;
- void **run_time_cache;
int last_cache_slot;
+ void **run_time_cache;
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
@@ -298,12 +314,12 @@ struct _zend_op_array {
typedef struct _zend_internal_function {
/* Common elements */
zend_uchar type;
+ uint32_t fn_flags;
zend_string* function_name;
zend_class_entry *scope;
- zend_uint fn_flags;
zend_function *prototype;
- zend_uint num_args;
- zend_uint required_num_args;
+ uint32_t num_args;
+ uint32_t required_num_args;
zend_arg_info *arg_info;
/* END of common elements */
@@ -318,12 +334,12 @@ union _zend_function {
struct {
zend_uchar type; /* never used */
+ uint32_t fn_flags;
zend_string *function_name;
zend_class_entry *scope;
- zend_uint fn_flags;
union _zend_function *prototype;
- zend_uint num_args;
- zend_uint required_num_args;
+ uint32_t num_args;
+ uint32_t required_num_args;
zend_arg_info *arg_info;
} common;
@@ -331,26 +347,6 @@ union _zend_function {
zend_internal_function internal_function;
};
-typedef struct _zend_function_call_entry {
- zend_function *fbc;
- zend_uint op_number;
- zend_uint arg_num;
- zend_bool uses_argument_unpacking;
-} zend_function_call_entry;
-
-typedef struct _zend_switch_entry {
- znode cond;
- int default_case;
- int control_var;
-} zend_switch_entry;
-
-
-typedef struct _list_llist_element {
- znode var;
- zend_llist dimensions;
- znode value;
-} list_llist_element;
-
typedef enum _vm_frame_kind {
VM_FRAME_NESTED_FUNCTION, /* stackless VM call to function */
VM_FRAME_NESTED_CODE, /* stackless VM call to include/require/eval */
@@ -359,11 +355,11 @@ typedef enum _vm_frame_kind {
} vm_frame_kind;
struct _zend_execute_data {
- struct _zend_op *opline; /* executed opline */
+ const zend_op *opline; /* executed opline */
zend_execute_data *call; /* current call */
void **run_time_cache;
zend_function *func; /* executed op_array */
- zend_uint num_args;
+ uint32_t num_args;
zend_uchar flags;
zend_uchar frame_kind;
zend_class_entry *called_scope;
@@ -373,7 +369,7 @@ struct _zend_execute_data {
zval *return_value;
zend_class_entry *scope; /* function scope (self) */
zend_array *symbol_table;
- struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
+ const zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
zend_object *delayed_exception;
zval old_error_reporting;
};
@@ -427,11 +423,7 @@ ZEND_API zend_string *zend_get_compiled_filename(TSRMLS_D);
ZEND_API int zend_get_compiled_lineno(TSRMLS_D);
ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D);
-void zend_resolve_non_class_name(znode *element_name, zend_bool *check_namespace, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC);
-void zend_resolve_function_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC);
-void zend_resolve_const_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC);
-void zend_resolve_class_name(znode *class_name TSRMLS_DC);
-ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var);
+ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var);
#ifdef ZTS
const char *zend_get_zendtext(TSRMLS_D);
@@ -439,95 +431,26 @@ int zend_get_zendleng(TSRMLS_D);
#endif
-/* parser-driven code generators */
-void zend_do_binary_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC);
-void zend_do_unary_op(zend_uchar op, znode *result, znode *op1 TSRMLS_DC);
-void zend_do_binary_assign_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC);
-void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC);
-void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC);
-void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC);
-void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC);
-void zend_do_indirect_references(znode *result, const znode *num_references, znode *variable TSRMLS_DC);
-void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC);
-void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC);
-
-void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC);
-void fetch_array_dim(znode *result, znode *parent, znode *dim TSRMLS_DC);
-void fetch_string_offset(znode *result, znode *parent, znode *offset TSRMLS_DC);
-void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC);
-void zend_do_print(znode *result, znode *arg TSRMLS_DC);
-void zend_do_echo(znode *arg TSRMLS_DC);
typedef int (*unary_op_type)(zval *, zval * TSRMLS_DC);
typedef int (*binary_op_type)(zval *, zval *, zval * TSRMLS_DC);
ZEND_API unary_op_type get_unary_op(int opcode);
ZEND_API binary_op_type get_binary_op(int opcode);
-void zend_do_while_cond(znode *expr, znode *close_bracket_token TSRMLS_DC);
-void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC);
-void zend_do_do_while_begin(TSRMLS_D);
-void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, znode *expr TSRMLS_DC);
-
-
-void zend_do_if_cond(znode *cond, znode *closing_bracket_token TSRMLS_DC);
-void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC);
-void zend_do_if_end(TSRMLS_D);
-
-void zend_do_for_cond(znode *expr, znode *second_semicolon_token TSRMLS_DC);
-void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC);
-void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC);
-
-void zend_do_pre_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC);
-void zend_do_post_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC);
-
-void zend_do_begin_variable_parse(TSRMLS_D);
-void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC);
-
-void zend_check_writable_variable(const znode *variable);
+void zend_stop_lexing(TSRMLS_D);
+void zend_emit_final_return(zval *zv TSRMLS_DC);
+zend_ast *zend_ast_append_str(zend_ast *left, zend_ast *right);
+uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag);
+zend_ast *zend_ast_append_doc_comment(zend_ast *list TSRMLS_DC);
+void zend_handle_encoding_declaration(zend_ast *ast TSRMLS_DC);
+/* parser-driven code generators */
void zend_do_free(znode *op1 TSRMLS_DC);
-void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC);
-void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC);
-
-int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier);
-void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC);
-void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC);
-void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization, znode *class_type, zend_bool pass_by_reference, zend_bool is_variadic TSRMLS_DC);
-int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC);
-void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC);
-void zend_do_clone(znode *result, znode *expr TSRMLS_DC);
-void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC);
-void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC);
-void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_class_member TSRMLS_DC);
-int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC);
-void zend_do_end_function_call(znode *function_name, znode *result, int is_method, int is_dynamic_fcall TSRMLS_DC);
-void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
-void zend_do_yield(znode *result, znode *value, znode *key, zend_bool is_variable TSRMLS_DC);
-void zend_do_handle_exception(TSRMLS_D);
-
-void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC);
-void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC);
-
-void zend_do_try(znode *try_token TSRMLS_DC);
-void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, znode *first_catch TSRMLS_DC);
-void zend_do_bind_catch(znode *try_token, znode *catch_token TSRMLS_DC);
-void zend_do_end_catch(znode *catch_token TSRMLS_DC);
-void zend_do_finally(znode *finally_token TSRMLS_DC);
-void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_token TSRMLS_DC);
-void zend_do_throw(znode *expr TSRMLS_DC);
-
-ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time TSRMLS_DC);
+ZEND_API int do_bind_function(const zend_op_array *op_array, const zend_op *opline, HashTable *function_table, zend_bool compile_time TSRMLS_DC);
ZEND_API zend_class_entry *do_bind_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC);
ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC);
ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC);
ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC);
-void zend_do_implements_interface(znode *interface_znode TSRMLS_DC);
-
-/* Trait related functions */
-void zend_do_use_trait(znode *trait_znode TSRMLS_DC);
-void zend_prepare_reference(znode *result, znode *class_name, znode *method_name TSRMLS_DC);
-void zend_add_trait_precedence(znode *method_reference, znode *trait_list TSRMLS_DC);
-void zend_add_trait_alias(znode *method_reference, znode *modifiers, znode *alias TSRMLS_DC);
ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC);
ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC);
@@ -536,116 +459,23 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
void zend_do_early_binding(TSRMLS_D);
ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC);
-void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC);
-void zend_do_unpack_params(znode *params TSRMLS_DC);
-
-
-void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC);
-void zend_do_boolean_or_end(znode *result, znode *expr1, znode *expr2, const znode *op_token TSRMLS_DC);
-void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC);
-void zend_do_boolean_and_end(znode *result, znode *expr1, znode *expr2, const znode *op_token TSRMLS_DC);
-
-void zend_do_brk_cont(zend_uchar op, znode *expr TSRMLS_DC);
-
-void zend_do_switch_cond(const znode *cond TSRMLS_DC);
-void zend_do_switch_end(const znode *case_list TSRMLS_DC);
-void zend_do_case_before_statement(const znode *case_list, znode *case_token, znode *case_expr TSRMLS_DC);
-void zend_do_case_after_statement(znode *result, const znode *case_token TSRMLS_DC);
-void zend_do_default_before_statement(const znode *case_list, znode *default_token TSRMLS_DC);
-
-void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC);
-void zend_do_end_class_declaration(const znode *class_token, const znode *parent_token TSRMLS_DC);
-void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC);
-void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC);
-
-void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS_DC);
-
-void zend_do_halt_compiler_register(TSRMLS_D);
-
-void zend_do_push_object(const znode *object TSRMLS_DC);
-void zend_do_pop_object(znode *object TSRMLS_DC);
-
-
-void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC);
-void zend_do_end_new_object(znode *result, const znode *new_token TSRMLS_DC);
-
-void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC);
-
-void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC);
-
-void zend_do_init_array(znode *result, znode *expr, znode *offset, zend_bool is_ref TSRMLS_DC);
-void zend_do_add_array_element(znode *result, znode *expr, znode *offset, zend_bool is_ref TSRMLS_DC);
-void zend_do_end_array(znode *result, const znode *array_node TSRMLS_DC);
-void zend_do_list_init(TSRMLS_D);
-void zend_do_list_end(znode *result, znode *expr TSRMLS_DC);
-void zend_do_add_list_element(const znode *element TSRMLS_DC);
-void zend_do_new_list_begin(TSRMLS_D);
-void zend_do_new_list_end(TSRMLS_D);
-
/* Functions for a null terminated pointer list, used for traits parsing and compilation */
void zend_init_list(void *result, void *item TSRMLS_DC);
void zend_add_to_list(void *result, void *item TSRMLS_DC);
-
-void zend_do_cast(znode *result, znode *expr, int type TSRMLS_DC);
-void zend_do_include_or_eval(int type, znode *result, znode *op1 TSRMLS_DC);
-
-void zend_do_unset(znode *variable TSRMLS_DC);
-void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC);
-
-void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC);
-
-void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, znode *as_token, int variable TSRMLS_DC);
-void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token, const znode *as_token, znode *value, znode *key TSRMLS_DC);
-void zend_do_foreach_end(const znode *foreach_token, const znode *as_token TSRMLS_DC);
-
-void zend_do_declare_begin(TSRMLS_D);
-void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC);
-void zend_do_declare_end(const znode *declare_token TSRMLS_DC);
-
-void zend_do_exit(znode *result, znode *message TSRMLS_DC);
-
-void zend_do_begin_silence(znode *strudel_token TSRMLS_DC);
-void zend_do_end_silence(znode *strudel_token TSRMLS_DC);
-
-void zend_do_jmp_set(znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC);
-void zend_do_jmp_set_else(znode *result, znode *false_value, const znode *jmp_token, znode *colon_token TSRMLS_DC);
-
-void zend_do_begin_qm_op(znode *cond, znode *qm_token TSRMLS_DC);
-void zend_do_qm_true(znode *true_value, znode *qm_token, znode *colon_token TSRMLS_DC);
-void zend_do_qm_false(znode *result, znode *false_value, znode *qm_token, const znode *colon_token TSRMLS_DC);
-
void zend_do_extended_info(TSRMLS_D);
void zend_do_extended_fcall_begin(TSRMLS_D);
void zend_do_extended_fcall_end(TSRMLS_D);
-void zend_do_ticks(TSRMLS_D);
-
-void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC);
-
-void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC);
-void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC);
-void zend_do_begin_namespace(znode *name, zend_bool with_brackets TSRMLS_DC);
-void zend_do_end_namespace(TSRMLS_D);
void zend_verify_namespace(TSRMLS_D);
-void zend_do_use(znode *name, znode *new_name, int is_global TSRMLS_DC);
-void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, int is_function, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC);
-void zend_do_use_function(znode *name, znode *new_name, int is_global TSRMLS_DC);
-void zend_do_use_const(znode *name, znode *new_name, int is_global TSRMLS_DC);
void zend_do_end_compilation(TSRMLS_D);
-void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC);
-void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC);
-
-void zend_do_label(znode *label TSRMLS_DC);
-void zend_do_goto(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(int temporary TSRMLS_DC);
ZEND_API void function_add_ref(zend_function *function);
#define INITIAL_OP_ARRAY_SIZE 64
-#define INITIAL_INTERACTIVE_OP_ARRAY_SIZE 8192
/* helper functions in zend_language_scanner.l */
@@ -661,16 +491,18 @@ ZEND_API void zend_cleanup_user_class_data(zend_class_entry *ce TSRMLS_DC);
ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC);
ZEND_API void zend_cleanup_internal_classes(TSRMLS_D);
ZEND_API void zend_cleanup_op_array_data(zend_op_array *op_array);
+ZEND_API int clean_non_persistent_function_full(zval *zv TSRMLS_DC);
+ZEND_API int clean_non_persistent_class_full(zval *zv TSRMLS_DC);
ZEND_API void destroy_zend_function(zend_function *function TSRMLS_DC);
ZEND_API void zend_function_dtor(zval *zv);
ZEND_API void destroy_zend_class(zval *zv);
void zend_class_add_ref(zval *zv);
-ZEND_API zend_string *zend_mangle_property_name(const char *src1, int src1_length, const char *src2, int src2_length, int internal);
-#define zend_unmangle_property_name(mangled_property, mangled_property_len, class_name, prop_name) \
- zend_unmangle_property_name_ex(mangled_property, mangled_property_len, class_name, prop_name, NULL)
-ZEND_API int zend_unmangle_property_name_ex(const char *mangled_property, int mangled_property_len, const char **class_name, const char **prop_name, int *prop_len);
+ZEND_API zend_string *zend_mangle_property_name(const char *src1, size_t src1_length, const char *src2, size_t src2_length, int internal);
+#define zend_unmangle_property_name(mangled_property, class_name, prop_name) \
+ zend_unmangle_property_name_ex(mangled_property, class_name, prop_name, NULL)
+ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char **class_name, const char **prop_name, size_t *prop_len);
#define ZEND_FUNCTION_DTOR zend_function_dtor
#define ZEND_CLASS_DTOR destroy_zend_class
@@ -682,13 +514,10 @@ int print_class(zend_class_entry *class_entry TSRMLS_DC);
void print_op_array(zend_op_array *op_array, int optimizations);
ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC);
zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array);
-void zend_do_first_catch(znode *open_parentheses TSRMLS_DC);
-void zend_initialize_try_catch_element(znode *catch_token TSRMLS_DC);
-void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additional_catch TSRMLS_DC);
ZEND_API zend_bool zend_is_compiling(TSRMLS_D);
ZEND_API char *zend_make_compiled_string_description(const char *name TSRMLS_DC);
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC);
-int zend_get_class_fetch_type(const char *class_name, uint class_name_len);
+uint32_t zend_get_class_fetch_type(zend_string *name);
typedef zend_bool (*zend_auto_global_callback)(zend_string *name TSRMLS_DC);
typedef struct _zend_auto_global {
@@ -703,7 +532,7 @@ ZEND_API void zend_activate_auto_globals(TSRMLS_D);
ZEND_API zend_bool zend_is_auto_global(zend_string *name TSRMLS_DC);
ZEND_API size_t zend_dirname(char *path, size_t len);
-int zendlex(znode *zendlval TSRMLS_DC);
+int zendlex(zend_parser_stack_elem *elem TSRMLS_DC);
int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
@@ -737,6 +566,13 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
#define ZEND_PARSED_NEW (1<<6)
#define ZEND_PARSED_LIST_EXPR (1<<7)
+#define ZEND_PARAM_REF (1<<0)
+#define ZEND_PARAM_VARIADIC (1<<1)
+
+#define ZEND_NAME_FQ 0
+#define ZEND_NAME_NOT_FQ 1
+#define ZEND_NAME_RELATIVE 2
+
/* unset types */
#define ZEND_UNSET_REG 0
@@ -745,9 +581,13 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
#define BP_VAR_W 1
#define BP_VAR_RW 2
#define BP_VAR_IS 3
-#define BP_VAR_NA 4 /* if not applicable */
-#define BP_VAR_FUNC_ARG 5
-#define BP_VAR_UNSET 6
+#define BP_VAR_FUNC_ARG 4
+#define BP_VAR_UNSET 5
+#define BP_VAR_REF 6 /* right-hand side of by-ref assignment */
+
+/* Bottom 3 bits are the type, top bits are arg num for BP_VAR_FUNC_ARG */
+#define BP_VAR_SHIFT 3
+#define BP_VAR_MASK 7
#define ZEND_INTERNAL_FUNCTION 1
@@ -810,21 +650,28 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
#define ZEND_SEND_BY_REF 1
#define ZEND_SEND_PREFER_REF 2
-#define CHECK_ARG_SEND_TYPE(zf, arg_num, m) \
- (EXPECTED((zf)->common.arg_info != NULL) && \
- (EXPECTED(arg_num <= (zf)->common.num_args) \
- ? ((zf)->common.arg_info[arg_num-1].pass_by_reference & (m)) \
- : (UNEXPECTED((zf)->common.fn_flags & ZEND_ACC_VARIADIC) != 0) && \
- ((zf)->common.arg_info[(zf)->common.num_args-1].pass_by_reference & (m))))
+static zend_always_inline int zend_check_arg_send_type(const zend_function *zf, uint32_t arg_num, uint32_t mask)
+{
+ if (UNEXPECTED(zf->common.arg_info == NULL)) {
+ return 0;
+ }
+ if (UNEXPECTED(arg_num > zf->common.num_args)) {
+ if (EXPECTED((zf->common.fn_flags & ZEND_ACC_VARIADIC) == 0)) {
+ return 0;
+ }
+ arg_num = zf->common.num_args;
+ }
+ return UNEXPECTED((zf->common.arg_info[arg_num-1].pass_by_reference & mask) != 0);
+}
#define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \
- CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF)
+ zend_check_arg_send_type(zf, arg_num, ZEND_SEND_BY_REF)
#define ARG_SHOULD_BE_SENT_BY_REF(zf, arg_num) \
- CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF)
+ zend_check_arg_send_type(zf, arg_num, ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF)
#define ARG_MAY_BE_SENT_BY_REF(zf, arg_num) \
- CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_PREFER_REF)
+ zend_check_arg_send_type(zf, arg_num, ZEND_SEND_PREFER_REF)
#define ZEND_RETURN_VAL 0
#define ZEND_RETURN_REF 1
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index 64ea7060fa..bca35cf591 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -37,7 +37,7 @@ void free_zend_constant(zval *zv)
zval_internal_dtor(&c->value);
}
if (c->name) {
- STR_RELEASE(c->name);
+ zend_string_release(c->name);
}
pefree(c, c->flags & CONST_PERSISTENT);
}
@@ -51,12 +51,12 @@ static void copy_zend_constant(zval *zv)
memcpy(Z_PTR_P(zv), c, sizeof(zend_constant));
c = Z_PTR_P(zv);
- c->name = STR_COPY(c->name);
+ c->name = zend_string_copy(c->name);
if (!(c->flags & CONST_PERSISTENT)) {
zval_copy_ctor(&c->value);
} else {
if (Z_TYPE(c->value) == IS_STRING) {
- Z_STR(c->value) = STR_DUP(Z_STR(c->value), 1);
+ Z_STR(c->value) = zend_string_dup(Z_STR(c->value), 1);
}
}
}
@@ -167,7 +167,7 @@ ZEND_API void zend_register_null_constant(const char *name, uint name_len, int f
ZVAL_NULL(&c.value);
c.flags = flags;
- c.name = STR_INIT(name, name_len, flags & CONST_PERSISTENT);
+ c.name = zend_string_init(name, name_len, flags & CONST_PERSISTENT);
c.module_number = module_number;
zend_register_constant(&c TSRMLS_CC);
}
@@ -178,18 +178,18 @@ ZEND_API void zend_register_bool_constant(const char *name, uint name_len, zend_
ZVAL_BOOL(&c.value, bval);
c.flags = flags;
- c.name = STR_INIT(name, name_len, flags & CONST_PERSISTENT);
+ c.name = zend_string_init(name, name_len, flags & CONST_PERSISTENT);
c.module_number = module_number;
zend_register_constant(&c TSRMLS_CC);
}
-ZEND_API void zend_register_long_constant(const char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC)
+ZEND_API void zend_register_long_constant(const char *name, uint name_len, zend_long lval, int flags, int module_number TSRMLS_DC)
{
zend_constant c;
ZVAL_LONG(&c.value, lval);
c.flags = flags;
- c.name = STR_INIT(name, name_len, flags & CONST_PERSISTENT);
+ c.name = zend_string_init(name, name_len, flags & CONST_PERSISTENT);
c.module_number = module_number;
zend_register_constant(&c TSRMLS_CC);
}
@@ -201,7 +201,7 @@ ZEND_API void zend_register_double_constant(const char *name, uint name_len, dou
ZVAL_DOUBLE(&c.value, dval);
c.flags = flags;
- c.name = STR_INIT(name, name_len, flags & CONST_PERSISTENT);
+ c.name = zend_string_init(name, name_len, flags & CONST_PERSISTENT);
c.module_number = module_number;
zend_register_constant(&c TSRMLS_CC);
}
@@ -211,9 +211,9 @@ ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, ch
{
zend_constant c;
- ZVAL_NEW_STR(&c.value, STR_INIT(strval, strlen, flags & CONST_PERSISTENT));
+ ZVAL_NEW_STR(&c.value, zend_string_init(strval, strlen, flags & CONST_PERSISTENT));
c.flags = flags;
- c.name = STR_INIT(name, name_len, flags & CONST_PERSISTENT);
+ c.name = zend_string_init(name, name_len, flags & CONST_PERSISTENT);
c.module_number = module_number;
zend_register_constant(&c TSRMLS_CC);
}
@@ -240,25 +240,25 @@ static zend_constant *zend_get_special_constant(const char *name, uint name_len
zend_string *const_name;
const_name_len = sizeof("\0__CLASS__") + EG(scope)->name->len;
- const_name = STR_ALLOC(const_name_len, 0);
+ const_name = zend_string_alloc(const_name_len, 0);
memcpy(const_name->val, "\0__CLASS__", sizeof("\0__CLASS__")-1);
zend_str_tolower_copy(const_name->val + sizeof("\0__CLASS__")-1, EG(scope)->name->val, EG(scope)->name->len);
if ((c = zend_hash_find_ptr(EG(zend_constants), const_name)) == NULL) {
c = emalloc(sizeof(zend_constant));
memset(c, 0, sizeof(zend_constant));
- ZVAL_STR(&c->value, STR_COPY(EG(scope)->name));
+ ZVAL_STR(&c->value, zend_string_copy(EG(scope)->name));
zend_hash_add_ptr(EG(zend_constants), const_name, c);
}
- STR_RELEASE(const_name);
+ zend_string_release(const_name);
} else {
- zend_string *const_name = STR_INIT("\0__CLASS__", sizeof("\0__CLASS__")-1, 0);
+ zend_string *const_name = zend_string_init("\0__CLASS__", sizeof("\0__CLASS__")-1, 0);
if ((c = zend_hash_find_ptr(EG(zend_constants), const_name)) == NULL) {
c = emalloc(sizeof(zend_constant));
memset(c, 0, sizeof(zend_constant));
ZVAL_EMPTY_STRING(&c->value);
zend_hash_add_ptr(EG(zend_constants), const_name, c);
}
- STR_RELEASE(const_name);
+ zend_string_release(const_name);
}
return c;
} else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
@@ -273,7 +273,7 @@ static zend_constant *zend_get_special_constant(const char *name, uint name_len
haltname = zend_mangle_property_name(haltoff,
sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
c = zend_hash_find_ptr(EG(zend_constants), haltname);
- STR_FREE(haltname);
+ zend_string_free(haltname);
return c;
} else {
return NULL;
@@ -323,7 +323,7 @@ ZEND_API zval *zend_get_constant(zend_string *name TSRMLS_DC)
return c ? &c->value : NULL;
}
-ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, ulong flags TSRMLS_DC)
+ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, zend_ulong flags TSRMLS_DC)
{
zend_constant *c;
const char *colon;
@@ -343,12 +343,12 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
colon > name && (*(colon - 1) == ':')) {
int class_name_len = colon - name - 1;
int const_name_len = name_len - class_name_len - 2;
- zend_string *constant_name = STR_INIT(colon + 1, const_name_len, 0);
+ zend_string *constant_name = zend_string_init(colon + 1, const_name_len, 0);
char *lcname;
zval *ret_constant = NULL;
ALLOCA_FLAG(use_heap)
- class_name = STR_INIT(name, class_name_len, 0);
+ class_name = zend_string_init(name, class_name_len, 0);
lcname = do_alloca(class_name_len + 1, use_heap);
zend_str_tolower_copy(lcname, name, class_name_len);
if (!scope) {
@@ -396,8 +396,8 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
ret_constant = Z_REFVAL_P(ret_constant);
}
}
- STR_RELEASE(class_name);
- STR_FREE(constant_name);
+ zend_string_release(class_name);
+ zend_string_free(constant_name);
if (ret_constant && Z_CONSTANT_P(ret_constant)) {
zval_update_constant_ex(ret_constant, 1, ce TSRMLS_CC);
}
@@ -449,7 +449,7 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
}
}
-zend_constant *zend_quick_get_constant(const zval *key, ulong flags TSRMLS_DC)
+zend_constant *zend_quick_get_constant(const zval *key, zend_ulong flags TSRMLS_DC)
{
zend_constant *c;
@@ -501,14 +501,14 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
#endif
if (!(c->flags & CONST_CS)) {
- lowercase_name = STR_ALLOC(c->name->len, c->flags & CONST_PERSISTENT);
+ lowercase_name = zend_string_alloc(c->name->len, c->flags & CONST_PERSISTENT);
zend_str_tolower_copy(lowercase_name->val, c->name->val, c->name->len);
lowercase_name = zend_new_interned_string(lowercase_name TSRMLS_CC);
name = lowercase_name;
} else {
char *slash = strrchr(c->name->val, '\\');
if (slash) {
- lowercase_name = STR_INIT(c->name->val, c->name->len, c->flags & CONST_PERSISTENT);
+ lowercase_name = zend_string_init(c->name->val, c->name->len, c->flags & CONST_PERSISTENT);
zend_str_tolower(lowercase_name->val, slash - c->name->val);
lowercase_name = zend_new_interned_string(lowercase_name TSRMLS_CC);
name = lowercase_name;
@@ -527,14 +527,14 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
&& memcmp(name->val, "\0__COMPILER_HALT_OFFSET__", sizeof("\0__COMPILER_HALT_OFFSET__")) == 0) {
}
zend_error(E_NOTICE,"Constant %s already defined", name->val);
- STR_RELEASE(c->name);
+ zend_string_release(c->name);
if (!(c->flags & CONST_PERSISTENT)) {
zval_dtor(&c->value);
}
ret = FAILURE;
}
if (lowercase_name) {
- STR_RELEASE(lowercase_name);
+ zend_string_release(lowercase_name);
}
return ret;
}
diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h
index 09a5dac63d..d81476f3f4 100644
--- a/Zend/zend_constants.h
+++ b/Zend/zend_constants.h
@@ -32,8 +32,8 @@
typedef struct _zend_constant {
zval value;
- int flags;
zend_string *name;
+ int flags;
int module_number;
} zend_constant;
@@ -67,16 +67,16 @@ void zend_register_standard_constants(TSRMLS_D);
void clean_non_persistent_constants(TSRMLS_D);
ZEND_API zval *zend_get_constant(zend_string *name TSRMLS_DC);
ZEND_API zval *zend_get_constant_str(const char *name, uint name_len TSRMLS_DC);
-ZEND_API zval *zend_get_constant_ex(zend_string *name, zend_class_entry *scope, ulong flags TSRMLS_DC);
+ZEND_API zval *zend_get_constant_ex(zend_string *name, zend_class_entry *scope, zend_ulong flags TSRMLS_DC);
ZEND_API void zend_register_bool_constant(const char *name, uint name_len, zend_bool bval, int flags, int module_number TSRMLS_DC);
ZEND_API void zend_register_null_constant(const char *name, uint name_len, int flags, int module_number TSRMLS_DC);
-ZEND_API void zend_register_long_constant(const char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC);
+ZEND_API void zend_register_long_constant(const char *name, uint name_len, zend_long lval, int flags, int module_number TSRMLS_DC);
ZEND_API void zend_register_double_constant(const char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC);
ZEND_API void zend_register_string_constant(const char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC);
ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, char *strval, uint strlen, int flags, int module_number TSRMLS_DC);
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC);
void zend_copy_constants(HashTable *target, HashTable *sourc);
-zend_constant *zend_quick_get_constant(const zval *key, ulong flags TSRMLS_DC);
+zend_constant *zend_quick_get_constant(const zval *key, zend_ulong flags TSRMLS_DC);
END_EXTERN_C()
#define ZEND_CONSTANT_DTOR free_zend_constant
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c
index 754927b577..c5193ce7b6 100644
--- a/Zend/zend_exceptions.c
+++ b/Zend/zend_exceptions.c
@@ -196,7 +196,7 @@ ZEND_METHOD(exception, __clone)
ZEND_METHOD(exception, __construct)
{
zend_string *message = NULL;
- long code = 0;
+ zend_long code = 0;
zval *object, *previous = NULL;
int argc = ZEND_NUM_ARGS();
@@ -225,9 +225,10 @@ ZEND_METHOD(exception, __construct)
ZEND_METHOD(error_exception, __construct)
{
char *message = NULL, *filename = NULL;
- long code = 0, severity = E_ERROR, lineno;
+ zend_long code = 0, severity = E_ERROR, lineno;
zval *object, *previous = NULL;
- int argc = ZEND_NUM_ARGS(), message_len, filename_len;
+ int argc = ZEND_NUM_ARGS();
+ size_t message_len, filename_len;
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|sllslO!", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, default_exception_ce) == FAILURE) {
zend_error(E_ERROR, "Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno [, Exception $previous = NULL]]]]]])");
@@ -335,12 +336,12 @@ ZEND_METHOD(error_exception, getSeverity)
/* {{{ gettraceasstring() macros */
#define TRACE_APPEND_CHR(chr) \
- str = STR_REALLOC(str, str->len + 1, 0); \
+ str = zend_string_realloc(str, str->len + 1, 0); \
str->val[str->len - 1] = chr
#define TRACE_APPEND_STRL(v, l) \
{ \
- str = STR_REALLOC(str, str->len + (l), 0); \
+ str = zend_string_realloc(str, str->len + (l), 0); \
memcpy(str->val + str->len - (l), (v), (l)); \
}
@@ -362,7 +363,7 @@ ZEND_METHOD(error_exception, getSeverity)
#define TRACE_ARG_APPEND(vallen) do { \
int len = str->len; \
- str = STR_REALLOC(str, len + vallen, 0); \
+ str = zend_string_realloc(str, len + vallen, 0); \
memmove(str->val + len - l_added + 1 + vallen, str->val + len - l_added + 1, l_added); \
} while (0)
@@ -459,18 +460,18 @@ static void _build_trace_args(zval *arg, zend_string **str_ptr TSRMLS_DC) /* {{{
TRACE_APPEND_STR("true, ");
break;
case IS_RESOURCE: {
- long lval = Z_RES_HANDLE_P(arg);
+ zend_long lval = Z_RES_HANDLE_P(arg);
char s_tmp[MAX_LENGTH_OF_LONG + 1];
- int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
+ int l_tmp = zend_sprintf(s_tmp, ZEND_LONG_FMT, lval); /* SAFE */
TRACE_APPEND_STR("Resource id #");
TRACE_APPEND_STRL(s_tmp, l_tmp);
TRACE_APPEND_STR(", ");
break;
}
case IS_LONG: {
- long lval = Z_LVAL_P(arg);
+ zend_long lval = Z_LVAL_P(arg);
char s_tmp[MAX_LENGTH_OF_LONG + 1];
- int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
+ int l_tmp = zend_sprintf(s_tmp, ZEND_LONG_FMT, lval); /* SAFE */
TRACE_APPEND_STRL(s_tmp, l_tmp);
TRACE_APPEND_STR(", ");
break;
@@ -509,17 +510,17 @@ static void _build_trace_args(zval *arg, zend_string **str_ptr TSRMLS_DC) /* {{{
}
/* }}} */
-static void _build_trace_string(zval *frame, ulong index, zend_string **str_ptr, int *num TSRMLS_DC) /* {{{ */
+static void _build_trace_string(zval *frame, zend_ulong index, zend_string **str_ptr, int *num TSRMLS_DC) /* {{{ */
{
char *s_tmp;
int len;
- long line;
+ zend_long line;
HashTable *ht;
zval *file, *tmp;
zend_string *str = *str_ptr;
if (Z_TYPE_P(frame) != IS_ARRAY) {
- zend_error(E_WARNING, "Expected array for frame %lu", index);
+ zend_error(E_WARNING, "Expected array for frame %pu", index);
return;
}
@@ -546,7 +547,7 @@ static void _build_trace_string(zval *frame, ulong index, zend_string **str_ptr,
line = 0;
}
s_tmp = emalloc(Z_STRLEN_P(file) + MAX_LENGTH_OF_LONG + 4 + 1);
- len = sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_P(file), line);
+ len = sprintf(s_tmp, "%s(" ZEND_LONG_FMT "): ", Z_STRVAL_P(file), line);
TRACE_APPEND_STRL(s_tmp, len);
efree(s_tmp);
}
@@ -584,17 +585,17 @@ static void _build_trace_string(zval *frame, ulong index, zend_string **str_ptr,
ZEND_METHOD(exception, getTraceAsString)
{
zval *trace, *frame;
- ulong index;
- zend_string *str, *key;
+ zend_ulong index;
+ zend_string *str;
int num = 0, len;
char s_tmp[MAX_LENGTH_OF_LONG + 7 + 1 + 1];
DEFAULT_0_PARAMS;
- str = STR_ALLOC(0, 0);
+ str = zend_string_alloc(0, 0);
trace = zend_read_property(default_exception_ce, getThis(), "trace", sizeof("trace")-1, 1 TSRMLS_CC);
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(trace), index, key, frame) {
+ ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) {
_build_trace_string(frame, index, &str, &num TSRMLS_CC);
} ZEND_HASH_FOREACH_END();
@@ -665,9 +666,9 @@ ZEND_METHOD(exception, __toString)
_default_exception_get_entry(exception, "file", sizeof("file")-1, &file TSRMLS_CC);
_default_exception_get_entry(exception, "line", sizeof("line")-1, &line TSRMLS_CC);
- convert_to_string(&message);
- convert_to_string(&file);
- convert_to_long(&line);
+ convert_to_string_ex(&message);
+ convert_to_string_ex(&file);
+ convert_to_long_ex(&line);
fci.size = sizeof(fci);
fci.function_table = &Z_OBJCE_P(exception)->function_table;
@@ -697,7 +698,7 @@ ZEND_METHOD(exception, __toString)
(Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
prev_str->len ? "\n\nNext " : "", prev_str->val);
}
- STR_RELEASE(prev_str);
+ zend_string_release(prev_str);
zval_dtor(&message);
zval_dtor(&file);
zval_dtor(&line);
@@ -800,7 +801,7 @@ ZEND_API zend_class_entry *zend_get_error_exception(TSRMLS_D) /* {{{ */
}
/* }}} */
-ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, long code TSRMLS_DC) /* {{{ */
+ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code TSRMLS_DC) /* {{{ */
{
zval ex;
@@ -827,7 +828,7 @@ ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const
}
/* }}} */
-ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, const char *format, ...) /* {{{ */
+ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code TSRMLS_DC, const char *format, ...) /* {{{ */
{
va_list arg;
char *message;
@@ -842,7 +843,7 @@ ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, lo
}
/* }}} */
-ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, long code, int severity TSRMLS_DC) /* {{{ */
+ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, zend_long code, int severity TSRMLS_DC) /* {{{ */
{
zval ex;
zend_object *obj = zend_throw_exception(exception_ce, message, code TSRMLS_CC);
@@ -894,7 +895,7 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity TSRMLS_DC) /* {
file = zend_read_property(default_exception_ce, &zv, "file", sizeof("file")-1, 1 TSRMLS_CC);
line = zend_read_property(default_exception_ce, &zv, "line", sizeof("line")-1, 1 TSRMLS_CC);
- convert_to_string(file);
+ convert_to_string_ex(file);
file = (Z_STRLEN_P(file) > 0) ? file : NULL;
line = (Z_TYPE_P(line) == IS_LONG) ? line : NULL;
} else {
@@ -908,9 +909,9 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity TSRMLS_DC) /* {
file = zend_read_property(default_exception_ce, &exception, "file", sizeof("file")-1, 1 TSRMLS_CC);
line = zend_read_property(default_exception_ce, &exception, "line", sizeof("line")-1, 1 TSRMLS_CC);
- convert_to_string(str);
- convert_to_string(file);
- convert_to_long(line);
+ convert_to_string_ex(str);
+ convert_to_string_ex(file);
+ convert_to_long_ex(line);
zend_error_va(severity, (Z_STRLEN_P(file) > 0) ? Z_STRVAL_P(file) : NULL, Z_LVAL_P(line), "Uncaught %s\n thrown", Z_STRVAL_P(str));
} else {
diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h
index a799786751..0c13b66281 100644
--- a/Zend/zend_exceptions.h
+++ b/Zend/zend_exceptions.h
@@ -40,12 +40,12 @@ ZEND_API void zend_register_default_classes(TSRMLS_D);
/* exception_ce NULL or zend_exception_get_default() or a derived class
* message NULL or the message of the exception */
-ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, long code TSRMLS_DC);
-ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, const char *format, ...);
+ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code TSRMLS_DC);
+ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code TSRMLS_DC, const char *format, ...);
ZEND_API void zend_throw_exception_object(zval *exception TSRMLS_DC);
ZEND_API void zend_clear_exception(TSRMLS_D);
-ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, long code, int severity TSRMLS_DC);
+ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, zend_long code, int severity TSRMLS_DC);
extern ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index f3e97d71d0..0c8e7379d7 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -64,27 +64,15 @@ static void zend_extension_fcall_end_handler(const zend_extension *extension, ze
#define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED))
-#define TEMP_VAR_STACK_LIMIT 2000
-
-static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free)
-{
- should_free->var = NULL;
- if (Z_REFCOUNTED_P(z) && !Z_DELREF_P(z)) {
- Z_SET_REFCOUNT_P(z, 1);
- should_free->var = z;
- /* should_free->is_var = 1; */
- }
-}
-
static ZEND_FUNCTION(pass)
{
}
static const zend_internal_function zend_pass_function = {
ZEND_INTERNAL_FUNCTION, /* type */
+ 0, /* fn_flags */
NULL, /* name */
NULL, /* scope */
- 0, /* fn_flags */
NULL, /* prototype */
0, /* num_args */
0, /* required_num_args */
@@ -95,12 +83,13 @@ static const zend_internal_function zend_pass_function = {
#undef zval_ptr_dtor
#define zval_ptr_dtor(zv) i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC TSRMLS_CC)
-#define zval_ptr_dtor_nogc(zv) i_zval_ptr_dtor_nogc(zv ZEND_FILE_LINE_CC TSRMLS_CC)
-#define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f)
#define PZVAL_LOCK(z) if (Z_REFCOUNTED_P(z)) Z_ADDREF_P((z))
#define SELECTIVE_PZVAL_LOCK(pzv, opline) if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(pzv); }
+#define READY_TO_DESTROY(zv) \
+ (zv && Z_REFCOUNTED_P(zv) && Z_REFCOUNT_P(zv) == 1)
+
#define EXTRACT_ZVAL_PTR(zv) do { \
zval *__zv = (zv); \
if (Z_TYPE_P(__zv) == IS_INDIRECT) { \
@@ -149,12 +138,12 @@ static const zend_internal_function zend_pass_function = {
#undef EX
#define EX(element) execute_data->element
-ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, zend_uint var)
+ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var)
{
return EX_VAR(var);
}
-static zend_always_inline zval *_get_zval_ptr_tmp(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
{
zval *ret = EX_VAR(var);
should_free->var = ret;
@@ -164,7 +153,7 @@ static zend_always_inline zval *_get_zval_ptr_tmp(zend_uint var, const zend_exec
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_var(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -172,7 +161,7 @@ static zend_always_inline zval *_get_zval_ptr_var(zend_uint var, const zend_exec
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_var_deref(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -181,7 +170,7 @@ static zend_always_inline zval *_get_zval_ptr_var_deref(zend_uint var, const zen
return ret;
}
-static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, zend_uint var, int type, const zend_execute_data *execute_data TSRMLS_DC)
+static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv;
@@ -205,7 +194,7 @@ static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, zend_uint var, int
return ptr;
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
@@ -213,7 +202,7 @@ static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, zend_uin
return &EG(uninitialized_zval);
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
@@ -221,12 +210,7 @@ static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, zend
return &EG(uninitialized_zval);
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_IS(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
-{
- return &EG(uninitialized_zval);
-}
-
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
@@ -235,13 +219,13 @@ static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, zend_ui
return ptr;
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
{
ZVAL_NULL(ptr);
return ptr;
}
-static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execute_data, zend_uint var, int type TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execute_data, uint32_t var, int type TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -251,7 +235,7 @@ static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execut
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *execute_data, zend_uint var, int type TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *execute_data, uint32_t var, int type TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -262,7 +246,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -272,7 +256,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_dat
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -283,7 +267,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execu
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -293,7 +277,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -304,28 +288,22 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_e
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
- if (Z_TYPE_P(ret) == IS_UNDEF) {
- return _get_zval_cv_lookup_BP_VAR_IS(ret, var, execute_data TSRMLS_CC);
- }
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
- if (Z_TYPE_P(ret) == IS_UNDEF) {
- return _get_zval_cv_lookup_BP_VAR_IS(ret, var, execute_data TSRMLS_CC);
- }
ZVAL_DEREF(ret);
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -335,7 +313,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_da
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -346,7 +324,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_exec
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -356,12 +334,12 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_dat
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
return EX_VAR(var);
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -432,18 +410,19 @@ static inline zval *_get_zval_ptr_deref(int op_type, const znode_op *node, const
return NULL;
}
-static zend_always_inline zval *_get_zval_ptr_ptr_var(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
{
zval *ret = EX_VAR(var);
if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
should_free->var = NULL;
return Z_INDIRECT_P(ret);
- } else if (!Z_REFCOUNTED_P(ret)) {
- should_free->var = ret; //???
+ } else if (!Z_REFCOUNTED_P(ret) || Z_REFCOUNT_P(ret) == 1) {
+ should_free->var = ret;
return ret;
} else {
- PZVAL_UNLOCK(ret, should_free);
+ Z_DELREF_P(ret);
+ should_free->var = NULL;
return ret;
}
}
@@ -525,7 +504,7 @@ static inline zval* make_real_object(zval *object_ptr TSRMLS_DC)
return object;
}
-ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC)
+ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, zend_ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC)
{
zend_string *key;
ALLOCA_FLAG(use_heap);
@@ -542,7 +521,7 @@ ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ul
}
}
-ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC)
+ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC)
{
zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
const char *fname = zf->common.function_name->val;
@@ -574,7 +553,7 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zen
}
}
-static void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
+static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zend_ulong fetch_type TSRMLS_DC)
{
zend_arg_info *cur_arg_info;
char *need_msg;
@@ -623,7 +602,7 @@ static void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg
}
}
-static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_num, ulong fetch_type TSRMLS_DC)
+static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num, zend_ulong fetch_type TSRMLS_DC)
{
zend_arg_info *cur_arg_info;
char *need_msg;
@@ -646,6 +625,7 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL TSRMLS_CC);
+ return 0;
} else if (cur_arg_info->type_hint) {
if (cur_arg_info->type_hint == IS_ARRAY) {
zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "", NULL TSRMLS_CC);
@@ -656,11 +636,12 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_
zend_error(E_ERROR, "Unknown typehint");
#endif
}
+ return 0;
}
- return 0;
+ return 1;
}
-static void zend_verify_missing_arg(zend_execute_data *execute_data, zend_uint arg_num TSRMLS_DC)
+static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num TSRMLS_DC)
{
if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
zend_verify_missing_arg_type(EX(func), arg_num, EX(opline)->extended_value TSRMLS_CC)) {
@@ -677,7 +658,7 @@ static void zend_verify_missing_arg(zend_execute_data *execute_data, zend_uint a
}
}
-static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *property_name, int value_type, znode_op *value_op, const zend_execute_data *execute_data, int opcode, void **cache_slot TSRMLS_DC)
+static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *property_name, int value_type, const znode_op *value_op, const zend_execute_data *execute_data, int opcode, void **cache_slot TSRMLS_DC)
{
zend_free_op free_value;
zval *value = get_zval_ptr(value_type, value_op, execute_data, &free_value, BP_VAR_R);
@@ -765,15 +746,13 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p
FREE_OP_IF_VAR(free_value);
}
-static void zend_assign_to_string_offset(zval *str_offset, zval *value, int value_type, zval *result TSRMLS_DC)
+static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, int value_type, zval *result TSRMLS_DC)
{
- zval *str = Z_STR_OFFSET_STR_P(str_offset);
- zend_uint offset = Z_STR_OFFSET_IDX_P(str_offset);
zend_string *old_str;
- if ((int)offset < 0) {
- zend_error(E_WARNING, "Illegal string offset: %d", offset);
- STR_RELEASE(Z_STR_P(str));
+ if (offset < 0) {
+ zend_error(E_WARNING, "Illegal string offset: " ZEND_LONG_FMT, offset);
+ zend_string_release(Z_STR_P(str));
if (result) {
ZVAL_NULL(result);
}
@@ -781,14 +760,14 @@ static void zend_assign_to_string_offset(zval *str_offset, zval *value, int valu
}
old_str = Z_STR_P(str);
- if (offset >= Z_STRLEN_P(str)) {
- int old_len = Z_STRLEN_P(str);
- Z_STR_P(str) = STR_REALLOC(Z_STR_P(str), offset + 1, 0);
+ if ((size_t)offset >= Z_STRLEN_P(str)) {
+ zend_long old_len = Z_STRLEN_P(str);
+ Z_STR_P(str) = zend_string_realloc(Z_STR_P(str), offset + 1, 0);
Z_TYPE_INFO_P(str) = IS_STRING_EX;
memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
Z_STRVAL_P(str)[offset+1] = 0;
} else if (IS_INTERNED(Z_STR_P(str))) {
- Z_STR_P(str) = STR_INIT(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
+ Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
Z_TYPE_INFO_P(str) = IS_STRING_EX;
}
@@ -796,7 +775,7 @@ static void zend_assign_to_string_offset(zval *str_offset, zval *value, int valu
zend_string *tmp = zval_get_string(value);
Z_STRVAL_P(str)[offset] = tmp->val[0];
- STR_RELEASE(tmp);
+ zend_string_release(tmp);
} else {
Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
if (value_type == IS_TMP_VAR) {
@@ -811,156 +790,73 @@ static void zend_assign_to_string_offset(zval *str_offset, zval *value, int valu
T(result->u.var).var = &T->str_offset.str;
*/
- STR_RELEASE(old_str);
+ zend_string_release(old_str);
if (result) {
zend_uchar c = (zend_uchar)Z_STRVAL_P(str)[offset];
if (CG(one_char_string)[c]) {
- ZVAL_INT_STR(result, CG(one_char_string)[c]);
+ ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
} else {
- ZVAL_NEW_STR(result, STR_INIT(Z_STRVAL_P(str) + offset, 1, 0));
+ ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(str) + offset, 1, 0));
}
}
}
-static inline zval* zend_assign_tmp_to_variable(zval *variable_ptr, zval *value TSRMLS_DC)
+static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type TSRMLS_DC)
{
- ZVAL_DEREF(variable_ptr);
-
- if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
- zend_refcounted *garbage;
-
- if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
- UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
- Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
- return variable_ptr;
- }
+ do {
+ if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
+ zend_refcounted *garbage;
- garbage = Z_COUNTED_P(variable_ptr);
- if (UNEXPECTED(GC_REFCOUNT(garbage) > 1)) {
- /* we need to split */
- GC_REFCOUNT(garbage)--;
- /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
- if ((Z_COLLECTABLE_P(variable_ptr)) &&
- UNEXPECTED(!GC_INFO(garbage))) {
- gc_possible_root(garbage TSRMLS_CC);
+ if (Z_ISREF_P(variable_ptr)) {
+ variable_ptr = Z_REFVAL_P(variable_ptr);
+ if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
+ break;
+ }
}
- } else {
- ZVAL_COPY_VALUE(variable_ptr, value);
- _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
- return variable_ptr;
- }
- }
-
- ZVAL_COPY_VALUE(variable_ptr, value);
-
- return variable_ptr;
-}
-
-static inline zval* zend_assign_const_to_variable(zval *variable_ptr, zval *value TSRMLS_DC)
-{
- ZVAL_DEREF(variable_ptr);
-
- if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
- zend_refcounted *garbage;
-
- if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
- UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
- Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
- return variable_ptr;
- }
-
- garbage = Z_COUNTED_P(variable_ptr);
- if (UNEXPECTED(GC_REFCOUNT(garbage) > 1)) {
- /* we need to split */
- GC_REFCOUNT(garbage)--;
- /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
- if (Z_COLLECTABLE_P(variable_ptr) &&
- UNEXPECTED(!GC_INFO(garbage))) {
- gc_possible_root(garbage TSRMLS_CC);
+ if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
+ UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
+ Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
+ return variable_ptr;
}
- } else {
- ZVAL_COPY_VALUE(variable_ptr, value);
- /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
- if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
- zval_copy_ctor_func(variable_ptr);
+ if ((value_type & (IS_VAR|IS_CV)) && variable_ptr == value) {
+ return variable_ptr;
}
- _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
- return variable_ptr;
- }
- }
-
- ZVAL_COPY_VALUE(variable_ptr, value);
- /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
- if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
- zval_copy_ctor_func(variable_ptr);
- }
-
- return variable_ptr;
-}
-
-static inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value TSRMLS_DC)
-{
- zend_refcounted *garbage;
-
- if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
- goto assign_simple;
- } else if (UNEXPECTED(variable_ptr == value)) {
- return variable_ptr;
- }
- if (Z_ISREF_P(variable_ptr)) {
- variable_ptr = Z_REFVAL_P(variable_ptr);
- if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
- goto assign_simple;
- } else if (UNEXPECTED(variable_ptr == value)) {
- return variable_ptr;
- }
- }
-
- if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
- UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
- Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
- } else {
- if (Z_REFCOUNT_P(variable_ptr)==1) {
garbage = Z_COUNTED_P(variable_ptr);
- if (UNEXPECTED(Z_REFCOUNTED_P(value))) {
- if (EXPECTED(!Z_ISREF_P(value))) {
- Z_ADDREF_P(value);
- } else {
- if (Z_REFCOUNT_P(value) == 1) {
- ZVAL_UNREF(value);
- } else {
- value = Z_REFVAL_P(value);
+ if (GC_REFCOUNT(garbage) == 1) {
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ if (value_type == IS_CONST) {
+ /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
+ zval_copy_ctor_func(variable_ptr);
}
- if (Z_REFCOUNTED_P(value)) {
- if (UNEXPECTED(variable_ptr == value)) {
- return variable_ptr;
- }
- Z_ADDREF_P(value);
+ } else if (value_type != IS_TMP_VAR) {
+ if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
+ Z_ADDREF_P(variable_ptr);
}
}
- }
- ZVAL_COPY_VALUE(variable_ptr, value);
- _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
- } else { /* we need to split */
- Z_DELREF_P(variable_ptr);
- GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
-assign_simple:
- if (UNEXPECTED(Z_REFCOUNTED_P(value))) {
- if (EXPECTED(!Z_ISREF_P(value))) {
- Z_ADDREF_P(value);
- } else {
- if (Z_REFCOUNT_P(value) == 1) {
- ZVAL_UNREF(value);
- } else {
- value = Z_REFVAL_P(value);
- }
- if (Z_REFCOUNTED_P(value)) {
- Z_ADDREF_P(value);
- }
+ _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
+ return variable_ptr;
+ } else { /* we need to split */
+ GC_REFCOUNT(garbage)--;
+ /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
+ if ((Z_COLLECTABLE_P(variable_ptr)) &&
+ UNEXPECTED(!GC_INFO(garbage))) {
+ gc_possible_root(garbage TSRMLS_CC);
}
}
- ZVAL_COPY_VALUE(variable_ptr, value);
+ }
+ } while (0);
+
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ if (value_type == IS_CONST) {
+ /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
+ zval_copy_ctor_func(variable_ptr);
+ }
+ } else if (value_type != IS_TMP_VAR) {
+ if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
+ Z_ADDREF_P(variable_ptr);
}
}
return variable_ptr;
@@ -1015,7 +911,7 @@ static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht
{
zval *retval;
zend_string *offset_key;
- ulong hval;
+ zend_ulong hval;
if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
hval = Z_LVAL_P(dim);
@@ -1024,14 +920,14 @@ num_index:
if (retval == NULL) {
switch (type) {
case BP_VAR_R:
- zend_error(E_NOTICE,"Undefined offset: %ld", hval);
+ zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, hval);
/* break missing intentionally */
case BP_VAR_UNSET:
case BP_VAR_IS:
retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined offset: %ld", hval);
+ zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, hval);
/* break missing intentionally */
case BP_VAR_W:
retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
@@ -1095,7 +991,7 @@ str_index:
hval = zend_dval_to_lval(Z_DVAL_P(dim));
goto num_index;
case IS_RESOURCE:
- zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
+ zend_error(E_STRICT, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
hval = Z_RES_HANDLE_P(dim);
goto num_index;
case IS_FALSE:
@@ -1113,7 +1009,7 @@ str_index:
return retval;
}
-static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container_ptr, zval *dim, int dim_type, int type, int is_ref TSRMLS_DC)
+static zend_always_inline zval *zend_fetch_dimension_address(zval *result, zval *container_ptr, zval *dim, int dim_type, int type, int is_ref, int allow_str_offset TSRMLS_DC)
{
zval *retval;
zval *container = container_ptr;
@@ -1139,7 +1035,7 @@ fetch_from_array:
ZVAL_INDIRECT(result, retval);
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- long offset;
+ zend_long offset;
if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
zval_dtor(container);
@@ -1148,14 +1044,11 @@ convert_to_array:
zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
goto fetch_from_array;
}
+
if (dim == NULL) {
zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
}
- if (type != BP_VAR_UNSET) {
- SEPARATE_STRING(container);
- }
-
if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
switch(Z_TYPE_P(dim)) {
case IS_STRING:
@@ -1182,8 +1075,14 @@ convert_to_array:
offset = Z_LVAL_P(dim);
}
- if (!IS_INTERNED(Z_STR_P(container))) STR_ADDREF(Z_STR_P(container));
- ZVAL_STR_OFFSET(result, container, offset);
+ if (allow_str_offset) {
+ SEPARATE_STRING(container);
+ if (!IS_INTERNED(Z_STR_P(container))) zend_string_addref(Z_STR_P(container));
+ ZVAL_LONG(result, offset);
+ return container; /* assignment to string offset */
+ } else {
+ ZVAL_INDIRECT(result, NULL); /* wrong string offset */
+ }
} else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (!Z_OBJ_HT_P(container)->read_dimension) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
@@ -1248,26 +1147,32 @@ convert_to_array:
ZVAL_INDIRECT(result, &EG(error_zval));
}
}
+ return NULL; /* not an assignment to string offset */
}
static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
{
- zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0 TSRMLS_CC);
+ zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 0 TSRMLS_CC);
+}
+
+static zend_never_inline zval *zend_fetch_dimension_address_W_str(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
+{
+ return zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 1 TSRMLS_CC);
}
static zend_never_inline void zend_fetch_dimension_address_W_ref(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
{
- zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1 TSRMLS_CC);
+ zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1, 0 TSRMLS_CC);
}
static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
{
- zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0 TSRMLS_CC);
+ zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0, 0 TSRMLS_CC);
}
static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
{
- zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0 TSRMLS_CC);
+ zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0, 0 TSRMLS_CC);
}
static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC)
@@ -1279,7 +1184,7 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
ZVAL_COPY(result, retval);
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- long offset;
+ zend_long offset;
if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
switch(Z_TYPE_P(dim)) {
@@ -1310,18 +1215,18 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
offset = Z_LVAL_P(dim);
}
- if (UNEXPECTED(offset < 0) || UNEXPECTED(Z_STRLEN_P(container) <= offset)) {
+ if (UNEXPECTED(offset < 0) || UNEXPECTED(Z_STRLEN_P(container) <= (size_t)offset)) {
if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Uninitialized string offset: %ld", offset);
+ zend_error(E_NOTICE, "Uninitialized string offset: %pd", offset);
}
ZVAL_EMPTY_STRING(result);
} else {
zend_uchar c = (zend_uchar)Z_STRVAL_P(container)[offset];
if (CG(one_char_string)[c]) {
- ZVAL_INT_STR(result, CG(one_char_string)[c]);
+ ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
} else {
- ZVAL_NEW_STR(result, STR_INIT(Z_STRVAL_P(container) + offset, 1, 0));
+ ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(container) + offset, 1, 0));
}
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
@@ -1552,7 +1457,7 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /*
static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
{
- zend_uint first_extra_arg;
+ uint32_t first_extra_arg;
ZEND_ASSERT(EX(func) == (zend_function*)op_array);
ZEND_ASSERT(EX(object) == Z_OBJ(EG(This)));
@@ -1625,7 +1530,7 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu
EX(delayed_exception) = NULL;
EX(call) = NULL;
- EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
+ EX(opline) = op_array->opcodes;
EX(scope) = EG(scope);
zend_attach_symbol_table(execute_data);
@@ -1654,13 +1559,13 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
EX(delayed_exception) = NULL;
EX(call) = NULL;
- EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
+ EX(opline) = op_array->opcodes;
EX(scope) = EG(scope);
if (UNEXPECTED(EX(symbol_table) != NULL)) {
zend_attach_symbol_table(execute_data);
} else {
- zend_uint first_extra_arg = op_array->num_args;
+ uint32_t first_extra_arg = op_array->num_args;
if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
first_extra_arg--;
@@ -1718,7 +1623,7 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data
* restore it simply by replacing a pointer.
*/
zend_execute_data *execute_data;
- zend_uint num_args = call->num_args;
+ uint32_t num_args = call->num_args;
EG(argument_stack) = zend_vm_stack_new_page(
MAX(ZEND_VM_STACK_PAGE_SIZE,
@@ -1738,7 +1643,7 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data
if (num_args > 0) {
zval *arg_src = ZEND_CALL_ARG(call, 1);
zval *arg_dst = ZEND_CALL_ARG(execute_data, 1);
- int i;
+ uint32_t i;
for (i = 0; i < num_args; i++) {
ZVAL_COPY_VALUE(arg_dst + i, arg_src + i);
@@ -1760,14 +1665,14 @@ ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_ar
}
/* }}} */
-static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(zend_op *opline, zend_execute_data *call TSRMLS_DC) /* {{{ */
+static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(const zend_op *opline, zend_execute_data *call TSRMLS_DC) /* {{{ */
{
- zend_uint arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
+ uint32_t arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
}
/* }}} */
-static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, zend_uint passed_args, zend_uint additional_args TSRMLS_DC) /* {{{ */
+static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
{
zend_execute_data *new_call;
int used_stack = (EG(argument_stack)->top - (zval*)call) + additional_args;
@@ -1803,7 +1708,7 @@ static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call,
}
/* }}} */
-static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, zend_uint passed_args, zend_uint additional_args TSRMLS_DC) /* {{{ */
+static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
{
if (EXPECTED(EG(argument_stack)->end - EG(argument_stack)->top > additional_args)) {
EG(argument_stack)->top += additional_args;
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index cb7ca70ef3..614cb07b4f 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -48,8 +48,8 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s
ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
-ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC);
-ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC);
+ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, zend_ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC);
+ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC);
static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC)
{
@@ -63,16 +63,6 @@ static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC
}
}
-static zend_always_inline void i_zval_ptr_dtor_nogc(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC)
-{
- if (Z_REFCOUNTED_P(zval_ptr)) {
- if (!Z_DELREF_P(zval_ptr)) {
- ZEND_ASSERT(zval_ptr != &EG(uninitialized_zval));
- _zval_dtor_func_for_ptr(Z_COUNTED_P(zval_ptr) ZEND_FILE_LINE_CC);
- }
- }
-}
-
static zend_always_inline int i_zend_is_true(zval *op TSRMLS_DC)
{
int result;
@@ -196,9 +186,9 @@ static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
}
}
-static zend_always_inline void zend_vm_stack_extend(int count TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_extend(uint32_t count TSRMLS_DC)
{
- int size = count * ZEND_MM_ALIGNED_SIZE(sizeof(zval));
+ uint32_t size = count * ZEND_MM_ALIGNED_SIZE(sizeof(zval));
zend_vm_stack p = zend_vm_stack_new_page(
(size >= (ZEND_VM_STACK_PAGE_SIZE - ZEND_VM_STACK_HEADER_SLOT) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) ?
(size + ((ZEND_VM_STACK_HEADER_SLOT + ZEND_VM_STACK_PAGE_SIZE) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) - 1) &
@@ -208,9 +198,9 @@ static zend_always_inline void zend_vm_stack_extend(int count TSRMLS_DC)
EG(argument_stack) = p;
}
-static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uchar flags, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
+static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_function *func, uint32_t num_args, zend_uchar flags, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
{
- int used_stack = ZEND_CALL_FRAME_SLOT + num_args;
+ uint32_t used_stack = ZEND_CALL_FRAME_SLOT + num_args;
zend_execute_data *call;
if (ZEND_USER_CODE(func->type)) {
@@ -230,21 +220,21 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_
static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call TSRMLS_DC)
{
- zend_uint first_extra_arg = call->func->op_array.num_args - ((call->func->common.fn_flags & ZEND_ACC_VARIADIC) != 0);
+ uint32_t first_extra_arg = call->func->op_array.num_args - ((call->func->common.fn_flags & ZEND_ACC_VARIADIC) != 0);
if (UNEXPECTED(call->num_args > first_extra_arg)) {
zval *end = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T);
zval *p = end + (call->num_args - first_extra_arg);
do {
p--;
- i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
+ zval_ptr_dtor_nogc(p);
} while (p != end);
}
}
static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call TSRMLS_DC)
{
- zend_uint num_args = call->num_args;
+ uint32_t num_args = call->num_args;
if (num_args > 0) {
zval *end = ZEND_CALL_ARG(call, 1);
@@ -252,7 +242,7 @@ static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call T
do {
p--;
- i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
+ zval_ptr_dtor_nogc(p);
} while (p != end);
}
}
@@ -269,9 +259,6 @@ static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *
}
}
-void execute_new_code(TSRMLS_D);
-
-
/* services */
ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC);
ZEND_API const char *get_active_function_name(TSRMLS_D);
@@ -279,7 +266,7 @@ ZEND_API const char *zend_get_executed_filename(TSRMLS_D);
ZEND_API uint zend_get_executed_lineno(TSRMLS_D);
ZEND_API zend_bool zend_is_executing(TSRMLS_D);
-ZEND_API void zend_set_timeout(long seconds, int reset_signals);
+ZEND_API void zend_set_timeout(zend_long seconds, int reset_signals);
ZEND_API void zend_unset_timeout(TSRMLS_D);
ZEND_API void zend_timeout(int dummy);
ZEND_API zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_type TSRMLS_DC);
@@ -300,7 +287,7 @@ void zend_shutdown_timeout_thread(void);
*/
#define Z_OBJ_CLASS_NAME_P(obj) (((obj) && (obj)->handlers->get_class_entry != NULL && (obj)->handlers->get_class_entry) ? (obj)->handlers->get_class_entry(obj TSRMLS_CC)->name->val : "")
-ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, zend_uint var);
+ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, uint32_t var);
#define ZEND_USER_OPCODE_CONTINUE 0 /* execute next opcode */
#define ZEND_USER_OPCODE_RETURN 1 /* exit from executor (return from function) */
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index b45a021650..85bd441efe 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -42,7 +42,7 @@ ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC);
ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value TSRMLS_DC);
/* true globals */
-ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, {{0}, {{0}}, {0}}, NULL, NULL, 0, NULL, NULL, 0 };
+ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, {{0}, {{0}}, {0}}, NULL, NULL, NULL, NULL, 0, 0 };
ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL, NULL };
#ifdef ZEND_WIN32
@@ -110,7 +110,7 @@ static int clean_non_persistent_function(zval *zv TSRMLS_DC) /* {{{ */
}
/* }}} */
-static int clean_non_persistent_function_full(zval *zv TSRMLS_DC) /* {{{ */
+ZEND_API int clean_non_persistent_function_full(zval *zv TSRMLS_DC) /* {{{ */
{
zend_function *function = Z_PTR_P(zv);
return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
@@ -124,7 +124,7 @@ static int clean_non_persistent_class(zval *zv TSRMLS_DC) /* {{{ */
}
/* }}} */
-static int clean_non_persistent_class_full(zval *zv TSRMLS_DC) /* {{{ */
+ZEND_API int clean_non_persistent_class_full(zval *zv TSRMLS_DC) /* {{{ */
{
zend_class_entry *ce = Z_PTR_P(zv);
return (ce->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
@@ -190,7 +190,6 @@ void init_executor(TSRMLS_D) /* {{{ */
ZVAL_OBJ(&EG(This), NULL);
EG(active) = 1;
- EG(start_op) = NULL;
}
/* }}} */
@@ -537,11 +536,11 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas
zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
len = Z_STRLEN_P(p) - ((colon - Z_STRVAL_P(p)) + 1);
if (inline_change) {
- zend_string *tmp = STR_INIT(colon + 1, len, 0);
- STR_RELEASE(Z_STR_P(p));
+ zend_string *tmp = zend_string_init(colon + 1, len, 0);
+ zend_string_release(Z_STR_P(p));
Z_STR_P(p) = tmp;
} else {
- Z_STR_P(p) = STR_INIT(colon + 1, len, 0);
+ Z_STR_P(p) = zend_string_init(colon + 1, len, 0);
}
Z_TYPE_FLAGS_P(p) = IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE;
} else {
@@ -552,7 +551,7 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas
actual = slash + 1;
actual_len -= (actual - Z_STRVAL_P(p));
if (inline_change) {
- zend_string *s = STR_INIT(actual, actual_len, 0);
+ zend_string *s = zend_string_init(actual, actual_len, 0);
Z_STR_P(p) = s;
Z_TYPE_FLAGS_P(p) = IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE;
}
@@ -573,7 +572,7 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas
zend_error(E_ERROR, "Undefined constant '%s'", save->val);
}
if (inline_change) {
- STR_RELEASE(save);
+ zend_string_release(save);
}
save = NULL;
}
@@ -584,13 +583,13 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas
Z_TYPE_INFO_P(p) = IS_INTERNED(Z_STR_P(p)) ?
IS_INTERNED_STRING_EX : IS_STRING_EX;
if (save && save->val != actual) {
- STR_RELEASE(save);
+ zend_string_release(save);
}
}
}
} else {
if (inline_change) {
- STR_RELEASE(Z_STR_P(p));
+ zend_string_release(Z_STR_P(p));
}
ZVAL_COPY_VALUE(p, const_value);
if (Z_OPT_CONSTANT_P(p)) {
@@ -606,8 +605,8 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas
zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope TSRMLS_CC);
if (inline_change) {
- zend_ast_destroy(Z_ASTVAL_P(p));
- efree(Z_AST_P(p));
+ zend_ast_destroy_and_free(Z_ASTVAL_P(p));
+ efree_size(Z_AST_P(p), sizeof(zend_ast_ref));
}
ZVAL_COPY_VALUE(p, &tmp);
}
@@ -633,13 +632,13 @@ ZEND_API int zval_update_constant(zval *pp, zend_bool inline_change TSRMLS_DC) /
}
/* }}} */
-int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, zend_uint param_count, zval params[] TSRMLS_DC) /* {{{ */
+int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[] TSRMLS_DC) /* {{{ */
{
return call_user_function_ex(function_table, object, function_name, retval_ptr, param_count, params, 1, NULL TSRMLS_CC);
}
/* }}} */
-int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, zend_uint param_count, zval params[], int no_separation, zend_array *symbol_table TSRMLS_DC) /* {{{ */
+int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation, zend_array *symbol_table TSRMLS_DC) /* {{{ */
{
zend_fcall_info fci;
@@ -659,7 +658,7 @@ int call_user_function_ex(HashTable *function_table, zval *object, zval *functio
int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC) /* {{{ */
{
- zend_uint i;
+ uint32_t i;
zend_class_entry *calling_scope = NULL;
zend_execute_data *call, dummy_execute_data;
zend_fcall_info_cache fci_cache_local;
@@ -724,7 +723,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
efree(error);
}
if (callable_name) {
- STR_RELEASE(callable_name);
+ zend_string_release(callable_name);
}
if (EG(current_execute_data) == &dummy_execute_data) {
EG(current_execute_data) = dummy_execute_data.prev_execute_data;
@@ -738,7 +737,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zend_error(E_STRICT, "%s", error);
efree(error);
}
- STR_RELEASE(callable_name);
+ zend_string_release(callable_name);
}
func = fci_cache->function_handler;
@@ -903,7 +902,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zend_vm_stack_free_call_frame(call TSRMLS_CC);
if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
- STR_RELEASE(func->common.function_name);
+ zend_string_release(func->common.function_name);
}
efree(func);
@@ -948,10 +947,10 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
}
if (name->val[0] == '\\') {
- lc_name = STR_ALLOC(name->len - 1, 0);
+ lc_name = zend_string_alloc(name->len - 1, 0);
zend_str_tolower_copy(lc_name->val, name->val + 1, name->len - 1);
} else {
- lc_name = STR_ALLOC(name->len, 0);
+ lc_name = zend_string_alloc(name->len, 0);
zend_str_tolower_copy(lc_name->val, name->val, name->len);
}
}
@@ -959,7 +958,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
ce = zend_hash_find_ptr(EG(class_table), lc_name);
if (ce) {
if (!key) {
- STR_FREE(lc_name);
+ zend_string_free(lc_name);
}
return ce;
}
@@ -969,7 +968,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
*/
if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
if (!key) {
- STR_FREE(lc_name);
+ zend_string_free(lc_name);
}
return NULL;
}
@@ -980,7 +979,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
EG(autoload_func) = func;
} else {
if (!key) {
- STR_FREE(lc_name);
+ zend_string_free(lc_name);
}
return NULL;
}
@@ -990,7 +989,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
/* Verify class name before passing it to __autoload() */
if (strspn(name->val, "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\") != name->len) {
if (!key) {
- STR_FREE(lc_name);
+ zend_string_free(lc_name);
}
return NULL;
}
@@ -1002,7 +1001,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
if (zend_hash_add_empty_element(EG(in_autoload), lc_name) == NULL) {
if (!key) {
- STR_FREE(lc_name);
+ zend_string_free(lc_name);
}
return NULL;
}
@@ -1012,12 +1011,12 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
if (name->val[0] == '\\') {
ZVAL_STRINGL(&args[0], name->val + 1, name->len - 1);
} else {
- ZVAL_STR(&args[0], STR_COPY(name));
+ ZVAL_STR(&args[0], zend_string_copy(name));
}
fcall_info.size = sizeof(fcall_info);
fcall_info.function_table = EG(function_table);
- ZVAL_STR(&fcall_info.function_name, STR_COPY(EG(autoload_func)->common.function_name));
+ ZVAL_STR(&fcall_info.function_name, zend_string_copy(EG(autoload_func)->common.function_name));
fcall_info.symbol_table = NULL;
fcall_info.retval = &local_retval;
fcall_info.param_count = 1;
@@ -1046,7 +1045,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k
ce = zend_hash_find_ptr(EG(class_table), lc_name);
}
if (!key) {
- STR_FREE(lc_name);
+ zend_string_free(lc_name);
}
return ce;
}
@@ -1062,11 +1061,11 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s
{
zval pv;
zend_op_array *new_op_array;
- zend_uint original_compiler_options;
+ uint32_t original_compiler_options;
int retval;
if (retval_ptr) {
- ZVAL_NEW_STR(&pv, STR_ALLOC(str_len + sizeof("return ;")-1, 1));
+ ZVAL_NEW_STR(&pv, zend_string_alloc(str_len + sizeof("return ;")-1, 1));
memcpy(Z_STRVAL(pv), "return ", sizeof("return ") - 1);
memcpy(Z_STRVAL(pv) + sizeof("return ") - 1, str, str_len);
Z_STRVAL(pv)[Z_STRLEN(pv) - 1] = ';';
@@ -1084,21 +1083,18 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s
if (new_op_array) {
zval local_retval;
- int orig_interactive = CG(interactive);
EG(no_extensions)=1;
- CG(interactive) = 0;
zend_try {
ZVAL_UNDEF(&local_retval);
zend_execute(new_op_array, &local_retval TSRMLS_CC);
} zend_catch {
destroy_op_array(new_op_array TSRMLS_CC);
- efree(new_op_array);
+ efree_size(new_op_array, sizeof(zend_op_array));
zend_bailout();
} zend_end_try();
- CG(interactive) = orig_interactive;
if (Z_TYPE(local_retval) != IS_UNDEF) {
if (retval_ptr) {
ZVAL_COPY_VALUE(retval_ptr, &local_retval);
@@ -1113,7 +1109,7 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s
EG(no_extensions)=0;
destroy_op_array(new_op_array TSRMLS_CC);
- efree(new_op_array);
+ efree_size(new_op_array, sizeof(zend_op_array));
retval = SUCCESS;
} else {
retval = FAILURE;
@@ -1148,84 +1144,6 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name,
}
/* }}} */
-void execute_new_code(TSRMLS_D) /* {{{ */
-{
- zend_op *opline, *end;
- zend_op *ret_opline;
- int orig_interactive;
-
- if (!(CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE)
- || CG(context).backpatch_count>0
- || CG(active_op_array)->function_name
- || CG(active_op_array)->type!=ZEND_USER_FUNCTION) {
- return;
- }
-
- ret_opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- ret_opline->opcode = ZEND_RETURN;
- ret_opline->op1_type = IS_CONST;
- ret_opline->op1.constant = zend_add_literal(CG(active_op_array), &EG(uninitialized_zval) TSRMLS_CC);
- SET_UNUSED(ret_opline->op2);
-
- if (!EG(start_op)) {
- EG(start_op) = CG(active_op_array)->opcodes;
- }
-
- opline=EG(start_op);
- end=CG(active_op_array)->opcodes+CG(active_op_array)->last;
-
- while (opline<end) {
- if (opline->op1_type == IS_CONST) {
- opline->op1.zv = &CG(active_op_array)->literals[opline->op1.constant];
- }
- if (opline->op2_type == IS_CONST) {
- opline->op2.zv = &CG(active_op_array)->literals[opline->op2.constant];
- }
- switch (opline->opcode) {
- case ZEND_GOTO:
- if (Z_TYPE_P(opline->op2.zv) != IS_LONG) {
- zend_resolve_goto_label(CG(active_op_array), opline, 1 TSRMLS_CC);
- }
- /* break omitted intentionally */
- case ZEND_JMP:
- opline->op1.jmp_addr = &CG(active_op_array)->opcodes[opline->op1.opline_num];
- break;
- case ZEND_JMPZNZ:
- /* absolute index to relative offset */
- opline->extended_value = (char*)(CG(active_op_array)->opcodes + opline->extended_value) - (char*)opline;
- /* break omitted intentionally */
- case ZEND_JMPZ:
- case ZEND_JMPNZ:
- case ZEND_JMPZ_EX:
- case ZEND_JMPNZ_EX:
- case ZEND_JMP_SET:
- case ZEND_JMP_SET_VAR:
- case ZEND_NEW:
- case ZEND_FE_RESET:
- case ZEND_FE_FETCH:
- opline->op2.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.opline_num];
- break;
- }
- ZEND_VM_SET_OPCODE_HANDLER(opline);
- opline++;
- }
-
- zend_release_labels(1 TSRMLS_CC);
-
- orig_interactive = CG(interactive);
- CG(interactive) = 0;
- zend_execute(CG(active_op_array), NULL TSRMLS_CC);
- CG(interactive) = orig_interactive;
-
- if (EG(exception)) {
- zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
- }
-
- CG(active_op_array)->last -= 1; /* get rid of that ZEND_RETURN */
- EG(start_op) = CG(active_op_array)->opcodes+CG(active_op_array)->last;
-}
-/* }}} */
-
ZEND_API void zend_timeout(int dummy) /* {{{ */
{
TSRMLS_FETCH();
@@ -1243,7 +1161,7 @@ ZEND_API void zend_timeout(int dummy) /* {{{ */
zend_on_timeout(EG(timeout_seconds) TSRMLS_CC);
}
- zend_error(E_ERROR, "Maximum execution time of %d second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
+ zend_error(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
}
/* }}} */
@@ -1360,7 +1278,7 @@ void zend_shutdown_timeout_thread(void) /* {{{ */
#define SIGPROF 27
#endif
-void zend_set_timeout(long seconds, int reset_signals) /* {{{ */
+void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */
{
TSRMLS_FETCH();
@@ -1468,7 +1386,7 @@ check_fetch_type:
}
return EG(current_execute_data)->called_scope;
case ZEND_FETCH_CLASS_AUTO: {
- fetch_type = zend_get_class_fetch_type(class_name->val, class_name->len);
+ fetch_type = zend_get_class_fetch_type(class_name);
if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) {
goto check_fetch_type;
}
@@ -1584,7 +1502,7 @@ ZEND_API int zend_delete_global_variable(zend_string *name TSRMLS_DC) /* {{{ */
ZEND_API zend_array *zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
{
- zend_uint i;
+ int i;
zend_execute_data *ex;
zend_array *symbol_table;
@@ -1680,7 +1598,7 @@ ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force TSRMLS
if (execute_data) {
if (!execute_data->symbol_table) {
- zend_ulong h = STR_HASH_VAL(name);
+ zend_ulong h = zend_string_hash_val(name);
zend_op_array *op_array = &execute_data->func->op_array;
int i;
diff --git a/Zend/zend_extensions.c b/Zend/zend_extensions.c
index 47284342fa..04150920af 100644
--- a/Zend/zend_extensions.c
+++ b/Zend/zend_extensions.c
@@ -105,6 +105,14 @@ int zend_load_extension(const char *path TSRMLS_DC)
#endif
DL_UNLOAD(handle);
return FAILURE;
+ } else if (zend_get_extension(new_extension->name)) {
+ fprintf(stderr, "Cannot load %s - it was already loaded\n", new_extension->name);
+/* See http://support.microsoft.com/kb/190351 */
+#ifdef PHP_WIN32
+ fflush(stderr);
+#endif
+ DL_UNLOAD(handle);
+ return FAILURE;
}
return zend_register_extension(new_extension, handle TSRMLS_CC);
@@ -187,7 +195,7 @@ void zend_shutdown_extensions(TSRMLS_D)
void zend_extension_dtor(zend_extension *extension)
{
#if ZEND_EXTENSIONS_SUPPORT && !ZEND_DEBUG
- if (extension->handle) {
+ if (extension->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) {
DL_UNLOAD(extension->handle);
}
#endif
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index adc02a3eb0..b331f979fd 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -99,6 +99,7 @@ ZEND_API void gc_reset(TSRMLS_D)
{
GC_G(gc_runs) = 0;
GC_G(collected) = 0;
+ GC_G(gc_full) = 0;
#if GC_BENCH
GC_G(root_buf_length) = 0;
@@ -185,14 +186,6 @@ ZEND_API void gc_remove_from_buffer(zend_refcounted *ref TSRMLS_DC)
{
gc_root_buffer *root;
- if (UNEXPECTED(/*GC_ADDRESS(GC_INFO(ref)) &&*/
- GC_GET_COLOR(GC_INFO(ref)) == GC_BLACK &&
- GC_ADDRESS(GC_INFO(ref)) >= GC_G(last_unused) - GC_G(buf))) {
- /* The given zval is a garbage that is going to be deleted by
- * currently running GC */
- return;
- }
-
root = GC_G(buf) + GC_ADDRESS(GC_INFO(ref));
GC_BENCH_INC(zval_remove_from_buffer);
GC_REMOVE_FROM_ROOTS(root);
@@ -492,8 +485,11 @@ tail_call:
} else if (GC_G(first_unused) != GC_G(last_unused)) {
buf = GC_G(first_unused);
GC_G(first_unused)++;
+ } else {
+ /* TODO: find a perfect way to handle such case */
+ GC_G(gc_full) = 1;
}
- /* TODO: what should we do if we don't have room ??? */
+
if (buf) {
buf->ref = ref;
buf->next = GC_G(roots).next;
@@ -609,6 +605,18 @@ static int gc_collect_roots(TSRMLS_D)
}
current = current->next;
}
+
+ if (GC_G(gc_full) == 1) {
+ current = GC_G(roots).next;
+ while (current != &GC_G(roots)) {
+ GC_SET_ADDRESS(GC_INFO(current->ref), 0);
+ GC_SET_BLACK(GC_INFO(current->ref));
+ current = current->next;
+ }
+ gc_reset(TSRMLS_C);
+ return 0;
+ }
+
/* relink remaining roots into list to free */
if (GC_G(roots).next != &GC_G(roots)) {
if (GC_G(to_free).next == &GC_G(to_free)) {
diff --git a/Zend/zend_gc.h b/Zend/zend_gc.h
index 8d619f2e5e..2eb8ea6ea3 100644
--- a/Zend/zend_gc.h
+++ b/Zend/zend_gc.h
@@ -77,12 +77,13 @@ typedef struct _gc_root_buffer {
zend_refcounted *ref;
struct _gc_root_buffer *next; /* double-linked list */
struct _gc_root_buffer *prev;
- zend_uint refcount;
+ uint32_t refcount;
} gc_root_buffer;
typedef struct _zend_gc_globals {
zend_bool gc_enabled;
zend_bool gc_active;
+ zend_bool gc_full;
gc_root_buffer *buf; /* preallocated arrays of buffers */
gc_root_buffer roots; /* list of possible roots of cycles */
@@ -93,16 +94,16 @@ typedef struct _zend_gc_globals {
gc_root_buffer to_free; /* list to free */
gc_root_buffer *next_to_free;
- zend_uint gc_runs;
- zend_uint collected;
+ uint32_t gc_runs;
+ uint32_t collected;
#if GC_BENCH
- zend_uint root_buf_length;
- zend_uint root_buf_peak;
- zend_uint zval_possible_root;
- zend_uint zval_buffered;
- zend_uint zval_remove_from_buffer;
- zend_uint zval_marked_grey;
+ uint32_t root_buf_length;
+ uint32_t root_buf_peak;
+ uint32_t zval_possible_root;
+ uint32_t zval_buffered;
+ uint32_t zval_remove_from_buffer;
+ uint32_t zval_marked_grey;
#endif
} zend_gc_globals;
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index 922c6a3f2b..449a374683 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -44,7 +44,7 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
{
/* -1 required because we want the last run opcode, not the
* next to-be-run one. */
- zend_uint op_num = execute_data->opline - op_array->opcodes - 1;
+ uint32_t op_num = execute_data->opline - op_array->opcodes - 1;
int i;
for (i = 0; i < op_array->last_brk_cont; ++i) {
@@ -130,7 +130,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
/* Free a clone of closure */
if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
destroy_op_array(op_array TSRMLS_CC);
- efree(op_array);
+ efree_size(op_array, sizeof(zend_op_array));
}
efree(generator->stack);
@@ -143,10 +143,10 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
{
zend_generator *generator = (zend_generator*) object;
zend_execute_data *ex = generator->execute_data;
- zend_uint op_num, finally_op_num;
+ uint32_t op_num, finally_op_num;
int i;
- if (!ex || !ex->func->op_array.has_finally_block) {
+ if (!ex || !(ex->func->op_array.fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
return;
}
diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h
index 5d1264cc4f..a85b8dd976 100644
--- a/Zend/zend_generators.h
+++ b/Zend/zend_generators.h
@@ -43,7 +43,7 @@ typedef struct _zend_generator {
/* Variable to put sent value into */
zval *send_target;
/* Largest used integer key for auto-incrementing keys */
- long largest_used_integer_key;
+ zend_long largest_used_integer_key;
/* ZEND_GENERATOR_* flags */
zend_uchar flags;
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index 082e733844..69e1cf9e68 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -71,21 +71,10 @@ typedef struct _zend_ini_entry zend_ini_entry;
struct _zend_compiler_globals {
- zend_stack bp_stack;
- zend_stack switch_cond_stack;
- zend_stack foreach_copy_stack;
- zend_stack object_stack;
- zend_stack declare_stack;
+ zend_stack loop_var_stack;
zend_class_entry *active_class_entry;
- /* variables for list() compilation */
- zend_llist list_llist;
- zend_llist dimension_llist;
- zend_stack list_stack;
-
- zend_stack function_call_stack;
-
zend_string *compiled_filename;
int zend_lineno;
@@ -112,24 +101,18 @@ struct _zend_compiler_globals {
zend_llist open_files;
- long catch_begin;
-
struct _zend_ini_parser_param *ini_parser_param;
- int interactive;
-
- zend_uint start_lineno;
+ uint32_t start_lineno;
zend_bool increment_lineno;
znode implementing_class;
- zend_uint access_type;
-
zend_string *doc_comment;
- zend_uint compiler_options; /* set of ZEND_COMPILE_* constants */
+ uint32_t compiler_options; /* set of ZEND_COMPILE_* constants */
- zval current_namespace;
+ zend_string *current_namespace;
HashTable *current_import;
HashTable *current_import_function;
HashTable *current_import_const;
@@ -154,6 +137,11 @@ struct _zend_compiler_globals {
zend_bool detect_unicode;
zend_bool encoding_declared;
+ zend_ast *ast;
+ zend_arena *ast_arena;
+
+ zend_stack delayed_oplines_stack;
+
#ifdef ZTS
zval **static_members_table;
int last_static_member;
@@ -188,7 +176,7 @@ struct _zend_executor_globals {
zval This;
- long precision;
+ zend_long precision;
int ticks_count;
@@ -220,7 +208,7 @@ struct _zend_executor_globals {
zend_class_entry *exception_class;
/* timeout support */
- int timeout_seconds;
+ zend_long timeout_seconds;
int lambda_count;
@@ -230,7 +218,7 @@ struct _zend_executor_globals {
zend_objects_store objects_store;
zend_object *exception, *prev_exception;
- zend_op *opline_before_exception;
+ const zend_op *opline_before_exception;
zend_op exception_op[3];
struct _zend_execute_data *current_execute_data;
@@ -242,8 +230,6 @@ struct _zend_executor_globals {
zend_bool active;
zend_bool valid_symbol_table;
- zend_op *start_op;
-
void *saved_fpu_cw_ptr;
#if XPFPA_HAVE_CW
XPFPA_CW_DATATYPE saved_fpu_cw;
@@ -268,7 +254,7 @@ struct _zend_ini_scanner_globals {
char *filename;
int lineno;
- /* Modes are: ZEND_INI_SCANNER_NORMAL, ZEND_INI_SCANNER_RAW */
+ /* Modes are: ZEND_INI_SCANNER_NORMAL, ZEND_INI_SCANNER_RAW, ZEND_INI_SCANNER_TYPED */
int scanner_mode;
};
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 78b38f7ea2..e651cd85e5 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -87,19 +87,19 @@ static void zend_hash_do_resize(HashTable *ht);
(ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT); \
(ht)->u.flags |= HASH_FLAG_PACKED; \
} else { \
- (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket) + sizeof(zend_uint), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT); \
- (ht)->arHash = (zend_uint*)((ht)->arData + (ht)->nTableSize); \
- memset((ht)->arHash, INVALID_IDX, (ht)->nTableSize * sizeof(zend_uint)); \
+ (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT); \
+ (ht)->arHash = (uint32_t*)((ht)->arData + (ht)->nTableSize); \
+ memset((ht)->arHash, INVALID_IDX, (ht)->nTableSize * sizeof(uint32_t)); \
} \
(ht)->nTableMask = (ht)->nTableSize - 1; \
} \
} while (0)
-static const zend_uint uninitialized_bucket = {INVALID_IDX};
+static const uint32_t uninitialized_bucket = {INVALID_IDX};
-ZEND_API void _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
+ZEND_API void _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
{
- uint i = 3;
+ uint32_t i = 3;
SET_INCONSISTENT(HT_OK);
@@ -118,7 +118,7 @@ ZEND_API void _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor
ht->nNumOfElements = 0;
ht->nNextFreeElement = 0;
ht->arData = NULL;
- ht->arHash = (zend_uint*)&uninitialized_bucket;
+ ht->arHash = (uint32_t*)&uninitialized_bucket;
ht->pDestructor = pDestructor;
ht->nInternalPointer = INVALID_IDX;
if (persistent) {
@@ -137,7 +137,7 @@ static void zend_hash_packed_grow(HashTable *ht)
HANDLE_UNBLOCK_INTERRUPTIONS();
}
-ZEND_API void zend_hash_real_init(HashTable *ht, int packed)
+ZEND_API void zend_hash_real_init(HashTable *ht, zend_bool packed)
{
IS_CONSISTENT(ht);
@@ -148,8 +148,8 @@ ZEND_API void zend_hash_packed_to_hash(HashTable *ht)
{
HANDLE_BLOCK_INTERRUPTIONS();
ht->u.flags &= ~HASH_FLAG_PACKED;
- ht->arData = (Bucket *) safe_perealloc(ht->arData, ht->nTableSize, sizeof(Bucket) + sizeof(zend_uint), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
- ht->arHash = (zend_uint*)(ht->arData + ht->nTableSize);
+ ht->arData = (Bucket *) safe_perealloc(ht->arData, ht->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
+ ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize);
zend_hash_rehash(ht);
HANDLE_UNBLOCK_INTERRUPTIONS();
}
@@ -159,11 +159,11 @@ ZEND_API void zend_hash_to_packed(HashTable *ht)
HANDLE_BLOCK_INTERRUPTIONS();
ht->u.flags |= HASH_FLAG_PACKED;
ht->arData = erealloc(ht->arData, ht->nTableSize * sizeof(Bucket));
- ht->arHash = (zend_uint*)&uninitialized_bucket;
+ ht->arHash = (uint32_t*)&uninitialized_bucket;
HANDLE_UNBLOCK_INTERRUPTIONS();
}
-ZEND_API void _zend_hash_init_ex(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
+ZEND_API void _zend_hash_init_ex(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
{
_zend_hash_init(ht, nSize, pDestructor, persistent ZEND_FILE_LINE_CC);
if (!bApplyProtection) {
@@ -183,12 +183,12 @@ ZEND_API void zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProt
static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zend_string *key)
{
- ulong h;
- uint nIndex;
- uint idx;
+ zend_ulong h;
+ uint32_t nIndex;
+ uint32_t idx;
Bucket *p;
- h = STR_HASH_VAL(key);
+ h = zend_string_hash_val(key);
nIndex = h & ht->nTableMask;
idx = ht->arHash[nIndex];
while (idx != INVALID_IDX) {
@@ -205,10 +205,10 @@ static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zen
return NULL;
}
-static zend_always_inline Bucket *zend_hash_str_find_bucket(const HashTable *ht, const char *str, int len, ulong h)
+static zend_always_inline Bucket *zend_hash_str_find_bucket(const HashTable *ht, const char *str, size_t len, zend_ulong h)
{
- uint nIndex;
- uint idx;
+ uint32_t nIndex;
+ uint32_t idx;
Bucket *p;
nIndex = h & ht->nTableMask;
@@ -227,10 +227,10 @@ static zend_always_inline Bucket *zend_hash_str_find_bucket(const HashTable *ht,
return NULL;
}
-static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *ht, ulong h)
+static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *ht, zend_ulong h)
{
- uint nIndex;
- uint idx;
+ uint32_t nIndex;
+ uint32_t idx;
Bucket *p;
nIndex = h & ht->nTableMask;
@@ -246,11 +246,11 @@ static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *h
return NULL;
}
-static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_string *key, zval *pData, int flag ZEND_FILE_LINE_DC)
+static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
{
- ulong h;
- uint nIndex;
- uint idx;
+ zend_ulong h;
+ uint32_t nIndex;
+ uint32_t idx;
Bucket *p;
#ifdef ZEND_SIGNALS
TSRMLS_FETCH();
@@ -263,7 +263,7 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s
zend_hash_packed_to_hash(ht);
}
- h = STR_HASH_VAL(key);
+ h = zend_string_hash_val(key);
if ((flag & HASH_ADD_NEW) == 0) {
p = zend_hash_find_bucket(ht, key);
@@ -300,7 +300,7 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s
p = ht->arData + idx;
p->h = h;
p->key = key;
- STR_ADDREF(key);
+ zend_string_addref(key);
ZVAL_COPY_VALUE(&p->val, pData);
nIndex = h & ht->nTableMask;
Z_NEXT(p->val) = ht->arHash[nIndex];
@@ -310,7 +310,7 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s
return &p->val;
}
-ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, int flag ZEND_FILE_LINE_DC)
+ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
{
return _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
}
@@ -335,47 +335,47 @@ ZEND_API zval *_zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData Z
return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
}
-ZEND_API zval *_zend_hash_str_add_or_update(HashTable *ht, const char *str, int len, zval *pData, int flag ZEND_FILE_LINE_DC)
+ZEND_API zval *_zend_hash_str_add_or_update(HashTable *ht, const char *str, size_t len, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
{
- zend_string *key = STR_INIT(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
+ zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
zval *ret = _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_CC);
- STR_RELEASE(key);
+ zend_string_release(key);
return ret;
}
-ZEND_API zval *_zend_hash_str_update(HashTable *ht, const char *str, int len, zval *pData ZEND_FILE_LINE_DC)
+ZEND_API zval *_zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
{
- zend_string *key = STR_INIT(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
+ zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_CC);
- STR_RELEASE(key);
+ zend_string_release(key);
return ret;
}
-ZEND_API zval *_zend_hash_str_update_ind(HashTable *ht, const char *str, int len, zval *pData ZEND_FILE_LINE_DC)
+ZEND_API zval *_zend_hash_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
{
- zend_string *key = STR_INIT(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
+ zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_CC);
- STR_RELEASE(key);
+ zend_string_release(key);
return ret;
}
-ZEND_API zval *_zend_hash_str_add(HashTable *ht, const char *str, int len, zval *pData ZEND_FILE_LINE_DC)
+ZEND_API zval *_zend_hash_str_add(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
{
- zend_string *key = STR_INIT(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
+ zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_CC);
- STR_RELEASE(key);
+ zend_string_release(key);
return ret;
}
-ZEND_API zval *_zend_hash_str_add_new(HashTable *ht, const char *str, int len, zval *pData ZEND_FILE_LINE_DC)
+ZEND_API zval *_zend_hash_str_add_new(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
{
- zend_string *key = STR_INIT(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
+ zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_CC);
- STR_RELEASE(key);
+ zend_string_release(key);
return ret;
}
-ZEND_API zval *zend_hash_index_add_empty_element(HashTable *ht, ulong h)
+ZEND_API zval *zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h)
{
zval dummy;
@@ -393,7 +393,7 @@ ZEND_API zval *zend_hash_add_empty_element(HashTable *ht, zend_string *key)
return zend_hash_add(ht, key, &dummy);
}
-ZEND_API zval *zend_hash_str_add_empty_element(HashTable *ht, const char *str, int len)
+ZEND_API zval *zend_hash_str_add_empty_element(HashTable *ht, const char *str, size_t len)
{
zval dummy;
@@ -402,10 +402,10 @@ ZEND_API zval *zend_hash_str_add_empty_element(HashTable *ht, const char *str, i
return zend_hash_str_add(ht, str, len, &dummy);
}
-static zend_always_inline zval *_zend_hash_index_update_or_next_insert_i(HashTable *ht, ulong h, zval *pData, int flag ZEND_FILE_LINE_DC)
+static zend_always_inline zval *_zend_hash_index_update_or_next_insert_i(HashTable *ht, zend_ulong h, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
{
- uint nIndex;
- uint idx;
+ uint32_t nIndex;
+ uint32_t idx;
Bucket *p;
#ifdef ZEND_SIGNALS
TSRMLS_FETCH();
@@ -430,8 +430,8 @@ static zend_always_inline zval *_zend_hash_index_update_or_next_insert_i(HashTab
ht->pDestructor(&p->val);
}
ZVAL_COPY_VALUE(&p->val, pData);
- if ((long)h >= (long)ht->nNextFreeElement) {
- ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
+ if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
+ ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
}
return &p->val;
} else { /* we have to keep the order :( */
@@ -460,8 +460,8 @@ static zend_always_inline zval *_zend_hash_index_update_or_next_insert_i(HashTab
if (ht->nInternalPointer == INVALID_IDX) {
ht->nInternalPointer = h;
}
- if ((long)h >= (long)ht->nNextFreeElement) {
- ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
+ if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
+ ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
}
p->h = h;
p->key = NULL;
@@ -490,8 +490,8 @@ convert_to_hash:
}
ZVAL_COPY_VALUE(&p->val, pData);
HANDLE_UNBLOCK_INTERRUPTIONS();
- if ((long)h >= (long)ht->nNextFreeElement) {
- ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
+ if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
+ ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
}
return &p->val;
}
@@ -505,8 +505,8 @@ convert_to_hash:
if (ht->nInternalPointer == INVALID_IDX) {
ht->nInternalPointer = idx;
}
- if ((long)h >= (long)ht->nNextFreeElement) {
- ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
+ if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
+ ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
}
p = ht->arData + idx;
p->h = h;
@@ -520,22 +520,22 @@ convert_to_hash:
return &p->val;
}
-ZEND_API zval *_zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, zval *pData, int flag ZEND_FILE_LINE_DC)
+ZEND_API zval *_zend_hash_index_update_or_next_insert(HashTable *ht, zend_ulong h, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
{
return _zend_hash_index_update_or_next_insert_i(ht, h, pData, flag ZEND_FILE_LINE_RELAY_CC);
}
-ZEND_API zval *_zend_hash_index_add(HashTable *ht, ulong h, zval *pData ZEND_FILE_LINE_DC)
+ZEND_API zval *_zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
{
return _zend_hash_index_update_or_next_insert_i(ht, h, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
}
-ZEND_API zval *_zend_hash_index_add_new(HashTable *ht, ulong h, zval *pData ZEND_FILE_LINE_DC)
+ZEND_API zval *_zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
{
return _zend_hash_index_update_or_next_insert_i(ht, h, pData, HASH_ADD | HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
}
-ZEND_API zval *_zend_hash_index_update(HashTable *ht, ulong h, zval *pData ZEND_FILE_LINE_DC)
+ZEND_API zval *_zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
{
return _zend_hash_index_update_or_next_insert_i(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
}
@@ -564,8 +564,8 @@ static void zend_hash_do_resize(HashTable *ht)
HANDLE_UNBLOCK_INTERRUPTIONS();
} else if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */
HANDLE_BLOCK_INTERRUPTIONS();
- ht->arData = (Bucket *) safe_perealloc(ht->arData, (ht->nTableSize << 1), sizeof(Bucket) + sizeof(zend_uint), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
- ht->arHash = (zend_uint*)(ht->arData + (ht->nTableSize << 1));
+ ht->arData = (Bucket *) safe_perealloc(ht->arData, (ht->nTableSize << 1), sizeof(Bucket) + sizeof(uint32_t), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
+ ht->arHash = (uint32_t*)(ht->arData + (ht->nTableSize << 1));
ht->nTableSize = (ht->nTableSize << 1);
ht->nTableMask = ht->nTableSize - 1;
zend_hash_rehash(ht);
@@ -576,18 +576,18 @@ static void zend_hash_do_resize(HashTable *ht)
ZEND_API int zend_hash_rehash(HashTable *ht)
{
Bucket *p;
- uint nIndex, i, j;
+ uint32_t nIndex, i, j;
IS_CONSISTENT(ht);
if (UNEXPECTED(ht->nNumOfElements == 0)) {
if (ht->nTableMask) {
- memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(zend_uint));
+ memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));
}
return SUCCESS;
}
- memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(zend_uint));
+ memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));
for (i = 0, j = 0; i < ht->nNumUsed; i++) {
p = ht->arData + i;
if (Z_TYPE(p->val) == IS_UNDEF) continue;
@@ -606,7 +606,7 @@ ZEND_API int zend_hash_rehash(HashTable *ht)
return SUCCESS;
}
-static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint idx, Bucket *p, Bucket *prev)
+static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev)
{
if (!(ht->u.flags & HASH_FLAG_PACKED)) {
if (prev) {
@@ -634,7 +634,7 @@ static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint idx, Buc
}
}
if (p->key) {
- STR_RELEASE(p->key);
+ zend_string_release(p->key);
}
if (ht->pDestructor) {
zval tmp;
@@ -646,9 +646,9 @@ static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint idx, Buc
}
}
-static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint idx, Bucket *p)
+static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint32_t idx, Bucket *p)
{
- uint nIndex;
+ uint32_t nIndex;
Bucket *prev = NULL;
if (!(ht->u.flags & HASH_FLAG_PACKED)) {
@@ -669,9 +669,9 @@ static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint idx, Bucket
ZEND_API int zend_hash_del(HashTable *ht, zend_string *key)
{
- ulong h;
- uint nIndex;
- uint idx;
+ zend_ulong h;
+ uint32_t nIndex;
+ uint32_t idx;
Bucket *p;
Bucket *prev = NULL;
#ifdef ZEND_SIGNALS
@@ -684,7 +684,7 @@ ZEND_API int zend_hash_del(HashTable *ht, zend_string *key)
return FAILURE;
}
- h = STR_HASH_VAL(key);
+ h = zend_string_hash_val(key);
nIndex = h & ht->nTableMask;
idx = ht->arHash[nIndex];
@@ -708,9 +708,9 @@ ZEND_API int zend_hash_del(HashTable *ht, zend_string *key)
ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key)
{
- ulong h;
- uint nIndex;
- uint idx;
+ zend_ulong h;
+ uint32_t nIndex;
+ uint32_t idx;
Bucket *p;
Bucket *prev = NULL;
#ifdef ZEND_SIGNALS
@@ -723,7 +723,7 @@ ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key)
return FAILURE;
}
- h = STR_HASH_VAL(key);
+ h = zend_string_hash_val(key);
nIndex = h & ht->nTableMask;
idx = ht->arHash[nIndex];
@@ -758,11 +758,11 @@ ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key)
return FAILURE;
}
-ZEND_API int zend_hash_str_del(HashTable *ht, const char *str, int len)
+ZEND_API int zend_hash_str_del(HashTable *ht, const char *str, size_t len)
{
- ulong h;
- uint nIndex;
- uint idx;
+ zend_ulong h;
+ uint32_t nIndex;
+ uint32_t idx;
Bucket *p;
Bucket *prev = NULL;
#ifdef ZEND_SIGNALS
@@ -809,11 +809,11 @@ ZEND_API int zend_hash_str_del(HashTable *ht, const char *str, int len)
return FAILURE;
}
-ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *str, int len)
+ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *str, size_t len)
{
- ulong h;
- uint nIndex;
- uint idx;
+ zend_ulong h;
+ uint32_t nIndex;
+ uint32_t idx;
Bucket *p;
Bucket *prev = NULL;
#ifdef ZEND_SIGNALS
@@ -843,10 +843,10 @@ ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *str, int len)
return FAILURE;
}
-ZEND_API int zend_hash_index_del(HashTable *ht, ulong h)
+ZEND_API int zend_hash_index_del(HashTable *ht, zend_ulong h)
{
- uint nIndex;
- uint idx;
+ uint32_t nIndex;
+ uint32_t idx;
Bucket *p;
Bucket *prev = NULL;
#ifdef ZEND_SIGNALS
@@ -856,7 +856,7 @@ ZEND_API int zend_hash_index_del(HashTable *ht, ulong h)
IS_CONSISTENT(ht);
if (ht->u.flags & HASH_FLAG_PACKED) {
- if (h >=0 && h < ht->nNumUsed) {
+ if (h < ht->nNumUsed) {
p = ht->arData + h;
if (Z_TYPE(p->val) != IS_UNDEF) {
HANDLE_BLOCK_INTERRUPTIONS();
@@ -886,34 +886,55 @@ ZEND_API int zend_hash_index_del(HashTable *ht, ulong h)
ZEND_API void zend_hash_destroy(HashTable *ht)
{
- uint idx;
- Bucket *p;
+ Bucket *p, *end;
IS_CONSISTENT(ht);
- SET_INCONSISTENT(HT_IS_DESTROYING);
-
- for (idx = 0 ; idx < ht->nNumUsed; idx++) {
- p = ht->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (ht->nNumUsed) {
+ p = ht->arData;
+ end = p + ht->nNumUsed;
if (ht->pDestructor) {
- ht->pDestructor(&p->val);
- }
- if (p->key) {
- STR_RELEASE(p->key);
+ SET_INCONSISTENT(HT_IS_DESTROYING);
+
+ if (ht->u.flags & HASH_FLAG_PACKED) {
+ do {
+ if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
+ ht->pDestructor(&p->val);
+ }
+ } while (++p != end);
+ } else {
+ do {
+ if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
+ ht->pDestructor(&p->val);
+ if (EXPECTED(p->key)) {
+ zend_string_release(p->key);
+ }
+ }
+ } while (++p != end);
+ }
+
+ SET_INCONSISTENT(HT_DESTROYED);
+ } else {
+ if (!(ht->u.flags & HASH_FLAG_PACKED)) {
+ do {
+ if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
+ if (EXPECTED(p->key)) {
+ zend_string_release(p->key);
+ }
+ }
+ } while (++p != end);
+ }
}
+ } else if (EXPECTED(!ht->nTableMask)) {
+ return;
}
- if (ht->nTableMask) {
- pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
- }
-
- SET_INCONSISTENT(HT_DESTROYED);
+ pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
}
ZEND_API void zend_hash_clean(HashTable *ht)
{
- uint idx;
+ uint32_t idx;
Bucket *p;
IS_CONSISTENT(ht);
@@ -925,7 +946,7 @@ ZEND_API void zend_hash_clean(HashTable *ht)
ht->pDestructor(&p->val);
}
if (p->key) {
- STR_RELEASE(p->key);
+ zend_string_release(p->key);
}
}
ht->nNumUsed = 0;
@@ -934,7 +955,7 @@ ZEND_API void zend_hash_clean(HashTable *ht)
ht->nInternalPointer = INVALID_IDX;
if (ht->nTableMask) {
if (!(ht->u.flags & HASH_FLAG_PACKED)) {
- memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(zend_uint));
+ memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));
}
}
}
@@ -944,7 +965,7 @@ ZEND_API void zend_hash_clean(HashTable *ht)
* next bucket. The hash *may* be altered during that time, the
* returned value will still be valid.
*/
-static void zend_hash_apply_deleter(HashTable *ht, uint idx, Bucket *p)
+static void zend_hash_apply_deleter(HashTable *ht, uint32_t idx, Bucket *p)
{
#ifdef ZEND_SIGNALS
TSRMLS_FETCH();
@@ -958,7 +979,7 @@ static void zend_hash_apply_deleter(HashTable *ht, uint idx, Bucket *p)
ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
{
- uint idx;
+ uint32_t idx;
Bucket *p;
IS_CONSISTENT(ht);
@@ -977,7 +998,7 @@ ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
{
- uint idx;
+ uint32_t idx;
Bucket *p;
IS_CONSISTENT(ht);
@@ -1008,7 +1029,7 @@ ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
{
- uint idx;
+ uint32_t idx;
Bucket *p;
int result;
@@ -1034,7 +1055,7 @@ ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument TSRMLS_DC)
{
- uint idx;
+ uint32_t idx;
Bucket *p;
int result;
@@ -1060,7 +1081,7 @@ ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t appl
ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func_args_t apply_func, int num_args, ...)
{
- uint idx;
+ uint32_t idx;
Bucket *p;
va_list args;
zend_hash_key hash_key;
@@ -1095,7 +1116,7 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func
ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
{
- uint idx;
+ uint32_t idx;
Bucket *p;
int result;
@@ -1123,7 +1144,7 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR
ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
{
- uint idx;
+ uint32_t idx;
Bucket *p;
zval *new_entry, *data;
zend_bool setTargetPointer;
@@ -1168,8 +1189,8 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_fun
ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
{
- uint idx, target_idx;
- uint nIndex;
+ uint32_t idx, target_idx;
+ uint32_t nIndex;
Bucket *p, *q;
zval *data;
@@ -1188,7 +1209,7 @@ ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
target->nNumOfElements = source->nNumOfElements;
target->nNextFreeElement = source->nNextFreeElement;
target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket), 0, 0);
- target->arHash = (zend_uint*)&uninitialized_bucket;
+ target->arHash = (uint32_t*)&uninitialized_bucket;
target->nInternalPointer = source->nInternalPointer;
for (idx = 0; idx < source->nNumUsed; idx++) {
@@ -1230,9 +1251,9 @@ ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
}
} else {
target->nNextFreeElement = source->nNextFreeElement;
- target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket) + sizeof(zend_uint), 0, 0);
- target->arHash = (zend_uint*)(target->arData + target->nTableSize);
- memset(target->arHash, INVALID_IDX, target->nTableSize * sizeof(zend_uint));
+ target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, 0);
+ target->arHash = (uint32_t*)(target->arData + target->nTableSize);
+ memset(target->arHash, INVALID_IDX, target->nTableSize * sizeof(uint32_t));
for (idx = 0; idx < source->nNumUsed; idx++) {
p = source->arData + idx;
@@ -1254,7 +1275,7 @@ ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
q->h = p->h;
q->key = p->key;
if (q->key) {
- STR_ADDREF(q->key);
+ zend_string_addref(q->key);
}
nIndex = q->h & target->nTableMask;
Z_NEXT(q->val) = target->arHash[nIndex];
@@ -1282,17 +1303,17 @@ ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
target->nNumOfElements = 0;
target->nNextFreeElement = 0;
target->arData = NULL;
- target->arHash = (zend_uint*)&uninitialized_bucket;
+ target->arHash = (uint32_t*)&uninitialized_bucket;
}
}
-ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, int overwrite ZEND_FILE_LINE_DC)
+ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, zend_bool overwrite ZEND_FILE_LINE_DC)
{
- uint idx;
+ uint32_t idx;
Bucket *p;
zval *t;
- int mode = (overwrite?HASH_UPDATE:HASH_ADD);
+ uint32_t mode = (overwrite?HASH_UPDATE:HASH_ADD);
IS_CONSISTENT(source);
IS_CONSISTENT(target);
@@ -1336,7 +1357,7 @@ static zend_bool zend_hash_replace_checker_wrapper(HashTable *target, zval *sour
ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam)
{
- uint idx;
+ uint32_t idx;
Bucket *p;
zval *t;
@@ -1381,9 +1402,9 @@ ZEND_API zval *zend_hash_find(const HashTable *ht, zend_string *key)
return p ? &p->val : NULL;
}
-ZEND_API zval *zend_hash_str_find(const HashTable *ht, const char *str, int len)
+ZEND_API zval *zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
{
- ulong h;
+ zend_ulong h;
Bucket *p;
IS_CONSISTENT(ht);
@@ -1397,7 +1418,7 @@ ZEND_API zval *zend_hash_str_find(const HashTable *ht, const char *str, int len)
return p ? &p->val : NULL;
}
-ZEND_API int zend_hash_exists(const HashTable *ht, zend_string *key)
+ZEND_API zend_bool zend_hash_exists(const HashTable *ht, zend_string *key)
{
Bucket *p;
@@ -1411,9 +1432,9 @@ ZEND_API int zend_hash_exists(const HashTable *ht, zend_string *key)
return p ? 1 : 0;
}
-ZEND_API int zend_hash_str_exists(const HashTable *ht, const char *str, int len)
+ZEND_API zend_bool zend_hash_str_exists(const HashTable *ht, const char *str, size_t len)
{
- ulong h;
+ zend_ulong h;
Bucket *p;
IS_CONSISTENT(ht);
@@ -1427,14 +1448,14 @@ ZEND_API int zend_hash_str_exists(const HashTable *ht, const char *str, int len)
return p ? 1 : 0;
}
-ZEND_API zval *zend_hash_index_find(const HashTable *ht, ulong h)
+ZEND_API zval *zend_hash_index_find(const HashTable *ht, zend_ulong h)
{
Bucket *p;
IS_CONSISTENT(ht);
if (ht->u.flags & HASH_FLAG_PACKED) {
- if (h >= 0 && h < ht->nNumUsed) {
+ if (h < ht->nNumUsed) {
p = ht->arData + h;
if (Z_TYPE(p->val) != IS_UNDEF) {
return &p->val;
@@ -1448,14 +1469,14 @@ ZEND_API zval *zend_hash_index_find(const HashTable *ht, ulong h)
}
-ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h)
+ZEND_API zend_bool zend_hash_index_exists(const HashTable *ht, zend_ulong h)
{
Bucket *p;
IS_CONSISTENT(ht);
if (ht->u.flags & HASH_FLAG_PACKED) {
- if (h >= 0 && h < ht->nNumUsed) {
+ if (h < ht->nNumUsed) {
if (Z_TYPE(ht->arData[h].val) != IS_UNDEF) {
return 1;
}
@@ -1468,61 +1489,9 @@ ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h)
}
-ZEND_API int zend_hash_get_pointer(const HashTable *ht, HashPointer *ptr)
-{
- ptr->pos = ht->nInternalPointer;
- ptr->ht = (HashTable*)ht;
- if (ht->nInternalPointer != INVALID_IDX) {
- ptr->h = ht->arData[ht->nInternalPointer].h;
- return 1;
- } else {
- ptr->h = 0;
- return 0;
- }
-}
-
-ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr)
-{
- uint idx;
-
- if (ptr->pos == INVALID_IDX) {
- ht->nInternalPointer = INVALID_IDX;
- } else if (ptr->ht != ht) {
- IS_CONSISTENT(ht);
- for (idx = 0; idx < ht->nNumUsed; idx++) {
- if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
- ht->nInternalPointer = idx;
- return 0;
- }
- }
- idx = INVALID_IDX;
- return 0;
- } else if (ht->nInternalPointer != ptr->pos) {
- IS_CONSISTENT(ht);
- if (ht->u.flags & HASH_FLAG_PACKED) {
- if (ptr->h < ht->nNumUsed &&
- Z_TYPE(ht->arData[ptr->h].val) != IS_UNDEF) {
- ht->nInternalPointer = ptr->h;
- return 1;
- }
- } else {
- idx = ht->arHash[ptr->h & ht->nTableMask];
- while (idx != INVALID_IDX) {
- if (ht->arData[idx].h == ptr->h && idx == ptr->pos) {
- ht->nInternalPointer = idx;
- return 1;
- }
- idx = Z_NEXT(ht->arData[idx].val);
- }
- }
- return 0;
- }
- return 1;
-}
-
ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
{
- uint idx;
+ uint32_t idx;
IS_CONSISTENT(ht);
for (idx = 0; idx < ht->nNumUsed; idx++) {
@@ -1540,7 +1509,7 @@ ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *p
*/
ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
{
- uint idx;
+ uint32_t idx;
IS_CONSISTENT(ht);
@@ -1558,7 +1527,7 @@ ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos
ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
{
- uint idx = *pos;
+ uint32_t idx = *pos;
IS_CONSISTENT(ht);
@@ -1581,7 +1550,7 @@ ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
{
- uint idx = *pos;
+ uint32_t idx = *pos;
IS_CONSISTENT(ht);
@@ -1602,9 +1571,9 @@ ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
/* This function should be made binary safe */
-ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, ulong *num_index, zend_bool duplicate, HashPosition *pos)
+ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, zend_bool duplicate, HashPosition *pos)
{
- uint idx = *pos;
+ uint32_t idx = *pos;
Bucket *p;
IS_CONSISTENT(ht);
@@ -1612,7 +1581,7 @@ ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str
p = ht->arData + idx;
if (p->key) {
if (duplicate) {
- *str_index = STR_COPY(p->key);
+ *str_index = zend_string_copy(p->key);
} else {
*str_index = p->key;
}
@@ -1627,7 +1596,7 @@ ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str
ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos)
{
- uint idx = *pos;
+ uint32_t idx = *pos;
Bucket *p;
IS_CONSISTENT(ht);
@@ -1637,7 +1606,7 @@ ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key,
p = ht->arData + idx;
if (p->key) {
ZVAL_STR(key, p->key);
- STR_ADDREF(p->key);
+ zend_string_addref(p->key);
} else {
ZVAL_LONG(key, p->h);
}
@@ -1646,7 +1615,7 @@ ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key,
ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
{
- uint idx = *pos;
+ uint32_t idx = *pos;
Bucket *p;
IS_CONSISTENT(ht);
@@ -1664,7 +1633,7 @@ ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
ZEND_API zval *zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
{
- uint idx = *pos;
+ uint32_t idx = *pos;
Bucket *p;
IS_CONSISTENT(ht);
@@ -1677,10 +1646,10 @@ ZEND_API zval *zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
}
ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
- compare_func_t compar, int renumber TSRMLS_DC)
+ compare_func_t compar, zend_bool renumber TSRMLS_DC)
{
Bucket *p;
- int i, j;
+ uint32_t i, j;
IS_CONSISTENT(ht);
@@ -1712,7 +1681,7 @@ ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
p = ht->arData + j;
p->h = j;
if (p->key) {
- STR_RELEASE(p->key);
+ zend_string_release(p->key);
p->key = NULL;
}
}
@@ -1728,7 +1697,7 @@ ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
if (renumber) {
ht->u.flags |= HASH_FLAG_PACKED;
ht->arData = erealloc(ht->arData, ht->nTableSize * sizeof(Bucket));
- ht->arHash = (zend_uint*)&uninitialized_bucket;
+ ht->arHash = (uint32_t*)&uninitialized_bucket;
} else {
zend_hash_rehash(ht);
}
@@ -1742,7 +1711,7 @@ ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC)
{
- uint idx1, idx2;
+ uint32_t idx1, idx2;
Bucket *p1, *p2 = NULL;
int result;
zval *pData1, *pData2;
@@ -1846,9 +1815,9 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
}
-ZEND_API zval *zend_hash_minmax(const HashTable *ht, compare_func_t compar, int flag TSRMLS_DC)
+ZEND_API zval *zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag TSRMLS_DC)
{
- uint idx;
+ uint32_t idx;
Bucket *p, *res;
IS_CONSISTENT(ht);
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index d7b419225e..6752ccb074 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -22,7 +22,6 @@
#ifndef ZEND_HASH_H
#define ZEND_HASH_H
-#include <sys/types.h>
#include "zend.h"
#define HASH_KEY_IS_STRING 1
@@ -36,7 +35,7 @@
#define HASH_UPDATE_INDIRECT (1<<3)
#define HASH_ADD_NEW (1<<4)
-#define INVALID_IDX ((uint)-1)
+#define INVALID_IDX ((uint32_t) -1)
#define HASH_FLAG_PERSISTENT (1<<0)
#define HASH_FLAG_APPLY_PROTECTION (1<<1)
@@ -45,30 +44,30 @@
#define HASH_MASK_CONSISTENCY 0x60
typedef struct _zend_hash_key {
- ulong h;
+ zend_ulong h;
zend_string *key;
} zend_hash_key;
typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, zval *source_data, zend_hash_key *hash_key, void *pParam);
-typedef uint HashPosition;
+typedef uint32_t HashPosition;
BEGIN_EXTERN_C()
/* startup/shutdown */
-ZEND_API void _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC);
-ZEND_API void _zend_hash_init_ex(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
+ZEND_API void _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC);
+ZEND_API void _zend_hash_init_ex(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
ZEND_API void zend_hash_destroy(HashTable *ht);
ZEND_API void zend_hash_clean(HashTable *ht);
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent) _zend_hash_init((ht), (nSize), (pDestructor), (persistent) ZEND_FILE_LINE_CC)
#define zend_hash_init_ex(ht, nSize, pHashFunction, pDestructor, persistent, bApplyProtection) _zend_hash_init_ex((ht), (nSize), (pDestructor), (persistent), (bApplyProtection) ZEND_FILE_LINE_CC)
-ZEND_API void zend_hash_real_init(HashTable *ht, int packed);
+ZEND_API void zend_hash_real_init(HashTable *ht, zend_bool packed);
ZEND_API void zend_hash_packed_to_hash(HashTable *ht);
ZEND_API void zend_hash_to_packed(HashTable *ht);
/* additions/updates/changes */
-ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, int flag ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC);
ZEND_API zval *_zend_hash_update(HashTable *ht, zend_string *key,zval *pData ZEND_FILE_LINE_DC);
ZEND_API zval *_zend_hash_update_ind(HashTable *ht, zend_string *key,zval *pData ZEND_FILE_LINE_DC);
ZEND_API zval *_zend_hash_add(HashTable *ht, zend_string *key,zval *pData ZEND_FILE_LINE_DC);
@@ -83,11 +82,11 @@ ZEND_API zval *_zend_hash_add_new(HashTable *ht, zend_string *key,zval *pData ZE
#define zend_hash_add_new(ht, key, pData) \
_zend_hash_add_new(ht, key, pData ZEND_FILE_LINE_CC)
-ZEND_API zval *_zend_hash_str_add_or_update(HashTable *ht, const char *key, int len, zval *pData, int flag ZEND_FILE_LINE_DC);
-ZEND_API zval *_zend_hash_str_update(HashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
-ZEND_API zval *_zend_hash_str_update_ind(HashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
-ZEND_API zval *_zend_hash_str_add(HashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
-ZEND_API zval *_zend_hash_str_add_new(HashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_hash_str_add_or_update(HashTable *ht, const char *key, size_t len, zval *pData, uint32_t flag ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_hash_str_update(HashTable *ht, const char *key, size_t len, zval *pData ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_hash_str_update_ind(HashTable *ht, const char *key, size_t len, zval *pData ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_hash_str_add(HashTable *ht, const char *key, size_t len, zval *pData ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_hash_str_add_new(HashTable *ht, const char *key, size_t len, zval *pData ZEND_FILE_LINE_DC);
#define zend_hash_str_update(ht, key, len, pData) \
_zend_hash_str_update(ht, key, len, pData ZEND_FILE_LINE_CC)
@@ -98,10 +97,10 @@ ZEND_API zval *_zend_hash_str_add_new(HashTable *ht, const char *key, int len, z
#define zend_hash_str_add_new(ht, key, len, pData) \
_zend_hash_str_add_new(ht, key, len, pData ZEND_FILE_LINE_CC)
-ZEND_API zval *_zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, zval *pData, int flag ZEND_FILE_LINE_DC);
-ZEND_API zval *_zend_hash_index_add(HashTable *ht, ulong h, zval *pData ZEND_FILE_LINE_DC);
-ZEND_API zval *_zend_hash_index_add_new(HashTable *ht, ulong h, zval *pData ZEND_FILE_LINE_DC);
-ZEND_API zval *_zend_hash_index_update(HashTable *ht, ulong h, zval *pData ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_hash_index_update_or_next_insert(HashTable *ht, zend_ulong h, zval *pData, uint32_t flag ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC);
ZEND_API zval *_zend_hash_next_index_insert(HashTable *ht, zval *pData ZEND_FILE_LINE_DC);
ZEND_API zval *_zend_hash_next_index_insert_new(HashTable *ht, zval *pData ZEND_FILE_LINE_DC);
@@ -116,9 +115,9 @@ ZEND_API zval *_zend_hash_next_index_insert_new(HashTable *ht, zval *pData ZEND_
#define zend_hash_next_index_insert_new(ht, pData) \
_zend_hash_next_index_insert_new(ht, pData ZEND_FILE_LINE_CC)
-ZEND_API zval *zend_hash_index_add_empty_element(HashTable *ht, ulong h);
+ZEND_API zval *zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h);
ZEND_API zval *zend_hash_add_empty_element(HashTable *ht, zend_string *key);
-ZEND_API zval *zend_hash_str_add_empty_element(HashTable *ht, const char *key, int len);
+ZEND_API zval *zend_hash_str_add_empty_element(HashTable *ht, const char *key, size_t len);
#define ZEND_HASH_APPLY_KEEP 0
#define ZEND_HASH_APPLY_REMOVE 1<<0
@@ -146,26 +145,26 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR
/* Deletes */
ZEND_API int zend_hash_del(HashTable *ht, zend_string *key);
ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key);
-ZEND_API int zend_hash_str_del(HashTable *ht, const char *key, int len);
-ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *key, int len);
-ZEND_API int zend_hash_index_del(HashTable *ht, ulong h);
+ZEND_API int zend_hash_str_del(HashTable *ht, const char *key, size_t len);
+ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *key, size_t len);
+ZEND_API int zend_hash_index_del(HashTable *ht, zend_ulong h);
/* Data retreival */
ZEND_API zval *zend_hash_find(const HashTable *ht, zend_string *key);
-ZEND_API zval *zend_hash_str_find(const HashTable *ht, const char *key, int len);
-ZEND_API zval *zend_hash_index_find(const HashTable *ht, ulong h);
+ZEND_API zval *zend_hash_str_find(const HashTable *ht, const char *key, size_t len);
+ZEND_API zval *zend_hash_index_find(const HashTable *ht, zend_ulong h);
/* Misc */
-ZEND_API int zend_hash_exists(const HashTable *ht, zend_string *key);
-ZEND_API int zend_hash_str_exists(const HashTable *ht, const char *str, int len);
-ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h);
+ZEND_API zend_bool zend_hash_exists(const HashTable *ht, zend_string *key);
+ZEND_API zend_bool zend_hash_str_exists(const HashTable *ht, const char *str, size_t len);
+ZEND_API zend_bool zend_hash_index_exists(const HashTable *ht, zend_ulong h);
/* traversing */
#define zend_hash_has_more_elements_ex(ht, pos) \
(zend_hash_get_current_key_type_ex(ht, pos) == HASH_KEY_NON_EXISTENT ? 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, zend_string **str_index, ulong *num_index, zend_bool duplicate, HashPosition *pos);
+ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_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 zval *zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos);
@@ -175,12 +174,9 @@ ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos
typedef struct _HashPointer {
HashPosition pos;
HashTable *ht;
- ulong h;
+ zend_ulong h;
} HashPointer;
-ZEND_API int zend_hash_get_pointer(const HashTable *ht, HashPointer *ptr);
-ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr);
-
#define zend_hash_has_more_elements(ht) \
zend_hash_has_more_elements_ex(ht, &(ht)->nInternalPointer)
#define zend_hash_move_forward(ht) \
@@ -202,11 +198,11 @@ ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr);
/* Copying, merging and sorting */
ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor);
-ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, int overwrite ZEND_FILE_LINE_DC);
+ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, zend_bool overwrite ZEND_FILE_LINE_DC);
ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam);
-ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber TSRMLS_DC);
+ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, zend_bool renumber TSRMLS_DC);
ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC);
-ZEND_API zval *zend_hash_minmax(const HashTable *ht, compare_func_t compar, int flag TSRMLS_DC);
+ZEND_API zval *zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag TSRMLS_DC);
#define zend_hash_merge(target, source, pCopyConstructor, overwrite) \
_zend_hash_merge(target, source, pCopyConstructor, overwrite ZEND_FILE_LINE_CC)
@@ -235,7 +231,7 @@ END_EXTERN_C()
#define ZEND_INIT_SYMTABLE_EX(ht, n, persistent) \
zend_hash_init(ht, n, NULL, ZVAL_PTR_DTOR, persistent)
-static inline int _zend_handle_numeric_str(const char *key, int length, ulong *idx)
+static inline int _zend_handle_numeric_str(const char *key, size_t length, zend_ulong *idx)
{
register const char *tmp = key;
const char *end;
@@ -258,7 +254,7 @@ static inline int _zend_handle_numeric_str(const char *key, int length, ulong *i
if ((*end != '\0') /* not a null terminated string */
|| (*tmp == '0' && length > 1) /* numbers with leading zeros */
|| (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */
- || (SIZEOF_LONG == 4 &&
+ || (SIZEOF_ZEND_LONG == 4 &&
end - tmp == MAX_LENGTH_OF_LONG - 1 &&
*tmp > '2')) { /* overflow */
return 0;
@@ -268,11 +264,11 @@ static inline int _zend_handle_numeric_str(const char *key, int length, ulong *i
++tmp;
if (tmp == end) {
if (*key == '-') {
- if (*idx-1 > LONG_MAX) { /* overflow */
+ if (*idx-1 > ZEND_LONG_MAX) { /* overflow */
return 0;
}
*idx = 0 - *idx;
- } else if (*idx > LONG_MAX) { /* overflow */
+ } else if (*idx > ZEND_LONG_MAX) { /* overflow */
return 0;
}
return 1;
@@ -322,7 +318,7 @@ static inline zval *zend_hash_str_find_ind(const HashTable *ht, const char *str,
static inline zval *zend_symtable_update(HashTable *ht, zend_string *key, zval *pData)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC(key, idx)) {
return zend_hash_index_update(ht, idx, pData);
@@ -334,7 +330,7 @@ static inline zval *zend_symtable_update(HashTable *ht, zend_string *key, zval *
static inline zval *zend_symtable_update_ind(HashTable *ht, zend_string *key, zval *pData)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC(key, idx)) {
return zend_hash_index_update(ht, idx, pData);
@@ -346,7 +342,7 @@ static inline zval *zend_symtable_update_ind(HashTable *ht, zend_string *key, zv
static inline int zend_symtable_del(HashTable *ht, zend_string *key)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC(key, idx)) {
return zend_hash_index_del(ht, idx);
@@ -358,7 +354,7 @@ static inline int zend_symtable_del(HashTable *ht, zend_string *key)
static inline int zend_symtable_del_ind(HashTable *ht, zend_string *key)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC(key, idx)) {
return zend_hash_index_del(ht, idx);
@@ -370,7 +366,7 @@ static inline int zend_symtable_del_ind(HashTable *ht, zend_string *key)
static inline zval *zend_symtable_find(const HashTable *ht, zend_string *key)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC(key, idx)) {
return zend_hash_index_find(ht, idx);
@@ -382,7 +378,7 @@ static inline zval *zend_symtable_find(const HashTable *ht, zend_string *key)
static inline zval *zend_symtable_find_ind(const HashTable *ht, zend_string *key)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC(key, idx)) {
return zend_hash_index_find(ht, idx);
@@ -394,7 +390,7 @@ static inline zval *zend_symtable_find_ind(const HashTable *ht, zend_string *key
static inline int zend_symtable_exists(HashTable *ht, zend_string *key)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC(key, idx)) {
return zend_hash_index_exists(ht, idx);
@@ -406,7 +402,7 @@ static inline int zend_symtable_exists(HashTable *ht, zend_string *key)
static inline zval *zend_symtable_str_update(HashTable *ht, const char *str, int len, zval *pData)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
return zend_hash_index_update(ht, idx, pData);
@@ -418,7 +414,7 @@ static inline zval *zend_symtable_str_update(HashTable *ht, const char *str, int
static inline zval *zend_symtable_str_update_ind(HashTable *ht, const char *str, int len, zval *pData)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
return zend_hash_index_update(ht, idx, pData);
@@ -430,7 +426,7 @@ static inline zval *zend_symtable_str_update_ind(HashTable *ht, const char *str,
static inline int zend_symtable_str_del(HashTable *ht, const char *str, int len)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
return zend_hash_index_del(ht, idx);
@@ -442,7 +438,7 @@ static inline int zend_symtable_str_del(HashTable *ht, const char *str, int len)
static inline int zend_symtable_str_del_ind(HashTable *ht, const char *str, int len)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
return zend_hash_index_del(ht, idx);
@@ -454,7 +450,7 @@ static inline int zend_symtable_str_del_ind(HashTable *ht, const char *str, int
static inline zval *zend_symtable_str_find(HashTable *ht, const char *str, int len)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
return zend_hash_index_find(ht, idx);
@@ -466,7 +462,7 @@ static inline zval *zend_symtable_str_find(HashTable *ht, const char *str, int l
static inline int zend_symtable_str_exists(HashTable *ht, const char *str, int len)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
return zend_hash_index_exists(ht, idx);
@@ -564,7 +560,7 @@ static inline void *zend_hash_str_update_mem(HashTable *ht, const char *str, int
return zend_hash_str_update_ptr(ht, str, len, p);
}
-static inline void *zend_hash_index_update_ptr(HashTable *ht, ulong h, void *pData)
+static inline void *zend_hash_index_update_ptr(HashTable *ht, zend_ulong h, void *pData)
{
zval tmp, *zv;
@@ -582,7 +578,7 @@ static inline void *zend_hash_next_index_insert_ptr(HashTable *ht, void *pData)
return zv ? Z_PTR_P(zv) : NULL;
}
-static inline void *zend_hash_index_update_mem(HashTable *ht, ulong h, void *pData, size_t size)
+static inline void *zend_hash_index_update_mem(HashTable *ht, zend_ulong h, void *pData, size_t size)
{
void *p;
@@ -620,7 +616,7 @@ static inline void *zend_hash_str_find_ptr(const HashTable *ht, const char *str,
return zv ? Z_PTR_P(zv) : NULL;
}
-static inline void *zend_hash_index_find_ptr(const HashTable *ht, ulong h)
+static inline void *zend_hash_index_find_ptr(const HashTable *ht, zend_ulong h)
{
zval *zv;
@@ -630,7 +626,7 @@ static inline void *zend_hash_index_find_ptr(const HashTable *ht, ulong h)
static inline void *zend_symtable_str_find_ptr(HashTable *ht, const char *str, int len)
{
- ulong idx;
+ zend_ulong idx;
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
return zend_hash_index_find_ptr(ht, idx);
@@ -702,6 +698,11 @@ static inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, HashPositio
ZEND_HASH_FOREACH(ht, 0); \
_h = _p->h; \
_key = _p->key;
+
+#define ZEND_HASH_FOREACH_NUM_KEY_VAL(ht, _h, _val) \
+ ZEND_HASH_FOREACH(ht, 0); \
+ _h = _p->h; \
+ _val = _z;
#define ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _key, _val) \
ZEND_HASH_FOREACH(ht, 0); \
diff --git a/Zend/zend_highlight.c b/Zend/zend_highlight.c
index 50a1edce38..26c34686a6 100644
--- a/Zend/zend_highlight.c
+++ b/Zend/zend_highlight.c
@@ -104,9 +104,15 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
break;
case T_OPEN_TAG:
case T_OPEN_TAG_WITH_ECHO:
- next_color = syntax_highlighter_ini->highlight_default;
- break;
case T_CLOSE_TAG:
+ case T_LINE:
+ case T_FILE:
+ case T_DIR:
+ case T_TRAIT_C:
+ case T_METHOD_C:
+ case T_FUNC_C:
+ case T_NS_C:
+ case T_CLASS_C:
next_color = syntax_highlighter_ini->highlight_default;
break;
case '"':
@@ -150,7 +156,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
case T_DOC_COMMENT:
break;
default:
- STR_RELEASE(Z_STR(token));
+ zend_string_release(Z_STR(token));
break;
}
}
@@ -211,7 +217,7 @@ ZEND_API void zend_strip(TSRMLS_D)
break;
default:
- STR_RELEASE(Z_STR(token));
+ zend_string_release(Z_STR(token));
break;
}
}
diff --git a/Zend/zend_indent.c b/Zend/zend_indent.c
index 05254a30bc..5ebc4527e2 100644
--- a/Zend/zend_indent.c
+++ b/Zend/zend_indent.c
@@ -138,7 +138,7 @@ dflt_printout:
case T_WHITESPACE:
break;
default:
- STR_RELEASE(Z_STR(token));
+ zend_string_release(Z_STR(token));
break;
}
}
diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c
index c3a02d53a3..e60e58d2aa 100644
--- a/Zend/zend_ini.c
+++ b/Zend/zend_ini.c
@@ -56,7 +56,7 @@ static int zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage TSRMLS
/* even if on_modify bails out, we have to continue on with restoring,
since there can be allocated variables that would be freed on MM shutdown
and would lead to memory corruption later ini entry is modified again */
- result = ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->orig_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC);
+ result = ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC);
} zend_end_try();
}
if (stage == ZEND_INI_STAGE_RUNTIME && result == FAILURE) {
@@ -64,14 +64,12 @@ static int zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage TSRMLS
return 1;
}
if (ini_entry->value != ini_entry->orig_value) {
- efree(ini_entry->value);
+ zend_string_release(ini_entry->value);
}
ini_entry->value = ini_entry->orig_value;
- ini_entry->value_length = ini_entry->orig_value_length;
ini_entry->modifiable = ini_entry->orig_modifiable;
ini_entry->modified = 0;
ini_entry->orig_value = NULL;
- ini_entry->orig_value_length = 0;
ini_entry->orig_modifiable = 0;
}
return 0;
@@ -86,9 +84,18 @@ static int zend_restore_ini_entry_wrapper(zval *el TSRMLS_DC) /* {{{ */
}
/* }}} */
-static void _free_ptr(zval *zv) /* {{{ */
+static void free_ini_entry(zval *zv) /* {{{ */
{
- free(Z_PTR_P(zv));
+ zend_ini_entry *entry = (zend_ini_entry*)Z_PTR_P(zv);
+
+ zend_string_release(entry->name);
+ if (entry->value) {
+ zend_string_release(entry->value);
+ }
+ if (entry->orig_value) {
+ zend_string_release(entry->orig_value);
+ }
+ free(entry);
}
/* }}} */
@@ -102,7 +109,7 @@ ZEND_API int zend_ini_startup(TSRMLS_D) /* {{{ */
EG(ini_directives) = registered_zend_ini_directives;
EG(modified_ini_directives) = NULL;
EG(error_reporting_ini_entry) = NULL;
- zend_hash_init_ex(registered_zend_ini_directives, 128, NULL, _free_ptr, 1, 0);
+ zend_hash_init_ex(registered_zend_ini_directives, 128, NULL, free_ini_entry, 1, 0);
return SUCCESS;
}
/* }}} */
@@ -136,13 +143,32 @@ ZEND_API int zend_ini_deactivate(TSRMLS_D) /* {{{ */
/* }}} */
#ifdef ZTS
+static void copy_ini_entry(zval *zv) /* {{{ */
+{
+ zend_ini_entry *old_entry = (zend_ini_entry*)Z_PTR_P(zv);
+ zend_ini_entry *new_entry = pemalloc(sizeof(zend_ini_entry), 1);
+
+ Z_PTR_P(zv) = new_entry;
+ memcpy(new_entry, old_entry, sizeof(zend_ini_entry));
+ if (old_entry->name) {
+ new_entry->name = zend_string_init(old_entry->name->val, old_entry->name->len, 1);
+ }
+ if (old_entry->value) {
+ new_entry->value = zend_string_init(old_entry->value->val, old_entry->value->len, 1);
+ }
+ if (old_entry->orig_value) {
+ new_entry->orig_value = zend_string_init(old_entry->orig_value->val, old_entry->orig_value->len, 1);
+ }
+}
+/* }}} */
+
ZEND_API int zend_copy_ini_directives(TSRMLS_D) /* {{{ */
{
EG(modified_ini_directives) = NULL;
EG(error_reporting_ini_entry) = NULL;
EG(ini_directives) = (HashTable *) malloc(sizeof(HashTable));
- zend_hash_init_ex(EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, NULL, 1, 0);
- zend_hash_copy(EG(ini_directives), registered_zend_ini_directives, NULL);
+ zend_hash_init_ex(EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, free_ini_entry, 1, 0);
+ zend_hash_copy(EG(ini_directives), registered_zend_ini_directives, copy_ini_entry);
return SUCCESS;
}
/* }}} */
@@ -177,13 +203,11 @@ ZEND_API void zend_ini_sort_entries(TSRMLS_D) /* {{{ */
/*
* Registration / unregistration
*/
-ZEND_API int zend_register_ini_entries(const zend_ini_entry *ini_entry, int module_number TSRMLS_DC) /* {{{ */
+ZEND_API int zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number TSRMLS_DC) /* {{{ */
{
- const zend_ini_entry *p = ini_entry;
- zend_ini_entry *hashed_ini_entry;
- zval default_value;
+ zend_ini_entry *p;
+ zval *default_value;
HashTable *directives = registered_zend_ini_directives;
- zend_bool config_directive_success = 0;
#ifdef ZTS
/* if we are called during the request, eg: from dl(),
@@ -199,26 +223,42 @@ ZEND_API int zend_register_ini_entries(const zend_ini_entry *ini_entry, int modu
}
#endif
- while (p->name) {
- config_directive_success = 0;
- if ((hashed_ini_entry = zend_hash_str_add_mem(directives, p->name, p->name_length, (void*)p, sizeof(zend_ini_entry))) == NULL) {
+ while (ini_entry->name) {
+ p = pemalloc(sizeof(zend_ini_entry), 1);
+ p->name = zend_string_init(ini_entry->name, ini_entry->name_length, 1);
+ p->on_modify = ini_entry->on_modify;
+ p->mh_arg1 = ini_entry->mh_arg1;
+ p->mh_arg2 = ini_entry->mh_arg2;
+ p->mh_arg3 = ini_entry->mh_arg3;
+ p->value = NULL;
+ p->orig_value = NULL;
+ p->displayer = ini_entry->displayer;
+ p->modifiable = ini_entry->modifiable;
+
+ p->orig_modifiable = 0;
+ p->modified = 0;
+ p->module_number = module_number;
+
+ if (zend_hash_add_ptr(directives, p->name, (void*)p) == NULL) {
+ if (p->name) {
+ zend_string_release(p->name);
+ }
zend_unregister_ini_entries(module_number TSRMLS_CC);
return FAILURE;
}
- hashed_ini_entry->module_number = module_number;
- if ((zend_get_configuration_directive(p->name, p->name_length, &default_value)) == SUCCESS) {
- if (!hashed_ini_entry->on_modify
- || hashed_ini_entry->on_modify(hashed_ini_entry, Z_STRVAL(default_value), Z_STRLEN(default_value), hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, hashed_ini_entry->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC) == SUCCESS) {
- hashed_ini_entry->value = Z_STRVAL(default_value);
- hashed_ini_entry->value_length = Z_STRLEN(default_value);
- config_directive_success = 1;
- }
- }
+ if (((default_value = zend_get_configuration_directive(p->name)) != NULL) &&
+ (!p->on_modify || p->on_modify(p, Z_STR_P(default_value), p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC) == SUCCESS)) {
+
+ p->value = zend_string_copy(Z_STR_P(default_value));
+ } else {
+ p->value = ini_entry->value ?
+ zend_string_init(ini_entry->value, ini_entry->value_length, 1) : NULL;
- if (!config_directive_success && hashed_ini_entry->on_modify) {
- hashed_ini_entry->on_modify(hashed_ini_entry, hashed_ini_entry->value, hashed_ini_entry->value_length, hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, hashed_ini_entry->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC);
+ if (p->on_modify) {
+ p->on_modify(p, p->value, p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC);
+ }
}
- p++;
+ ini_entry++;
}
return SUCCESS;
}
@@ -237,7 +277,7 @@ static int zend_ini_refresh_cache(zval *el, void *arg TSRMLS_DC) /* {{{ */
int stage = (int)(zend_intptr_t)arg;
if (p->on_modify) {
- p->on_modify(p, p->value, p->value_length, p->mh_arg1, p->mh_arg2, p->mh_arg3, stage TSRMLS_CC);
+ p->on_modify(p, p->value, p->mh_arg1, p->mh_arg2, p->mh_arg3, stage TSRMLS_CC);
}
return 0;
}
@@ -250,18 +290,43 @@ ZEND_API void zend_ini_refresh_caches(int stage TSRMLS_DC) /* {{{ */
/* }}} */
#endif
-ZEND_API int zend_alter_ini_entry(zend_string *name, char *new_value, uint new_value_length, int modify_type, int stage) /* {{{ */
+ZEND_API int zend_alter_ini_entry(zend_string *name, zend_string *new_value, int modify_type, int stage) /* {{{ */
{
TSRMLS_FETCH();
- return zend_alter_ini_entry_ex(name, new_value, new_value_length, modify_type, stage, 0 TSRMLS_CC);
+ return zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0 TSRMLS_CC);
+}
+/* }}} */
+
+ZEND_API int zend_alter_ini_entry_chars(zend_string *name, const char *value, size_t value_length, int modify_type, int stage) /* {{{ */
+{
+ int ret;
+ zend_string *new_value;
+ TSRMLS_FETCH();
+
+ new_value = zend_string_init(value, value_length, stage != ZEND_INI_STAGE_RUNTIME);
+ ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0 TSRMLS_CC);
+ zend_string_release(new_value);
+ return ret;
+}
+/* }}} */
+
+ZEND_API int zend_alter_ini_entry_chars_ex(zend_string *name, const char *value, size_t value_length, int modify_type, int stage, int force_change TSRMLS_DC) /* {{{ */
+{
+ int ret;
+ zend_string *new_value;
+
+ new_value = zend_string_init(value, value_length, stage != ZEND_INI_STAGE_RUNTIME);
+ ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, force_change TSRMLS_CC);
+ zend_string_release(new_value);
+ return ret;
}
/* }}} */
-ZEND_API int zend_alter_ini_entry_ex(zend_string *name, char *new_value, uint new_value_length, int modify_type, int stage, int force_change TSRMLS_DC) /* {{{ */
+ZEND_API int zend_alter_ini_entry_ex(zend_string *name, zend_string *new_value, int modify_type, int stage, int force_change TSRMLS_DC) /* {{{ */
{
zend_ini_entry *ini_entry;
- char *duplicate;
+ zend_string *duplicate;
zend_bool modifiable;
zend_bool modified;
@@ -288,23 +353,21 @@ ZEND_API int zend_alter_ini_entry_ex(zend_string *name, char *new_value, uint ne
}
if (!modified) {
ini_entry->orig_value = ini_entry->value;
- ini_entry->orig_value_length = ini_entry->value_length;
ini_entry->orig_modifiable = modifiable;
ini_entry->modified = 1;
zend_hash_add_ptr(EG(modified_ini_directives), name, ini_entry);
}
- duplicate = estrndup(new_value, new_value_length);
+ duplicate = zend_string_copy(new_value);
if (!ini_entry->on_modify
- || ini_entry->on_modify(ini_entry, duplicate, new_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC) == SUCCESS) {
+ || ini_entry->on_modify(ini_entry, duplicate, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC) == SUCCESS) {
if (modified && ini_entry->orig_value != ini_entry->value) { /* we already changed the value, free the changed value */
- efree(ini_entry->value);
+ zend_string_release(ini_entry->value);
}
ini_entry->value = duplicate;
- ini_entry->value_length = new_value_length;
} else {
- efree(duplicate);
+ zend_string_release(duplicate);
return FAILURE;
}
@@ -352,7 +415,7 @@ ZEND_API int zend_ini_register_displayer(char *name, uint name_length, void (*di
* Data retrieval
*/
-ZEND_API long zend_ini_long(char *name, uint name_length, int orig) /* {{{ */
+ZEND_API zend_long zend_ini_long(char *name, uint name_length, int orig) /* {{{ */
{
zend_ini_entry *ini_entry;
TSRMLS_FETCH();
@@ -360,9 +423,9 @@ ZEND_API long zend_ini_long(char *name, uint name_length, int orig) /* {{{ */
ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
if (ini_entry) {
if (orig && ini_entry->modified) {
- return (ini_entry->orig_value ? strtol(ini_entry->orig_value, NULL, 0) : 0);
+ return (ini_entry->orig_value ? ZEND_STRTOL(ini_entry->orig_value->val, NULL, 0) : 0);
} else {
- return (ini_entry->value ? strtol(ini_entry->value, NULL, 0) : 0);
+ return (ini_entry->value ? ZEND_STRTOL(ini_entry->value->val, NULL, 0) : 0);
}
}
@@ -378,9 +441,9 @@ ZEND_API double zend_ini_double(char *name, uint name_length, int orig) /* {{{ *
ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
if (ini_entry) {
if (orig && ini_entry->modified) {
- return (double) (ini_entry->orig_value ? zend_strtod(ini_entry->orig_value, NULL) : 0.0);
+ return (double) (ini_entry->orig_value ? zend_strtod(ini_entry->orig_value->val, NULL) : 0.0);
} else {
- return (double) (ini_entry->value ? zend_strtod(ini_entry->value, NULL) : 0.0);
+ return (double) (ini_entry->value ? zend_strtod(ini_entry->value->val, NULL) : 0.0);
}
}
@@ -400,9 +463,9 @@ ZEND_API char *zend_ini_string_ex(char *name, uint name_length, int orig, zend_b
}
if (orig && ini_entry->modified) {
- return ini_entry->orig_value;
+ return ini_entry->orig_value ? ini_entry->orig_value->val : NULL;
} else {
- return ini_entry->value;
+ return ini_entry->value ? ini_entry->value->val : NULL;
}
} else {
if (exists) {
@@ -470,29 +533,26 @@ static void zend_ini_displayer_cb(zend_ini_entry *ini_entry, int type) /* {{{ */
ZEND_INI_DISP(zend_ini_boolean_displayer_cb) /* {{{ */
{
- int value, tmp_value_len;
- char *tmp_value;
+ int value;
+ zend_string *tmp_value;
if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
tmp_value = (ini_entry->orig_value ? ini_entry->orig_value : NULL );
- tmp_value_len = ini_entry->orig_value_length;
} else if (ini_entry->value) {
tmp_value = ini_entry->value;
- tmp_value_len = ini_entry->value_length;
} else {
tmp_value = NULL;
- tmp_value_len = 0;
}
if (tmp_value) {
- if (tmp_value_len == 4 && strcasecmp(tmp_value, "true") == 0) {
+ if (tmp_value->len == 4 && strcasecmp(tmp_value->val, "true") == 0) {
value = 1;
- } else if (tmp_value_len == 3 && strcasecmp(tmp_value, "yes") == 0) {
+ } else if (tmp_value->len == 3 && strcasecmp(tmp_value->val, "yes") == 0) {
value = 1;
- } else if (tmp_value_len == 2 && strcasecmp(tmp_value, "on") == 0) {
+ } else if (tmp_value->len == 2 && strcasecmp(tmp_value->val, "on") == 0) {
value = 1;
} else {
- value = atoi(tmp_value);
+ value = atoi(tmp_value->val);
}
} else {
value = 0;
@@ -511,9 +571,9 @@ ZEND_INI_DISP(zend_ini_color_displayer_cb) /* {{{ */
char *value;
if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
- value = ini_entry->orig_value;
+ value = ini_entry->orig_value->val;
} else if (ini_entry->value) {
- value = ini_entry->value;
+ value = ini_entry->value->val;
} else {
value = NULL;
}
@@ -538,9 +598,9 @@ ZEND_INI_DISP(display_link_numbers) /* {{{ */
char *value;
if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
- value = ini_entry->orig_value;
+ value = ini_entry->orig_value->val;
} else if (ini_entry->value) {
- value = ini_entry->value;
+ value = ini_entry->value->val;
} else {
value = NULL;
}
@@ -569,17 +629,17 @@ ZEND_API ZEND_INI_MH(OnUpdateBool) /* {{{ */
p = (zend_bool *) (base+(size_t) mh_arg1);
- if (new_value_length == 2 && strcasecmp("on", new_value) == 0) {
+ if (new_value->len == 2 && strcasecmp("on", new_value->val) == 0) {
*p = (zend_bool) 1;
}
- else if (new_value_length == 3 && strcasecmp("yes", new_value) == 0) {
+ else if (new_value->len == 3 && strcasecmp("yes", new_value->val) == 0) {
*p = (zend_bool) 1;
}
- else if (new_value_length == 4 && strcasecmp("true", new_value) == 0) {
+ else if (new_value->len == 4 && strcasecmp("true", new_value->val) == 0) {
*p = (zend_bool) 1;
}
else {
- *p = (zend_bool) atoi(new_value);
+ *p = (zend_bool) atoi(new_value->val);
}
return SUCCESS;
}
@@ -587,7 +647,7 @@ ZEND_API ZEND_INI_MH(OnUpdateBool) /* {{{ */
ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */
{
- long *p;
+ zend_long *p;
#ifndef ZTS
char *base = (char *) mh_arg2;
#else
@@ -596,16 +656,16 @@ ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */
base = (char *) ts_resource(*((int *) mh_arg2));
#endif
- p = (long *) (base+(size_t) mh_arg1);
+ p = (zend_long *) (base+(size_t) mh_arg1);
- *p = zend_atol(new_value, new_value_length);
+ *p = zend_atol(new_value->val, new_value->len);
return SUCCESS;
}
/* }}} */
ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */
{
- long *p, tmp;
+ zend_long *p, tmp;
#ifndef ZTS
char *base = (char *) mh_arg2;
#else
@@ -614,12 +674,12 @@ ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */
base = (char *) ts_resource(*((int *) mh_arg2));
#endif
- tmp = zend_atol(new_value, new_value_length);
+ tmp = zend_atol(new_value->val, new_value->len);
if (tmp < 0) {
return FAILURE;
}
- p = (long *) (base+(size_t) mh_arg1);
+ p = (zend_long *) (base+(size_t) mh_arg1);
*p = tmp;
return SUCCESS;
@@ -639,7 +699,7 @@ ZEND_API ZEND_INI_MH(OnUpdateReal) /* {{{ */
p = (double *) (base+(size_t) mh_arg1);
- *p = zend_strtod(new_value, NULL);
+ *p = zend_strtod(new_value->val, NULL);
return SUCCESS;
}
/* }}} */
@@ -657,7 +717,7 @@ ZEND_API ZEND_INI_MH(OnUpdateString) /* {{{ */
p = (char **) (base+(size_t) mh_arg1);
- *p = new_value;
+ *p = new_value ? new_value->val : NULL;
return SUCCESS;
}
/* }}} */
@@ -673,13 +733,13 @@ ZEND_API ZEND_INI_MH(OnUpdateStringUnempty) /* {{{ */
base = (char *) ts_resource(*((int *) mh_arg2));
#endif
- if (new_value && !new_value[0]) {
+ if (new_value && !new_value->val[0]) {
return FAILURE;
}
p = (char **) (base+(size_t) mh_arg1);
- *p = new_value;
+ *p = new_value ? new_value->val : NULL;
return SUCCESS;
}
/* }}} */
diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h
index 0a0c1137e1..f0a72c5142 100644
--- a/Zend/zend_ini.h
+++ b/Zend/zend_ini.h
@@ -27,28 +27,37 @@
#define ZEND_INI_ALL (ZEND_INI_USER|ZEND_INI_PERDIR|ZEND_INI_SYSTEM)
-#define ZEND_INI_MH(name) int name(zend_ini_entry *entry, char *new_value, uint new_value_length, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage TSRMLS_DC)
+#define ZEND_INI_MH(name) int name(zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage TSRMLS_DC)
#define ZEND_INI_DISP(name) void name(zend_ini_entry *ini_entry, int type)
-struct _zend_ini_entry {
- int module_number;
- int modifiable;
- char *name; // TODO: convert into zend_string ???
- uint name_length;
+typedef struct _zend_ini_entry_def {
+ const char *name;
ZEND_INI_MH((*on_modify));
void *mh_arg1;
void *mh_arg2;
void *mh_arg3;
+ const char *value;
+ void (*displayer)(zend_ini_entry *ini_entry, int type);
+ int modifiable;
- char *value; // TODO: convert into zend_string ???
+ uint name_length;
uint value_length;
+} zend_ini_entry_def;
+
+struct _zend_ini_entry {
+ zend_string *name;
+ ZEND_INI_MH((*on_modify));
+ void *mh_arg1;
+ void *mh_arg2;
+ void *mh_arg3;
+ zend_string *value;
+ zend_string *orig_value;
+ void (*displayer)(zend_ini_entry *ini_entry, int type);
+ int modifiable;
- char *orig_value; // TODO: convert into zend_string ???
- uint orig_value_length;
int orig_modifiable;
int modified;
-
- void (*displayer)(zend_ini_entry *ini_entry, int type);
+ int module_number;
};
BEGIN_EXTERN_C()
@@ -61,15 +70,17 @@ ZEND_API int zend_copy_ini_directives(TSRMLS_D);
ZEND_API void zend_ini_sort_entries(TSRMLS_D);
-ZEND_API int zend_register_ini_entries(const zend_ini_entry *ini_entry, int module_number TSRMLS_DC);
+ZEND_API int zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number TSRMLS_DC);
ZEND_API void zend_unregister_ini_entries(int module_number TSRMLS_DC);
ZEND_API void zend_ini_refresh_caches(int stage TSRMLS_DC);
-ZEND_API int zend_alter_ini_entry(zend_string *name, char *new_value, uint new_value_length, int modify_type, int stage);
-ZEND_API int zend_alter_ini_entry_ex(zend_string *name, char *new_value, uint new_value_length, int modify_type, int stage, int force_change TSRMLS_DC);
+ZEND_API int zend_alter_ini_entry(zend_string *name, zend_string *new_value, int modify_type, int stage);
+ZEND_API int zend_alter_ini_entry_ex(zend_string *name, zend_string *new_value, int modify_type, int stage, int force_change TSRMLS_DC);
+ZEND_API int zend_alter_ini_entry_chars(zend_string *name, const char *value, size_t value_length, int modify_type, int stage);
+ZEND_API int zend_alter_ini_entry_chars_ex(zend_string *name, const char *value, size_t value_length, int modify_type, int stage, int force_change TSRMLS_DC);
ZEND_API int zend_restore_ini_entry(zend_string *name, int stage);
ZEND_API void display_ini_entries(zend_module_entry *module);
-ZEND_API long zend_ini_long(char *name, uint name_length, int orig);
+ZEND_API zend_long zend_ini_long(char *name, uint name_length, int orig);
ZEND_API double zend_ini_double(char *name, uint name_length, int orig);
ZEND_API char *zend_ini_string(char *name, uint name_length, int orig);
ZEND_API char *zend_ini_string_ex(char *name, uint name_length, int orig, zend_bool *exists);
@@ -81,11 +92,11 @@ ZEND_API ZEND_INI_DISP(zend_ini_color_displayer_cb);
ZEND_API ZEND_INI_DISP(display_link_numbers);
END_EXTERN_C()
-#define ZEND_INI_BEGIN() static const zend_ini_entry ini_entries[] = {
-#define ZEND_INI_END() { 0, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 0, NULL } };
+#define ZEND_INI_BEGIN() static const zend_ini_entry_def ini_entries[] = {
+#define ZEND_INI_END() { NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0} };
#define ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, arg1, arg2, arg3, displayer) \
- { 0, modifiable, name, sizeof(name)-1, on_modify, arg1, arg2, arg3, default_value, sizeof(default_value)-1, NULL, 0, 0, 0, displayer },
+ { name, on_modify, arg1, arg2, arg3, default_value, displayer, modifiable, sizeof(name)-1, sizeof(default_value)-1 },
#define ZEND_INI_ENTRY3(name, default_value, modifiable, on_modify, arg1, arg2, arg3) \
ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, arg1, arg2, arg3, NULL)
diff --git a/Zend/zend_ini_parser.y b/Zend/zend_ini_parser.y
index eaf451a3a1..e343fcd92a 100644
--- a/Zend/zend_ini_parser.y
+++ b/Zend/zend_ini_parser.y
@@ -53,10 +53,10 @@ static void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
char str_result[MAX_LENGTH_OF_LONG];
i_op1 = atoi(Z_STRVAL_P(op1));
- STR_FREE(Z_STR_P(op1));
+ zend_string_free(Z_STR_P(op1));
if (op2) {
i_op2 = atoi(Z_STRVAL_P(op2));
- STR_FREE(Z_STR_P(op2));
+ zend_string_free(Z_STR_P(op2));
} else {
i_op2 = 0;
}
@@ -102,7 +102,7 @@ static void zend_ini_add_string(zval *result, zval *op1, zval *op2)
int op1_len = Z_STRLEN_P(op1);
int length = op1_len + Z_STRLEN_P(op2);
- ZVAL_NEW_STR(result, STR_REALLOC(Z_STR_P(op1), length, 1));
+ ZVAL_NEW_STR(result, zend_string_realloc(Z_STR_P(op1), length, 1));
memcpy(Z_STRVAL_P(result)+op1_len, Z_STRVAL_P(op2), Z_STRLEN_P(op2));
Z_STRVAL_P(result)[length] = 0;
}
@@ -130,7 +130,7 @@ static void zend_ini_get_constant(zval *result, zval *name TSRMLS_DC)
if (c == &tmp) {
zval_dtor(&tmp);
}
- STR_FREE(Z_STR_P(name));
+ zend_string_free(Z_STR_P(name));
} else {
*result = *name;
}
@@ -141,12 +141,12 @@ static void zend_ini_get_constant(zval *result, zval *name TSRMLS_DC)
*/
static void zend_ini_get_var(zval *result, zval *name TSRMLS_DC)
{
- zval curval;
+ zval *curval;
char *envvar;
/* Fetch configuration option value */
- if (zend_get_configuration_directive(Z_STRVAL_P(name), Z_STRLEN_P(name), &curval) == SUCCESS) {
- ZVAL_PSTRINGL(result, Z_STRVAL(curval), Z_STRLEN(curval));
+ if ((curval = zend_get_configuration_directive(Z_STR_P(name))) != NULL) {
+ ZVAL_PSTRINGL(result, Z_STRVAL_P(curval), Z_STRLEN_P(curval));
/* ..or if not found, try ENV */
} else if ((envvar = zend_getenv(Z_STRVAL_P(name), Z_STRLEN_P(name) TSRMLS_CC)) != NULL ||
(envvar = getenv(Z_STRVAL_P(name))) != NULL) {
@@ -264,6 +264,7 @@ ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, int s
%token TC_QUOTED_STRING
%token BOOL_TRUE
%token BOOL_FALSE
+%token NULL_NULL
%token END_OF_LINE
%token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@' '{' '}'
%left '|' '&' '^'
@@ -282,26 +283,26 @@ statement:
printf("SECTION: [%s]\n", Z_STRVAL($2));
#endif
ZEND_INI_PARSER_CB(&$2, NULL, NULL, ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG TSRMLS_CC);
- STR_RELEASE(Z_STR($2));
+ zend_string_release(Z_STR($2));
}
| TC_LABEL '=' string_or_value {
#if DEBUG_CFG_PARSER
printf("NORMAL: '%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3));
#endif
ZEND_INI_PARSER_CB(&$1, &$3, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
- STR_RELEASE(Z_STR($1));
- STR_RELEASE(Z_STR($3));
+ zend_string_release(Z_STR($1));
+ zval_ptr_dtor(&$3);
}
| TC_OFFSET option_offset ']' '=' string_or_value {
#if DEBUG_CFG_PARSER
printf("OFFSET: '%s'[%s] = '%s'\n", Z_STRVAL($1), Z_STRVAL($2), Z_STRVAL($5));
#endif
ZEND_INI_PARSER_CB(&$1, &$5, &$2, ZEND_INI_PARSER_POP_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
- STR_RELEASE(Z_STR($1));
- STR_RELEASE(Z_STR($2));
- STR_RELEASE(Z_STR($5));
+ zend_string_release(Z_STR($1));
+ zend_string_release(Z_STR($2));
+ zval_ptr_dtor(&$5);
}
- | TC_LABEL { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); STR_RELEASE(Z_STR($1)); }
+ | TC_LABEL { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); zend_string_release(Z_STR($1)); }
| END_OF_LINE
;
@@ -314,6 +315,7 @@ string_or_value:
expr { $$ = $1; }
| BOOL_TRUE { $$ = $1; }
| BOOL_FALSE { $$ = $1; }
+ | NULL_NULL { $$ = $1; }
| END_OF_LINE { zend_ini_init_string(&$$); }
;
@@ -323,8 +325,8 @@ option_offset:
;
encapsed_list:
- encapsed_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
- | encapsed_list TC_QUOTED_STRING { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
+ encapsed_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
+ | encapsed_list TC_QUOTED_STRING { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
| /* empty */ { zend_ini_init_string(&$$); }
;
@@ -332,18 +334,18 @@ var_string_list_section:
cfg_var_ref { $$ = $1; }
| constant_literal { $$ = $1; }
| '"' encapsed_list '"' { $$ = $2; }
- | var_string_list_section cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
- | var_string_list_section constant_literal { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
- | var_string_list_section '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); STR_FREE(Z_STR($3)); }
+ | var_string_list_section cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
+ | var_string_list_section constant_literal { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
+ | var_string_list_section '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); zend_string_free(Z_STR($3)); }
;
var_string_list:
cfg_var_ref { $$ = $1; }
| constant_string { $$ = $1; }
| '"' encapsed_list '"' { $$ = $2; }
- | var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
- | var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); STR_FREE(Z_STR($2)); }
- | var_string_list '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); STR_FREE(Z_STR($3)); }
+ | var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
+ | var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
+ | var_string_list '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); zend_string_free(Z_STR($3)); }
;
expr:
@@ -357,7 +359,7 @@ expr:
;
cfg_var_ref:
- TC_DOLLAR_CURLY TC_VARNAME '}' { zend_ini_get_var(&$$, &$2 TSRMLS_CC); STR_FREE(Z_STR($2)); }
+ TC_DOLLAR_CURLY TC_VARNAME '}' { zend_ini_get_var(&$$, &$2 TSRMLS_CC); zend_string_free(Z_STR($2)); }
;
constant_literal:
diff --git a/Zend/zend_ini_scanner.c b/Zend/zend_ini_scanner.c
index b71f1ccb3c..2abf1140fc 100644
--- a/Zend/zend_ini_scanner.c
+++ b/Zend/zend_ini_scanner.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include "zend.h"
+#include "zend_API.h"
#include "zend_globals.h"
#include <zend_ini_parser.h>
#include "zend_ini_scanner.h"
@@ -134,12 +135,58 @@ ZEND_API zend_ini_scanner_globals ini_scanner_globals;
#define EAT_TRAILING_WHITESPACE() EAT_TRAILING_WHITESPACE_EX('X')
#define zend_ini_copy_value(retval, str, len) \
- ZVAL_NEW_STR(retval, STR_INIT(str, len, 1))
+ ZVAL_NEW_STR(retval, zend_string_init(str, len, 1))
-#define RETURN_TOKEN(type, str, len) { \
- zend_ini_copy_value(ini_lval, str, len); \
- return type; \
+#define RETURN_TOKEN(type, str, len) { \
+ if (SCNG(scanner_mode) == ZEND_INI_SCANNER_TYPED) { \
+ zend_ini_copy_typed_value(ini_lval, type, str, len); \
+ } else { \
+ zend_ini_copy_value(ini_lval, str, len); \
+ } \
+ return type; \
+}
+
+static inline int convert_to_number(zval *retval, const char *str, const int str_len)
+{
+ zend_uchar type;
+ int overflow;
+ zend_long lval;
+ double dval;
+
+ if ((type = is_numeric_string_ex(str, str_len, &lval, &dval, 0, &overflow)) != 0) {
+ if (type == IS_LONG) {
+ ZVAL_LONG(retval, lval);
+ return SUCCESS;
+ } else if (type == IS_DOUBLE && !overflow) {
+ ZVAL_DOUBLE(retval, dval);
+ return SUCCESS;
+ }
+ }
+
+ return FAILURE;
+}
+
+static void zend_ini_copy_typed_value(zval *retval, const int type, const char *str, int len)
+{
+ switch (type) {
+ case BOOL_FALSE:
+ case BOOL_TRUE:
+ ZVAL_BOOL(retval, type == BOOL_TRUE);
+ break;
+
+ case NULL_NULL:
+ ZVAL_NULL(retval);
+ break;
+
+ case TC_NUMBER:
+ if (convert_to_number(retval, str, len) == SUCCESS) {
+ break;
+ }
+ /* intentional fall-through */
+ default:
+ zend_ini_copy_value(retval, str, len);
+ }
}
static void _yy_push_state(int new_state TSRMLS_DC)
@@ -171,7 +218,7 @@ static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC)
static int init_ini_scanner(int scanner_mode, zend_file_handle *fh TSRMLS_DC)
{
/* Sanity check */
- if (scanner_mode != ZEND_INI_SCANNER_NORMAL && scanner_mode != ZEND_INI_SCANNER_RAW) {
+ if (scanner_mode != ZEND_INI_SCANNER_NORMAL && scanner_mode != ZEND_INI_SCANNER_RAW && scanner_mode != ZEND_INI_SCANNER_TYPED) {
zend_error(E_WARNING, "Invalid scanner mode");
return FAILURE;
}
@@ -330,7 +377,7 @@ restart:
}
}
-#line 334 "Zend/zend_ini_scanner.c"
+#line 381 "Zend/zend_ini_scanner.c"
{
YYCTYPE yych;
unsigned int yyaccept = 0;
@@ -459,7 +506,7 @@ yy2:
yy3:
YYDEBUG(3, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 426 "Zend/zend_ini_scanner.l"
+#line 477 "Zend/zend_ini_scanner.l"
{ /* Get option name */
/* Eat leading whitespace */
EAT_LEADING_WHITESPACE();
@@ -469,37 +516,37 @@ yy3:
RETURN_TOKEN(TC_LABEL, yytext, yyleng);
}
-#line 473 "Zend/zend_ini_scanner.c"
+#line 520 "Zend/zend_ini_scanner.c"
yy4:
YYDEBUG(4, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy68;
+ goto yy73;
yy5:
YYDEBUG(5, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 572 "Zend/zend_ini_scanner.l"
+#line 623 "Zend/zend_ini_scanner.l"
{
/* eat whitespace */
goto restart;
}
-#line 487 "Zend/zend_ini_scanner.c"
+#line 534 "Zend/zend_ini_scanner.c"
yy6:
YYDEBUG(6, *YYCURSOR);
++YYCURSOR;
yy7:
YYDEBUG(7, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 577 "Zend/zend_ini_scanner.l"
+#line 628 "Zend/zend_ini_scanner.l"
{
SCNG(lineno)++;
return END_OF_LINE;
}
-#line 499 "Zend/zend_ini_scanner.c"
+#line 546 "Zend/zend_ini_scanner.c"
yy8:
YYDEBUG(8, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy71;
+ if (yych == '\n') goto yy76;
goto yy7;
yy9:
YYDEBUG(9, *YYCURSOR);
@@ -508,20 +555,20 @@ yy9:
if (yych <= ' ') {
if (yych <= '\n') {
if (yych <= 0x08) goto yy26;
- if (yych <= '\t') goto yy67;
- goto yy71;
+ if (yych <= '\t') goto yy72;
+ goto yy76;
} else {
- if (yych == '\r') goto yy72;
+ if (yych == '\r') goto yy77;
if (yych <= 0x1F) goto yy26;
- goto yy69;
+ goto yy74;
}
} else {
if (yych <= ':') {
- if (yych == '#') goto yy58;
+ if (yych == '#') goto yy63;
goto yy26;
} else {
- if (yych <= ';') goto yy53;
- if (yych == '=') goto yy51;
+ if (yych <= ';') goto yy58;
+ if (yych == '=') goto yy56;
goto yy26;
}
}
@@ -530,16 +577,16 @@ yy10:
++YYCURSOR;
YYDEBUG(11, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 500 "Zend/zend_ini_scanner.l"
+#line 551 "Zend/zend_ini_scanner.l"
{ /* Disallow these chars outside option values */
return yytext[0];
}
-#line 538 "Zend/zend_ini_scanner.c"
+#line 585 "Zend/zend_ini_scanner.c"
yy12:
YYDEBUG(12, *YYCURSOR);
yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy59;
+ goto yy64;
yy13:
YYDEBUG(13, *YYCURSOR);
yych = *++YYCURSOR;
@@ -548,23 +595,23 @@ yy14:
YYDEBUG(14, *YYCURSOR);
yyaccept = 2;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy54;
+ goto yy59;
YYDEBUG(15, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 600 "Zend/zend_ini_scanner.l"
+#line 651 "Zend/zend_ini_scanner.l"
{
return 0;
}
-#line 559 "Zend/zend_ini_scanner.c"
+#line 606 "Zend/zend_ini_scanner.c"
yy16:
YYDEBUG(16, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy52;
+ goto yy57;
yy17:
YYDEBUG(17, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 436 "Zend/zend_ini_scanner.l"
+#line 487 "Zend/zend_ini_scanner.l"
{ /* Start option value */
if (SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW) {
yy_push_state(ST_RAW TSRMLS_CC);
@@ -573,12 +620,12 @@ yy17:
}
return '=';
}
-#line 577 "Zend/zend_ini_scanner.c"
+#line 624 "Zend/zend_ini_scanner.c"
yy18:
YYDEBUG(18, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy48;
- if (yych == 'a') goto yy48;
+ if (yych == 'A') goto yy53;
+ if (yych == 'a') goto yy53;
goto yy26;
yy19:
YYDEBUG(19, *YYCURSOR);
@@ -629,7 +676,7 @@ yy23:
++YYCURSOR;
YYDEBUG(24, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 355 "Zend/zend_ini_scanner.l"
+#line 402 "Zend/zend_ini_scanner.l"
{ /* Section start */
/* Enter section data lookup state */
if (SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW) {
@@ -639,7 +686,7 @@ yy23:
}
return TC_SECTION;
}
-#line 643 "Zend/zend_ini_scanner.c"
+#line 690 "Zend/zend_ini_scanner.c"
yy25:
YYDEBUG(25, *YYCURSOR);
++YYCURSOR;
@@ -669,7 +716,7 @@ yy28:
}
YYDEBUG(30, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 380 "Zend/zend_ini_scanner.l"
+#line 427 "Zend/zend_ini_scanner.l"
{ /* Start of option with offset */
/* Eat leading whitespace */
EAT_LEADING_WHITESPACE();
@@ -682,7 +729,7 @@ yy28:
RETURN_TOKEN(TC_OFFSET, yytext, yyleng);
}
-#line 686 "Zend/zend_ini_scanner.c"
+#line 733 "Zend/zend_ini_scanner.c"
yy31:
YYDEBUG(31, *YYCURSOR);
++YYCURSOR;
@@ -728,11 +775,11 @@ yy31:
yy33:
YYDEBUG(33, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 418 "Zend/zend_ini_scanner.l"
+#line 465 "Zend/zend_ini_scanner.l"
{ /* TRUE value (when used outside option value/offset this causes parse error!) */
RETURN_TOKEN(BOOL_TRUE, "1", 1);
}
-#line 736 "Zend/zend_ini_scanner.c"
+#line 783 "Zend/zend_ini_scanner.c"
yy34:
YYDEBUG(34, *YYCURSOR);
++YYCURSOR;
@@ -802,11 +849,11 @@ yy39:
yy41:
YYDEBUG(41, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 422 "Zend/zend_ini_scanner.l"
+#line 469 "Zend/zend_ini_scanner.l"
{ /* FALSE value (when used outside option value/offset this causes parse error!)*/
RETURN_TOKEN(BOOL_FALSE, "", 0);
}
-#line 810 "Zend/zend_ini_scanner.c"
+#line 857 "Zend/zend_ini_scanner.c"
yy42:
YYDEBUG(42, *YYCURSOR);
++YYCURSOR;
@@ -849,14 +896,14 @@ yy44:
} else {
if (yych == '=') goto yy41;
if (yych <= 'M') goto yy26;
- goto yy47;
+ goto yy52;
}
} else {
if (yych <= 'm') {
if (yych == '^') goto yy41;
goto yy26;
} else {
- if (yych <= 'n') goto yy47;
+ if (yych <= 'n') goto yy52;
if (yych <= 'z') goto yy26;
if (yych <= '~') goto yy41;
goto yy26;
@@ -871,205 +918,262 @@ yy45:
yy46:
YYDEBUG(46, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy39;
- if (yych == 'l') goto yy39;
- goto yy26;
+ if (yych == 'L') goto yy47;
+ if (yych != 'l') goto yy26;
yy47:
YYDEBUG(47, *YYCURSOR);
+ ++YYCURSOR;
+ YYFILL(1);
+ yych = *YYCURSOR;
+ YYDEBUG(48, *YYCURSOR);
+ if (yych <= '&') {
+ if (yych <= 0x1F) {
+ if (yych <= '\n') {
+ if (yych <= 0x08) goto yy25;
+ if (yych <= '\t') goto yy50;
+ } else {
+ if (yych != '\r') goto yy25;
+ }
+ } else {
+ if (yych <= '#') {
+ if (yych <= ' ') goto yy47;
+ if (yych >= '#') goto yy25;
+ } else {
+ if (yych == '%') goto yy25;
+ }
+ }
+ } else {
+ if (yych <= '=') {
+ if (yych <= ':') {
+ if (yych <= '\'') goto yy25;
+ if (yych >= '*') goto yy25;
+ } else {
+ if (yych == '<') goto yy25;
+ }
+ } else {
+ if (yych <= ']') {
+ if (yych == '[') goto yy28;
+ goto yy25;
+ } else {
+ if (yych <= '^') goto yy49;
+ if (yych <= 'z') goto yy25;
+ if (yych >= 0x7F) goto yy25;
+ }
+ }
+ }
+yy49:
+ YYDEBUG(49, *YYCURSOR);
+ yyleng = YYCURSOR - SCNG(yy_text);
+#line 473 "Zend/zend_ini_scanner.l"
+ {
+ RETURN_TOKEN(NULL_NULL, "", 0);
+}
+#line 972 "Zend/zend_ini_scanner.c"
+yy50:
+ YYDEBUG(50, *YYCURSOR);
+ ++YYCURSOR;
+ YYFILL(1);
+ yych = *YYCURSOR;
+ YYDEBUG(51, *YYCURSOR);
+ if (yych == '\t') goto yy50;
+ if (yych == ' ') goto yy50;
+ goto yy49;
+yy52:
+ YYDEBUG(52, *YYCURSOR);
yych = *++YYCURSOR;
if (yych == 'E') goto yy39;
if (yych == 'e') goto yy39;
goto yy26;
-yy48:
- YYDEBUG(48, *YYCURSOR);
+yy53:
+ YYDEBUG(53, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy49;
+ if (yych == 'L') goto yy54;
if (yych != 'l') goto yy26;
-yy49:
- YYDEBUG(49, *YYCURSOR);
+yy54:
+ YYDEBUG(54, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy50;
+ if (yych == 'S') goto yy55;
if (yych != 's') goto yy26;
-yy50:
- YYDEBUG(50, *YYCURSOR);
+yy55:
+ YYDEBUG(55, *YYCURSOR);
yych = *++YYCURSOR;
if (yych == 'E') goto yy39;
if (yych == 'e') goto yy39;
goto yy26;
-yy51:
- YYDEBUG(51, *YYCURSOR);
+yy56:
+ YYDEBUG(56, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy52:
- YYDEBUG(52, *YYCURSOR);
- if (yych == '\t') goto yy51;
- if (yych == ' ') goto yy51;
+yy57:
+ YYDEBUG(57, *YYCURSOR);
+ if (yych == '\t') goto yy56;
+ if (yych == ' ') goto yy56;
goto yy17;
-yy53:
- YYDEBUG(53, *YYCURSOR);
+yy58:
+ YYDEBUG(58, *YYCURSOR);
++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
-yy54:
- YYDEBUG(54, *YYCURSOR);
+yy59:
+ YYDEBUG(59, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy53;
+ goto yy58;
}
- if (yych >= '\r') goto yy57;
-yy55:
- YYDEBUG(55, *YYCURSOR);
+ if (yych >= '\r') goto yy62;
+yy60:
+ YYDEBUG(60, *YYCURSOR);
++YYCURSOR;
-yy56:
- YYDEBUG(56, *YYCURSOR);
+yy61:
+ YYDEBUG(61, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 582 "Zend/zend_ini_scanner.l"
+#line 633 "Zend/zend_ini_scanner.l"
{ /* Comment */
BEGIN(INITIAL);
SCNG(lineno)++;
return END_OF_LINE;
}
-#line 933 "Zend/zend_ini_scanner.c"
-yy57:
- YYDEBUG(57, *YYCURSOR);
+#line 1037 "Zend/zend_ini_scanner.c"
+yy62:
+ YYDEBUG(62, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy55;
- goto yy56;
-yy58:
- YYDEBUG(58, *YYCURSOR);
+ if (yych == '\n') goto yy60;
+ goto yy61;
+yy63:
+ YYDEBUG(63, *YYCURSOR);
yyaccept = 1;
YYMARKER = ++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
-yy59:
- YYDEBUG(59, *YYCURSOR);
+yy64:
+ YYDEBUG(64, *YYCURSOR);
if (yych <= '\'') {
if (yych <= ' ') {
if (yych <= '\n') {
- if (yych <= 0x08) goto yy58;
- if (yych >= '\n') goto yy64;
+ if (yych <= 0x08) goto yy63;
+ if (yych >= '\n') goto yy69;
} else {
- if (yych == '\r') goto yy66;
- goto yy58;
+ if (yych == '\r') goto yy71;
+ goto yy63;
}
} else {
if (yych <= '$') {
- if (yych == '#') goto yy58;
+ if (yych == '#') goto yy63;
} else {
- if (yych != '&') goto yy58;
+ if (yych != '&') goto yy63;
}
}
} else {
if (yych <= 'Z') {
if (yych <= ';') {
- if (yych <= ')') goto yy60;
- if (yych <= ':') goto yy58;
+ if (yych <= ')') goto yy65;
+ if (yych <= ':') goto yy63;
} else {
- if (yych != '=') goto yy58;
+ if (yych != '=') goto yy63;
}
} else {
if (yych <= '^') {
- if (yych <= '[') goto yy62;
- if (yych <= ']') goto yy58;
+ if (yych <= '[') goto yy67;
+ if (yych <= ']') goto yy63;
} else {
- if (yych <= 'z') goto yy58;
- if (yych >= 0x7F) goto yy58;
+ if (yych <= 'z') goto yy63;
+ if (yych >= 0x7F) goto yy63;
}
}
}
-yy60:
- YYDEBUG(60, *YYCURSOR);
+yy65:
+ YYDEBUG(65, *YYCURSOR);
++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
- YYDEBUG(61, *YYCURSOR);
- if (yych == '\n') goto yy64;
- if (yych == '\r') goto yy66;
- goto yy60;
-yy62:
- YYDEBUG(62, *YYCURSOR);
+ YYDEBUG(66, *YYCURSOR);
+ if (yych == '\n') goto yy69;
+ if (yych == '\r') goto yy71;
+ goto yy65;
+yy67:
+ YYDEBUG(67, *YYCURSOR);
yyaccept = 3;
YYMARKER = ++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
- YYDEBUG(63, *YYCURSOR);
+ YYDEBUG(68, *YYCURSOR);
if (yych <= '\f') {
- if (yych <= 0x08) goto yy60;
- if (yych <= '\t') goto yy62;
- if (yych >= '\v') goto yy60;
+ if (yych <= 0x08) goto yy65;
+ if (yych <= '\t') goto yy67;
+ if (yych >= '\v') goto yy65;
} else {
- if (yych <= '\r') goto yy66;
- if (yych == ' ') goto yy62;
- goto yy60;
+ if (yych <= '\r') goto yy71;
+ if (yych == ' ') goto yy67;
+ goto yy65;
}
-yy64:
- YYDEBUG(64, *YYCURSOR);
+yy69:
+ YYDEBUG(69, *YYCURSOR);
++YYCURSOR;
-yy65:
- YYDEBUG(65, *YYCURSOR);
+yy70:
+ YYDEBUG(70, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 588 "Zend/zend_ini_scanner.l"
+#line 639 "Zend/zend_ini_scanner.l"
{ /* #Comment */
zend_error(E_DEPRECATED, "Comments starting with '#' are deprecated in %s on line %d", zend_ini_scanner_get_filename(TSRMLS_C), SCNG(lineno));
BEGIN(INITIAL);
SCNG(lineno)++;
return END_OF_LINE;
}
-#line 1019 "Zend/zend_ini_scanner.c"
-yy66:
- YYDEBUG(66, *YYCURSOR);
+#line 1123 "Zend/zend_ini_scanner.c"
+yy71:
+ YYDEBUG(71, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy64;
- goto yy65;
-yy67:
- YYDEBUG(67, *YYCURSOR);
+ if (yych == '\n') goto yy69;
+ goto yy70;
+yy72:
+ YYDEBUG(72, *YYCURSOR);
yyaccept = 0;
YYMARKER = ++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
-yy68:
- YYDEBUG(68, *YYCURSOR);
+yy73:
+ YYDEBUG(73, *YYCURSOR);
if (yych <= ' ') {
if (yych <= '\n') {
if (yych <= 0x08) goto yy5;
- if (yych <= '\t') goto yy67;
- goto yy71;
+ if (yych <= '\t') goto yy72;
+ goto yy76;
} else {
- if (yych == '\r') goto yy72;
+ if (yych == '\r') goto yy77;
if (yych <= 0x1F) goto yy5;
- goto yy67;
+ goto yy72;
}
} else {
if (yych <= ':') {
- if (yych == '#') goto yy60;
+ if (yych == '#') goto yy65;
goto yy5;
} else {
- if (yych <= ';') goto yy53;
- if (yych == '=') goto yy51;
+ if (yych <= ';') goto yy58;
+ if (yych == '=') goto yy56;
goto yy5;
}
}
-yy69:
- YYDEBUG(69, *YYCURSOR);
+yy74:
+ YYDEBUG(74, *YYCURSOR);
yyaccept = 1;
YYMARKER = ++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
- YYDEBUG(70, *YYCURSOR);
+ YYDEBUG(75, *YYCURSOR);
if (yych <= '&') {
if (yych <= 0x1F) {
if (yych <= '\n') {
if (yych <= 0x08) goto yy25;
- if (yych <= '\t') goto yy67;
+ if (yych <= '\t') goto yy72;
} else {
- if (yych == '\r') goto yy72;
+ if (yych == '\r') goto yy77;
goto yy25;
}
} else {
if (yych <= '#') {
- if (yych <= ' ') goto yy69;
+ if (yych <= ' ') goto yy74;
if (yych <= '"') goto yy3;
- goto yy58;
+ goto yy63;
} else {
if (yych == '%') goto yy25;
goto yy3;
@@ -1082,9 +1186,9 @@ yy69:
if (yych <= ')') goto yy3;
goto yy25;
} else {
- if (yych <= ';') goto yy53;
+ if (yych <= ';') goto yy58;
if (yych <= '<') goto yy25;
- goto yy51;
+ goto yy56;
}
} else {
if (yych <= ']') {
@@ -1098,14 +1202,14 @@ yy69:
}
}
}
-yy71:
- YYDEBUG(71, *YYCURSOR);
+yy76:
+ YYDEBUG(76, *YYCURSOR);
yych = *++YYCURSOR;
goto yy7;
-yy72:
- YYDEBUG(72, *YYCURSOR);
+yy77:
+ YYDEBUG(77, *YYCURSOR);
++YYCURSOR;
- if ((yych = *YYCURSOR) == '\n') goto yy71;
+ if ((yych = *YYCURSOR) == '\n') goto yy76;
goto yy7;
}
/* *********************************** */
@@ -1145,17 +1249,17 @@ yyc_ST_DOUBLE_QUOTES:
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
- YYDEBUG(73, *YYCURSOR);
+ YYDEBUG(78, *YYCURSOR);
YYFILL(2);
yych = *YYCURSOR;
- if (yych == '"') goto yy77;
- if (yych == '$') goto yy79;
- YYDEBUG(75, *YYCURSOR);
+ if (yych == '"') goto yy82;
+ if (yych == '$') goto yy84;
+ YYDEBUG(80, *YYCURSOR);
++YYCURSOR;
-yy76:
- YYDEBUG(76, *YYCURSOR);
+yy81:
+ YYDEBUG(81, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 532 "Zend/zend_ini_scanner.l"
+#line 583 "Zend/zend_ini_scanner.l"
{ /* Escape double quoted string contents */
if (YYCURSOR > YYLIMIT) {
return 0;
@@ -1191,46 +1295,46 @@ yy76:
zend_ini_escape_string(ini_lval, yytext, yyleng, '"' TSRMLS_CC);
return TC_QUOTED_STRING;
}
-#line 1195 "Zend/zend_ini_scanner.c"
-yy77:
- YYDEBUG(77, *YYCURSOR);
+#line 1299 "Zend/zend_ini_scanner.c"
+yy82:
+ YYDEBUG(82, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy83;
-yy78:
- YYDEBUG(78, *YYCURSOR);
+ goto yy88;
+yy83:
+ YYDEBUG(83, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 527 "Zend/zend_ini_scanner.l"
+#line 578 "Zend/zend_ini_scanner.l"
{ /* Double quoted '"' string ends */
yy_pop_state(TSRMLS_C);
return '"';
}
-#line 1209 "Zend/zend_ini_scanner.c"
-yy79:
- YYDEBUG(79, *YYCURSOR);
+#line 1313 "Zend/zend_ini_scanner.c"
+yy84:
+ YYDEBUG(84, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych != '{') goto yy76;
- YYDEBUG(80, *YYCURSOR);
+ if (yych != '{') goto yy81;
+ YYDEBUG(85, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(81, *YYCURSOR);
+ YYDEBUG(86, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 398 "Zend/zend_ini_scanner.l"
+#line 445 "Zend/zend_ini_scanner.l"
{ /* Variable start */
yy_push_state(ST_VARNAME TSRMLS_CC);
return TC_DOLLAR_CURLY;
}
-#line 1223 "Zend/zend_ini_scanner.c"
-yy82:
- YYDEBUG(82, *YYCURSOR);
+#line 1327 "Zend/zend_ini_scanner.c"
+yy87:
+ YYDEBUG(87, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy83:
- YYDEBUG(83, *YYCURSOR);
+yy88:
+ YYDEBUG(88, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy82;
+ goto yy87;
}
- goto yy78;
+ goto yy83;
}
/* *********************************** */
yyc_ST_OFFSET:
@@ -1269,496 +1373,496 @@ yyc_ST_OFFSET:
66, 66, 66, 66, 66, 66, 66, 66,
66, 66, 66, 66, 66, 66, 66, 66,
};
- YYDEBUG(84, *YYCURSOR);
+ YYDEBUG(89, *YYCURSOR);
YYFILL(2);
yych = *YYCURSOR;
if (yych <= '-') {
if (yych <= ' ') {
if (yych <= '\n') {
- if (yych <= 0x08) goto yy86;
- if (yych <= '\t') goto yy88;
- goto yy89;
+ if (yych <= 0x08) goto yy91;
+ if (yych <= '\t') goto yy93;
+ goto yy94;
} else {
- if (yych == '\r') goto yy89;
- if (yych >= ' ') goto yy88;
+ if (yych == '\r') goto yy94;
+ if (yych >= ' ') goto yy93;
}
} else {
if (yych <= '$') {
- if (yych == '"') goto yy91;
- if (yych >= '$') goto yy93;
+ if (yych == '"') goto yy96;
+ if (yych >= '$') goto yy98;
} else {
- if (yych == '\'') goto yy94;
- if (yych >= '-') goto yy95;
+ if (yych == '\'') goto yy99;
+ if (yych >= '-') goto yy100;
}
}
} else {
if (yych <= 'Z') {
if (yych <= '9') {
- if (yych <= '.') goto yy96;
- if (yych >= '0') goto yy97;
+ if (yych <= '.') goto yy101;
+ if (yych >= '0') goto yy102;
} else {
- if (yych == ';') goto yy89;
- if (yych >= 'A') goto yy99;
+ if (yych == ';') goto yy94;
+ if (yych >= 'A') goto yy104;
}
} else {
if (yych <= '^') {
- if (yych <= '[') goto yy86;
- if (yych <= '\\') goto yy101;
- if (yych <= ']') goto yy102;
+ if (yych <= '[') goto yy91;
+ if (yych <= '\\') goto yy106;
+ if (yych <= ']') goto yy107;
} else {
- if (yych == '`') goto yy86;
- if (yych <= 'z') goto yy99;
+ if (yych == '`') goto yy91;
+ if (yych <= 'z') goto yy104;
}
}
}
-yy86:
- YYDEBUG(86, *YYCURSOR);
+yy91:
+ YYDEBUG(91, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy105;
-yy87:
- YYDEBUG(87, *YYCURSOR);
+ goto yy110;
+yy92:
+ YYDEBUG(92, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 518 "Zend/zend_ini_scanner.l"
+#line 569 "Zend/zend_ini_scanner.l"
{ /* Get rest as section/offset value */
RETURN_TOKEN(TC_STRING, yytext, yyleng);
}
-#line 1327 "Zend/zend_ini_scanner.c"
-yy88:
- YYDEBUG(88, *YYCURSOR);
+#line 1431 "Zend/zend_ini_scanner.c"
+yy93:
+ YYDEBUG(93, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy131;
+ goto yy136;
}
- if (yych == '"') goto yy133;
- if (yych == ']') goto yy134;
- goto yy105;
-yy89:
- YYDEBUG(89, *YYCURSOR);
+ if (yych == '"') goto yy138;
+ if (yych == ']') goto yy139;
+ goto yy110;
+yy94:
+ YYDEBUG(94, *YYCURSOR);
++YYCURSOR;
-yy90:
- YYDEBUG(90, *YYCURSOR);
+yy95:
+ YYDEBUG(95, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 600 "Zend/zend_ini_scanner.l"
+#line 651 "Zend/zend_ini_scanner.l"
{
return 0;
}
-#line 1348 "Zend/zend_ini_scanner.c"
-yy91:
- YYDEBUG(91, *YYCURSOR);
+#line 1452 "Zend/zend_ini_scanner.c"
+yy96:
+ YYDEBUG(96, *YYCURSOR);
++YYCURSOR;
-yy92:
- YYDEBUG(92, *YYCURSOR);
+yy97:
+ YYDEBUG(97, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 522 "Zend/zend_ini_scanner.l"
+#line 573 "Zend/zend_ini_scanner.l"
{ /* Double quoted '"' string start */
yy_push_state(ST_DOUBLE_QUOTES TSRMLS_CC);
return '"';
}
-#line 1360 "Zend/zend_ini_scanner.c"
-yy93:
- YYDEBUG(93, *YYCURSOR);
+#line 1464 "Zend/zend_ini_scanner.c"
+yy98:
+ YYDEBUG(98, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= '\\') {
- if (yych <= 0x00) goto yy90;
- if (yych <= '[') goto yy104;
- goto yy109;
+ if (yych <= 0x00) goto yy95;
+ if (yych <= '[') goto yy109;
+ goto yy114;
} else {
- if (yych == '{') goto yy129;
- goto yy104;
+ if (yych == '{') goto yy134;
+ goto yy109;
}
-yy94:
- YYDEBUG(94, *YYCURSOR);
+yy99:
+ YYDEBUG(99, *YYCURSOR);
yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 64) {
- goto yy125;
+ goto yy130;
}
- goto yy90;
-yy95:
- YYDEBUG(95, *YYCURSOR);
+ goto yy95;
+yy100:
+ YYDEBUG(100, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych <= '/') goto yy105;
- if (yych <= '9') goto yy123;
- goto yy105;
-yy96:
- YYDEBUG(96, *YYCURSOR);
+ if (yych <= '/') goto yy110;
+ if (yych <= '9') goto yy128;
+ goto yy110;
+yy101:
+ YYDEBUG(101, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych <= '/') goto yy105;
- if (yych <= '9') goto yy121;
- goto yy105;
-yy97:
- YYDEBUG(97, *YYCURSOR);
+ if (yych <= '/') goto yy110;
+ if (yych <= '9') goto yy126;
+ goto yy110;
+yy102:
+ YYDEBUG(102, *YYCURSOR);
yyaccept = 2;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '\'') {
if (yych <= '\r') {
- if (yych == '\n') goto yy98;
- if (yych <= '\f') goto yy105;
+ if (yych == '\n') goto yy103;
+ if (yych <= '\f') goto yy110;
} else {
- if (yych == '"') goto yy98;
- if (yych <= '&') goto yy105;
+ if (yych == '"') goto yy103;
+ if (yych <= '&') goto yy110;
}
} else {
if (yych <= '9') {
- if (yych == '.') goto yy117;
- if (yych <= '/') goto yy105;
- goto yy119;
+ if (yych == '.') goto yy122;
+ if (yych <= '/') goto yy110;
+ goto yy124;
} else {
if (yych <= ';') {
- if (yych <= ':') goto yy105;
+ if (yych <= ':') goto yy110;
} else {
- if (yych != ']') goto yy105;
+ if (yych != ']') goto yy110;
}
}
}
-yy98:
- YYDEBUG(98, *YYCURSOR);
+yy103:
+ YYDEBUG(103, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 496 "Zend/zend_ini_scanner.l"
+#line 547 "Zend/zend_ini_scanner.l"
{ /* Get number option value as string */
RETURN_TOKEN(TC_NUMBER, yytext, yyleng);
}
-#line 1426 "Zend/zend_ini_scanner.c"
-yy99:
- YYDEBUG(99, *YYCURSOR);
+#line 1530 "Zend/zend_ini_scanner.c"
+yy104:
+ YYDEBUG(104, *YYCURSOR);
yyaccept = 3;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 16) {
- goto yy115;
+ goto yy120;
}
if (yych <= '"') {
if (yych <= '\f') {
- if (yych != '\n') goto yy105;
+ if (yych != '\n') goto yy110;
} else {
- if (yych <= '\r') goto yy100;
- if (yych <= '!') goto yy105;
+ if (yych <= '\r') goto yy105;
+ if (yych <= '!') goto yy110;
}
} else {
if (yych <= ':') {
- if (yych != '\'') goto yy105;
+ if (yych != '\'') goto yy110;
} else {
- if (yych <= ';') goto yy100;
- if (yych != ']') goto yy105;
+ if (yych <= ';') goto yy105;
+ if (yych != ']') goto yy110;
}
}
-yy100:
- YYDEBUG(100, *YYCURSOR);
+yy105:
+ YYDEBUG(105, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 492 "Zend/zend_ini_scanner.l"
+#line 543 "Zend/zend_ini_scanner.l"
{ /* Get constant option value */
RETURN_TOKEN(TC_CONSTANT, yytext, yyleng);
}
-#line 1456 "Zend/zend_ini_scanner.c"
-yy101:
- YYDEBUG(101, *YYCURSOR);
+#line 1560 "Zend/zend_ini_scanner.c"
+yy106:
+ YYDEBUG(106, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy104;
-yy102:
- YYDEBUG(102, *YYCURSOR);
+ goto yy109;
+yy107:
+ YYDEBUG(107, *YYCURSOR);
++YYCURSOR;
-yy103:
- YYDEBUG(103, *YYCURSOR);
+yy108:
+ YYDEBUG(108, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 393 "Zend/zend_ini_scanner.l"
+#line 440 "Zend/zend_ini_scanner.l"
{ /* End of section or an option offset */
BEGIN(INITIAL);
return ']';
}
-#line 1472 "Zend/zend_ini_scanner.c"
-yy104:
- YYDEBUG(104, *YYCURSOR);
+#line 1576 "Zend/zend_ini_scanner.c"
+yy109:
+ YYDEBUG(109, *YYCURSOR);
yyaccept = 0;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy105:
- YYDEBUG(105, *YYCURSOR);
+yy110:
+ YYDEBUG(110, *YYCURSOR);
if (yybm[0+yych] & 2) {
- goto yy104;
+ goto yy109;
}
- if (yych == '$') goto yy107;
- if (yych != '\\') goto yy87;
-yy106:
- YYDEBUG(106, *YYCURSOR);
+ if (yych == '$') goto yy112;
+ if (yych != '\\') goto yy92;
+yy111:
+ YYDEBUG(111, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- goto yy104;
-yy107:
- YYDEBUG(107, *YYCURSOR);
+ goto yy109;
+yy112:
+ YYDEBUG(112, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
if (yych <= '\\') {
- if (yych <= 0x00) goto yy108;
- if (yych <= '[') goto yy104;
- goto yy109;
+ if (yych <= 0x00) goto yy113;
+ if (yych <= '[') goto yy109;
+ goto yy114;
} else {
- if (yych != '{') goto yy104;
+ if (yych != '{') goto yy109;
}
-yy108:
- YYDEBUG(108, *YYCURSOR);
+yy113:
+ YYDEBUG(113, *YYCURSOR);
YYCURSOR = YYMARKER;
if (yyaccept <= 1) {
if (yyaccept <= 0) {
- goto yy87;
+ goto yy92;
} else {
- goto yy90;
+ goto yy95;
}
} else {
if (yyaccept <= 2) {
- goto yy98;
+ goto yy103;
} else {
- goto yy100;
+ goto yy105;
}
}
-yy109:
- YYDEBUG(109, *YYCURSOR);
+yy114:
+ YYDEBUG(114, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
if (yybm[0+yych] & 4) {
- goto yy110;
+ goto yy115;
}
- if (yych == '\\') goto yy112;
- goto yy104;
-yy110:
- YYDEBUG(110, *YYCURSOR);
+ if (yych == '\\') goto yy117;
+ goto yy109;
+yy115:
+ YYDEBUG(115, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(111, *YYCURSOR);
+ YYDEBUG(116, *YYCURSOR);
if (yybm[0+yych] & 4) {
- goto yy110;
+ goto yy115;
}
- if (yych == '\\') goto yy114;
- goto yy104;
-yy112:
- YYDEBUG(112, *YYCURSOR);
+ if (yych == '\\') goto yy119;
+ goto yy109;
+yy117:
+ YYDEBUG(117, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(113, *YYCURSOR);
+ YYDEBUG(118, *YYCURSOR);
if (yybm[0+yych] & 4) {
- goto yy110;
+ goto yy115;
}
- if (yych == '\\') goto yy112;
- goto yy104;
-yy114:
- YYDEBUG(114, *YYCURSOR);
+ if (yych == '\\') goto yy117;
+ goto yy109;
+yy119:
+ YYDEBUG(119, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
if (yybm[0+yych] & 4) {
- goto yy110;
+ goto yy115;
}
- if (yych == '\\') goto yy112;
- goto yy104;
-yy115:
- YYDEBUG(115, *YYCURSOR);
+ if (yych == '\\') goto yy117;
+ goto yy109;
+yy120:
+ YYDEBUG(120, *YYCURSOR);
yyaccept = 3;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(116, *YYCURSOR);
+ YYDEBUG(121, *YYCURSOR);
if (yybm[0+yych] & 16) {
- goto yy115;
+ goto yy120;
}
if (yych <= '$') {
if (yych <= '\r') {
- if (yych == '\n') goto yy100;
- if (yych <= '\f') goto yy104;
- goto yy100;
+ if (yych == '\n') goto yy105;
+ if (yych <= '\f') goto yy109;
+ goto yy105;
} else {
- if (yych == '"') goto yy100;
- if (yych <= '#') goto yy104;
- goto yy107;
+ if (yych == '"') goto yy105;
+ if (yych <= '#') goto yy109;
+ goto yy112;
}
} else {
if (yych <= ';') {
- if (yych == '\'') goto yy100;
- if (yych <= ':') goto yy104;
- goto yy100;
+ if (yych == '\'') goto yy105;
+ if (yych <= ':') goto yy109;
+ goto yy105;
} else {
- if (yych <= '[') goto yy104;
- if (yych <= '\\') goto yy106;
- if (yych <= ']') goto yy100;
- goto yy104;
+ if (yych <= '[') goto yy109;
+ if (yych <= '\\') goto yy111;
+ if (yych <= ']') goto yy105;
+ goto yy109;
}
}
-yy117:
- YYDEBUG(117, *YYCURSOR);
+yy122:
+ YYDEBUG(122, *YYCURSOR);
yyaccept = 2;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(118, *YYCURSOR);
+ YYDEBUG(123, *YYCURSOR);
if (yybm[0+yych] & 32) {
- goto yy117;
+ goto yy122;
}
if (yych <= '$') {
if (yych <= '\r') {
- if (yych == '\n') goto yy98;
- if (yych <= '\f') goto yy104;
- goto yy98;
+ if (yych == '\n') goto yy103;
+ if (yych <= '\f') goto yy109;
+ goto yy103;
} else {
- if (yych == '"') goto yy98;
- if (yych <= '#') goto yy104;
- goto yy107;
+ if (yych == '"') goto yy103;
+ if (yych <= '#') goto yy109;
+ goto yy112;
}
} else {
if (yych <= ';') {
- if (yych == '\'') goto yy98;
- if (yych <= ':') goto yy104;
- goto yy98;
+ if (yych == '\'') goto yy103;
+ if (yych <= ':') goto yy109;
+ goto yy103;
} else {
- if (yych <= '[') goto yy104;
- if (yych <= '\\') goto yy106;
- if (yych <= ']') goto yy98;
- goto yy104;
+ if (yych <= '[') goto yy109;
+ if (yych <= '\\') goto yy111;
+ if (yych <= ']') goto yy103;
+ goto yy109;
}
}
-yy119:
- YYDEBUG(119, *YYCURSOR);
+yy124:
+ YYDEBUG(124, *YYCURSOR);
yyaccept = 2;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(120, *YYCURSOR);
+ YYDEBUG(125, *YYCURSOR);
if (yych <= '\'') {
if (yych <= '!') {
if (yych <= '\n') {
- if (yych <= '\t') goto yy104;
- goto yy98;
+ if (yych <= '\t') goto yy109;
+ goto yy103;
} else {
- if (yych == '\r') goto yy98;
- goto yy104;
+ if (yych == '\r') goto yy103;
+ goto yy109;
}
} else {
if (yych <= '#') {
- if (yych <= '"') goto yy98;
- goto yy104;
+ if (yych <= '"') goto yy103;
+ goto yy109;
} else {
- if (yych <= '$') goto yy107;
- if (yych <= '&') goto yy104;
- goto yy98;
+ if (yych <= '$') goto yy112;
+ if (yych <= '&') goto yy109;
+ goto yy103;
}
}
} else {
if (yych <= ':') {
if (yych <= '.') {
- if (yych <= '-') goto yy104;
- goto yy117;
+ if (yych <= '-') goto yy109;
+ goto yy122;
} else {
- if (yych <= '/') goto yy104;
- if (yych <= '9') goto yy119;
- goto yy104;
+ if (yych <= '/') goto yy109;
+ if (yych <= '9') goto yy124;
+ goto yy109;
}
} else {
if (yych <= '[') {
- if (yych <= ';') goto yy98;
- goto yy104;
+ if (yych <= ';') goto yy103;
+ goto yy109;
} else {
- if (yych <= '\\') goto yy106;
- if (yych <= ']') goto yy98;
- goto yy104;
+ if (yych <= '\\') goto yy111;
+ if (yych <= ']') goto yy103;
+ goto yy109;
}
}
}
-yy121:
- YYDEBUG(121, *YYCURSOR);
+yy126:
+ YYDEBUG(126, *YYCURSOR);
yyaccept = 2;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(122, *YYCURSOR);
+ YYDEBUG(127, *YYCURSOR);
if (yych <= '&') {
if (yych <= '\r') {
- if (yych == '\n') goto yy98;
- if (yych <= '\f') goto yy104;
- goto yy98;
+ if (yych == '\n') goto yy103;
+ if (yych <= '\f') goto yy109;
+ goto yy103;
} else {
if (yych <= '"') {
- if (yych <= '!') goto yy104;
- goto yy98;
+ if (yych <= '!') goto yy109;
+ goto yy103;
} else {
- if (yych == '$') goto yy107;
- goto yy104;
+ if (yych == '$') goto yy112;
+ goto yy109;
}
}
} else {
if (yych <= ':') {
- if (yych <= '\'') goto yy98;
- if (yych <= '/') goto yy104;
- if (yych <= '9') goto yy121;
- goto yy104;
+ if (yych <= '\'') goto yy103;
+ if (yych <= '/') goto yy109;
+ if (yych <= '9') goto yy126;
+ goto yy109;
} else {
if (yych <= '[') {
- if (yych <= ';') goto yy98;
- goto yy104;
+ if (yych <= ';') goto yy103;
+ goto yy109;
} else {
- if (yych <= '\\') goto yy106;
- if (yych <= ']') goto yy98;
- goto yy104;
+ if (yych <= '\\') goto yy111;
+ if (yych <= ']') goto yy103;
+ goto yy109;
}
}
}
-yy123:
- YYDEBUG(123, *YYCURSOR);
+yy128:
+ YYDEBUG(128, *YYCURSOR);
yyaccept = 2;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(124, *YYCURSOR);
+ YYDEBUG(129, *YYCURSOR);
if (yych <= '&') {
if (yych <= '\r') {
- if (yych == '\n') goto yy98;
- if (yych <= '\f') goto yy104;
- goto yy98;
+ if (yych == '\n') goto yy103;
+ if (yych <= '\f') goto yy109;
+ goto yy103;
} else {
if (yych <= '"') {
- if (yych <= '!') goto yy104;
- goto yy98;
+ if (yych <= '!') goto yy109;
+ goto yy103;
} else {
- if (yych == '$') goto yy107;
- goto yy104;
+ if (yych == '$') goto yy112;
+ goto yy109;
}
}
} else {
if (yych <= ':') {
- if (yych <= '\'') goto yy98;
- if (yych <= '/') goto yy104;
- if (yych <= '9') goto yy123;
- goto yy104;
+ if (yych <= '\'') goto yy103;
+ if (yych <= '/') goto yy109;
+ if (yych <= '9') goto yy128;
+ goto yy109;
} else {
if (yych <= '[') {
- if (yych <= ';') goto yy98;
- goto yy104;
+ if (yych <= ';') goto yy103;
+ goto yy109;
} else {
- if (yych <= '\\') goto yy106;
- if (yych <= ']') goto yy98;
- goto yy104;
+ if (yych <= '\\') goto yy111;
+ if (yych <= ']') goto yy103;
+ goto yy109;
}
}
}
-yy125:
- YYDEBUG(125, *YYCURSOR);
+yy130:
+ YYDEBUG(130, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(126, *YYCURSOR);
+ YYDEBUG(131, *YYCURSOR);
if (yybm[0+yych] & 64) {
- goto yy125;
+ goto yy130;
}
- YYDEBUG(127, *YYCURSOR);
+ YYDEBUG(132, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(128, *YYCURSOR);
+ YYDEBUG(133, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 365 "Zend/zend_ini_scanner.l"
+#line 412 "Zend/zend_ini_scanner.l"
{ /* Raw string */
/* Eat leading and trailing single quotes */
if (yytext[0] == '\'' && yytext[yyleng - 1] == '\'') {
@@ -1767,59 +1871,59 @@ yy125:
}
RETURN_TOKEN(TC_RAW, yytext, yyleng);
}
-#line 1771 "Zend/zend_ini_scanner.c"
-yy129:
- YYDEBUG(129, *YYCURSOR);
+#line 1875 "Zend/zend_ini_scanner.c"
+yy134:
+ YYDEBUG(134, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(130, *YYCURSOR);
+ YYDEBUG(135, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 398 "Zend/zend_ini_scanner.l"
+#line 445 "Zend/zend_ini_scanner.l"
{ /* Variable start */
yy_push_state(ST_VARNAME TSRMLS_CC);
return TC_DOLLAR_CURLY;
}
-#line 1782 "Zend/zend_ini_scanner.c"
-yy131:
- YYDEBUG(131, *YYCURSOR);
+#line 1886 "Zend/zend_ini_scanner.c"
+yy136:
+ YYDEBUG(136, *YYCURSOR);
yyaccept = 0;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(132, *YYCURSOR);
+ YYDEBUG(137, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy131;
+ goto yy136;
}
if (yych <= '$') {
if (yych <= '\r') {
- if (yych == '\n') goto yy87;
- if (yych <= '\f') goto yy104;
- goto yy87;
+ if (yych == '\n') goto yy92;
+ if (yych <= '\f') goto yy109;
+ goto yy92;
} else {
- if (yych == '"') goto yy133;
- if (yych <= '#') goto yy104;
- goto yy107;
+ if (yych == '"') goto yy138;
+ if (yych <= '#') goto yy109;
+ goto yy112;
}
} else {
if (yych <= ';') {
- if (yych == '\'') goto yy87;
- if (yych <= ':') goto yy104;
- goto yy87;
+ if (yych == '\'') goto yy92;
+ if (yych <= ':') goto yy109;
+ goto yy92;
} else {
- if (yych <= '[') goto yy104;
- if (yych <= '\\') goto yy106;
- if (yych <= ']') goto yy134;
- goto yy104;
+ if (yych <= '[') goto yy109;
+ if (yych <= '\\') goto yy111;
+ if (yych <= ']') goto yy139;
+ goto yy109;
}
}
-yy133:
- YYDEBUG(133, *YYCURSOR);
+yy138:
+ YYDEBUG(138, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy92;
-yy134:
- YYDEBUG(134, *YYCURSOR);
+ goto yy97;
+yy139:
+ YYDEBUG(139, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy103;
+ goto yy108;
}
/* *********************************** */
yyc_ST_RAW:
@@ -1858,46 +1962,46 @@ yyc_ST_RAW:
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
};
- YYDEBUG(135, *YYCURSOR);
+ YYDEBUG(140, *YYCURSOR);
YYFILL(3);
yych = *YYCURSOR;
if (yych <= '\f') {
if (yych <= 0x08) {
- if (yych >= 0x01) goto yy139;
+ if (yych >= 0x01) goto yy144;
} else {
- if (yych <= '\t') goto yy141;
- if (yych <= '\n') goto yy142;
- goto yy139;
+ if (yych <= '\t') goto yy146;
+ if (yych <= '\n') goto yy147;
+ goto yy144;
}
} else {
if (yych <= ' ') {
- if (yych <= '\r') goto yy144;
- if (yych <= 0x1F) goto yy139;
- goto yy141;
+ if (yych <= '\r') goto yy149;
+ if (yych <= 0x1F) goto yy144;
+ goto yy146;
} else {
- if (yych == ';') goto yy145;
- goto yy139;
+ if (yych == ';') goto yy150;
+ goto yy144;
}
}
- YYDEBUG(137, *YYCURSOR);
+ YYDEBUG(142, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(138, *YYCURSOR);
+ YYDEBUG(143, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 595 "Zend/zend_ini_scanner.l"
+#line 646 "Zend/zend_ini_scanner.l"
{ /* End of option value (if EOF is reached before EOL */
BEGIN(INITIAL);
return END_OF_LINE;
}
-#line 1892 "Zend/zend_ini_scanner.c"
-yy139:
- YYDEBUG(139, *YYCURSOR);
+#line 1996 "Zend/zend_ini_scanner.c"
+yy144:
+ YYDEBUG(144, *YYCURSOR);
++YYCURSOR;
-yy140:
- YYDEBUG(140, *YYCURSOR);
+yy145:
+ YYDEBUG(145, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 445 "Zend/zend_ini_scanner.l"
+#line 496 "Zend/zend_ini_scanner.l"
{ /* Raw value, only used when SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW. */
- char *sc = NULL;
+ unsigned char *sc = NULL;
while (YYCURSOR < YYLIMIT) {
switch (*YYCURSOR) {
case '\n':
@@ -1932,111 +2036,111 @@ end_raw_value_chars:
}
RETURN_TOKEN(TC_RAW, yytext, yyleng);
}
-#line 1936 "Zend/zend_ini_scanner.c"
-yy141:
- YYDEBUG(141, *YYCURSOR);
+#line 2040 "Zend/zend_ini_scanner.c"
+yy146:
+ YYDEBUG(146, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '\r') {
- if (yych <= 0x08) goto yy140;
- if (yych <= '\n') goto yy153;
- if (yych <= '\f') goto yy140;
- goto yy153;
+ if (yych <= 0x08) goto yy145;
+ if (yych <= '\n') goto yy158;
+ if (yych <= '\f') goto yy145;
+ goto yy158;
} else {
if (yych <= ' ') {
- if (yych <= 0x1F) goto yy140;
- goto yy153;
+ if (yych <= 0x1F) goto yy145;
+ goto yy158;
} else {
- if (yych == ';') goto yy153;
- goto yy140;
+ if (yych == ';') goto yy158;
+ goto yy145;
}
}
-yy142:
- YYDEBUG(142, *YYCURSOR);
+yy147:
+ YYDEBUG(147, *YYCURSOR);
++YYCURSOR;
-yy143:
- YYDEBUG(143, *YYCURSOR);
+yy148:
+ YYDEBUG(148, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 486 "Zend/zend_ini_scanner.l"
+#line 537 "Zend/zend_ini_scanner.l"
{ /* End of option value */
BEGIN(INITIAL);
SCNG(lineno)++;
return END_OF_LINE;
}
-#line 1967 "Zend/zend_ini_scanner.c"
-yy144:
- YYDEBUG(144, *YYCURSOR);
+#line 2071 "Zend/zend_ini_scanner.c"
+yy149:
+ YYDEBUG(149, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy151;
- goto yy143;
-yy145:
- YYDEBUG(145, *YYCURSOR);
+ if (yych == '\n') goto yy156;
+ goto yy148;
+yy150:
+ YYDEBUG(150, *YYCURSOR);
yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy147;
-yy146:
- YYDEBUG(146, *YYCURSOR);
+ goto yy152;
+yy151:
+ YYDEBUG(151, *YYCURSOR);
++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
-yy147:
- YYDEBUG(147, *YYCURSOR);
+yy152:
+ YYDEBUG(152, *YYCURSOR);
if (yybm[0+yych] & 64) {
- goto yy146;
+ goto yy151;
}
- if (yych >= '\r') goto yy150;
-yy148:
- YYDEBUG(148, *YYCURSOR);
+ if (yych >= '\r') goto yy155;
+yy153:
+ YYDEBUG(153, *YYCURSOR);
++YYCURSOR;
-yy149:
- YYDEBUG(149, *YYCURSOR);
+yy154:
+ YYDEBUG(154, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 582 "Zend/zend_ini_scanner.l"
+#line 633 "Zend/zend_ini_scanner.l"
{ /* Comment */
BEGIN(INITIAL);
SCNG(lineno)++;
return END_OF_LINE;
}
-#line 2001 "Zend/zend_ini_scanner.c"
-yy150:
- YYDEBUG(150, *YYCURSOR);
+#line 2105 "Zend/zend_ini_scanner.c"
+yy155:
+ YYDEBUG(155, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy148;
- goto yy149;
-yy151:
- YYDEBUG(151, *YYCURSOR);
+ if (yych == '\n') goto yy153;
+ goto yy154;
+yy156:
+ YYDEBUG(156, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy143;
-yy152:
- YYDEBUG(152, *YYCURSOR);
+ goto yy148;
+yy157:
+ YYDEBUG(157, *YYCURSOR);
yyaccept = 2;
YYMARKER = ++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
-yy153:
- YYDEBUG(153, *YYCURSOR);
+yy158:
+ YYDEBUG(158, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy152;
+ goto yy157;
}
if (yych <= '\f') {
- if (yych == '\n') goto yy151;
+ if (yych == '\n') goto yy156;
} else {
- if (yych <= '\r') goto yy155;
- if (yych == ';') goto yy146;
+ if (yych <= '\r') goto yy160;
+ if (yych == ';') goto yy151;
}
- YYDEBUG(154, *YYCURSOR);
+ YYDEBUG(159, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 572 "Zend/zend_ini_scanner.l"
+#line 623 "Zend/zend_ini_scanner.l"
{
/* eat whitespace */
goto restart;
}
-#line 2035 "Zend/zend_ini_scanner.c"
-yy155:
- YYDEBUG(155, *YYCURSOR);
+#line 2139 "Zend/zend_ini_scanner.c"
+yy160:
+ YYDEBUG(160, *YYCURSOR);
++YYCURSOR;
- if ((yych = *YYCURSOR) == '\n') goto yy151;
- goto yy143;
+ if ((yych = *YYCURSOR) == '\n') goto yy156;
+ goto yy148;
}
/* *********************************** */
yyc_ST_SECTION_RAW:
@@ -2075,85 +2179,85 @@ yyc_ST_SECTION_RAW:
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
};
- YYDEBUG(156, *YYCURSOR);
+ YYDEBUG(161, *YYCURSOR);
YYFILL(3);
yych = *YYCURSOR;
if (yych <= '\f') {
- if (yych == '\n') goto yy160;
+ if (yych == '\n') goto yy165;
} else {
- if (yych <= '\r') goto yy160;
- if (yych == ']') goto yy162;
+ if (yych <= '\r') goto yy165;
+ if (yych == ']') goto yy167;
}
- YYDEBUG(158, *YYCURSOR);
+ YYDEBUG(163, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy169;
-yy159:
- YYDEBUG(159, *YYCURSOR);
+ goto yy174;
+yy164:
+ YYDEBUG(164, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 482 "Zend/zend_ini_scanner.l"
+#line 533 "Zend/zend_ini_scanner.l"
{ /* Raw value, only used when SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW. */
RETURN_TOKEN(TC_RAW, yytext, yyleng);
}
-#line 2099 "Zend/zend_ini_scanner.c"
-yy160:
- YYDEBUG(160, *YYCURSOR);
+#line 2203 "Zend/zend_ini_scanner.c"
+yy165:
+ YYDEBUG(165, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(161, *YYCURSOR);
+ YYDEBUG(166, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 600 "Zend/zend_ini_scanner.l"
+#line 651 "Zend/zend_ini_scanner.l"
{
return 0;
}
-#line 2109 "Zend/zend_ini_scanner.c"
-yy162:
- YYDEBUG(162, *YYCURSOR);
+#line 2213 "Zend/zend_ini_scanner.c"
+yy167:
+ YYDEBUG(167, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy165;
-yy163:
- YYDEBUG(163, *YYCURSOR);
+ goto yy170;
+yy168:
+ YYDEBUG(168, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 374 "Zend/zend_ini_scanner.l"
+#line 421 "Zend/zend_ini_scanner.l"
{ /* End of section */
BEGIN(INITIAL);
SCNG(lineno)++;
return ']';
}
-#line 2124 "Zend/zend_ini_scanner.c"
-yy164:
- YYDEBUG(164, *YYCURSOR);
+#line 2228 "Zend/zend_ini_scanner.c"
+yy169:
+ YYDEBUG(169, *YYCURSOR);
++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
-yy165:
- YYDEBUG(165, *YYCURSOR);
+yy170:
+ YYDEBUG(170, *YYCURSOR);
if (yybm[0+yych] & 64) {
- goto yy164;
+ goto yy169;
}
- if (yych == '\n') goto yy166;
- if (yych == '\r') goto yy167;
- goto yy163;
-yy166:
- YYDEBUG(166, *YYCURSOR);
+ if (yych == '\n') goto yy171;
+ if (yych == '\r') goto yy172;
+ goto yy168;
+yy171:
+ YYDEBUG(171, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy163;
-yy167:
- YYDEBUG(167, *YYCURSOR);
+ goto yy168;
+yy172:
+ YYDEBUG(172, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy166;
- goto yy163;
-yy168:
- YYDEBUG(168, *YYCURSOR);
+ if (yych == '\n') goto yy171;
+ goto yy168;
+yy173:
+ YYDEBUG(173, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy169:
- YYDEBUG(169, *YYCURSOR);
+yy174:
+ YYDEBUG(174, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy168;
+ goto yy173;
}
- goto yy159;
+ goto yy164;
}
/* *********************************** */
yyc_ST_SECTION_VALUE:
@@ -2192,523 +2296,523 @@ yyc_ST_SECTION_VALUE:
132, 132, 132, 132, 132, 132, 132, 132,
132, 132, 132, 132, 132, 132, 132, 132,
};
- YYDEBUG(170, *YYCURSOR);
+ YYDEBUG(175, *YYCURSOR);
YYFILL(3);
yych = *YYCURSOR;
if (yych <= '-') {
if (yych <= ' ') {
if (yych <= '\n') {
- if (yych <= 0x08) goto yy172;
- if (yych <= '\t') goto yy174;
- goto yy175;
+ if (yych <= 0x08) goto yy177;
+ if (yych <= '\t') goto yy179;
+ goto yy180;
} else {
- if (yych == '\r') goto yy175;
- if (yych >= ' ') goto yy174;
+ if (yych == '\r') goto yy180;
+ if (yych >= ' ') goto yy179;
}
} else {
if (yych <= '$') {
- if (yych == '"') goto yy177;
- if (yych >= '$') goto yy179;
+ if (yych == '"') goto yy182;
+ if (yych >= '$') goto yy184;
} else {
- if (yych == '\'') goto yy180;
- if (yych >= '-') goto yy181;
+ if (yych == '\'') goto yy185;
+ if (yych >= '-') goto yy186;
}
}
} else {
if (yych <= 'Z') {
if (yych <= '9') {
- if (yych <= '.') goto yy182;
- if (yych >= '0') goto yy183;
+ if (yych <= '.') goto yy187;
+ if (yych >= '0') goto yy188;
} else {
- if (yych == ';') goto yy175;
- if (yych >= 'A') goto yy185;
+ if (yych == ';') goto yy180;
+ if (yych >= 'A') goto yy190;
}
} else {
if (yych <= '^') {
- if (yych <= '[') goto yy172;
- if (yych <= '\\') goto yy187;
- if (yych <= ']') goto yy188;
+ if (yych <= '[') goto yy177;
+ if (yych <= '\\') goto yy192;
+ if (yych <= ']') goto yy193;
} else {
- if (yych == '`') goto yy172;
- if (yych <= 'z') goto yy185;
+ if (yych == '`') goto yy177;
+ if (yych <= 'z') goto yy190;
}
}
}
-yy172:
- YYDEBUG(172, *YYCURSOR);
+yy177:
+ YYDEBUG(177, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy195;
-yy173:
- YYDEBUG(173, *YYCURSOR);
+ goto yy200;
+yy178:
+ YYDEBUG(178, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 518 "Zend/zend_ini_scanner.l"
+#line 569 "Zend/zend_ini_scanner.l"
{ /* Get rest as section/offset value */
RETURN_TOKEN(TC_STRING, yytext, yyleng);
}
-#line 2250 "Zend/zend_ini_scanner.c"
-yy174:
- YYDEBUG(174, *YYCURSOR);
+#line 2354 "Zend/zend_ini_scanner.c"
+yy179:
+ YYDEBUG(179, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= 0x1F) {
- if (yych == '\t') goto yy221;
- goto yy195;
+ if (yych == '\t') goto yy226;
+ goto yy200;
} else {
- if (yych <= ' ') goto yy221;
- if (yych == '"') goto yy223;
- goto yy195;
+ if (yych <= ' ') goto yy226;
+ if (yych == '"') goto yy228;
+ goto yy200;
}
-yy175:
- YYDEBUG(175, *YYCURSOR);
+yy180:
+ YYDEBUG(180, *YYCURSOR);
++YYCURSOR;
-yy176:
- YYDEBUG(176, *YYCURSOR);
+yy181:
+ YYDEBUG(181, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 600 "Zend/zend_ini_scanner.l"
+#line 651 "Zend/zend_ini_scanner.l"
{
return 0;
}
-#line 2273 "Zend/zend_ini_scanner.c"
-yy177:
- YYDEBUG(177, *YYCURSOR);
+#line 2377 "Zend/zend_ini_scanner.c"
+yy182:
+ YYDEBUG(182, *YYCURSOR);
++YYCURSOR;
-yy178:
- YYDEBUG(178, *YYCURSOR);
+yy183:
+ YYDEBUG(183, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 522 "Zend/zend_ini_scanner.l"
+#line 573 "Zend/zend_ini_scanner.l"
{ /* Double quoted '"' string start */
yy_push_state(ST_DOUBLE_QUOTES TSRMLS_CC);
return '"';
}
-#line 2285 "Zend/zend_ini_scanner.c"
-yy179:
- YYDEBUG(179, *YYCURSOR);
+#line 2389 "Zend/zend_ini_scanner.c"
+yy184:
+ YYDEBUG(184, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= '\\') {
- if (yych <= 0x00) goto yy176;
- if (yych <= '[') goto yy194;
- goto yy199;
+ if (yych <= 0x00) goto yy181;
+ if (yych <= '[') goto yy199;
+ goto yy204;
} else {
- if (yych == '{') goto yy219;
- goto yy194;
+ if (yych == '{') goto yy224;
+ goto yy199;
}
-yy180:
- YYDEBUG(180, *YYCURSOR);
+yy185:
+ YYDEBUG(185, *YYCURSOR);
yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy215;
+ goto yy220;
}
- goto yy176;
-yy181:
- YYDEBUG(181, *YYCURSOR);
+ goto yy181;
+yy186:
+ YYDEBUG(186, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych <= '/') goto yy195;
- if (yych <= '9') goto yy213;
- goto yy195;
-yy182:
- YYDEBUG(182, *YYCURSOR);
+ if (yych <= '/') goto yy200;
+ if (yych <= '9') goto yy218;
+ goto yy200;
+yy187:
+ YYDEBUG(187, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych <= '/') goto yy195;
- if (yych <= '9') goto yy211;
- goto yy195;
-yy183:
- YYDEBUG(183, *YYCURSOR);
+ if (yych <= '/') goto yy200;
+ if (yych <= '9') goto yy216;
+ goto yy200;
+yy188:
+ YYDEBUG(188, *YYCURSOR);
yyaccept = 2;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '\'') {
if (yych <= '\r') {
- if (yych == '\n') goto yy184;
- if (yych <= '\f') goto yy195;
+ if (yych == '\n') goto yy189;
+ if (yych <= '\f') goto yy200;
} else {
- if (yych == '"') goto yy184;
- if (yych <= '&') goto yy195;
+ if (yych == '"') goto yy189;
+ if (yych <= '&') goto yy200;
}
} else {
if (yych <= '9') {
- if (yych == '.') goto yy207;
- if (yych <= '/') goto yy195;
- goto yy209;
+ if (yych == '.') goto yy212;
+ if (yych <= '/') goto yy200;
+ goto yy214;
} else {
if (yych <= ';') {
- if (yych <= ':') goto yy195;
+ if (yych <= ':') goto yy200;
} else {
- if (yych != ']') goto yy195;
+ if (yych != ']') goto yy200;
}
}
}
-yy184:
- YYDEBUG(184, *YYCURSOR);
+yy189:
+ YYDEBUG(189, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 496 "Zend/zend_ini_scanner.l"
+#line 547 "Zend/zend_ini_scanner.l"
{ /* Get number option value as string */
RETURN_TOKEN(TC_NUMBER, yytext, yyleng);
}
-#line 2351 "Zend/zend_ini_scanner.c"
-yy185:
- YYDEBUG(185, *YYCURSOR);
+#line 2455 "Zend/zend_ini_scanner.c"
+yy190:
+ YYDEBUG(190, *YYCURSOR);
yyaccept = 3;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 32) {
- goto yy205;
+ goto yy210;
}
if (yych <= '"') {
if (yych <= '\f') {
- if (yych != '\n') goto yy195;
+ if (yych != '\n') goto yy200;
} else {
- if (yych <= '\r') goto yy186;
- if (yych <= '!') goto yy195;
+ if (yych <= '\r') goto yy191;
+ if (yych <= '!') goto yy200;
}
} else {
if (yych <= ':') {
- if (yych != '\'') goto yy195;
+ if (yych != '\'') goto yy200;
} else {
- if (yych <= ';') goto yy186;
- if (yych != ']') goto yy195;
+ if (yych <= ';') goto yy191;
+ if (yych != ']') goto yy200;
}
}
-yy186:
- YYDEBUG(186, *YYCURSOR);
+yy191:
+ YYDEBUG(191, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 492 "Zend/zend_ini_scanner.l"
+#line 543 "Zend/zend_ini_scanner.l"
{ /* Get constant option value */
RETURN_TOKEN(TC_CONSTANT, yytext, yyleng);
}
-#line 2381 "Zend/zend_ini_scanner.c"
-yy187:
- YYDEBUG(187, *YYCURSOR);
+#line 2485 "Zend/zend_ini_scanner.c"
+yy192:
+ YYDEBUG(192, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy194;
-yy188:
- YYDEBUG(188, *YYCURSOR);
+ goto yy199;
+yy193:
+ YYDEBUG(193, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy191;
-yy189:
- YYDEBUG(189, *YYCURSOR);
+ goto yy196;
+yy194:
+ YYDEBUG(194, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 374 "Zend/zend_ini_scanner.l"
+#line 421 "Zend/zend_ini_scanner.l"
{ /* End of section */
BEGIN(INITIAL);
SCNG(lineno)++;
return ']';
}
-#line 2400 "Zend/zend_ini_scanner.c"
-yy190:
- YYDEBUG(190, *YYCURSOR);
+#line 2504 "Zend/zend_ini_scanner.c"
+yy195:
+ YYDEBUG(195, *YYCURSOR);
++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
-yy191:
- YYDEBUG(191, *YYCURSOR);
+yy196:
+ YYDEBUG(196, *YYCURSOR);
if (yybm[0+yych] & 2) {
- goto yy190;
+ goto yy195;
}
- if (yych == '\n') goto yy192;
- if (yych == '\r') goto yy193;
- goto yy189;
-yy192:
- YYDEBUG(192, *YYCURSOR);
+ if (yych == '\n') goto yy197;
+ if (yych == '\r') goto yy198;
+ goto yy194;
+yy197:
+ YYDEBUG(197, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy189;
-yy193:
- YYDEBUG(193, *YYCURSOR);
+ goto yy194;
+yy198:
+ YYDEBUG(198, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy192;
- goto yy189;
-yy194:
- YYDEBUG(194, *YYCURSOR);
+ if (yych == '\n') goto yy197;
+ goto yy194;
+yy199:
+ YYDEBUG(199, *YYCURSOR);
yyaccept = 0;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy195:
- YYDEBUG(195, *YYCURSOR);
+yy200:
+ YYDEBUG(200, *YYCURSOR);
if (yybm[0+yych] & 4) {
- goto yy194;
+ goto yy199;
}
- if (yych == '$') goto yy197;
- if (yych != '\\') goto yy173;
-yy196:
- YYDEBUG(196, *YYCURSOR);
+ if (yych == '$') goto yy202;
+ if (yych != '\\') goto yy178;
+yy201:
+ YYDEBUG(201, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- goto yy194;
-yy197:
- YYDEBUG(197, *YYCURSOR);
+ goto yy199;
+yy202:
+ YYDEBUG(202, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
if (yych <= '\\') {
- if (yych <= 0x00) goto yy198;
- if (yych <= '[') goto yy194;
- goto yy199;
+ if (yych <= 0x00) goto yy203;
+ if (yych <= '[') goto yy199;
+ goto yy204;
} else {
- if (yych != '{') goto yy194;
+ if (yych != '{') goto yy199;
}
-yy198:
- YYDEBUG(198, *YYCURSOR);
+yy203:
+ YYDEBUG(203, *YYCURSOR);
YYCURSOR = YYMARKER;
if (yyaccept <= 1) {
if (yyaccept <= 0) {
- goto yy173;
+ goto yy178;
} else {
- goto yy176;
+ goto yy181;
}
} else {
if (yyaccept <= 2) {
- goto yy184;
+ goto yy189;
} else {
- goto yy186;
+ goto yy191;
}
}
-yy199:
- YYDEBUG(199, *YYCURSOR);
+yy204:
+ YYDEBUG(204, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
if (yybm[0+yych] & 8) {
- goto yy200;
+ goto yy205;
}
- if (yych == '\\') goto yy202;
- goto yy194;
-yy200:
- YYDEBUG(200, *YYCURSOR);
+ if (yych == '\\') goto yy207;
+ goto yy199;
+yy205:
+ YYDEBUG(205, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(201, *YYCURSOR);
+ YYDEBUG(206, *YYCURSOR);
if (yybm[0+yych] & 8) {
- goto yy200;
+ goto yy205;
}
- if (yych == '\\') goto yy204;
- goto yy194;
-yy202:
- YYDEBUG(202, *YYCURSOR);
+ if (yych == '\\') goto yy209;
+ goto yy199;
+yy207:
+ YYDEBUG(207, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(203, *YYCURSOR);
+ YYDEBUG(208, *YYCURSOR);
if (yybm[0+yych] & 8) {
- goto yy200;
+ goto yy205;
}
- if (yych == '\\') goto yy202;
- goto yy194;
-yy204:
- YYDEBUG(204, *YYCURSOR);
+ if (yych == '\\') goto yy207;
+ goto yy199;
+yy209:
+ YYDEBUG(209, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
if (yybm[0+yych] & 8) {
- goto yy200;
+ goto yy205;
}
- if (yych == '\\') goto yy202;
- goto yy194;
-yy205:
- YYDEBUG(205, *YYCURSOR);
+ if (yych == '\\') goto yy207;
+ goto yy199;
+yy210:
+ YYDEBUG(210, *YYCURSOR);
yyaccept = 3;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(206, *YYCURSOR);
+ YYDEBUG(211, *YYCURSOR);
if (yybm[0+yych] & 32) {
- goto yy205;
+ goto yy210;
}
if (yych <= '$') {
if (yych <= '\r') {
- if (yych == '\n') goto yy186;
- if (yych <= '\f') goto yy194;
- goto yy186;
+ if (yych == '\n') goto yy191;
+ if (yych <= '\f') goto yy199;
+ goto yy191;
} else {
- if (yych == '"') goto yy186;
- if (yych <= '#') goto yy194;
- goto yy197;
+ if (yych == '"') goto yy191;
+ if (yych <= '#') goto yy199;
+ goto yy202;
}
} else {
if (yych <= ';') {
- if (yych == '\'') goto yy186;
- if (yych <= ':') goto yy194;
- goto yy186;
+ if (yych == '\'') goto yy191;
+ if (yych <= ':') goto yy199;
+ goto yy191;
} else {
- if (yych <= '[') goto yy194;
- if (yych <= '\\') goto yy196;
- if (yych <= ']') goto yy186;
- goto yy194;
+ if (yych <= '[') goto yy199;
+ if (yych <= '\\') goto yy201;
+ if (yych <= ']') goto yy191;
+ goto yy199;
}
}
-yy207:
- YYDEBUG(207, *YYCURSOR);
+yy212:
+ YYDEBUG(212, *YYCURSOR);
yyaccept = 2;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(208, *YYCURSOR);
+ YYDEBUG(213, *YYCURSOR);
if (yybm[0+yych] & 64) {
- goto yy207;
+ goto yy212;
}
if (yych <= '$') {
if (yych <= '\r') {
- if (yych == '\n') goto yy184;
- if (yych <= '\f') goto yy194;
- goto yy184;
+ if (yych == '\n') goto yy189;
+ if (yych <= '\f') goto yy199;
+ goto yy189;
} else {
- if (yych == '"') goto yy184;
- if (yych <= '#') goto yy194;
- goto yy197;
+ if (yych == '"') goto yy189;
+ if (yych <= '#') goto yy199;
+ goto yy202;
}
} else {
if (yych <= ';') {
- if (yych == '\'') goto yy184;
- if (yych <= ':') goto yy194;
- goto yy184;
+ if (yych == '\'') goto yy189;
+ if (yych <= ':') goto yy199;
+ goto yy189;
} else {
- if (yych <= '[') goto yy194;
- if (yych <= '\\') goto yy196;
- if (yych <= ']') goto yy184;
- goto yy194;
+ if (yych <= '[') goto yy199;
+ if (yych <= '\\') goto yy201;
+ if (yych <= ']') goto yy189;
+ goto yy199;
}
}
-yy209:
- YYDEBUG(209, *YYCURSOR);
+yy214:
+ YYDEBUG(214, *YYCURSOR);
yyaccept = 2;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(210, *YYCURSOR);
+ YYDEBUG(215, *YYCURSOR);
if (yych <= '\'') {
if (yych <= '!') {
if (yych <= '\n') {
- if (yych <= '\t') goto yy194;
- goto yy184;
+ if (yych <= '\t') goto yy199;
+ goto yy189;
} else {
- if (yych == '\r') goto yy184;
- goto yy194;
+ if (yych == '\r') goto yy189;
+ goto yy199;
}
} else {
if (yych <= '#') {
- if (yych <= '"') goto yy184;
- goto yy194;
+ if (yych <= '"') goto yy189;
+ goto yy199;
} else {
- if (yych <= '$') goto yy197;
- if (yych <= '&') goto yy194;
- goto yy184;
+ if (yych <= '$') goto yy202;
+ if (yych <= '&') goto yy199;
+ goto yy189;
}
}
} else {
if (yych <= ':') {
if (yych <= '.') {
- if (yych <= '-') goto yy194;
- goto yy207;
+ if (yych <= '-') goto yy199;
+ goto yy212;
} else {
- if (yych <= '/') goto yy194;
- if (yych <= '9') goto yy209;
- goto yy194;
+ if (yych <= '/') goto yy199;
+ if (yych <= '9') goto yy214;
+ goto yy199;
}
} else {
if (yych <= '[') {
- if (yych <= ';') goto yy184;
- goto yy194;
+ if (yych <= ';') goto yy189;
+ goto yy199;
} else {
- if (yych <= '\\') goto yy196;
- if (yych <= ']') goto yy184;
- goto yy194;
+ if (yych <= '\\') goto yy201;
+ if (yych <= ']') goto yy189;
+ goto yy199;
}
}
}
-yy211:
- YYDEBUG(211, *YYCURSOR);
+yy216:
+ YYDEBUG(216, *YYCURSOR);
yyaccept = 2;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(212, *YYCURSOR);
+ YYDEBUG(217, *YYCURSOR);
if (yych <= '&') {
if (yych <= '\r') {
- if (yych == '\n') goto yy184;
- if (yych <= '\f') goto yy194;
- goto yy184;
+ if (yych == '\n') goto yy189;
+ if (yych <= '\f') goto yy199;
+ goto yy189;
} else {
if (yych <= '"') {
- if (yych <= '!') goto yy194;
- goto yy184;
+ if (yych <= '!') goto yy199;
+ goto yy189;
} else {
- if (yych == '$') goto yy197;
- goto yy194;
+ if (yych == '$') goto yy202;
+ goto yy199;
}
}
} else {
if (yych <= ':') {
- if (yych <= '\'') goto yy184;
- if (yych <= '/') goto yy194;
- if (yych <= '9') goto yy211;
- goto yy194;
+ if (yych <= '\'') goto yy189;
+ if (yych <= '/') goto yy199;
+ if (yych <= '9') goto yy216;
+ goto yy199;
} else {
if (yych <= '[') {
- if (yych <= ';') goto yy184;
- goto yy194;
+ if (yych <= ';') goto yy189;
+ goto yy199;
} else {
- if (yych <= '\\') goto yy196;
- if (yych <= ']') goto yy184;
- goto yy194;
+ if (yych <= '\\') goto yy201;
+ if (yych <= ']') goto yy189;
+ goto yy199;
}
}
}
-yy213:
- YYDEBUG(213, *YYCURSOR);
+yy218:
+ YYDEBUG(218, *YYCURSOR);
yyaccept = 2;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(214, *YYCURSOR);
+ YYDEBUG(219, *YYCURSOR);
if (yych <= '&') {
if (yych <= '\r') {
- if (yych == '\n') goto yy184;
- if (yych <= '\f') goto yy194;
- goto yy184;
+ if (yych == '\n') goto yy189;
+ if (yych <= '\f') goto yy199;
+ goto yy189;
} else {
if (yych <= '"') {
- if (yych <= '!') goto yy194;
- goto yy184;
+ if (yych <= '!') goto yy199;
+ goto yy189;
} else {
- if (yych == '$') goto yy197;
- goto yy194;
+ if (yych == '$') goto yy202;
+ goto yy199;
}
}
} else {
if (yych <= ':') {
- if (yych <= '\'') goto yy184;
- if (yych <= '/') goto yy194;
- if (yych <= '9') goto yy213;
- goto yy194;
+ if (yych <= '\'') goto yy189;
+ if (yych <= '/') goto yy199;
+ if (yych <= '9') goto yy218;
+ goto yy199;
} else {
if (yych <= '[') {
- if (yych <= ';') goto yy184;
- goto yy194;
+ if (yych <= ';') goto yy189;
+ goto yy199;
} else {
- if (yych <= '\\') goto yy196;
- if (yych <= ']') goto yy184;
- goto yy194;
+ if (yych <= '\\') goto yy201;
+ if (yych <= ']') goto yy189;
+ goto yy199;
}
}
}
-yy215:
- YYDEBUG(215, *YYCURSOR);
+yy220:
+ YYDEBUG(220, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(216, *YYCURSOR);
+ YYDEBUG(221, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy215;
+ goto yy220;
}
- YYDEBUG(217, *YYCURSOR);
+ YYDEBUG(222, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(218, *YYCURSOR);
+ YYDEBUG(223, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 365 "Zend/zend_ini_scanner.l"
+#line 412 "Zend/zend_ini_scanner.l"
{ /* Raw string */
/* Eat leading and trailing single quotes */
if (yytext[0] == '\'' && yytext[yyleng - 1] == '\'') {
@@ -2717,65 +2821,65 @@ yy215:
}
RETURN_TOKEN(TC_RAW, yytext, yyleng);
}
-#line 2721 "Zend/zend_ini_scanner.c"
-yy219:
- YYDEBUG(219, *YYCURSOR);
+#line 2825 "Zend/zend_ini_scanner.c"
+yy224:
+ YYDEBUG(224, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(220, *YYCURSOR);
+ YYDEBUG(225, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 398 "Zend/zend_ini_scanner.l"
+#line 445 "Zend/zend_ini_scanner.l"
{ /* Variable start */
yy_push_state(ST_VARNAME TSRMLS_CC);
return TC_DOLLAR_CURLY;
}
-#line 2732 "Zend/zend_ini_scanner.c"
-yy221:
- YYDEBUG(221, *YYCURSOR);
+#line 2836 "Zend/zend_ini_scanner.c"
+yy226:
+ YYDEBUG(226, *YYCURSOR);
yyaccept = 0;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(222, *YYCURSOR);
+ YYDEBUG(227, *YYCURSOR);
if (yych <= '"') {
if (yych <= '\f') {
- if (yych <= 0x08) goto yy194;
- if (yych <= '\t') goto yy221;
- if (yych <= '\n') goto yy173;
- goto yy194;
+ if (yych <= 0x08) goto yy199;
+ if (yych <= '\t') goto yy226;
+ if (yych <= '\n') goto yy178;
+ goto yy199;
} else {
if (yych <= 0x1F) {
- if (yych <= '\r') goto yy173;
- goto yy194;
+ if (yych <= '\r') goto yy178;
+ goto yy199;
} else {
- if (yych <= ' ') goto yy221;
- if (yych <= '!') goto yy194;
+ if (yych <= ' ') goto yy226;
+ if (yych <= '!') goto yy199;
}
}
} else {
if (yych <= ':') {
if (yych <= '$') {
- if (yych <= '#') goto yy194;
- goto yy197;
+ if (yych <= '#') goto yy199;
+ goto yy202;
} else {
- if (yych == '\'') goto yy173;
- goto yy194;
+ if (yych == '\'') goto yy178;
+ goto yy199;
}
} else {
if (yych <= '[') {
- if (yych <= ';') goto yy173;
- goto yy194;
+ if (yych <= ';') goto yy178;
+ goto yy199;
} else {
- if (yych <= '\\') goto yy196;
- if (yych <= ']') goto yy173;
- goto yy194;
+ if (yych <= '\\') goto yy201;
+ if (yych <= ']') goto yy178;
+ goto yy199;
}
}
}
-yy223:
- YYDEBUG(223, *YYCURSOR);
+yy228:
+ YYDEBUG(228, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy178;
+ goto yy183;
}
/* *********************************** */
yyc_ST_VALUE:
@@ -2814,28 +2918,28 @@ yyc_ST_VALUE:
162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162,
};
- YYDEBUG(224, *YYCURSOR);
+ YYDEBUG(229, *YYCURSOR);
YYFILL(6);
yych = *YYCURSOR;
YYDEBUG(-1, yych);
switch (yych) {
- case 0x00: goto yy226;
+ case 0x00: goto yy231;
case '\t':
- case ' ': goto yy230;
- case '\n': goto yy232;
- case '\r': goto yy234;
+ case ' ': goto yy235;
+ case '\n': goto yy237;
+ case '\r': goto yy239;
case '!':
case '&':
case '(':
case ')':
case '^':
case '|':
- case '~': goto yy235;
- case '"': goto yy237;
- case '$': goto yy239;
- case '\'': goto yy240;
- case '-': goto yy241;
- case '.': goto yy242;
+ case '~': goto yy240;
+ case '"': goto yy242;
+ case '$': goto yy244;
+ case '\'': goto yy245;
+ case '-': goto yy246;
+ case '.': goto yy247;
case '0':
case '1':
case '2':
@@ -2845,9 +2949,9 @@ yyc_ST_VALUE:
case '6':
case '7':
case '8':
- case '9': goto yy243;
- case ';': goto yy245;
- case '=': goto yy246;
+ case '9': goto yy248;
+ case ';': goto yy250;
+ case '=': goto yy251;
case 'A':
case 'B':
case 'C':
@@ -2890,1576 +2994,1637 @@ yyc_ST_VALUE:
case 'v':
case 'w':
case 'x':
- case 'z': goto yy248;
+ case 'z': goto yy253;
case 'F':
- case 'f': goto yy250;
+ case 'f': goto yy255;
case 'N':
- case 'n': goto yy251;
+ case 'n': goto yy256;
case 'O':
- case 'o': goto yy252;
+ case 'o': goto yy257;
case 'T':
- case 't': goto yy253;
+ case 't': goto yy258;
case 'Y':
- case 'y': goto yy254;
- default: goto yy228;
+ case 'y': goto yy259;
+ default: goto yy233;
}
-yy226:
- YYDEBUG(226, *YYCURSOR);
+yy231:
+ YYDEBUG(231, *YYCURSOR);
++YYCURSOR;
-yy227:
- YYDEBUG(227, *YYCURSOR);
+yy232:
+ YYDEBUG(232, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 595 "Zend/zend_ini_scanner.l"
+#line 646 "Zend/zend_ini_scanner.l"
{ /* End of option value (if EOF is reached before EOL */
BEGIN(INITIAL);
return END_OF_LINE;
}
-#line 2918 "Zend/zend_ini_scanner.c"
-yy228:
- YYDEBUG(228, *YYCURSOR);
+#line 3022 "Zend/zend_ini_scanner.c"
+yy233:
+ YYDEBUG(233, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy256;
-yy229:
- YYDEBUG(229, *YYCURSOR);
+ goto yy261;
+yy234:
+ YYDEBUG(234, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 514 "Zend/zend_ini_scanner.l"
+#line 565 "Zend/zend_ini_scanner.l"
{ /* Get everything else as option/offset value */
RETURN_TOKEN(TC_STRING, yytext, yyleng);
}
-#line 2931 "Zend/zend_ini_scanner.c"
-yy230:
- YYDEBUG(230, *YYCURSOR);
+#line 3035 "Zend/zend_ini_scanner.c"
+yy235:
+ YYDEBUG(235, *YYCURSOR);
yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy306;
-yy231:
- YYDEBUG(231, *YYCURSOR);
+ goto yy315;
+yy236:
+ YYDEBUG(236, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 568 "Zend/zend_ini_scanner.l"
+#line 619 "Zend/zend_ini_scanner.l"
{
RETURN_TOKEN(TC_WHITESPACE, yytext, yyleng);
}
-#line 2944 "Zend/zend_ini_scanner.c"
-yy232:
- YYDEBUG(232, *YYCURSOR);
+#line 3048 "Zend/zend_ini_scanner.c"
+yy237:
+ YYDEBUG(237, *YYCURSOR);
++YYCURSOR;
-yy233:
- YYDEBUG(233, *YYCURSOR);
+yy238:
+ YYDEBUG(238, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 486 "Zend/zend_ini_scanner.l"
+#line 537 "Zend/zend_ini_scanner.l"
{ /* End of option value */
BEGIN(INITIAL);
SCNG(lineno)++;
return END_OF_LINE;
}
-#line 2957 "Zend/zend_ini_scanner.c"
-yy234:
- YYDEBUG(234, *YYCURSOR);
+#line 3061 "Zend/zend_ini_scanner.c"
+yy239:
+ YYDEBUG(239, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy304;
- goto yy233;
-yy235:
- YYDEBUG(235, *YYCURSOR);
+ if (yych == '\n') goto yy313;
+ goto yy238;
+yy240:
+ YYDEBUG(240, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy303;
-yy236:
- YYDEBUG(236, *YYCURSOR);
+ goto yy312;
+yy241:
+ YYDEBUG(241, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 504 "Zend/zend_ini_scanner.l"
+#line 555 "Zend/zend_ini_scanner.l"
{ /* Boolean operators */
return yytext[0];
}
-#line 2975 "Zend/zend_ini_scanner.c"
-yy237:
- YYDEBUG(237, *YYCURSOR);
+#line 3079 "Zend/zend_ini_scanner.c"
+yy242:
+ YYDEBUG(242, *YYCURSOR);
++YYCURSOR;
-yy238:
- YYDEBUG(238, *YYCURSOR);
+yy243:
+ YYDEBUG(243, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 522 "Zend/zend_ini_scanner.l"
+#line 573 "Zend/zend_ini_scanner.l"
{ /* Double quoted '"' string start */
yy_push_state(ST_DOUBLE_QUOTES TSRMLS_CC);
return '"';
}
-#line 2987 "Zend/zend_ini_scanner.c"
-yy239:
- YYDEBUG(239, *YYCURSOR);
+#line 3091 "Zend/zend_ini_scanner.c"
+yy244:
+ YYDEBUG(244, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= '\\') {
- if (yych <= 0x00) goto yy227;
- if (yych <= '[') goto yy255;
- goto yy262;
+ if (yych <= 0x00) goto yy232;
+ if (yych <= '[') goto yy260;
+ goto yy267;
} else {
- if (yych == '{') goto yy300;
- goto yy255;
+ if (yych == '{') goto yy309;
+ goto yy260;
}
-yy240:
- YYDEBUG(240, *YYCURSOR);
+yy245:
+ YYDEBUG(245, *YYCURSOR);
yyaccept = 2;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy296;
+ goto yy305;
}
- goto yy227;
-yy241:
- YYDEBUG(241, *YYCURSOR);
+ goto yy232;
+yy246:
+ YYDEBUG(246, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych <= '/') goto yy256;
- if (yych <= '9') goto yy294;
- goto yy256;
-yy242:
- YYDEBUG(242, *YYCURSOR);
+ if (yych <= '/') goto yy261;
+ if (yych <= '9') goto yy303;
+ goto yy261;
+yy247:
+ YYDEBUG(247, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych <= '/') goto yy256;
- if (yych <= '9') goto yy292;
- goto yy256;
-yy243:
- YYDEBUG(243, *YYCURSOR);
+ if (yych <= '/') goto yy261;
+ if (yych <= '9') goto yy301;
+ goto yy261;
+yy248:
+ YYDEBUG(248, *YYCURSOR);
yyaccept = 3;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '/') {
if (yych <= 0x1F) {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy244;
- if (yych <= 0x08) goto yy256;
+ if (yych <= 0x00) goto yy249;
+ if (yych <= 0x08) goto yy261;
} else {
- if (yych != '\r') goto yy256;
+ if (yych != '\r') goto yy261;
}
} else {
if (yych <= ')') {
- if (yych <= '"') goto yy244;
- if (yych <= '%') goto yy256;
+ if (yych <= '"') goto yy249;
+ if (yych <= '%') goto yy261;
} else {
- if (yych == '.') goto yy288;
- goto yy256;
+ if (yych == '.') goto yy297;
+ goto yy261;
}
}
} else {
if (yych <= ']') {
if (yych <= ';') {
- if (yych <= '9') goto yy290;
- if (yych <= ':') goto yy256;
+ if (yych <= '9') goto yy299;
+ if (yych <= ':') goto yy261;
} else {
- if (yych != '=') goto yy256;
+ if (yych != '=') goto yy261;
}
} else {
if (yych <= '|') {
- if (yych <= '^') goto yy244;
- if (yych <= '{') goto yy256;
+ if (yych <= '^') goto yy249;
+ if (yych <= '{') goto yy261;
} else {
- if (yych != '~') goto yy256;
+ if (yych != '~') goto yy261;
}
}
}
-yy244:
- YYDEBUG(244, *YYCURSOR);
+yy249:
+ YYDEBUG(249, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 496 "Zend/zend_ini_scanner.l"
+#line 547 "Zend/zend_ini_scanner.l"
{ /* Get number option value as string */
RETURN_TOKEN(TC_NUMBER, yytext, yyleng);
}
-#line 3066 "Zend/zend_ini_scanner.c"
-yy245:
- YYDEBUG(245, *YYCURSOR);
+#line 3170 "Zend/zend_ini_scanner.c"
+yy250:
+ YYDEBUG(250, *YYCURSOR);
yyaccept = 2;
yych = *(YYMARKER = ++YYCURSOR);
- goto yy284;
-yy246:
- YYDEBUG(246, *YYCURSOR);
+ goto yy293;
+yy251:
+ YYDEBUG(251, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(247, *YYCURSOR);
+ YYDEBUG(252, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 508 "Zend/zend_ini_scanner.l"
+#line 559 "Zend/zend_ini_scanner.l"
{ /* Make = used in option value to trigger error */
yyless(0);
BEGIN(INITIAL);
return END_OF_LINE;
}
-#line 3083 "Zend/zend_ini_scanner.c"
-yy248:
- YYDEBUG(248, *YYCURSOR);
+#line 3187 "Zend/zend_ini_scanner.c"
+yy253:
+ YYDEBUG(253, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 4) {
- goto yy257;
+ goto yy262;
}
if (yych <= ':') {
if (yych <= '\r') {
if (yych <= 0x08) {
- if (yych >= 0x01) goto yy256;
+ if (yych >= 0x01) goto yy261;
} else {
- if (yych <= '\n') goto yy249;
- if (yych <= '\f') goto yy256;
+ if (yych <= '\n') goto yy254;
+ if (yych <= '\f') goto yy261;
}
} else {
if (yych <= '"') {
- if (yych <= 0x1F) goto yy256;
+ if (yych <= 0x1F) goto yy261;
} else {
- if (yych <= '%') goto yy256;
- if (yych >= '*') goto yy256;
+ if (yych <= '%') goto yy261;
+ if (yych >= '*') goto yy261;
}
}
} else {
if (yych <= '^') {
if (yych <= '<') {
- if (yych >= '<') goto yy256;
+ if (yych >= '<') goto yy261;
} else {
- if (yych <= '=') goto yy249;
- if (yych <= ']') goto yy256;
+ if (yych <= '=') goto yy254;
+ if (yych <= ']') goto yy261;
}
} else {
if (yych <= '|') {
- if (yych <= '{') goto yy256;
+ if (yych <= '{') goto yy261;
} else {
- if (yych != '~') goto yy256;
+ if (yych != '~') goto yy261;
}
}
}
-yy249:
- YYDEBUG(249, *YYCURSOR);
+yy254:
+ YYDEBUG(254, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 492 "Zend/zend_ini_scanner.l"
+#line 543 "Zend/zend_ini_scanner.l"
{ /* Get constant option value */
RETURN_TOKEN(TC_CONSTANT, yytext, yyleng);
}
-#line 3130 "Zend/zend_ini_scanner.c"
-yy250:
- YYDEBUG(250, *YYCURSOR);
+#line 3234 "Zend/zend_ini_scanner.c"
+yy255:
+ YYDEBUG(255, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '<') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '/') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- goto yy256;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ goto yy261;
} else {
- if (yych <= '9') goto yy257;
- if (yych == ';') goto yy249;
- goto yy256;
+ if (yych <= '9') goto yy262;
+ if (yych == ';') goto yy254;
+ goto yy261;
}
}
} else {
if (yych <= '_') {
if (yych <= 'A') {
- if (yych <= '=') goto yy249;
- if (yych <= '@') goto yy256;
- goto yy280;
+ if (yych <= '=') goto yy254;
+ if (yych <= '@') goto yy261;
+ goto yy289;
} else {
- if (yych <= 'Z') goto yy257;
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- goto yy257;
+ if (yych <= 'Z') goto yy262;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ goto yy262;
}
} else {
if (yych <= '{') {
- if (yych <= '`') goto yy256;
- if (yych <= 'a') goto yy280;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych <= '`') goto yy261;
+ if (yych <= 'a') goto yy289;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy251:
- YYDEBUG(251, *YYCURSOR);
+yy256:
+ YYDEBUG(256, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= 'N') {
if (yych <= '%') {
if (yych <= '\f') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- if (yych <= '\n') goto yy249;
- goto yy256;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ if (yych <= '\n') goto yy254;
+ goto yy261;
} else {
- if (yych <= '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- if (yych <= '"') goto yy249;
- goto yy256;
+ if (yych <= '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ if (yych <= '"') goto yy254;
+ goto yy261;
}
} else {
if (yych <= ':') {
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- if (yych <= '9') goto yy257;
- goto yy256;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ if (yych <= '9') goto yy262;
+ goto yy261;
} else {
if (yych <= '<') {
- if (yych <= ';') goto yy249;
- goto yy256;
+ if (yych <= ';') goto yy254;
+ goto yy261;
} else {
- if (yych <= '=') goto yy249;
- if (yych <= '@') goto yy256;
- goto yy257;
+ if (yych <= '=') goto yy254;
+ if (yych <= '@') goto yy261;
+ goto yy262;
}
}
}
} else {
if (yych <= 'n') {
if (yych <= 'Z') {
- if (yych <= 'O') goto yy276;
- if (yych == 'U') goto yy277;
- goto yy257;
+ if (yych <= 'O') goto yy281;
+ if (yych == 'U') goto yy282;
+ goto yy262;
} else {
if (yych <= '^') {
- if (yych <= ']') goto yy256;
- goto yy249;
+ if (yych <= ']') goto yy261;
+ goto yy254;
} else {
- if (yych == '`') goto yy256;
- goto yy257;
+ if (yych == '`') goto yy261;
+ goto yy262;
}
}
} else {
if (yych <= 'z') {
- if (yych <= 'o') goto yy276;
- if (yych == 'u') goto yy277;
- goto yy257;
+ if (yych <= 'o') goto yy281;
+ if (yych == 'u') goto yy282;
+ goto yy262;
} else {
if (yych <= '|') {
- if (yych <= '{') goto yy256;
- goto yy249;
+ if (yych <= '{') goto yy261;
+ goto yy254;
} else {
- if (yych == '~') goto yy249;
- goto yy256;
+ if (yych == '~') goto yy254;
+ goto yy261;
}
}
}
}
-yy252:
- YYDEBUG(252, *YYCURSOR);
+yy257:
+ YYDEBUG(257, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= 'E') {
if (yych <= '%') {
if (yych <= '\f') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- if (yych <= '\n') goto yy249;
- goto yy256;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ if (yych <= '\n') goto yy254;
+ goto yy261;
} else {
- if (yych <= '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- if (yych <= '"') goto yy249;
- goto yy256;
+ if (yych <= '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ if (yych <= '"') goto yy254;
+ goto yy261;
}
} else {
if (yych <= ':') {
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- if (yych <= '9') goto yy257;
- goto yy256;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ if (yych <= '9') goto yy262;
+ goto yy261;
} else {
if (yych <= '<') {
- if (yych <= ';') goto yy249;
- goto yy256;
+ if (yych <= ';') goto yy254;
+ goto yy261;
} else {
- if (yych <= '=') goto yy249;
- if (yych <= '@') goto yy256;
- goto yy257;
+ if (yych <= '=') goto yy254;
+ if (yych <= '@') goto yy261;
+ goto yy262;
}
}
}
} else {
if (yych <= 'e') {
if (yych <= 'Z') {
- if (yych <= 'F') goto yy271;
- if (yych == 'N') goto yy265;
- goto yy257;
+ if (yych <= 'F') goto yy276;
+ if (yych == 'N') goto yy270;
+ goto yy262;
} else {
if (yych <= '^') {
- if (yych <= ']') goto yy256;
- goto yy249;
+ if (yych <= ']') goto yy261;
+ goto yy254;
} else {
- if (yych == '`') goto yy256;
- goto yy257;
+ if (yych == '`') goto yy261;
+ goto yy262;
}
}
} else {
if (yych <= 'z') {
- if (yych <= 'f') goto yy271;
- if (yych == 'n') goto yy265;
- goto yy257;
+ if (yych <= 'f') goto yy276;
+ if (yych == 'n') goto yy270;
+ goto yy262;
} else {
if (yych <= '|') {
- if (yych <= '{') goto yy256;
- goto yy249;
+ if (yych <= '{') goto yy261;
+ goto yy254;
} else {
- if (yych == '~') goto yy249;
- goto yy256;
+ if (yych == '~') goto yy254;
+ goto yy261;
}
}
}
}
-yy253:
- YYDEBUG(253, *YYCURSOR);
+yy258:
+ YYDEBUG(258, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych == 'R') goto yy269;
- goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych == 'R') goto yy274;
+ goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 'r') goto yy269;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 'r') goto yy274;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy254:
- YYDEBUG(254, *YYCURSOR);
+yy259:
+ YYDEBUG(259, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych == 'E') goto yy259;
- goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych == 'E') goto yy264;
+ goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 'e') goto yy259;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 'e') goto yy264;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy255:
- YYDEBUG(255, *YYCURSOR);
+yy260:
+ YYDEBUG(260, *YYCURSOR);
yyaccept = 0;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy256:
- YYDEBUG(256, *YYCURSOR);
+yy261:
+ YYDEBUG(261, *YYCURSOR);
if (yybm[0+yych] & 2) {
- goto yy255;
+ goto yy260;
}
- if (yych == '$') goto yy260;
- goto yy229;
-yy257:
- YYDEBUG(257, *YYCURSOR);
+ if (yych == '$') goto yy265;
+ goto yy234;
+yy262:
+ YYDEBUG(262, *YYCURSOR);
yyaccept = 4;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(258, *YYCURSOR);
+ YYDEBUG(263, *YYCURSOR);
if (yybm[0+yych] & 4) {
- goto yy257;
+ goto yy262;
}
if (yych <= ')') {
if (yych <= '\r') {
if (yych <= 0x08) {
- if (yych <= 0x00) goto yy249;
- goto yy255;
+ if (yych <= 0x00) goto yy254;
+ goto yy260;
} else {
- if (yych <= '\n') goto yy249;
- if (yych <= '\f') goto yy255;
- goto yy249;
+ if (yych <= '\n') goto yy254;
+ if (yych <= '\f') goto yy260;
+ goto yy254;
}
} else {
if (yych <= '#') {
- if (yych <= 0x1F) goto yy255;
- if (yych <= '"') goto yy249;
- goto yy255;
+ if (yych <= 0x1F) goto yy260;
+ if (yych <= '"') goto yy254;
+ goto yy260;
} else {
- if (yych <= '$') goto yy260;
- if (yych <= '%') goto yy255;
- goto yy249;
+ if (yych <= '$') goto yy265;
+ if (yych <= '%') goto yy260;
+ goto yy254;
}
}
} else {
if (yych <= ']') {
if (yych <= ';') {
- if (yych <= ':') goto yy255;
- goto yy249;
+ if (yych <= ':') goto yy260;
+ goto yy254;
} else {
- if (yych == '=') goto yy249;
- goto yy255;
+ if (yych == '=') goto yy254;
+ goto yy260;
}
} else {
if (yych <= '|') {
- if (yych <= '^') goto yy249;
- if (yych <= '{') goto yy255;
- goto yy249;
+ if (yych <= '^') goto yy254;
+ if (yych <= '{') goto yy260;
+ goto yy254;
} else {
- if (yych == '~') goto yy249;
- goto yy255;
+ if (yych == '~') goto yy254;
+ goto yy260;
}
}
}
-yy259:
- YYDEBUG(259, *YYCURSOR);
+yy264:
+ YYDEBUG(264, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych == 'S') goto yy265;
- goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych == 'S') goto yy270;
+ goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 's') goto yy265;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 's') goto yy270;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy260:
- YYDEBUG(260, *YYCURSOR);
+yy265:
+ YYDEBUG(265, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
if (yych <= '\\') {
- if (yych <= 0x00) goto yy261;
- if (yych <= '[') goto yy255;
- goto yy262;
+ if (yych <= 0x00) goto yy266;
+ if (yych <= '[') goto yy260;
+ goto yy267;
} else {
- if (yych != '{') goto yy255;
+ if (yych != '{') goto yy260;
}
-yy261:
- YYDEBUG(261, *YYCURSOR);
+yy266:
+ YYDEBUG(266, *YYCURSOR);
YYCURSOR = YYMARKER;
if (yyaccept <= 3) {
if (yyaccept <= 1) {
if (yyaccept <= 0) {
- goto yy229;
+ goto yy234;
} else {
- goto yy231;
+ goto yy236;
}
} else {
if (yyaccept <= 2) {
- goto yy227;
+ goto yy232;
} else {
- goto yy244;
+ goto yy249;
}
}
} else {
if (yyaccept <= 5) {
if (yyaccept <= 4) {
- goto yy249;
+ goto yy254;
} else {
- goto yy266;
+ goto yy271;
}
} else {
- goto yy273;
+ if (yyaccept <= 6) {
+ goto yy278;
+ } else {
+ goto yy285;
+ }
}
}
-yy262:
- YYDEBUG(262, *YYCURSOR);
+yy267:
+ YYDEBUG(267, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
if (yybm[0+yych] & 8) {
- goto yy263;
+ goto yy268;
}
- goto yy255;
-yy263:
- YYDEBUG(263, *YYCURSOR);
+ goto yy260;
+yy268:
+ YYDEBUG(268, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(264, *YYCURSOR);
+ YYDEBUG(269, *YYCURSOR);
if (yybm[0+yych] & 8) {
- goto yy263;
+ goto yy268;
}
- if (yych <= 0x00) goto yy229;
- if (yych == '\\') goto yy262;
- goto yy255;
-yy265:
- YYDEBUG(265, *YYCURSOR);
+ if (yych <= 0x00) goto yy234;
+ if (yych == '\\') goto yy267;
+ goto yy260;
+yy270:
+ YYDEBUG(270, *YYCURSOR);
yyaccept = 5;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 16) {
- goto yy267;
+ goto yy272;
}
if (yych <= ';') {
if (yych <= ' ') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy266;
- if (yych <= '\t') goto yy256;
+ if (yych <= 0x00) goto yy271;
+ if (yych <= '\t') goto yy261;
} else {
- if (yych != '\r') goto yy256;
+ if (yych != '\r') goto yy261;
}
} else {
if (yych <= ')') {
- if (yych <= '"') goto yy266;
- if (yych <= '%') goto yy256;
+ if (yych <= '"') goto yy271;
+ if (yych <= '%') goto yy261;
} else {
- if (yych <= '/') goto yy256;
- if (yych <= '9') goto yy257;
- if (yych <= ':') goto yy256;
+ if (yych <= '/') goto yy261;
+ if (yych <= '9') goto yy262;
+ if (yych <= ':') goto yy261;
}
}
} else {
if (yych <= '_') {
if (yych <= '@') {
- if (yych != '=') goto yy256;
+ if (yych != '=') goto yy261;
} else {
- if (yych <= 'Z') goto yy257;
- if (yych <= ']') goto yy256;
- if (yych >= '_') goto yy257;
+ if (yych <= 'Z') goto yy262;
+ if (yych <= ']') goto yy261;
+ if (yych >= '_') goto yy262;
}
} else {
if (yych <= '{') {
- if (yych <= '`') goto yy256;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych <= '`') goto yy261;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych >= 0x7F) goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych >= 0x7F) goto yy261;
}
}
}
-yy266:
- YYDEBUG(266, *YYCURSOR);
+yy271:
+ YYDEBUG(271, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 418 "Zend/zend_ini_scanner.l"
+#line 465 "Zend/zend_ini_scanner.l"
{ /* TRUE value (when used outside option value/offset this causes parse error!) */
RETURN_TOKEN(BOOL_TRUE, "1", 1);
}
-#line 3642 "Zend/zend_ini_scanner.c"
-yy267:
- YYDEBUG(267, *YYCURSOR);
+#line 3750 "Zend/zend_ini_scanner.c"
+yy272:
+ YYDEBUG(272, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(268, *YYCURSOR);
+ YYDEBUG(273, *YYCURSOR);
if (yybm[0+yych] & 16) {
- goto yy267;
+ goto yy272;
}
- goto yy266;
-yy269:
- YYDEBUG(269, *YYCURSOR);
+ goto yy271;
+yy274:
+ YYDEBUG(274, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych != 'U') goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych != 'U') goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 'u') goto yy270;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 'u') goto yy275;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy270:
- YYDEBUG(270, *YYCURSOR);
+yy275:
+ YYDEBUG(275, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych == 'E') goto yy265;
- goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych == 'E') goto yy270;
+ goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 'e') goto yy265;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 'e') goto yy270;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy271:
- YYDEBUG(271, *YYCURSOR);
+yy276:
+ YYDEBUG(276, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych != 'F') goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych != 'F') goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 'f') goto yy272;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 'f') goto yy277;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy272:
- YYDEBUG(272, *YYCURSOR);
+yy277:
+ YYDEBUG(277, *YYCURSOR);
yyaccept = 6;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 4) {
- goto yy257;
+ goto yy262;
}
if (yych <= ')') {
if (yych <= '\f') {
if (yych <= 0x08) {
- if (yych >= 0x01) goto yy256;
+ if (yych >= 0x01) goto yy261;
} else {
- if (yych <= '\t') goto yy274;
- if (yych >= '\v') goto yy256;
+ if (yych <= '\t') goto yy279;
+ if (yych >= '\v') goto yy261;
}
} else {
if (yych <= ' ') {
- if (yych <= '\r') goto yy273;
- if (yych <= 0x1F) goto yy256;
- goto yy274;
+ if (yych <= '\r') goto yy278;
+ if (yych <= 0x1F) goto yy261;
+ goto yy279;
} else {
- if (yych <= '"') goto yy273;
- if (yych <= '%') goto yy256;
+ if (yych <= '"') goto yy278;
+ if (yych <= '%') goto yy261;
}
}
} else {
if (yych <= ']') {
if (yych <= ';') {
- if (yych <= ':') goto yy256;
+ if (yych <= ':') goto yy261;
} else {
- if (yych != '=') goto yy256;
+ if (yych != '=') goto yy261;
}
} else {
if (yych <= '|') {
- if (yych <= '^') goto yy273;
- if (yych <= '{') goto yy256;
+ if (yych <= '^') goto yy278;
+ if (yych <= '{') goto yy261;
} else {
- if (yych != '~') goto yy256;
+ if (yych != '~') goto yy261;
}
}
}
-yy273:
- YYDEBUG(273, *YYCURSOR);
+yy278:
+ YYDEBUG(278, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 422 "Zend/zend_ini_scanner.l"
+#line 469 "Zend/zend_ini_scanner.l"
{ /* FALSE value (when used outside option value/offset this causes parse error!)*/
RETURN_TOKEN(BOOL_FALSE, "", 0);
}
-#line 3852 "Zend/zend_ini_scanner.c"
-yy274:
- YYDEBUG(274, *YYCURSOR);
+#line 3960 "Zend/zend_ini_scanner.c"
+yy279:
+ YYDEBUG(279, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(275, *YYCURSOR);
- if (yych == '\t') goto yy274;
- if (yych == ' ') goto yy274;
- goto yy273;
-yy276:
- YYDEBUG(276, *YYCURSOR);
+ YYDEBUG(280, *YYCURSOR);
+ if (yych == '\t') goto yy279;
+ if (yych == ' ') goto yy279;
+ goto yy278;
+yy281:
+ YYDEBUG(281, *YYCURSOR);
yyaccept = 6;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '<') {
if (yych <= ' ') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy273;
- if (yych <= 0x08) goto yy256;
- if (yych <= '\t') goto yy274;
- goto yy273;
+ if (yych <= 0x00) goto yy278;
+ if (yych <= 0x08) goto yy261;
+ if (yych <= '\t') goto yy279;
+ goto yy278;
} else {
- if (yych == '\r') goto yy273;
- if (yych <= 0x1F) goto yy256;
- goto yy274;
+ if (yych == '\r') goto yy278;
+ if (yych <= 0x1F) goto yy261;
+ goto yy279;
}
} else {
if (yych <= '/') {
- if (yych <= '"') goto yy273;
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy273;
- goto yy256;
+ if (yych <= '"') goto yy278;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy278;
+ goto yy261;
} else {
- if (yych <= '9') goto yy257;
- if (yych == ';') goto yy273;
- goto yy256;
+ if (yych <= '9') goto yy262;
+ if (yych == ';') goto yy278;
+ goto yy261;
}
}
} else {
if (yych <= '_') {
if (yych <= 'N') {
- if (yych <= '=') goto yy273;
- if (yych <= '@') goto yy256;
- if (yych <= 'M') goto yy257;
- goto yy279;
+ if (yych <= '=') goto yy278;
+ if (yych <= '@') goto yy261;
+ if (yych <= 'M') goto yy262;
+ goto yy288;
} else {
- if (yych <= 'Z') goto yy257;
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy273;
- goto yy257;
+ if (yych <= 'Z') goto yy262;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy278;
+ goto yy262;
}
} else {
if (yych <= 'z') {
- if (yych <= '`') goto yy256;
- if (yych == 'n') goto yy279;
- goto yy257;
+ if (yych <= '`') goto yy261;
+ if (yych == 'n') goto yy288;
+ goto yy262;
} else {
if (yych <= '|') {
- if (yych <= '{') goto yy256;
- goto yy273;
+ if (yych <= '{') goto yy261;
+ goto yy278;
} else {
- if (yych == '~') goto yy273;
- goto yy256;
+ if (yych == '~') goto yy278;
+ goto yy261;
}
}
}
}
-yy277:
- YYDEBUG(277, *YYCURSOR);
+yy282:
+ YYDEBUG(282, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych != 'L') goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych != 'L') goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 'l') goto yy278;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 'l') goto yy283;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy278:
- YYDEBUG(278, *YYCURSOR);
+yy283:
+ YYDEBUG(283, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych == 'L') goto yy272;
- goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych != 'L') goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 'l') goto yy272;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 'l') goto yy284;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy279:
- YYDEBUG(279, *YYCURSOR);
+yy284:
+ YYDEBUG(284, *YYCURSOR);
+ yyaccept = 7;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if (yybm[0+yych] & 4) {
+ goto yy262;
+ }
+ if (yych <= ')') {
+ if (yych <= '\f') {
+ if (yych <= 0x08) {
+ if (yych >= 0x01) goto yy261;
+ } else {
+ if (yych <= '\t') goto yy286;
+ if (yych >= '\v') goto yy261;
+ }
+ } else {
+ if (yych <= ' ') {
+ if (yych <= '\r') goto yy285;
+ if (yych <= 0x1F) goto yy261;
+ goto yy286;
+ } else {
+ if (yych <= '"') goto yy285;
+ if (yych <= '%') goto yy261;
+ }
+ }
+ } else {
+ if (yych <= ']') {
+ if (yych <= ';') {
+ if (yych <= ':') goto yy261;
+ } else {
+ if (yych != '=') goto yy261;
+ }
+ } else {
+ if (yych <= '|') {
+ if (yych <= '^') goto yy285;
+ if (yych <= '{') goto yy261;
+ } else {
+ if (yych != '~') goto yy261;
+ }
+ }
+ }
+yy285:
+ YYDEBUG(285, *YYCURSOR);
+ yyleng = YYCURSOR - SCNG(yy_text);
+#line 473 "Zend/zend_ini_scanner.l"
+ {
+ RETURN_TOKEN(NULL_NULL, "", 0);
+}
+#line 4175 "Zend/zend_ini_scanner.c"
+yy286:
+ YYDEBUG(286, *YYCURSOR);
+ ++YYCURSOR;
+ YYFILL(1);
+ yych = *YYCURSOR;
+ YYDEBUG(287, *YYCURSOR);
+ if (yych == '\t') goto yy286;
+ if (yych == ' ') goto yy286;
+ goto yy285;
+yy288:
+ YYDEBUG(288, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych == 'E') goto yy272;
- goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych == 'E') goto yy277;
+ goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 'e') goto yy272;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 'e') goto yy277;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy280:
- YYDEBUG(280, *YYCURSOR);
+yy289:
+ YYDEBUG(289, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych != 'L') goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych != 'L') goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 'l') goto yy281;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 'l') goto yy290;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy281:
- YYDEBUG(281, *YYCURSOR);
+yy290:
+ YYDEBUG(290, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych != 'S') goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych != 'S') goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 's') goto yy282;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 's') goto yy291;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy282:
- YYDEBUG(282, *YYCURSOR);
+yy291:
+ YYDEBUG(291, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= '=') {
if (yych <= '"') {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy249;
- if (yych <= 0x08) goto yy256;
- goto yy249;
+ if (yych <= 0x00) goto yy254;
+ if (yych <= 0x08) goto yy261;
+ goto yy254;
} else {
- if (yych == '\r') goto yy249;
- if (yych <= 0x1F) goto yy256;
- goto yy249;
+ if (yych == '\r') goto yy254;
+ if (yych <= 0x1F) goto yy261;
+ goto yy254;
}
} else {
if (yych <= '9') {
- if (yych <= '%') goto yy256;
- if (yych <= ')') goto yy249;
- if (yych <= '/') goto yy256;
- goto yy257;
+ if (yych <= '%') goto yy261;
+ if (yych <= ')') goto yy254;
+ if (yych <= '/') goto yy261;
+ goto yy262;
} else {
- if (yych == ';') goto yy249;
- if (yych <= '<') goto yy256;
- goto yy249;
+ if (yych == ';') goto yy254;
+ if (yych <= '<') goto yy261;
+ goto yy254;
}
}
} else {
if (yych <= '`') {
if (yych <= 'Z') {
- if (yych <= '@') goto yy256;
- if (yych == 'E') goto yy272;
- goto yy257;
+ if (yych <= '@') goto yy261;
+ if (yych == 'E') goto yy277;
+ goto yy262;
} else {
- if (yych <= ']') goto yy256;
- if (yych <= '^') goto yy249;
- if (yych <= '_') goto yy257;
- goto yy256;
+ if (yych <= ']') goto yy261;
+ if (yych <= '^') goto yy254;
+ if (yych <= '_') goto yy262;
+ goto yy261;
}
} else {
if (yych <= '{') {
- if (yych == 'e') goto yy272;
- if (yych <= 'z') goto yy257;
- goto yy256;
+ if (yych == 'e') goto yy277;
+ if (yych <= 'z') goto yy262;
+ goto yy261;
} else {
- if (yych == '}') goto yy256;
- if (yych <= '~') goto yy249;
- goto yy256;
+ if (yych == '}') goto yy261;
+ if (yych <= '~') goto yy254;
+ goto yy261;
}
}
}
-yy283:
- YYDEBUG(283, *YYCURSOR);
+yy292:
+ YYDEBUG(292, *YYCURSOR);
++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
-yy284:
- YYDEBUG(284, *YYCURSOR);
+yy293:
+ YYDEBUG(293, *YYCURSOR);
if (yybm[0+yych] & 32) {
- goto yy283;
+ goto yy292;
}
- if (yych >= '\r') goto yy287;
-yy285:
- YYDEBUG(285, *YYCURSOR);
+ if (yych >= '\r') goto yy296;
+yy294:
+ YYDEBUG(294, *YYCURSOR);
++YYCURSOR;
-yy286:
- YYDEBUG(286, *YYCURSOR);
+yy295:
+ YYDEBUG(295, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 582 "Zend/zend_ini_scanner.l"
+#line 633 "Zend/zend_ini_scanner.l"
{ /* Comment */
BEGIN(INITIAL);
SCNG(lineno)++;
return END_OF_LINE;
}
-#line 4245 "Zend/zend_ini_scanner.c"
-yy287:
- YYDEBUG(287, *YYCURSOR);
+#line 4410 "Zend/zend_ini_scanner.c"
+yy296:
+ YYDEBUG(296, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy285;
- goto yy286;
-yy288:
- YYDEBUG(288, *YYCURSOR);
+ if (yych == '\n') goto yy294;
+ goto yy295;
+yy297:
+ YYDEBUG(297, *YYCURSOR);
yyaccept = 3;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(289, *YYCURSOR);
+ YYDEBUG(298, *YYCURSOR);
if (yybm[0+yych] & 64) {
- goto yy288;
+ goto yy297;
}
if (yych <= ')') {
if (yych <= '\r') {
if (yych <= 0x08) {
- if (yych <= 0x00) goto yy244;
- goto yy255;
+ if (yych <= 0x00) goto yy249;
+ goto yy260;
} else {
- if (yych <= '\n') goto yy244;
- if (yych <= '\f') goto yy255;
- goto yy244;
+ if (yych <= '\n') goto yy249;
+ if (yych <= '\f') goto yy260;
+ goto yy249;
}
} else {
if (yych <= '#') {
- if (yych <= 0x1F) goto yy255;
- if (yych <= '"') goto yy244;
- goto yy255;
+ if (yych <= 0x1F) goto yy260;
+ if (yych <= '"') goto yy249;
+ goto yy260;
} else {
- if (yych <= '$') goto yy260;
- if (yych <= '%') goto yy255;
- goto yy244;
+ if (yych <= '$') goto yy265;
+ if (yych <= '%') goto yy260;
+ goto yy249;
}
}
} else {
if (yych <= ']') {
if (yych <= ';') {
- if (yych <= ':') goto yy255;
- goto yy244;
+ if (yych <= ':') goto yy260;
+ goto yy249;
} else {
- if (yych == '=') goto yy244;
- goto yy255;
+ if (yych == '=') goto yy249;
+ goto yy260;
}
} else {
if (yych <= '|') {
- if (yych <= '^') goto yy244;
- if (yych <= '{') goto yy255;
- goto yy244;
+ if (yych <= '^') goto yy249;
+ if (yych <= '{') goto yy260;
+ goto yy249;
} else {
- if (yych == '~') goto yy244;
- goto yy255;
+ if (yych == '~') goto yy249;
+ goto yy260;
}
}
}
-yy290:
- YYDEBUG(290, *YYCURSOR);
+yy299:
+ YYDEBUG(299, *YYCURSOR);
yyaccept = 3;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(291, *YYCURSOR);
+ YYDEBUG(300, *YYCURSOR);
if (yych <= '.') {
if (yych <= 0x1F) {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy244;
- if (yych <= 0x08) goto yy255;
- goto yy244;
+ if (yych <= 0x00) goto yy249;
+ if (yych <= 0x08) goto yy260;
+ goto yy249;
} else {
- if (yych == '\r') goto yy244;
- goto yy255;
+ if (yych == '\r') goto yy249;
+ goto yy260;
}
} else {
if (yych <= '$') {
- if (yych <= '"') goto yy244;
- if (yych <= '#') goto yy255;
- goto yy260;
+ if (yych <= '"') goto yy249;
+ if (yych <= '#') goto yy260;
+ goto yy265;
} else {
- if (yych <= '%') goto yy255;
- if (yych <= ')') goto yy244;
- if (yych <= '-') goto yy255;
- goto yy288;
+ if (yych <= '%') goto yy260;
+ if (yych <= ')') goto yy249;
+ if (yych <= '-') goto yy260;
+ goto yy297;
}
}
} else {
if (yych <= '=') {
if (yych <= ':') {
- if (yych <= '/') goto yy255;
- if (yych <= '9') goto yy290;
- goto yy255;
+ if (yych <= '/') goto yy260;
+ if (yych <= '9') goto yy299;
+ goto yy260;
} else {
- if (yych == '<') goto yy255;
- goto yy244;
+ if (yych == '<') goto yy260;
+ goto yy249;
}
} else {
if (yych <= '{') {
- if (yych == '^') goto yy244;
- goto yy255;
+ if (yych == '^') goto yy249;
+ goto yy260;
} else {
- if (yych == '}') goto yy255;
- if (yych <= '~') goto yy244;
- goto yy255;
+ if (yych == '}') goto yy260;
+ if (yych <= '~') goto yy249;
+ goto yy260;
}
}
}
-yy292:
- YYDEBUG(292, *YYCURSOR);
+yy301:
+ YYDEBUG(301, *YYCURSOR);
yyaccept = 3;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(293, *YYCURSOR);
+ YYDEBUG(302, *YYCURSOR);
if (yych <= '/') {
if (yych <= 0x1F) {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy244;
- if (yych <= 0x08) goto yy255;
- goto yy244;
+ if (yych <= 0x00) goto yy249;
+ if (yych <= 0x08) goto yy260;
+ goto yy249;
} else {
- if (yych == '\r') goto yy244;
- goto yy255;
+ if (yych == '\r') goto yy249;
+ goto yy260;
}
} else {
if (yych <= '$') {
- if (yych <= '"') goto yy244;
- if (yych <= '#') goto yy255;
- goto yy260;
+ if (yych <= '"') goto yy249;
+ if (yych <= '#') goto yy260;
+ goto yy265;
} else {
- if (yych <= '%') goto yy255;
- if (yych <= ')') goto yy244;
- goto yy255;
+ if (yych <= '%') goto yy260;
+ if (yych <= ')') goto yy249;
+ goto yy260;
}
}
} else {
if (yych <= ']') {
if (yych <= ';') {
- if (yych <= '9') goto yy292;
- if (yych <= ':') goto yy255;
- goto yy244;
+ if (yych <= '9') goto yy301;
+ if (yych <= ':') goto yy260;
+ goto yy249;
} else {
- if (yych == '=') goto yy244;
- goto yy255;
+ if (yych == '=') goto yy249;
+ goto yy260;
}
} else {
if (yych <= '|') {
- if (yych <= '^') goto yy244;
- if (yych <= '{') goto yy255;
- goto yy244;
+ if (yych <= '^') goto yy249;
+ if (yych <= '{') goto yy260;
+ goto yy249;
} else {
- if (yych == '~') goto yy244;
- goto yy255;
+ if (yych == '~') goto yy249;
+ goto yy260;
}
}
}
-yy294:
- YYDEBUG(294, *YYCURSOR);
+yy303:
+ YYDEBUG(303, *YYCURSOR);
yyaccept = 3;
YYMARKER = ++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(295, *YYCURSOR);
+ YYDEBUG(304, *YYCURSOR);
if (yych <= '/') {
if (yych <= 0x1F) {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy244;
- if (yych <= 0x08) goto yy255;
- goto yy244;
+ if (yych <= 0x00) goto yy249;
+ if (yych <= 0x08) goto yy260;
+ goto yy249;
} else {
- if (yych == '\r') goto yy244;
- goto yy255;
+ if (yych == '\r') goto yy249;
+ goto yy260;
}
} else {
if (yych <= '$') {
- if (yych <= '"') goto yy244;
- if (yych <= '#') goto yy255;
- goto yy260;
+ if (yych <= '"') goto yy249;
+ if (yych <= '#') goto yy260;
+ goto yy265;
} else {
- if (yych <= '%') goto yy255;
- if (yych <= ')') goto yy244;
- goto yy255;
+ if (yych <= '%') goto yy260;
+ if (yych <= ')') goto yy249;
+ goto yy260;
}
}
} else {
if (yych <= ']') {
if (yych <= ';') {
- if (yych <= '9') goto yy294;
- if (yych <= ':') goto yy255;
- goto yy244;
+ if (yych <= '9') goto yy303;
+ if (yych <= ':') goto yy260;
+ goto yy249;
} else {
- if (yych == '=') goto yy244;
- goto yy255;
+ if (yych == '=') goto yy249;
+ goto yy260;
}
} else {
if (yych <= '|') {
- if (yych <= '^') goto yy244;
- if (yych <= '{') goto yy255;
- goto yy244;
+ if (yych <= '^') goto yy249;
+ if (yych <= '{') goto yy260;
+ goto yy249;
} else {
- if (yych == '~') goto yy244;
- goto yy255;
+ if (yych == '~') goto yy249;
+ goto yy260;
}
}
}
-yy296:
- YYDEBUG(296, *YYCURSOR);
+yy305:
+ YYDEBUG(305, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(297, *YYCURSOR);
+ YYDEBUG(306, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy296;
+ goto yy305;
}
- YYDEBUG(298, *YYCURSOR);
+ YYDEBUG(307, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(299, *YYCURSOR);
+ YYDEBUG(308, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 365 "Zend/zend_ini_scanner.l"
+#line 412 "Zend/zend_ini_scanner.l"
{ /* Raw string */
/* Eat leading and trailing single quotes */
if (yytext[0] == '\'' && yytext[yyleng - 1] == '\'') {
@@ -4468,66 +4633,66 @@ yy296:
}
RETURN_TOKEN(TC_RAW, yytext, yyleng);
}
-#line 4472 "Zend/zend_ini_scanner.c"
-yy300:
- YYDEBUG(300, *YYCURSOR);
+#line 4637 "Zend/zend_ini_scanner.c"
+yy309:
+ YYDEBUG(309, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(301, *YYCURSOR);
+ YYDEBUG(310, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 398 "Zend/zend_ini_scanner.l"
+#line 445 "Zend/zend_ini_scanner.l"
{ /* Variable start */
yy_push_state(ST_VARNAME TSRMLS_CC);
return TC_DOLLAR_CURLY;
}
-#line 4483 "Zend/zend_ini_scanner.c"
-yy302:
- YYDEBUG(302, *YYCURSOR);
+#line 4648 "Zend/zend_ini_scanner.c"
+yy311:
+ YYDEBUG(311, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy303:
- YYDEBUG(303, *YYCURSOR);
- if (yych == '\t') goto yy302;
- if (yych == ' ') goto yy302;
- goto yy236;
-yy304:
- YYDEBUG(304, *YYCURSOR);
+yy312:
+ YYDEBUG(312, *YYCURSOR);
+ if (yych == '\t') goto yy311;
+ if (yych == ' ') goto yy311;
+ goto yy241;
+yy313:
+ YYDEBUG(313, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy233;
-yy305:
- YYDEBUG(305, *YYCURSOR);
+ goto yy238;
+yy314:
+ YYDEBUG(314, *YYCURSOR);
yyaccept = 1;
YYMARKER = ++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
-yy306:
- YYDEBUG(306, *YYCURSOR);
+yy315:
+ YYDEBUG(315, *YYCURSOR);
if (yych <= 0x1F) {
if (yych <= '\n') {
- if (yych <= 0x08) goto yy231;
- if (yych <= '\t') goto yy305;
- goto yy304;
+ if (yych <= 0x08) goto yy236;
+ if (yych <= '\t') goto yy314;
+ goto yy313;
} else {
- if (yych == '\r') goto yy308;
- goto yy231;
+ if (yych == '\r') goto yy317;
+ goto yy236;
}
} else {
if (yych <= '"') {
- if (yych <= ' ') goto yy305;
- if (yych <= '!') goto yy231;
+ if (yych <= ' ') goto yy314;
+ if (yych <= '!') goto yy236;
} else {
- if (yych == ';') goto yy283;
- goto yy231;
+ if (yych == ';') goto yy292;
+ goto yy236;
}
}
- YYDEBUG(307, *YYCURSOR);
+ YYDEBUG(316, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy238;
-yy308:
- YYDEBUG(308, *YYCURSOR);
+ goto yy243;
+yy317:
+ YYDEBUG(317, *YYCURSOR);
++YYCURSOR;
- if ((yych = *YYCURSOR) == '\n') goto yy304;
- goto yy233;
+ if ((yych = *YYCURSOR) == '\n') goto yy313;
+ goto yy238;
}
/* *********************************** */
yyc_ST_VARNAME:
@@ -4566,51 +4731,51 @@ yyc_ST_VARNAME:
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
};
- YYDEBUG(309, *YYCURSOR);
+ YYDEBUG(318, *YYCURSOR);
YYFILL(2);
yych = *YYCURSOR;
if (yych <= ')') {
if (yych <= '"') {
if (yych <= '\f') {
- if (yych <= 0x08) goto yy311;
- if (yych <= '\n') goto yy313;
+ if (yych <= 0x08) goto yy320;
+ if (yych <= '\n') goto yy322;
} else {
- if (yych <= '\r') goto yy313;
- if (yych >= '!') goto yy313;
+ if (yych <= '\r') goto yy322;
+ if (yych >= '!') goto yy322;
}
} else {
if (yych <= '%') {
- if (yych == '$') goto yy313;
+ if (yych == '$') goto yy322;
} else {
- if (yych != '\'') goto yy313;
+ if (yych != '\'') goto yy322;
}
}
} else {
if (yych <= '[') {
if (yych <= '<') {
- if (yych == ';') goto yy313;
+ if (yych == ';') goto yy322;
} else {
- if (yych <= '=') goto yy313;
- if (yych >= '[') goto yy313;
+ if (yych <= '=') goto yy322;
+ if (yych >= '[') goto yy322;
}
} else {
if (yych <= 'z') {
- if (yych == '^') goto yy313;
+ if (yych == '^') goto yy322;
} else {
- if (yych == '}') goto yy315;
- if (yych <= '~') goto yy313;
+ if (yych == '}') goto yy324;
+ if (yych <= '~') goto yy322;
}
}
}
-yy311:
- YYDEBUG(311, *YYCURSOR);
+yy320:
+ YYDEBUG(320, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy318;
-yy312:
- YYDEBUG(312, *YYCURSOR);
+ goto yy327;
+yy321:
+ YYDEBUG(321, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 403 "Zend/zend_ini_scanner.l"
+#line 450 "Zend/zend_ini_scanner.l"
{ /* Variable name */
/* Eat leading whitespace */
EAT_LEADING_WHITESPACE();
@@ -4620,41 +4785,41 @@ yy312:
RETURN_TOKEN(TC_VARNAME, yytext, yyleng);
}
-#line 4624 "Zend/zend_ini_scanner.c"
-yy313:
- YYDEBUG(313, *YYCURSOR);
+#line 4789 "Zend/zend_ini_scanner.c"
+yy322:
+ YYDEBUG(322, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(314, *YYCURSOR);
+ YYDEBUG(323, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 600 "Zend/zend_ini_scanner.l"
+#line 651 "Zend/zend_ini_scanner.l"
{
return 0;
}
-#line 4634 "Zend/zend_ini_scanner.c"
-yy315:
- YYDEBUG(315, *YYCURSOR);
+#line 4799 "Zend/zend_ini_scanner.c"
+yy324:
+ YYDEBUG(324, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(316, *YYCURSOR);
+ YYDEBUG(325, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 413 "Zend/zend_ini_scanner.l"
+#line 460 "Zend/zend_ini_scanner.l"
{ /* Variable end */
yy_pop_state(TSRMLS_C);
return '}';
}
-#line 4645 "Zend/zend_ini_scanner.c"
-yy317:
- YYDEBUG(317, *YYCURSOR);
+#line 4810 "Zend/zend_ini_scanner.c"
+yy326:
+ YYDEBUG(326, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy318:
- YYDEBUG(318, *YYCURSOR);
+yy327:
+ YYDEBUG(327, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy317;
+ goto yy326;
}
- goto yy312;
+ goto yy321;
}
}
-#line 604 "Zend/zend_ini_scanner.l"
+#line 655 "Zend/zend_ini_scanner.l"
}
diff --git a/Zend/zend_ini_scanner.h b/Zend/zend_ini_scanner.h
index aafe7efdde..c81e3605d8 100644
--- a/Zend/zend_ini_scanner.h
+++ b/Zend/zend_ini_scanner.h
@@ -25,6 +25,7 @@
/* Scanner modes */
#define ZEND_INI_SCANNER_NORMAL 0 /* Normal mode. [DEFAULT] */
#define ZEND_INI_SCANNER_RAW 1 /* Raw mode. Option values are not parsed */
+#define ZEND_INI_SCANNER_TYPED 2 /* Typed mode. */
BEGIN_EXTERN_C()
int zend_ini_scanner_get_lineno(TSRMLS_D);
diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l
index bbc48d1fc1..3bfb1557b1 100644
--- a/Zend/zend_ini_scanner.l
+++ b/Zend/zend_ini_scanner.l
@@ -24,6 +24,7 @@
#include <errno.h>
#include "zend.h"
+#include "zend_API.h"
#include "zend_globals.h"
#include <zend_ini_parser.h>
#include "zend_ini_scanner.h"
@@ -132,12 +133,58 @@ ZEND_API zend_ini_scanner_globals ini_scanner_globals;
#define EAT_TRAILING_WHITESPACE() EAT_TRAILING_WHITESPACE_EX('X')
#define zend_ini_copy_value(retval, str, len) \
- ZVAL_NEW_STR(retval, STR_INIT(str, len, 1))
+ ZVAL_NEW_STR(retval, zend_string_init(str, len, 1))
-#define RETURN_TOKEN(type, str, len) { \
- zend_ini_copy_value(ini_lval, str, len); \
- return type; \
+#define RETURN_TOKEN(type, str, len) { \
+ if (SCNG(scanner_mode) == ZEND_INI_SCANNER_TYPED) { \
+ zend_ini_copy_typed_value(ini_lval, type, str, len); \
+ } else { \
+ zend_ini_copy_value(ini_lval, str, len); \
+ } \
+ return type; \
+}
+
+static inline int convert_to_number(zval *retval, const char *str, const int str_len)
+{
+ zend_uchar type;
+ int overflow;
+ zend_long lval;
+ double dval;
+
+ if ((type = is_numeric_string_ex(str, str_len, &lval, &dval, 0, &overflow)) != 0) {
+ if (type == IS_LONG) {
+ ZVAL_LONG(retval, lval);
+ return SUCCESS;
+ } else if (type == IS_DOUBLE && !overflow) {
+ ZVAL_DOUBLE(retval, dval);
+ return SUCCESS;
+ }
+ }
+
+ return FAILURE;
+}
+
+static void zend_ini_copy_typed_value(zval *retval, const int type, const char *str, int len)
+{
+ switch (type) {
+ case BOOL_FALSE:
+ case BOOL_TRUE:
+ ZVAL_BOOL(retval, type == BOOL_TRUE);
+ break;
+
+ case NULL_NULL:
+ ZVAL_NULL(retval);
+ break;
+
+ case TC_NUMBER:
+ if (convert_to_number(retval, str, len) == SUCCESS) {
+ break;
+ }
+ /* intentional fall-through */
+ default:
+ zend_ini_copy_value(retval, str, len);
+ }
}
static void _yy_push_state(int new_state TSRMLS_DC)
@@ -169,7 +216,7 @@ static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC)
static int init_ini_scanner(int scanner_mode, zend_file_handle *fh TSRMLS_DC)
{
/* Sanity check */
- if (scanner_mode != ZEND_INI_SCANNER_NORMAL && scanner_mode != ZEND_INI_SCANNER_RAW) {
+ if (scanner_mode != ZEND_INI_SCANNER_NORMAL && scanner_mode != ZEND_INI_SCANNER_RAW && scanner_mode != ZEND_INI_SCANNER_TYPED) {
zend_error(E_WARNING, "Invalid scanner mode");
return FAILURE;
}
@@ -419,10 +466,14 @@ SECTION_VALUE_CHARS ([^$\n\r;"'\]\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
RETURN_TOKEN(BOOL_TRUE, "1", 1);
}
-<INITIAL,ST_VALUE>("false"|"off"|"no"|"none"|"null"){TABS_AND_SPACES}* { /* FALSE value (when used outside option value/offset this causes parse error!)*/
+<INITIAL,ST_VALUE>("false"|"off"|"no"|"none"){TABS_AND_SPACES}* { /* FALSE value (when used outside option value/offset this causes parse error!)*/
RETURN_TOKEN(BOOL_FALSE, "", 0);
}
+<INITIAL,ST_VALUE>("null"){TABS_AND_SPACES}* {
+ RETURN_TOKEN(NULL_NULL, "", 0);
+}
+
<INITIAL>{LABEL} { /* Get option name */
/* Eat leading whitespace */
EAT_LEADING_WHITESPACE();
@@ -443,7 +494,7 @@ SECTION_VALUE_CHARS ([^$\n\r;"'\]\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
}
<ST_RAW>{RAW_VALUE_CHARS} { /* Raw value, only used when SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW. */
- char *sc = NULL;
+ unsigned char *sc = NULL;
while (YYCURSOR < YYLIMIT) {
switch (*YYCURSOR) {
case '\n':
diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c
index d5420dae76..26507ad23b 100644
--- a/Zend/zend_interfaces.c
+++ b/Zend/zend_interfaces.c
@@ -303,7 +303,7 @@ ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *c
static int zend_implement_traversable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
{
/* check that class_type is traversable at c-level or implements at least one of 'aggregate' and 'Iterator' */
- zend_uint i;
+ uint32_t i;
if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) {
return SUCCESS;
@@ -325,7 +325,8 @@ static int zend_implement_traversable(zend_class_entry *interface, zend_class_en
/* {{{ zend_implement_aggregate */
static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
{
- int i, t = -1;
+ uint32_t i;
+ int t = -1;
if (class_type->get_iterator) {
if (class_type->type == ZEND_INTERNAL_CLASS) {
@@ -406,7 +407,7 @@ static int zend_implement_arrayaccess(zend_class_entry *interface, zend_class_en
/* }}}*/
/* {{{ zend_user_serialize */
-ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC)
+ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data TSRMLS_DC)
{
zend_class_entry * ce = Z_OBJCE_P(object);
zval retval;
@@ -443,7 +444,7 @@ ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint
/* }}} */
/* {{{ zend_user_unserialize */
-ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC)
+ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buf, size_t buf_len, zend_unserialize_data *data TSRMLS_DC)
{
zval zdata;
@@ -463,7 +464,7 @@ ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const uns
}
/* }}} */
-ZEND_API int zend_class_serialize_deny(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC) /* {{{ */
+ZEND_API int zend_class_serialize_deny(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data TSRMLS_DC) /* {{{ */
{
zend_class_entry *ce = Z_OBJCE_P(object);
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Serialization of '%s' is not allowed", ce->name->val);
@@ -471,7 +472,7 @@ ZEND_API int zend_class_serialize_deny(zval *object, unsigned char **buffer, zen
}
/* }}} */
-ZEND_API int zend_class_unserialize_deny(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */
+ZEND_API int zend_class_unserialize_deny(zval *object, zend_class_entry *ce, const unsigned char *buf, size_t buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */
{
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Unserialization of '%s' is not allowed", ce->name->val);
return FAILURE;
diff --git a/Zend/zend_interfaces.h b/Zend/zend_interfaces.h
index 7fe0e4e2f0..9bfef0990d 100644
--- a/Zend/zend_interfaces.h
+++ b/Zend/zend_interfaces.h
@@ -61,11 +61,11 @@ ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *c
ZEND_API void zend_register_interfaces(TSRMLS_D);
-ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);
-ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
+ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data TSRMLS_DC);
+ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buf, size_t buf_len, zend_unserialize_data *data TSRMLS_DC);
-ZEND_API int zend_class_serialize_deny(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);
-ZEND_API int zend_class_unserialize_deny(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
+ZEND_API int zend_class_serialize_deny(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data TSRMLS_DC);
+ZEND_API int zend_class_unserialize_deny(zval *object, zend_class_entry *ce, const unsigned char *buf, size_t buf_len, zend_unserialize_data *data TSRMLS_DC);
END_EXTERN_C()
diff --git a/Zend/zend_iterators.c b/Zend/zend_iterators.c
index faf4f91d84..c2f51c4dd6 100644
--- a/Zend/zend_iterators.c
+++ b/Zend/zend_iterators.c
@@ -24,13 +24,14 @@
static zend_class_entry zend_iterator_class_entry;
+static void iter_wrapper_free(zend_object *object TSRMLS_DC);
static void iter_wrapper_dtor(zend_object *object TSRMLS_DC);
static zend_object_handlers iterator_object_handlers = {
0,
+ iter_wrapper_free,
iter_wrapper_dtor,
NULL,
- NULL,
NULL, /* prop read */
NULL, /* prop write */
NULL, /* read dim */
@@ -58,12 +59,16 @@ ZEND_API void zend_register_iterator_wrapper(TSRMLS_D)
INIT_CLASS_ENTRY(zend_iterator_class_entry, "__iterator_wrapper", NULL);
}
-static void iter_wrapper_dtor(zend_object *object TSRMLS_DC)
+static void iter_wrapper_free(zend_object *object TSRMLS_DC)
{
zend_object_iterator *iter = (zend_object_iterator*)object;
iter->funcs->dtor(iter TSRMLS_CC);
}
+static void iter_wrapper_dtor(zend_object *object TSRMLS_DC)
+{
+}
+
ZEND_API void zend_iterator_init(zend_object_iterator *iter TSRMLS_DC)
{
zend_object_std_init(&iter->std, &zend_iterator_class_entry TSRMLS_CC);
@@ -79,29 +84,13 @@ ZEND_API void zend_iterator_dtor(zend_object_iterator *iter TSRMLS_DC)
zend_objects_store_del(&iter->std TSRMLS_CC);
}
-ZEND_API enum zend_object_iterator_kind zend_iterator_unwrap(
- zval *array_ptr, zend_object_iterator **iter TSRMLS_DC)
+ZEND_API zend_object_iterator* zend_iterator_unwrap(zval *array_ptr TSRMLS_DC)
{
- switch (Z_TYPE_P(array_ptr)) {
- case IS_OBJECT:
- if (Z_OBJ_HT_P(array_ptr) == &iterator_object_handlers) {
- *iter = (zend_object_iterator *)Z_OBJ_P(array_ptr);
- return ZEND_ITER_OBJECT;
- }
- if (Z_OBJPROP_P(array_ptr)) {
- return ZEND_ITER_PLAIN_OBJECT;
- }
- return ZEND_ITER_INVALID;
-
- case IS_ARRAY:
- if (Z_ARRVAL_P(array_ptr)) {
- return ZEND_ITER_PLAIN_ARRAY;
- }
- return ZEND_ITER_INVALID;
-
- default:
- return ZEND_ITER_INVALID;
+ if (Z_TYPE_P(array_ptr) &&
+ Z_OBJ_HT_P(array_ptr) == &iterator_object_handlers) {
+ return (zend_object_iterator *)Z_OBJ_P(array_ptr);
}
+ return NULL;
}
/*
diff --git a/Zend/zend_iterators.h b/Zend/zend_iterators.h
index 09346aee90..a1148db214 100644
--- a/Zend/zend_iterators.h
+++ b/Zend/zend_iterators.h
@@ -58,7 +58,7 @@ struct _zend_object_iterator {
zend_object std;
zval data;
zend_object_iterator_funcs *funcs;
- ulong index; /* private to fe_reset/fe_fetch opcodes */
+ zend_ulong index; /* private to fe_reset/fe_fetch opcodes */
};
typedef struct _zend_class_iterator_funcs {
@@ -71,16 +71,9 @@ typedef struct _zend_class_iterator_funcs {
union _zend_function *zf_rewind;
} zend_class_iterator_funcs;
-enum zend_object_iterator_kind {
- ZEND_ITER_INVALID,
- ZEND_ITER_PLAIN_ARRAY,
- ZEND_ITER_PLAIN_OBJECT,
- ZEND_ITER_OBJECT
-};
-
BEGIN_EXTERN_C()
/* given a zval, returns stuff that can be used to iterate it. */
-ZEND_API enum zend_object_iterator_kind zend_iterator_unwrap(zval *array_ptr, zend_object_iterator **iter TSRMLS_DC);
+ZEND_API zend_object_iterator* zend_iterator_unwrap(zval *array_ptr TSRMLS_DC);
/* given an iterator, wrap it up as a zval for use by the engine opcodes */
ZEND_API void zend_iterator_init(zend_object_iterator *iter TSRMLS_DC);
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 38b1bcc2b4..6bfef2219e 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -15,6 +15,7 @@
+----------------------------------------------------------------------+
| Authors: Andi Gutmans <andi@zend.com> |
| Zeev Suraski <zeev@zend.com> |
+ | Nikita Popov <nikic@php.net> |
+----------------------------------------------------------------------+
*/
@@ -40,12 +41,12 @@
static YYSIZE_T zend_yytnamerr(char*, const char*);
#define YYERROR_VERBOSE
-#define YYSTYPE znode
+#define YYSTYPE zend_parser_stack_elem
%}
%pure_parser
-%expect 3
+%expect 2
%code requires {
#ifdef ZTS
@@ -54,25 +55,61 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
#endif
}
-%token END 0 "end of file"
+%destructor { zend_ast_destroy($$); } <ast>
+%destructor { if ($$) zend_string_release($$); } <str>
+
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
+%left ','
+%left T_LOGICAL_OR
+%left T_LOGICAL_XOR
+%left T_LOGICAL_AND
+%right T_PRINT
+%right T_YIELD
+%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL
+%left '?' ':'
+%left T_BOOLEAN_OR
+%left T_BOOLEAN_AND
+%left '|'
+%left '^'
+%left '&'
+%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL
+%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
+%left T_SL T_SR
+%left '+' '-' '.'
+%left '*' '/' '%'
+%right '!'
+%nonassoc T_INSTANCEOF
+%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
+%right T_POW
+%right '['
+%nonassoc T_NEW T_CLONE
+%left T_ELSEIF
+%left T_ELSE
+%left T_ENDIF
+%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
+%right T_DOUBLE_ARROW
+
+%token <ast> T_LNUMBER "integer number (T_LNUMBER)"
+%token <ast> T_DNUMBER "floating-point number (T_DNUMBER)"
+%token <ast> T_STRING "identifier (T_STRING)"
+%token <ast> T_VARIABLE "variable (T_VARIABLE)"
+%token <ast> T_INLINE_HTML
+%token <ast> T_ENCAPSED_AND_WHITESPACE "quoted-string and whitespace (T_ENCAPSED_AND_WHITESPACE)"
+%token <ast> T_CONSTANT_ENCAPSED_STRING "quoted-string (T_CONSTANT_ENCAPSED_STRING)"
+%token <ast> T_STRING_VARNAME "variable name (T_STRING_VARNAME)"
+%token <ast> T_NUM_STRING "number (T_NUM_STRING)"
+
+%token END 0 "end of file"
%token T_INCLUDE "include (T_INCLUDE)"
%token T_INCLUDE_ONCE "include_once (T_INCLUDE_ONCE)"
%token T_EVAL "eval (T_EVAL)"
%token T_REQUIRE "require (T_REQUIRE)"
%token T_REQUIRE_ONCE "require_once (T_REQUIRE_ONCE)"
-%left ','
-%left T_LOGICAL_OR
%token T_LOGICAL_OR "or (T_LOGICAL_OR)"
-%left T_LOGICAL_XOR
%token T_LOGICAL_XOR "xor (T_LOGICAL_XOR)"
-%left T_LOGICAL_AND
%token T_LOGICAL_AND "and (T_LOGICAL_AND)"
-%right T_PRINT
%token T_PRINT "print (T_PRINT)"
-%right T_YIELD
%token T_YIELD "yield (T_YIELD)"
-%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL
%token T_PLUS_EQUAL "+= (T_PLUS_EQUAL)"
%token T_MINUS_EQUAL "-= (T_MINUS_EQUAL)"
%token T_MUL_EQUAL "*= (T_MUL_EQUAL)"
@@ -84,32 +121,17 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%token T_XOR_EQUAL "^= (T_XOR_EQUAL)"
%token T_SL_EQUAL "<<= (T_SL_EQUAL)"
%token T_SR_EQUAL ">>= (T_SR_EQUAL)"
-%left '?' ':'
-%left T_BOOLEAN_OR
%token T_BOOLEAN_OR "|| (T_BOOLEAN_OR)"
-%left T_BOOLEAN_AND
%token T_BOOLEAN_AND "&& (T_BOOLEAN_AND)"
-%left '|'
-%left '^'
-%left '&'
-%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL
%token T_IS_EQUAL "== (T_IS_EQUAL)"
%token T_IS_NOT_EQUAL "!= (T_IS_NOT_EQUAL)"
%token T_IS_IDENTICAL "=== (T_IS_IDENTICAL)"
%token T_IS_NOT_IDENTICAL "!== (T_IS_NOT_IDENTICAL)"
-%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
%token T_IS_SMALLER_OR_EQUAL "<= (T_IS_SMALLER_OR_EQUAL)"
%token T_IS_GREATER_OR_EQUAL ">= (T_IS_GREATER_OR_EQUAL)"
-%left T_SL T_SR
%token T_SL "<< (T_SL)"
%token T_SR ">> (T_SR)"
-%left '+' '-' '.'
-%left '*' '/' '%'
-%right '!'
-%nonassoc T_INSTANCEOF
%token T_INSTANCEOF "instanceof (T_INSTANCEOF)"
-%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
-%right T_POW
%token T_INC "++ (T_INC)"
%token T_DEC "-- (T_DEC)"
%token T_INT_CAST "(int) (T_INT_CAST)"
@@ -119,29 +141,15 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%token T_OBJECT_CAST "(object) (T_OBJECT_CAST)"
%token T_BOOL_CAST "(bool) (T_BOOL_CAST)"
%token T_UNSET_CAST "(unset) (T_UNSET_CAST)"
-%right '['
-%nonassoc T_NEW T_CLONE
%token T_NEW "new (T_NEW)"
%token T_CLONE "clone (T_CLONE)"
%token T_EXIT "exit (T_EXIT)"
%token T_IF "if (T_IF)"
-%left T_ELSEIF
%token T_ELSEIF "elseif (T_ELSEIF)"
-%left T_ELSE
%token T_ELSE "else (T_ELSE)"
-%left T_ENDIF
%token T_ENDIF "endif (T_ENDIF)"
-%token T_LNUMBER "integer number (T_LNUMBER)"
-%token T_DNUMBER "floating-point number (T_DNUMBER)"
-%token T_STRING "identifier (T_STRING)"
-%token T_STRING_VARNAME "variable name (T_STRING_VARNAME)"
-%token T_VARIABLE "variable (T_VARIABLE)"
-%token T_NUM_STRING "number (T_NUM_STRING)"
-%token T_INLINE_HTML
%token T_CHARACTER
%token T_BAD_CHARACTER
-%token T_ENCAPSED_AND_WHITESPACE "quoted-string and whitespace (T_ENCAPSED_AND_WHITESPACE)"
-%token T_CONSTANT_ENCAPSED_STRING "quoted-string (T_CONSTANT_ENCAPSED_STRING)"
%token T_ECHO "echo (T_ECHO)"
%token T_DO "do (T_DO)"
%token T_WHILE "while (T_WHILE)"
@@ -170,7 +178,6 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%token T_USE "use (T_USE)"
%token T_INSTEADOF "insteadof (T_INSTEADOF)"
%token T_GLOBAL "global (T_GLOBAL)"
-%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
%token T_STATIC "static (T_STATIC)"
%token T_ABSTRACT "abstract (T_ABSTRACT)"
%token T_FINAL "final (T_FINAL)"
@@ -192,12 +199,13 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%token T_LIST "list (T_LIST)"
%token T_ARRAY "array (T_ARRAY)"
%token T_CALLABLE "callable (T_CALLABLE)"
+%token T_LINE "__LINE__ (T_LINE)"
+%token T_FILE "__FILE__ (T_FILE)"
+%token T_DIR "__DIR__ (T_DIR)"
%token T_CLASS_C "__CLASS__ (T_CLASS_C)"
%token T_TRAIT_C "__TRAIT__ (T_TRAIT_C)"
%token T_METHOD_C "__METHOD__ (T_METHOD_C)"
%token T_FUNC_C "__FUNCTION__ (T_FUNC_C)"
-%token T_LINE "__LINE__ (T_LINE)"
-%token T_FILE "__FILE__ (T_FILE)"
%token T_COMMENT "comment (T_COMMENT)"
%token T_DOC_COMMENT "doc comment (T_DOC_COMMENT)"
%token T_OPEN_TAG "open tag (T_OPEN_TAG)"
@@ -211,293 +219,255 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%token T_PAAMAYIM_NEKUDOTAYIM ":: (T_PAAMAYIM_NEKUDOTAYIM)"
%token T_NAMESPACE "namespace (T_NAMESPACE)"
%token T_NS_C "__NAMESPACE__ (T_NS_C)"
-%token T_DIR "__DIR__ (T_DIR)"
%token T_NS_SEPARATOR "\\ (T_NS_SEPARATOR)"
%token T_ELLIPSIS "... (T_ELLIPSIS)"
%token T_POW "** (T_POW)"
%token T_POW_EQUAL "**= (T_POW_EQUAL)"
+%type <ast> top_statement namespace_name name statement function_declaration_statement
+%type <ast> class_declaration_statement use_declaration const_decl inner_statement
+%type <ast> expr optional_expr while_statement for_statement foreach_variable
+%type <ast> foreach_statement declare_statement finally_statement unset_variable variable
+%type <ast> extends_from parameter optional_type argument expr_without_variable global_var
+%type <ast> static_var class_statement trait_adaptation trait_precedence trait_alias
+%type <ast> absolute_trait_method_reference trait_method_reference property echo_expr
+%type <ast> new_expr class_name class_name_reference simple_variable internal_functions_in_yacc
+%type <ast> exit_expr scalar backticks_expr lexical_var function_call member_name
+%type <ast> variable_class_name dereferencable_scalar class_name_scalar constant dereferencable
+%type <ast> callable_expr callable_variable static_member new_variable
+%type <ast> assignment_list_element array_pair encaps_var encaps_var_offset isset_variables
+%type <ast> isset_variable
+%type <ast> top_statement_list use_declarations const_list inner_statement_list if_stmt
+%type <ast> alt_if_stmt for_exprs switch_case_list global_var_list static_var_list
+%type <ast> echo_expr_list unset_variables catch_list parameter_list class_statement_list
+%type <ast> implements_list interface_extends_list case_list if_stmt_without_else
+%type <ast> non_empty_parameter_list argument_list non_empty_argument_list property_list
+%type <ast> class_const_list name_list trait_adaptations method_body non_empty_for_exprs
+%type <ast> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars
+%type <ast> lexical_var_list encaps_list array_pair_list non_empty_array_pair_list
+%type <ast> assignment_list
+
+%type <num> returns_ref function is_reference is_variadic class_type variable_modifiers
+%type <num> method_modifiers trait_modifiers non_empty_member_modifiers member_modifier
+
+%type <str> backup_doc_comment
+
%% /* Rules */
start:
- top_statement_list { zend_do_end_compilation(TSRMLS_C); }
+ top_statement_list { CG(ast) = $1; }
;
top_statement_list:
- top_statement_list { zend_do_extended_info(TSRMLS_C); } top_statement { HANDLE_INTERACTIVE(); }
- | /* empty */
+ top_statement_list top_statement { $$ = zend_ast_list_add($1, $2); }
+ | /* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); }
;
namespace_name:
- T_STRING { $$ = $1; }
- | namespace_name T_NS_SEPARATOR T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
+ T_STRING { $$ = $1; }
+ | namespace_name T_NS_SEPARATOR T_STRING { $$ = zend_ast_append_str($1, $3); }
+;
+
+name:
+ namespace_name { $$ = $1; $$->attr = ZEND_NAME_NOT_FQ; }
+ | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$ = $3; $$->attr = ZEND_NAME_RELATIVE; }
+ | T_NS_SEPARATOR namespace_name { $$ = $2; $$->attr = ZEND_NAME_FQ; }
;
top_statement:
- statement { zend_verify_namespace(TSRMLS_C); }
- | function_declaration_statement { zend_verify_namespace(TSRMLS_C); zend_do_early_binding(TSRMLS_C); }
- | class_declaration_statement { zend_verify_namespace(TSRMLS_C); zend_do_early_binding(TSRMLS_C); }
- | T_HALT_COMPILER '(' ')' ';' { zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
- | T_NAMESPACE namespace_name ';' { zend_do_begin_namespace(&$2, 0 TSRMLS_CC); }
- | T_NAMESPACE namespace_name '{' { zend_do_begin_namespace(&$2, 1 TSRMLS_CC); }
- top_statement_list '}' { zend_do_end_namespace(TSRMLS_C); }
- | T_NAMESPACE '{' { zend_do_begin_namespace(NULL, 1 TSRMLS_CC); }
- top_statement_list '}' { zend_do_end_namespace(TSRMLS_C); }
- | T_USE use_declarations ';' { zend_verify_namespace(TSRMLS_C); }
- | T_USE T_FUNCTION use_function_declarations ';' { zend_verify_namespace(TSRMLS_C); }
- | T_USE T_CONST use_const_declarations ';' { zend_verify_namespace(TSRMLS_C); }
- | constant_declaration ';' { zend_verify_namespace(TSRMLS_C); }
+ statement { $$ = $1; }
+ | function_declaration_statement { $$ = $1; }
+ | class_declaration_statement { $$ = $1; }
+ | T_HALT_COMPILER '(' ')' ';'
+ { $$ = zend_ast_create(ZEND_AST_HALT_COMPILER,
+ zend_ast_create_zval_from_long(zend_get_scanned_file_offset(TSRMLS_C)));
+ zend_stop_lexing(TSRMLS_C); }
+ | T_NAMESPACE namespace_name ';'
+ { $$ = zend_ast_create(ZEND_AST_NAMESPACE, $2, NULL);
+ RESET_DOC_COMMENT(); }
+ | T_NAMESPACE namespace_name { RESET_DOC_COMMENT(); }
+ '{' top_statement_list '}'
+ { $$ = zend_ast_create(ZEND_AST_NAMESPACE, $2, $5); }
+ | T_NAMESPACE { RESET_DOC_COMMENT(); }
+ '{' top_statement_list '}'
+ { $$ = zend_ast_create(ZEND_AST_NAMESPACE, NULL, $4); }
+ | T_USE use_declarations ';' { $$ = $2; $$->attr = T_CLASS; }
+ | T_USE T_FUNCTION use_declarations ';' { $$ = $3; $$->attr = T_FUNCTION; }
+ | T_USE T_CONST use_declarations ';' { $$ = $3; $$->attr = T_CONST; }
+ | T_CONST const_list ';' { $$ = $2; }
;
use_declarations:
use_declarations ',' use_declaration
+ { $$ = zend_ast_list_add($1, $3); }
| use_declaration
+ { $$ = zend_ast_create_list(1, ZEND_AST_USE, $1); }
;
use_declaration:
- namespace_name { zend_do_use(&$1, NULL, 0 TSRMLS_CC); }
- | namespace_name T_AS T_STRING { zend_do_use(&$1, &$3, 0 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name { zend_do_use(&$2, NULL, 1 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use(&$2, &$4, 1 TSRMLS_CC); }
+ namespace_name
+ { $$ = zend_ast_create(ZEND_AST_USE_ELEM, $1, NULL); }
+ | namespace_name T_AS T_STRING
+ { $$ = zend_ast_create(ZEND_AST_USE_ELEM, $1, $3); }
+ | T_NS_SEPARATOR namespace_name
+ { $$ = zend_ast_create(ZEND_AST_USE_ELEM, $2, NULL); }
+ | T_NS_SEPARATOR namespace_name T_AS T_STRING
+ { $$ = zend_ast_create(ZEND_AST_USE_ELEM, $2, $4); }
;
-use_function_declarations:
- use_function_declarations ',' use_function_declaration
- | use_function_declaration
-;
-
-use_function_declaration:
- namespace_name { zend_do_use_function(&$1, NULL, 0 TSRMLS_CC); }
- | namespace_name T_AS T_STRING { zend_do_use_function(&$1, &$3, 0 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name { zend_do_use_function(&$2, NULL, 1 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use_function(&$2, &$4, 1 TSRMLS_CC); }
-;
-
-use_const_declarations:
- use_const_declarations ',' use_const_declaration
- | use_const_declaration
-;
-
-use_const_declaration:
- namespace_name { zend_do_use_const(&$1, NULL, 0 TSRMLS_CC); }
- | namespace_name T_AS T_STRING { zend_do_use_const(&$1, &$3, 0 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name { zend_do_use_const(&$2, NULL, 1 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use_const(&$2, &$4, 1 TSRMLS_CC); }
-;
-
-constant_declaration:
- constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_constant(&$3, &$5 TSRMLS_CC); }
- | T_CONST T_STRING '=' static_scalar { zend_do_declare_constant(&$2, &$4 TSRMLS_CC); }
+const_list:
+ const_list ',' const_decl { $$ = zend_ast_list_add($1, $3); }
+ | const_decl { $$ = zend_ast_create_list(1, ZEND_AST_CONST_DECL, $1); }
;
inner_statement_list:
- inner_statement_list { zend_do_extended_info(TSRMLS_C); } inner_statement { HANDLE_INTERACTIVE(); }
+ inner_statement_list inner_statement
+ { $$ = zend_ast_list_add($1, $2); }
| /* empty */
+ { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); }
;
inner_statement:
- statement
- | function_declaration_statement
- | class_declaration_statement
- | T_HALT_COMPILER '(' ')' ';' { zend_error_noreturn(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope"); }
+ statement { $$ = $1; }
+ | function_declaration_statement { $$ = $1; }
+ | class_declaration_statement { $$ = $1; }
+ | T_HALT_COMPILER '(' ')' ';'
+ { $$ = NULL; zend_error_noreturn(E_COMPILE_ERROR,
+ "__HALT_COMPILER() can only be used from the outermost scope"); }
;
statement:
- unticked_statement { DO_TICKS(); }
- | T_STRING ':' { zend_do_label(&$1 TSRMLS_CC); }
+ '{' inner_statement_list '}' { $$ = $2; }
+ | if_stmt { $$ = $1; }
+ | alt_if_stmt { $$ = $1; }
+ | T_WHILE '(' expr ')' while_statement
+ { $$ = zend_ast_create(ZEND_AST_WHILE, $3, $5); }
+ | T_DO statement T_WHILE '(' expr ')' ';'
+ { $$ = zend_ast_create(ZEND_AST_DO_WHILE, $2, $5); }
+ | T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement
+ { $$ = zend_ast_create(ZEND_AST_FOR, $3, $5, $7, $9); }
+ | T_SWITCH '(' expr ')' switch_case_list
+ { $$ = zend_ast_create(ZEND_AST_SWITCH, $3, $5); }
+ | T_BREAK optional_expr ';' { $$ = zend_ast_create(ZEND_AST_BREAK, $2); }
+ | T_CONTINUE optional_expr ';' { $$ = zend_ast_create(ZEND_AST_CONTINUE, $2); }
+ | T_RETURN optional_expr ';' { $$ = zend_ast_create(ZEND_AST_RETURN, $2); }
+ | T_GLOBAL global_var_list ';' { $$ = $2; }
+ | T_STATIC static_var_list ';' { $$ = $2; }
+ | T_ECHO echo_expr_list ';' { $$ = $2; }
+ | T_INLINE_HTML { $$ = zend_ast_create(ZEND_AST_ECHO, $1); }
+ | expr ';' { $$ = $1; }
+ | T_UNSET '(' unset_variables ')' ';' { $$ = $3; }
+ | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
+ { $$ = zend_ast_create(ZEND_AST_FOREACH, $3, $5, NULL, $7); }
+ | T_FOREACH '(' expr T_AS foreach_variable T_DOUBLE_ARROW foreach_variable ')'
+ foreach_statement
+ { $$ = zend_ast_create(ZEND_AST_FOREACH, $3, $7, $5, $9); }
+ | T_DECLARE '(' const_list ')'
+ { zend_handle_encoding_declaration($3 TSRMLS_CC); }
+ declare_statement
+ { $$ = zend_ast_create(ZEND_AST_DECLARE, $3, $6); }
+ | ';' /* empty statement */ { $$ = NULL; }
+ | T_TRY '{' inner_statement_list '}' catch_list finally_statement
+ { $$ = zend_ast_create(ZEND_AST_TRY, $3, $5, $6); }
+ | T_THROW expr ';' { $$ = zend_ast_create(ZEND_AST_THROW, $2); }
+ | T_GOTO T_STRING ';' { $$ = zend_ast_create(ZEND_AST_GOTO, $2); }
+ | T_STRING ':' { $$ = zend_ast_create(ZEND_AST_LABEL, $1); }
+;
+
+catch_list:
+ /* empty */
+ { $$ = zend_ast_create_list(0, ZEND_AST_CATCH_LIST); }
+ | catch_list T_CATCH '(' name T_VARIABLE ')' '{' inner_statement_list '}'
+ { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_CATCH, $4, $5, $8)); }
;
-unticked_statement:
- '{' inner_statement_list '}'
- | T_IF parenthesis_expr { zend_do_if_cond(&$2, &$1 TSRMLS_CC); } statement { zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); }
- | T_IF parenthesis_expr ':' { zend_do_if_cond(&$2, &$1 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } new_elseif_list new_else_single T_ENDIF ';' { zend_do_if_end(TSRMLS_C); }
- | T_WHILE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); } parenthesis_expr { zend_do_while_cond(&$3, &$$ TSRMLS_CC); } while_statement { zend_do_while_end(&$1, &$4 TSRMLS_CC); }
- | T_DO { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_do_while_begin(TSRMLS_C); } statement T_WHILE { $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); } parenthesis_expr ';' { zend_do_do_while_end(&$1, &$4, &$6 TSRMLS_CC); }
- | T_FOR
- '('
- for_expr
- ';' { zend_do_free(&$3 TSRMLS_CC); $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); }
- for_expr
- ';' { zend_do_extended_info(TSRMLS_C); zend_do_for_cond(&$6, &$7 TSRMLS_CC); }
- for_expr
- ')' { zend_do_free(&$9 TSRMLS_CC); zend_do_for_before_statement(&$4, &$7 TSRMLS_CC); }
- for_statement { zend_do_for_end(&$7 TSRMLS_CC); }
- | T_SWITCH parenthesis_expr { zend_do_switch_cond(&$2 TSRMLS_CC); } switch_case_list { zend_do_switch_end(&$4 TSRMLS_CC); }
- | T_BREAK ';' { zend_do_brk_cont(ZEND_BRK, NULL TSRMLS_CC); }
- | T_BREAK expr ';' { zend_do_brk_cont(ZEND_BRK, &$2 TSRMLS_CC); }
- | T_CONTINUE ';' { zend_do_brk_cont(ZEND_CONT, NULL TSRMLS_CC); }
- | T_CONTINUE expr ';' { zend_do_brk_cont(ZEND_CONT, &$2 TSRMLS_CC); }
- | T_RETURN ';' { zend_do_return(NULL, 0 TSRMLS_CC); }
- | T_RETURN expr_without_variable ';' { zend_do_return(&$2, 0 TSRMLS_CC); }
- | T_RETURN variable ';' { zend_do_return(&$2, 1 TSRMLS_CC); }
- | yield_expr ';' { zend_do_free(&$1 TSRMLS_CC); }
- | T_GLOBAL global_var_list ';'
- | T_STATIC static_var_list ';'
- | T_ECHO echo_expr_list ';'
- | T_INLINE_HTML { zend_do_echo(&$1 TSRMLS_CC); }
- | expr ';' { zend_do_free(&$1 TSRMLS_CC); }
- | T_UNSET '(' unset_variables ')' ';'
- | T_FOREACH '(' variable T_AS
- { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 1 TSRMLS_CC); }
- foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
- foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
- | T_FOREACH '(' expr_without_variable T_AS
- { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
- foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
- foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
- | T_DECLARE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); }
- | ';' /* empty statement */
- | T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
- catch_statement { zend_do_bind_catch(&$1, &$6 TSRMLS_CC); }
- finally_statement { zend_do_end_finally(&$1, &$6, &$8 TSRMLS_CC); }
- | T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); }
- | T_GOTO T_STRING ';' { zend_do_goto(&$2 TSRMLS_CC); }
-;
-
-catch_statement:
- /* empty */ { $$.op_type = IS_UNUSED; }
- | T_CATCH '(' { zend_initialize_try_catch_element(&$1 TSRMLS_CC); }
- fully_qualified_class_name { zend_do_first_catch(&$2 TSRMLS_CC); }
- T_VARIABLE ')' { zend_do_begin_catch(&$1, &$4, &$6, &$2 TSRMLS_CC); }
- '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
- additional_catches { zend_do_mark_last_catch(&$2, &$13 TSRMLS_CC); $$ = $1;}
-
finally_statement:
- /* empty */ { $$.op_type = IS_UNUSED; }
- | T_FINALLY { zend_do_finally(&$1 TSRMLS_CC); } '{' inner_statement_list '}' { $$ = $1; }
-;
-
-additional_catches:
- non_empty_additional_catches { $$ = $1; }
- | /* empty */ { $$.u.op.opline_num = -1; }
-;
-
-non_empty_additional_catches:
- additional_catch { $$ = $1; }
- | non_empty_additional_catches additional_catch { $$ = $2; }
-;
-
-additional_catch:
- T_CATCH '(' fully_qualified_class_name { $$.u.op.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, NULL TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
+ /* empty */ { $$ = NULL; }
+ | T_FINALLY '{' inner_statement_list '}' { $$ = $3; }
;
unset_variables:
- unset_variable
- | unset_variables ',' unset_variable
+ unset_variable { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); }
+ | unset_variables ',' unset_variable { $$ = zend_ast_list_add($1, $3); }
;
unset_variable:
- variable { zend_do_end_variable_parse(&$1, BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); }
+ variable { $$ = zend_ast_create(ZEND_AST_UNSET, $1); }
;
function_declaration_statement:
- unticked_function_declaration_statement { DO_TICKS(); }
-;
-
-class_declaration_statement:
- unticked_class_declaration_statement { DO_TICKS(); }
+ function returns_ref T_STRING '(' parameter_list ')' backup_doc_comment
+ '{' inner_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_FUNC_DECL, $2, $1, $7,
+ zend_ast_get_str($3), $5, NULL, $9); }
;
is_reference:
- /* empty */ { $$.op_type = 0; }
- | '&' { $$.op_type = 1; }
+ /* empty */ { $$ = 0; }
+ | '&' { $$ = ZEND_PARAM_REF; }
;
is_variadic:
- /* empty */ { $$.op_type = 0; }
- | T_ELLIPSIS { $$.op_type = 1; }
-;
-
-unticked_function_declaration_statement:
- function is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$3, 0, $2.op_type, NULL TSRMLS_CC); }
- '(' parameter_list ')'
- '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
+ /* empty */ { $$ = 0; }
+ | T_ELLIPSIS { $$ = ZEND_PARAM_VARIADIC; }
;
-unticked_class_declaration_statement:
- class_entry_type T_STRING extends_from
- { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); }
- implements_list
- '{'
- class_statement_list
- '}' { zend_do_end_class_declaration(&$1, &$3 TSRMLS_CC); }
- | interface_entry T_STRING
- { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); }
- interface_extends_list
- '{'
- class_statement_list
- '}' { zend_do_end_class_declaration(&$1, NULL TSRMLS_CC); }
+class_declaration_statement:
+ class_type { $<num>$ = CG(zend_lineno); }
+ T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $<num>2, $6,
+ zend_ast_get_str($3), $4, $5, $8); }
+ | T_INTERFACE { $<num>$ = CG(zend_lineno); }
+ T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $<num>2, $5,
+ zend_ast_get_str($3), NULL, $4, $7); }
;
-
-class_entry_type:
- T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = 0; }
- | T_ABSTRACT T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; }
- | T_TRAIT { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_TRAIT; }
- | T_FINAL T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_FINAL_CLASS; }
+class_type:
+ T_CLASS { $$ = 0; }
+ | T_ABSTRACT T_CLASS { $$ = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; }
+ | T_FINAL T_CLASS { $$ = ZEND_ACC_FINAL_CLASS; }
+ | T_TRAIT { $$ = ZEND_ACC_TRAIT; }
;
extends_from:
- /* empty */ { $$.op_type = IS_UNUSED; }
- | T_EXTENDS fully_qualified_class_name { zend_do_fetch_class(&$$, &$2 TSRMLS_CC); }
-;
-
-interface_entry:
- T_INTERFACE { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_INTERFACE; }
+ /* empty */ { $$ = NULL; }
+ | T_EXTENDS name { $$ = $2; }
;
interface_extends_list:
- /* empty */
- | T_EXTENDS interface_list
+ /* empty */ { $$ = NULL; }
+ | T_EXTENDS name_list { $$ = $2; }
;
implements_list:
- /* empty */
- | T_IMPLEMENTS interface_list
-;
-
-interface_list:
- fully_qualified_class_name { zend_do_implements_interface(&$1 TSRMLS_CC); }
- | interface_list ',' fully_qualified_class_name { zend_do_implements_interface(&$3 TSRMLS_CC); }
-;
-
-foreach_optional_arg:
- /* empty */ { $$.op_type = IS_UNUSED; }
- | T_DOUBLE_ARROW foreach_variable { $$ = $2; }
+ /* empty */ { $$ = NULL; }
+ | T_IMPLEMENTS name_list { $$ = $2; }
;
foreach_variable:
- variable { zend_check_writable_variable(&$1); $$ = $1; }
- | '&' variable { zend_check_writable_variable(&$2); $$ = $2; $$.EA |= ZEND_PARSED_REFERENCE_VARIABLE; }
- | T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' { $$ = $1; $$.EA = ZEND_PARSED_LIST_EXPR; }
+ variable { $$ = $1; }
+ | '&' variable { $$ = zend_ast_create(ZEND_AST_REF, $2); }
+ | T_LIST '(' assignment_list ')' { $$ = $3; }
;
for_statement:
- statement
- | ':' inner_statement_list T_ENDFOR ';'
+ statement { $$ = $1; }
+ | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; }
;
-
foreach_statement:
- statement
- | ':' inner_statement_list T_ENDFOREACH ';'
+ statement { $$ = $1; }
+ | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; }
;
-
declare_statement:
- statement
- | ':' inner_statement_list T_ENDDECLARE ';'
+ statement { $$ = $1; }
+ | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; }
;
-
-declare_list:
- T_STRING '=' static_scalar { zend_do_declare_stmt(&$1, &$3 TSRMLS_CC); }
- | declare_list ',' T_STRING '=' static_scalar { zend_do_declare_stmt(&$3, &$5 TSRMLS_CC); }
-;
-
-
switch_case_list:
'{' case_list '}' { $$ = $2; }
| '{' ';' case_list '}' { $$ = $3; }
@@ -505,14 +475,14 @@ switch_case_list:
| ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; }
;
-
case_list:
- /* empty */ { $$.op_type = IS_UNUSED; }
- | case_list T_CASE expr case_separator { zend_do_extended_info(TSRMLS_C); zend_do_case_before_statement(&$1, &$2, &$3 TSRMLS_CC); } inner_statement_list { zend_do_case_after_statement(&$$, &$2 TSRMLS_CC); $$.op_type = IS_CONST; }
- | case_list T_DEFAULT case_separator { zend_do_extended_info(TSRMLS_C); zend_do_default_before_statement(&$1, &$2 TSRMLS_CC); } inner_statement_list { zend_do_case_after_statement(&$$, &$2 TSRMLS_CC); $$.op_type = IS_CONST; }
+ /* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_SWITCH_LIST); }
+ | case_list T_CASE expr case_separator inner_statement_list
+ { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_SWITCH_CASE, $3, $5)); }
+ | case_list T_DEFAULT case_separator inner_statement_list
+ { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_SWITCH_CASE, NULL, $4)); }
;
-
case_separator:
':'
| ';'
@@ -520,547 +490,474 @@ case_separator:
while_statement:
- statement
- | ':' inner_statement_list T_ENDWHILE ';'
+ statement { $$ = $1; }
+ | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; }
;
-
-elseif_list:
- /* empty */
- | elseif_list T_ELSEIF parenthesis_expr { zend_do_if_cond(&$3, &$2 TSRMLS_CC); } statement { zend_do_if_after_statement(&$2, 0 TSRMLS_CC); }
+if_stmt_without_else:
+ T_IF '(' expr ')' statement
+ { $$ = zend_ast_create_list(1, ZEND_AST_IF,
+ zend_ast_create(ZEND_AST_IF_ELEM, $3, $5)); }
+ | if_stmt_without_else T_ELSEIF '(' expr ')' statement
+ { $$ = zend_ast_list_add($1,
+ zend_ast_create(ZEND_AST_IF_ELEM, $4, $6)); }
;
-
-new_elseif_list:
- /* empty */
- | new_elseif_list T_ELSEIF parenthesis_expr ':' { zend_do_if_cond(&$3, &$2 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$2, 0 TSRMLS_CC); }
+if_stmt:
+ if_stmt_without_else { $$ = $1; }
+ | if_stmt_without_else T_ELSE statement
+ { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_IF_ELEM, NULL, $3)); }
;
-
-else_single:
- /* empty */
- | T_ELSE statement
+alt_if_stmt_without_else:
+ T_IF '(' expr ')' ':' inner_statement_list
+ { $$ = zend_ast_create_list(1, ZEND_AST_IF,
+ zend_ast_create(ZEND_AST_IF_ELEM, $3, $6)); }
+ | alt_if_stmt_without_else T_ELSEIF '(' expr ')' ':' inner_statement_list
+ { $$ = zend_ast_list_add($1,
+ zend_ast_create(ZEND_AST_IF_ELEM, $4, $7)); }
;
-
-new_else_single:
- /* empty */
- | T_ELSE ':' inner_statement_list
+alt_if_stmt:
+ alt_if_stmt_without_else T_ENDIF ';' { $$ = $1; }
+ | alt_if_stmt_without_else T_ELSE ':' inner_statement_list T_ENDIF ';'
+ { $$ = zend_ast_list_add($1,
+ zend_ast_create(ZEND_AST_IF_ELEM, NULL, $4)); }
;
-
parameter_list:
- non_empty_parameter_list
- | /* empty */
+ non_empty_parameter_list { $$ = $1; }
+ | /* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_PARAM_LIST); }
;
non_empty_parameter_list:
parameter
+ { $$ = zend_ast_create_list(1, ZEND_AST_PARAM_LIST, $1); }
| non_empty_parameter_list ',' parameter
+ { $$ = zend_ast_list_add($1, $3); }
;
parameter:
- optional_class_type is_reference is_variadic T_VARIABLE
- { zend_do_receive_param(ZEND_RECV, &$4, NULL, &$1, $2.op_type, $3.op_type TSRMLS_CC); }
- | optional_class_type is_reference is_variadic T_VARIABLE '=' static_scalar
- { zend_do_receive_param(ZEND_RECV_INIT, &$4, &$6, &$1, $2.op_type, $3.op_type TSRMLS_CC); }
+ optional_type is_reference is_variadic T_VARIABLE
+ { $$ = zend_ast_create_ex(ZEND_AST_PARAM, $2 | $3, $1, $4, NULL); }
+ | optional_type is_reference is_variadic T_VARIABLE '=' expr
+ { $$ = zend_ast_create_ex(ZEND_AST_PARAM, $2 | $3, $1, $4, $6); }
;
-optional_class_type:
- /* empty */ { $$.op_type = IS_UNUSED; }
- | T_ARRAY { $$.op_type = IS_CONST; Z_TYPE_INFO($$.u.constant)=IS_ARRAY; }
- | T_CALLABLE { $$.op_type = IS_CONST; Z_TYPE_INFO($$.u.constant)=IS_CALLABLE; }
- | fully_qualified_class_name { $$ = $1; }
+optional_type:
+ /* empty */ { $$ = NULL; }
+ | T_ARRAY { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_ARRAY); }
+ | T_CALLABLE { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_CALLABLE); }
+ | name { $$ = $1; }
;
-
-function_call_parameter_list:
- '(' ')' { Z_LVAL($$.u.constant) = 0; }
- | '(' non_empty_function_call_parameter_list ')' { $$ = $2; }
- | '(' yield_expr ')' { zend_do_pass_param(&$2, ZEND_SEND_VAL TSRMLS_CC); }
+argument_list:
+ '(' ')' { $$ = zend_ast_create_list(0, ZEND_AST_ARG_LIST); }
+ | '(' non_empty_argument_list ')' { $$ = $2; }
;
-
-non_empty_function_call_parameter_list:
- function_call_parameter
- | non_empty_function_call_parameter_list ',' function_call_parameter
+non_empty_argument_list:
+ argument
+ { $$ = zend_ast_create_list(1, ZEND_AST_ARG_LIST, $1); }
+ | non_empty_argument_list ',' argument
+ { $$ = zend_ast_list_add($1, $3); }
;
-function_call_parameter:
- expr_without_variable { zend_do_pass_param(&$1, ZEND_SEND_VAL TSRMLS_CC); }
- | variable { zend_do_pass_param(&$1, ZEND_SEND_VAR TSRMLS_CC); }
- | '&' w_variable { zend_do_pass_param(&$2, ZEND_SEND_REF TSRMLS_CC); }
- | T_ELLIPSIS expr { zend_do_unpack_params(&$2 TSRMLS_CC); }
+argument:
+ expr { $$ = $1; }
+ | T_ELLIPSIS expr { $$ = zend_ast_create(ZEND_AST_UNPACK, $2); }
;
global_var_list:
- global_var_list ',' global_var { zend_do_fetch_global_variable(&$3, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }
- | global_var { zend_do_fetch_global_variable(&$1, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }
+ global_var_list ',' global_var { $$ = zend_ast_list_add($1, $3); }
+ | global_var { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); }
;
-
global_var:
- T_VARIABLE { $$ = $1; }
- | '$' r_variable { $$ = $2; }
- | '$' '{' expr '}' { $$ = $3; }
+ simple_variable
+ { $$ = zend_ast_create(ZEND_AST_GLOBAL, zend_ast_create(ZEND_AST_VAR, $1)); }
;
static_var_list:
- static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
- | static_var_list ',' T_VARIABLE '=' static_scalar { Z_CONST_FLAGS($5.u.constant) = 0; zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); }
- | T_VARIABLE { zend_do_fetch_static_variable(&$1, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
- | T_VARIABLE '=' static_scalar { Z_CONST_FLAGS($3.u.constant) = 0; zend_do_fetch_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); }
+ static_var_list ',' static_var { $$ = zend_ast_list_add($1, $3); }
+ | static_var { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); }
+;
+static_var:
+ T_VARIABLE { $$ = zend_ast_create(ZEND_AST_STATIC, $1, NULL); }
+ | T_VARIABLE '=' expr { $$ = zend_ast_create(ZEND_AST_STATIC, $1, $3); }
;
class_statement_list:
class_statement_list class_statement
+ { $$ = zend_ast_list_add($1, $2); }
| /* empty */
+ { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); }
;
class_statement:
- variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';'
- | class_constant_declaration ';'
- | trait_use_statement
- | method_modifiers function is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); }
- '(' parameter_list ')'
- method_body { zend_do_abstract_method(&$4, &$1, &$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
-;
-
-trait_use_statement:
- T_USE trait_list trait_adaptations
+ variable_modifiers property_list ';'
+ { $$ = zend_ast_append_doc_comment($2 TSRMLS_CC); $$->attr = $1; }
+ | T_CONST class_const_list ';'
+ { $$ = $2; RESET_DOC_COMMENT(); }
+ | T_USE name_list trait_adaptations
+ { $$ = zend_ast_create(ZEND_AST_USE_TRAIT, $2, $3); }
+ | method_modifiers function returns_ref T_STRING '(' parameter_list ')' backup_doc_comment
+ method_body
+ { $$ = zend_ast_create_decl(ZEND_AST_METHOD, $3 | $1, $2, $8,
+ zend_ast_get_str($4), $6, NULL, $9); }
;
-trait_list:
- fully_qualified_class_name { zend_do_use_trait(&$1 TSRMLS_CC); }
- | trait_list ',' fully_qualified_class_name { zend_do_use_trait(&$3 TSRMLS_CC); }
+name_list:
+ name { $$ = zend_ast_create_list(1, ZEND_AST_NAME_LIST, $1); }
+ | name_list ',' name { $$ = zend_ast_list_add($1, $3); }
;
trait_adaptations:
- ';'
- | '{' trait_adaptation_list '}'
+ ';' { $$ = NULL; }
+ | '{' '}' { $$ = NULL; }
+ | '{' trait_adaptation_list '}' { $$ = $2; }
;
trait_adaptation_list:
- /* empty */
- | non_empty_trait_adaptation_list
+ trait_adaptation
+ { $$ = zend_ast_create_list(1, ZEND_AST_TRAIT_ADAPTATIONS, $1); }
+ | trait_adaptation_list trait_adaptation
+ { $$ = zend_ast_list_add($1, $2); }
;
-non_empty_trait_adaptation_list:
- trait_adaptation_statement
- | non_empty_trait_adaptation_list trait_adaptation_statement
-;
-
-trait_adaptation_statement:
- trait_precedence ';'
- | trait_alias ';'
+trait_adaptation:
+ trait_precedence ';' { $$ = $1; }
+ | trait_alias ';' { $$ = $1; }
;
trait_precedence:
- trait_method_reference_fully_qualified T_INSTEADOF trait_reference_list { zend_add_trait_precedence(&$1, &$3 TSRMLS_CC); }
+ absolute_trait_method_reference T_INSTEADOF name_list
+ { $$ = zend_ast_create(ZEND_AST_TRAIT_PRECEDENCE, $1, $3); }
;
-trait_reference_list:
- fully_qualified_class_name { zend_resolve_class_name(&$1 TSRMLS_CC); zend_init_list(&$$.u.op.ptr, Z_STR($1.u.constant) TSRMLS_CC); }
- | trait_reference_list ',' fully_qualified_class_name { zend_resolve_class_name(&$3 TSRMLS_CC); zend_add_to_list(&$1.u.op.ptr, Z_STR($3.u.constant) TSRMLS_CC); $$ = $1; }
+trait_alias:
+ trait_method_reference T_AS trait_modifiers T_STRING
+ { $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, $3, $1, $4); }
+ | trait_method_reference T_AS member_modifier
+ { $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, $3, $1, NULL); }
;
trait_method_reference:
- T_STRING { zend_prepare_reference(&$$, NULL, &$1 TSRMLS_CC); }
- | trait_method_reference_fully_qualified { $$ = $1; }
+ T_STRING
+ { $$ = zend_ast_create(ZEND_AST_METHOD_REFERENCE, NULL, $1); }
+ | absolute_trait_method_reference { $$ = $1; }
;
-trait_method_reference_fully_qualified:
- fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_prepare_reference(&$$, &$1, &$3 TSRMLS_CC); }
-;
-
-trait_alias:
- trait_method_reference T_AS trait_modifiers T_STRING { zend_add_trait_alias(&$1, &$3, &$4 TSRMLS_CC); }
- | trait_method_reference T_AS member_modifier { zend_add_trait_alias(&$1, &$3, NULL TSRMLS_CC); }
+absolute_trait_method_reference:
+ name T_PAAMAYIM_NEKUDOTAYIM T_STRING
+ { $$ = zend_ast_create(ZEND_AST_METHOD_REFERENCE, $1, $3); }
;
trait_modifiers:
- /* empty */ { Z_LVAL($$.u.constant) = 0x0; } /* No change of methods visibility */
- | member_modifier { $$ = $1; } /* REM: Keep in mind, there are not only visibility modifiers */
+ /* empty */ { $$ = 0; }
+ | member_modifier { $$ = $1; }
;
method_body:
- ';' /* abstract method */ { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; }
- | '{' inner_statement_list '}' { Z_LVAL($$.u.constant) = 0; }
+ ';' /* abstract method */ { $$ = NULL; }
+ | '{' inner_statement_list '}' { $$ = $2; }
;
variable_modifiers:
non_empty_member_modifiers { $$ = $1; }
- | T_VAR { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
+ | T_VAR { $$ = ZEND_ACC_PUBLIC; }
;
method_modifiers:
- /* empty */ { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
- | non_empty_member_modifiers { $$ = $1; if (!(Z_LVAL($$.u.constant) & ZEND_ACC_PPP_MASK)) { Z_LVAL($$.u.constant) |= ZEND_ACC_PUBLIC; } }
+ /* empty */ { $$ = ZEND_ACC_PUBLIC; }
+ | non_empty_member_modifiers
+ { $$ = $1; if (!($$ & ZEND_ACC_PPP_MASK)) { $$ |= ZEND_ACC_PUBLIC; } }
;
non_empty_member_modifiers:
- member_modifier { $$ = $1; }
- | non_empty_member_modifiers member_modifier { Z_LVAL($$.u.constant) = zend_do_verify_access_types(&$1, &$2); }
+ member_modifier { $$ = $1; }
+ | non_empty_member_modifiers member_modifier
+ { $$ = zend_add_member_modifier($1, $2); }
;
member_modifier:
- T_PUBLIC { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
- | T_PROTECTED { Z_LVAL($$.u.constant) = ZEND_ACC_PROTECTED; }
- | T_PRIVATE { Z_LVAL($$.u.constant) = ZEND_ACC_PRIVATE; }
- | T_STATIC { Z_LVAL($$.u.constant) = ZEND_ACC_STATIC; }
- | T_ABSTRACT { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; }
- | T_FINAL { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; }
+ T_PUBLIC { $$ = ZEND_ACC_PUBLIC; }
+ | T_PROTECTED { $$ = ZEND_ACC_PROTECTED; }
+ | T_PRIVATE { $$ = ZEND_ACC_PRIVATE; }
+ | T_STATIC { $$ = ZEND_ACC_STATIC; }
+ | T_ABSTRACT { $$ = ZEND_ACC_ABSTRACT; }
+ | T_FINAL { $$ = ZEND_ACC_FINAL; }
;
-class_variable_declaration:
- class_variable_declaration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); }
- | class_variable_declaration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); }
- | T_VARIABLE { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); }
- | T_VARIABLE '=' static_scalar { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); }
+property_list:
+ property_list ',' property { $$ = zend_ast_list_add($1, $3); }
+ | property { $$ = zend_ast_create_list(1, ZEND_AST_PROP_DECL, $1); }
;
-class_constant_declaration:
- class_constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_class_constant(&$3, &$5 TSRMLS_CC); }
- | T_CONST T_STRING '=' static_scalar { zend_do_declare_class_constant(&$2, &$4 TSRMLS_CC); }
+property:
+ T_VARIABLE { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, NULL); }
+ | T_VARIABLE '=' expr
+ { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, $3); }
;
-echo_expr_list:
- echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); }
- | expr { zend_do_echo(&$1 TSRMLS_CC); }
-;
-
-
-for_expr:
- /* empty */ { $$.op_type = IS_CONST; ZVAL_BOOL(&$$.u.constant, 1); }
- | non_empty_for_expr { $$ = $1; }
+class_const_list:
+ class_const_list ',' const_decl { $$ = zend_ast_list_add($1, $3); }
+ | const_decl { $$ = zend_ast_create_list(1, ZEND_AST_CLASS_CONST_DECL, $1); }
;
-non_empty_for_expr:
- non_empty_for_expr ',' { zend_do_free(&$1 TSRMLS_CC); } expr { $$ = $4; }
- | expr { $$ = $1; }
+const_decl:
+ T_STRING '=' expr { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3); }
;
-chaining_method_or_property:
- chaining_method_or_property variable_property { $$.EA = $2.EA; }
- | variable_property { $$.EA = $1.EA; }
+echo_expr_list:
+ echo_expr_list ',' echo_expr { $$ = zend_ast_list_add($1, $3); }
+ | echo_expr { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); }
;
-
-chaining_dereference:
- chaining_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
- | '[' dim_offset ']' { zend_do_pop_object(&$1 TSRMLS_CC); fetch_array_dim(&$$, &$1, &$2 TSRMLS_CC); }
+echo_expr:
+ expr { $$ = zend_ast_create(ZEND_AST_ECHO, $1); }
;
-chaining_instance_call:
- chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); } chaining_method_or_property { $$ = $3; }
- | chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); $$ = $1; }
- | chaining_method_or_property { $$ = $1; }
+for_exprs:
+ /* empty */ { $$ = NULL; }
+ | non_empty_for_exprs { $$ = $1; }
;
-instance_call:
- /* empty */ { $$ = $0; }
- | { zend_do_push_object(&$0 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); }
- chaining_instance_call { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); }
+non_empty_for_exprs:
+ non_empty_for_exprs ',' expr { $$ = zend_ast_list_add($1, $3); }
+ | expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); }
;
new_expr:
- T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+ T_NEW class_name_reference ctor_arguments
+ { $$ = zend_ast_create(ZEND_AST_NEW, $2, $3); }
;
expr_without_variable:
- T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
- | variable '=' expr { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
- | variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
- | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
- | T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
- | variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_MUL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_POW_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_POW, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_DIV_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_CONCAT_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_MOD_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_AND_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_OR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_XOR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_SL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_SR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 TSRMLS_CC); }
- | rw_variable T_INC { zend_do_post_incdec(&$$, &$1, ZEND_POST_INC TSRMLS_CC); }
- | T_INC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_INC TSRMLS_CC); }
- | rw_variable T_DEC { zend_do_post_incdec(&$$, &$1, ZEND_POST_DEC TSRMLS_CC); }
- | T_DEC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_DEC TSRMLS_CC); }
- | expr T_BOOLEAN_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
- | expr T_BOOLEAN_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
- | expr T_LOGICAL_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
- | expr T_LOGICAL_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
- | expr T_LOGICAL_XOR expr { zend_do_binary_op(ZEND_BOOL_XOR, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '|' expr { zend_do_binary_op(ZEND_BW_OR, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '&' expr { zend_do_binary_op(ZEND_BW_AND, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '^' expr { zend_do_binary_op(ZEND_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '.' expr { zend_do_binary_op(ZEND_CONCAT, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '+' expr { zend_do_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '-' expr { zend_do_binary_op(ZEND_SUB, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '*' expr { zend_do_binary_op(ZEND_MUL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_POW expr { zend_do_binary_op(ZEND_POW, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '/' expr { zend_do_binary_op(ZEND_DIV, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '%' expr { zend_do_binary_op(ZEND_MOD, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_SL expr { zend_do_binary_op(ZEND_SL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_SR expr { zend_do_binary_op(ZEND_SR, &$$, &$1, &$3 TSRMLS_CC); }
- | '+' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; zend_do_binary_op(ZEND_ADD, &$$, &$1, &$2 TSRMLS_CC); } }
- | '-' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; zend_do_binary_op(ZEND_SUB, &$$, &$1, &$2 TSRMLS_CC); } }
- | '!' expr { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$2 TSRMLS_CC); }
- | '~' expr { zend_do_unary_op(ZEND_BW_NOT, &$$, &$2 TSRMLS_CC); }
- | expr T_IS_IDENTICAL expr { zend_do_binary_op(ZEND_IS_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_IS_NOT_IDENTICAL expr { zend_do_binary_op(ZEND_IS_NOT_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_IS_EQUAL expr { zend_do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_IS_NOT_EQUAL expr { zend_do_binary_op(ZEND_IS_NOT_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '<' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_IS_SMALLER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); }
- | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
- | expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); }
- | parenthesis_expr { $$ = $1; }
- | new_expr { $$ = $1; }
- | '(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; }
- | expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
- expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
- expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
- | expr '?' ':' { zend_do_jmp_set(&$1, &$2, &$3 TSRMLS_CC); }
- expr { zend_do_jmp_set_else(&$$, &$5, &$2, &$3 TSRMLS_CC); }
+ T_LIST '(' assignment_list ')' '=' expr
+ { $$ = zend_ast_create(ZEND_AST_ASSIGN, $3, $6); }
+ | variable '=' expr
+ { $$ = zend_ast_create(ZEND_AST_ASSIGN, $1, $3); }
+ | variable '=' '&' variable
+ { $$ = zend_ast_create(ZEND_AST_ASSIGN_REF, $1, $4); }
+ | variable '=' '&' new_expr
+ { $$ = zend_ast_create(ZEND_AST_ASSIGN_REF, $1, $4); }
+ | T_CLONE expr { $$ = zend_ast_create(ZEND_AST_CLONE, $2); }
+ | variable T_PLUS_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_ADD, $1, $3); }
+ | variable T_MINUS_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_SUB, $1, $3); }
+ | variable T_MUL_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_MUL, $1, $3); }
+ | variable T_POW_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_POW, $1, $3); }
+ | variable T_DIV_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_DIV, $1, $3); }
+ | variable T_CONCAT_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_CONCAT, $1, $3); }
+ | variable T_MOD_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_MOD, $1, $3); }
+ | variable T_AND_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_BW_AND, $1, $3); }
+ | variable T_OR_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_BW_OR, $1, $3); }
+ | variable T_XOR_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_BW_XOR, $1, $3); }
+ | variable T_SL_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_SL, $1, $3); }
+ | variable T_SR_EQUAL expr
+ { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_SR, $1, $3); }
+ | variable T_INC { $$ = zend_ast_create(ZEND_AST_POST_INC, $1); }
+ | T_INC variable { $$ = zend_ast_create(ZEND_AST_PRE_INC, $2); }
+ | variable T_DEC { $$ = zend_ast_create(ZEND_AST_POST_DEC, $1); }
+ | T_DEC variable { $$ = zend_ast_create(ZEND_AST_PRE_DEC, $2); }
+ | expr T_BOOLEAN_OR expr
+ { $$ = zend_ast_create(ZEND_AST_OR, $1, $3); }
+ | expr T_BOOLEAN_AND expr
+ { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); }
+ | expr T_LOGICAL_OR expr
+ { $$ = zend_ast_create(ZEND_AST_OR, $1, $3); }
+ | expr T_LOGICAL_AND expr
+ { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); }
+ | expr T_LOGICAL_XOR expr
+ { $$ = zend_ast_create_binary_op(ZEND_BOOL_XOR, $1, $3); }
+ | expr '|' expr { $$ = zend_ast_create_binary_op(ZEND_BW_OR, $1, $3); }
+ | expr '&' expr { $$ = zend_ast_create_binary_op(ZEND_BW_AND, $1, $3); }
+ | expr '^' expr { $$ = zend_ast_create_binary_op(ZEND_BW_XOR, $1, $3); }
+ | expr '.' expr { $$ = zend_ast_create_binary_op(ZEND_CONCAT, $1, $3); }
+ | expr '+' expr { $$ = zend_ast_create_binary_op(ZEND_ADD, $1, $3); }
+ | expr '-' expr { $$ = zend_ast_create_binary_op(ZEND_SUB, $1, $3); }
+ | expr '*' expr { $$ = zend_ast_create_binary_op(ZEND_MUL, $1, $3); }
+ | expr T_POW expr { $$ = zend_ast_create_binary_op(ZEND_POW, $1, $3); }
+ | expr '/' expr { $$ = zend_ast_create_binary_op(ZEND_DIV, $1, $3); }
+ | expr '%' expr { $$ = zend_ast_create_binary_op(ZEND_MOD, $1, $3); }
+ | expr T_SL expr { $$ = zend_ast_create_binary_op(ZEND_SL, $1, $3); }
+ | expr T_SR expr { $$ = zend_ast_create_binary_op(ZEND_SR, $1, $3); }
+ | '+' expr %prec T_INC { $$ = zend_ast_create(ZEND_AST_UNARY_PLUS, $2); }
+ | '-' expr %prec T_INC { $$ = zend_ast_create(ZEND_AST_UNARY_MINUS, $2); }
+ | '!' expr { $$ = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, $2); }
+ | '~' expr { $$ = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BW_NOT, $2); }
+ | expr T_IS_IDENTICAL expr
+ { $$ = zend_ast_create_binary_op(ZEND_IS_IDENTICAL, $1, $3); }
+ | expr T_IS_NOT_IDENTICAL expr
+ { $$ = zend_ast_create_binary_op(ZEND_IS_NOT_IDENTICAL, $1, $3); }
+ | expr T_IS_EQUAL expr
+ { $$ = zend_ast_create_binary_op(ZEND_IS_EQUAL, $1, $3); }
+ | expr T_IS_NOT_EQUAL expr
+ { $$ = zend_ast_create_binary_op(ZEND_IS_NOT_EQUAL, $1, $3); }
+ | expr '<' expr
+ { $$ = zend_ast_create_binary_op(ZEND_IS_SMALLER, $1, $3); }
+ | expr T_IS_SMALLER_OR_EQUAL expr
+ { $$ = zend_ast_create_binary_op(ZEND_IS_SMALLER_OR_EQUAL, $1, $3); }
+ | expr '>' expr
+ { $$ = zend_ast_create(ZEND_AST_GREATER, $1, $3); }
+ | expr T_IS_GREATER_OR_EQUAL expr
+ { $$ = zend_ast_create(ZEND_AST_GREATER_EQUAL, $1, $3); }
+ | expr T_INSTANCEOF class_name_reference
+ { $$ = zend_ast_create(ZEND_AST_INSTANCEOF, $1, $3); }
+ | '(' expr ')' { $$ = $2; }
+ | new_expr { $$ = $1; }
+ | expr '?' expr ':' expr
+ { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, $3, $5); }
+ | expr '?' ':' expr
+ { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, NULL, $4); }
| internal_functions_in_yacc { $$ = $1; }
- | T_INT_CAST expr { zend_do_cast(&$$, &$2, IS_LONG TSRMLS_CC); }
- | T_DOUBLE_CAST expr { zend_do_cast(&$$, &$2, IS_DOUBLE TSRMLS_CC); }
- | T_STRING_CAST expr { zend_do_cast(&$$, &$2, IS_STRING TSRMLS_CC); }
- | T_ARRAY_CAST expr { zend_do_cast(&$$, &$2, IS_ARRAY TSRMLS_CC); }
- | T_OBJECT_CAST expr { zend_do_cast(&$$, &$2, IS_OBJECT TSRMLS_CC); }
- | T_BOOL_CAST expr { zend_do_cast(&$$, &$2, _IS_BOOL TSRMLS_CC); }
- | T_UNSET_CAST expr { zend_do_cast(&$$, &$2, IS_NULL TSRMLS_CC); }
- | T_EXIT exit_expr { zend_do_exit(&$$, &$2 TSRMLS_CC); }
- | '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
- | scalar { $$ = $1; }
- | combined_scalar_offset { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); }
- | combined_scalar { $$ = $1; }
- | '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
- | T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
- | T_YIELD { zend_do_yield(&$$, NULL, NULL, 0 TSRMLS_CC); }
- | function is_reference { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type, 0 TSRMLS_CC); }
- '(' parameter_list ')' lexical_vars
- '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $3; }
- | T_STATIC function is_reference { zend_do_begin_lambda_function_declaration(&$$, &$2, $3.op_type, 1 TSRMLS_CC); }
- '(' parameter_list ')' lexical_vars
- '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); $$ = $4; }
-;
-
-yield_expr:
- T_YIELD expr_without_variable { zend_do_yield(&$$, &$2, NULL, 0 TSRMLS_CC); }
- | T_YIELD variable { zend_do_yield(&$$, &$2, NULL, 1 TSRMLS_CC); }
- | T_YIELD expr T_DOUBLE_ARROW expr_without_variable { zend_do_yield(&$$, &$4, &$2, 0 TSRMLS_CC); }
- | T_YIELD expr T_DOUBLE_ARROW variable { zend_do_yield(&$$, &$4, &$2, 1 TSRMLS_CC); }
-;
-
-combined_scalar_offset:
- combined_scalar '[' dim_offset ']' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
- | combined_scalar_offset '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
- | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' { $1.EA = 0; zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
- | general_constant '[' dim_offset ']' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
-;
-
-combined_scalar:
- T_ARRAY '(' array_pair_list ')' { $$ = $3; }
- | '[' array_pair_list ']' { $$ = $2; }
+ | T_INT_CAST expr { $$ = zend_ast_create_cast(IS_LONG, $2); }
+ | T_DOUBLE_CAST expr { $$ = zend_ast_create_cast(IS_DOUBLE, $2); }
+ | T_STRING_CAST expr { $$ = zend_ast_create_cast(IS_STRING, $2); }
+ | T_ARRAY_CAST expr { $$ = zend_ast_create_cast(IS_ARRAY, $2); }
+ | T_OBJECT_CAST expr { $$ = zend_ast_create_cast(IS_OBJECT, $2); }
+ | T_BOOL_CAST expr { $$ = zend_ast_create_cast(_IS_BOOL, $2); }
+ | T_UNSET_CAST expr { $$ = zend_ast_create_cast(IS_NULL, $2); }
+ | T_EXIT exit_expr { $$ = zend_ast_create(ZEND_AST_EXIT, $2); }
+ | '@' expr { $$ = zend_ast_create(ZEND_AST_SILENCE, $2); }
+ | scalar { $$ = $1; }
+ | '`' backticks_expr '`' { $$ = zend_ast_create(ZEND_AST_SHELL_EXEC, $2); }
+ | T_PRINT expr { $$ = zend_ast_create(ZEND_AST_PRINT, $2); }
+ | T_YIELD { $$ = zend_ast_create(ZEND_AST_YIELD, NULL, NULL); }
+ | T_YIELD expr { $$ = zend_ast_create(ZEND_AST_YIELD, $2, NULL); }
+ | T_YIELD expr T_DOUBLE_ARROW expr { $$ = zend_ast_create(ZEND_AST_YIELD, $4, $2); }
+ | function returns_ref '(' parameter_list ')' lexical_vars backup_doc_comment
+ '{' inner_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $2, $1, $7,
+ zend_string_init("{closure}", sizeof("{closure}") - 1, 0),
+ $4, $6, $9); }
+ | T_STATIC function returns_ref '(' parameter_list ')' lexical_vars backup_doc_comment
+ '{' inner_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $3 | ZEND_ACC_STATIC, $2, $8,
+ zend_string_init("{closure}", sizeof("{closure}") - 1, 0),
+ $5, $7, $10); }
;
function:
- T_FUNCTION { $$.u.op.opline_num = CG(zend_lineno); }
+ T_FUNCTION { $$ = CG(zend_lineno); }
;
-lexical_vars:
- /* empty */
- | T_USE '(' lexical_var_list ')'
+backup_doc_comment:
+ /* empty */ { $$ = CG(doc_comment); CG(doc_comment) = NULL; }
;
-lexical_var_list:
- lexical_var_list ',' T_VARIABLE { zend_do_fetch_lexical_variable(&$3, 0 TSRMLS_CC); }
- | lexical_var_list ',' '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$4, 1 TSRMLS_CC); }
- | T_VARIABLE { zend_do_fetch_lexical_variable(&$1, 0 TSRMLS_CC); }
- | '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$2, 1 TSRMLS_CC); }
+returns_ref:
+ /* empty */ { $$ = 0; }
+ | '&' { $$ = ZEND_ACC_RETURN_REFERENCE; }
;
-function_call:
- namespace_name { $$.u.op.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); }
- function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, $2.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
- | T_NAMESPACE T_NS_SEPARATOR namespace_name { $1.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$1.u.constant); zend_do_build_namespace_name(&$1, &$1, &$3 TSRMLS_CC); $$.u.op.opline_num = zend_do_begin_function_call(&$1, 0 TSRMLS_CC); }
- function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
- | T_NS_SEPARATOR namespace_name { $$.u.op.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); }
- function_call_parameter_list { zend_do_end_function_call(&$2, &$$, 0, $3.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
- | class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { $$.u.op.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
- function_call_parameter_list { zend_do_end_function_call($4.u.op.opline_num?NULL:&$3, &$$, $4.u.op.opline_num, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
- | class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
- function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
- | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
- function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
- | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
- function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
- | variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); }
- function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+lexical_vars:
+ /* empty */ { $$ = NULL; }
+ | T_USE '(' lexical_var_list ')' { $$ = $3; }
;
-class_name:
- T_STATIC { $$.op_type = IS_CONST; ZVAL_STRINGL(&$$.u.constant, "static", sizeof("static")-1);}
- | namespace_name { $$ = $1; }
- | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); $$ = $2; }
+lexical_var_list:
+ lexical_var_list ',' lexical_var { $$ = zend_ast_list_add($1, $3); }
+ | lexical_var { $$ = zend_ast_create_list(1, ZEND_AST_CLOSURE_USES, $1); }
;
-fully_qualified_class_name:
- namespace_name { $$ = $1; }
- | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); $$ = $2; }
+lexical_var:
+ T_VARIABLE { $$ = $1; }
+ | '&' T_VARIABLE { $$ = $2; $$->attr = 1; }
;
-
-
-class_name_reference:
- class_name { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
- | dynamic_class_name_reference { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
-;
-
-
-dynamic_class_name_reference:
- base_variable T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); }
- object_property { zend_do_push_object(&$4 TSRMLS_CC); } dynamic_class_name_variable_properties
- { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = ZEND_PARSED_MEMBER; }
- | base_variable { $$ = $1; }
+function_call:
+ name argument_list
+ { $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); }
+ | class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
+ { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); }
+ | variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
+ { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); }
+ | callable_expr argument_list
+ { $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); }
;
-
-dynamic_class_name_variable_properties:
- dynamic_class_name_variable_properties dynamic_class_name_variable_property
- | /* empty */
+class_name:
+ T_STATIC
+ { zval zv; ZVAL_STRINGL(&zv, "static", sizeof("static")-1);
+ $$ = zend_ast_create_zval_ex(&zv, ZEND_NAME_NOT_FQ); }
+ | name { $$ = $1; }
;
-
-dynamic_class_name_variable_property:
- T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); }
+class_name_reference:
+ class_name { $$ = $1; }
+ | new_variable { $$ = $1; }
;
exit_expr:
- /* empty */ { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; }
- | '(' ')' { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; }
- | parenthesis_expr { $$ = $1; }
+ /* empty */ { $$ = NULL; }
+ | '(' optional_expr ')' { $$ = $2; }
;
backticks_expr:
- /* empty */ { ZVAL_EMPTY_STRING(&$$.u.constant); $$.op_type = IS_CONST; }
- | T_ENCAPSED_AND_WHITESPACE { $$ = $1; }
- | encaps_list { $$ = $1; }
+ /* empty */
+ { $$ = zend_ast_create_zval_from_str(STR_EMPTY_ALLOC()); }
+ | T_ENCAPSED_AND_WHITESPACE { $$ = $1; }
+ | encaps_list { $$ = $1; }
;
ctor_arguments:
- /* empty */ { Z_LVAL($$.u.constant) = 0; }
- | function_call_parameter_list { $$ = $1; }
-;
-
-
-common_scalar:
- T_LNUMBER { $$ = $1; }
- | T_DNUMBER { $$ = $1; }
- | T_CONSTANT_ENCAPSED_STRING { $$ = $1; }
- | T_LINE { $$ = $1; }
- | T_FILE { $$ = $1; }
- | T_DIR { $$ = $1; }
- | T_TRAIT_C { $$ = $1; }
- | T_METHOD_C { $$ = $1; }
- | T_FUNC_C { $$ = $1; }
- | T_NS_C { $$ = $1; }
- | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; }
- | T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); $$.op_type = IS_CONST; }
-;
-
-static_class_constant:
- class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
-;
-
-static_scalar: /* compile-time evaluated scalars */
- static_scalar_value { zend_do_constant_expression(&$$, $1.u.ast TSRMLS_CC); }
-;
-
-static_scalar_value:
- common_scalar { $$.u.ast = zend_ast_create_constant(&$1.u.constant); }
- | static_class_name_scalar { $$.u.ast = zend_ast_create_constant(&$1.u.constant); }
- | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
- | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
- | T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
- | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; }
- | '[' static_array_pair_list ']' { $$ = $2; }
- | static_class_constant { $$.u.ast = zend_ast_create_constant(&$1.u.constant); }
- | T_CLASS_C { $$.u.ast = zend_ast_create_constant(&$1.u.constant); }
- | static_operation { $$ = $1; }
-;
-
-static_operation:
- static_scalar_value '[' static_scalar_value ']' { $$.u.ast = zend_ast_create_binary(ZEND_FETCH_DIM_R, $1.u.ast, $3.u.ast); }
- | static_scalar_value '+' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_ADD, $1.u.ast, $3.u.ast); }
- | static_scalar_value '-' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_SUB, $1.u.ast, $3.u.ast); }
- | static_scalar_value '*' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_MUL, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_POW static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_POW, $1.u.ast, $3.u.ast); }
- | static_scalar_value '/' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_DIV, $1.u.ast, $3.u.ast); }
- | static_scalar_value '%' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_MOD, $1.u.ast, $3.u.ast); }
- | '!' static_scalar_value { $$.u.ast = zend_ast_create_unary(ZEND_BOOL_NOT, $2.u.ast); }
- | '~' static_scalar_value { $$.u.ast = zend_ast_create_unary(ZEND_BW_NOT, $2.u.ast); }
- | static_scalar_value '|' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BW_OR, $1.u.ast, $3.u.ast); }
- | static_scalar_value '&' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BW_AND, $1.u.ast, $3.u.ast); }
- | static_scalar_value '^' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BW_XOR, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_SL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_SL, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_SR static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_SR, $1.u.ast, $3.u.ast); }
- | static_scalar_value '.' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_CONCAT, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_LOGICAL_XOR static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BOOL_XOR, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_LOGICAL_AND static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BOOL_AND, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_LOGICAL_OR static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BOOL_OR, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_BOOLEAN_AND static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BOOL_AND, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_BOOLEAN_OR static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BOOL_OR, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_IS_IDENTICAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_IDENTICAL, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_IS_NOT_IDENTICAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_NOT_IDENTICAL, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_IS_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_EQUAL, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_IS_NOT_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_NOT_EQUAL, $1.u.ast, $3.u.ast); }
- | static_scalar_value '<' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_SMALLER, $1.u.ast, $3.u.ast); }
- | static_scalar_value '>' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_SMALLER, $3.u.ast, $1.u.ast); }
- | static_scalar_value T_IS_SMALLER_OR_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_SMALLER_OR_EQUAL, $1.u.ast, $3.u.ast); }
- | static_scalar_value T_IS_GREATER_OR_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_SMALLER_OR_EQUAL, $3.u.ast, $1.u.ast); }
- | static_scalar_value '?' ':' static_scalar_value { $$.u.ast = zend_ast_create_ternary(ZEND_SELECT, $1.u.ast, NULL, $4.u.ast); }
- | static_scalar_value '?' static_scalar_value ':' static_scalar_value { $$.u.ast = zend_ast_create_ternary(ZEND_SELECT, $1.u.ast, $3.u.ast, $5.u.ast); }
- | '+' static_scalar_value { $$.u.ast = zend_ast_create_unary(ZEND_UNARY_PLUS, $2.u.ast); }
- | '-' static_scalar_value { $$.u.ast = zend_ast_create_unary(ZEND_UNARY_MINUS, $2.u.ast); }
- | '(' static_scalar_value ')' { $$ = $2; }
-;
-
-general_constant:
- class_constant { $$ = $1; }
- | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC); }
- | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_RT, 0 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); }
+ /* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_ARG_LIST); }
+ | argument_list { $$ = $1; }
+;
+
+
+dereferencable_scalar:
+ T_ARRAY '(' array_pair_list ')' { $$ = $3; }
+ | '[' array_pair_list ']' { $$ = $2; }
+ | T_CONSTANT_ENCAPSED_STRING { $$ = $1; }
;
scalar:
- T_STRING_VARNAME { $$ = $1; }
- | general_constant { $$ = $1; }
- | class_name_scalar { $$ = $1; }
- | common_scalar { $$ = $1; }
- | '"' encaps_list '"' { $$ = $2; }
+ T_LNUMBER { $$ = $1; }
+ | T_DNUMBER { $$ = $1; }
+ | T_LINE { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_LINE); }
+ | T_FILE { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_FILE); }
+ | T_DIR { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_DIR); }
+ | T_TRAIT_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_TRAIT_C); }
+ | T_METHOD_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_METHOD_C); }
+ | T_FUNC_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_FUNC_C); }
+ | T_NS_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_NS_C); }
+ | T_CLASS_C { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_CLASS_C); }
+ | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; }
+ | T_START_HEREDOC T_END_HEREDOC
+ { $$ = zend_ast_create_zval_from_str(STR_EMPTY_ALLOC()); }
+ | '"' encaps_list '"' { $$ = $2; }
| T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; }
- | T_CLASS_C { if (Z_TYPE($1.u.constant) == IS_CONSTANT) {zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC);} else {$$ = $1;} }
+ | dereferencable_scalar { $$ = $1; }
+ | class_name_scalar { $$ = $1; }
+ | constant { $$ = $1; }
;
-static_array_pair_list:
- /* empty */ { $$.op_type = IS_CONST; array_init(&$$.u.constant); $$.u.ast = zend_ast_create_constant(&$$.u.constant); }
- | non_empty_static_array_pair_list possible_comma { zend_ast_dynamic_shrink(&$1.u.ast); $$ = $1; }
+constant:
+ name { $$ = zend_ast_create(ZEND_AST_CONST, $1); }
+ | class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING
+ { $$ = zend_ast_create(ZEND_AST_CLASS_CONST, $1, $3); }
+ | variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING
+ { $$ = zend_ast_create(ZEND_AST_CLASS_CONST, $1, $3); }
;
possible_comma:
@@ -1068,232 +965,190 @@ possible_comma:
| ','
;
-non_empty_static_array_pair_list:
- non_empty_static_array_pair_list ',' static_scalar_value T_DOUBLE_ARROW static_scalar_value { zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); zend_ast_dynamic_add(&$$.u.ast, $5.u.ast); }
- | non_empty_static_array_pair_list ',' static_scalar_value { zend_ast_dynamic_add(&$$.u.ast, NULL); zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); }
- | static_scalar_value T_DOUBLE_ARROW static_scalar_value { $$.u.ast = zend_ast_create_dynamic(ZEND_INIT_ARRAY); zend_ast_dynamic_add(&$$.u.ast, $1.u.ast); zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); }
- | static_scalar_value { $$.u.ast = zend_ast_create_dynamic(ZEND_INIT_ARRAY); zend_ast_dynamic_add(&$$.u.ast, NULL); zend_ast_dynamic_add(&$$.u.ast, $1.u.ast); }
-;
-
expr:
- r_variable { $$ = $1; }
+ variable { $$ = $1; }
| expr_without_variable { $$ = $1; }
;
-parenthesis_expr:
- '(' expr ')' { $$ = $2; }
- | '(' yield_expr ')' { $$ = $2; }
-;
-
-
-r_variable:
- variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; }
-;
-
-
-w_variable:
- variable { zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $$ = $1;
- zend_check_writable_variable(&$1); }
-;
-
-rw_variable:
- variable { zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); $$ = $1;
- zend_check_writable_variable(&$1); }
-;
-
-variable:
- base_variable_with_function_calls T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); }
- object_property { zend_do_push_object(&$4 TSRMLS_CC); } method_or_not variable_properties
- { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = $1.EA | ($7.EA ? $7.EA : $6.EA); }
- | base_variable_with_function_calls { $$ = $1; }
-;
-
-variable_properties:
- variable_properties variable_property { $$.EA = $2.EA; }
- | /* empty */ { $$.EA = 0; }
-;
-
-
-variable_property:
- T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); } method_or_not { $$.EA = $4.EA; }
-;
-
-array_method_dereference:
- array_method_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
- | method '[' dim_offset ']' { $1.EA = ZEND_PARSED_METHOD_CALL; fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
-;
-
-method:
- { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_begin_method_call(&$$ TSRMLS_CC); }
- function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
-;
-
-method_or_not:
- method { $$ = $1; $$.EA = ZEND_PARSED_METHOD_CALL; zend_do_push_object(&$$ TSRMLS_CC); }
- | array_method_dereference { $$ = $1; zend_do_push_object(&$$ TSRMLS_CC); }
- | /* empty */ { $$.EA = ZEND_PARSED_MEMBER; }
-;
-
-variable_without_objects:
- reference_variable { $$ = $1; }
- | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); }
-;
-
-static_member:
- class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
- | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
-
+optional_expr:
+ /* empty */ { $$ = NULL; }
+ | expr { $$ = $1; }
;
variable_class_name:
- reference_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$=$1;; }
+ dereferencable { $$ = $1; }
;
-array_function_dereference:
- array_function_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
- | function_call { zend_do_begin_variable_parse(TSRMLS_C); $1.EA = ZEND_PARSED_FUNCTION_CALL; }
- '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$4 TSRMLS_CC); }
+dereferencable:
+ variable { $$ = $1; }
+ | '(' expr ')' { $$ = $2; }
+ | dereferencable_scalar { $$ = $1; }
;
-base_variable_with_function_calls:
- base_variable { $$ = $1; }
- | array_function_dereference { $$ = $1; }
- | function_call { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; $$.EA = ZEND_PARSED_FUNCTION_CALL; }
+callable_expr:
+ callable_variable { $$ = $1; }
+ | '(' expr ')' { $$ = $2; }
+ | dereferencable_scalar { $$ = $1; }
;
-
-base_variable:
- reference_variable { $$ = $1; $$.EA = ZEND_PARSED_VARIABLE; }
- | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); $$.EA = ZEND_PARSED_VARIABLE; }
- | static_member { $$ = $1; $$.EA = ZEND_PARSED_STATIC_MEMBER; }
+callable_variable:
+ simple_variable
+ { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
+ | dereferencable '[' optional_expr ']'
+ { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
+ | constant '[' optional_expr ']'
+ { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
+ | dereferencable '{' expr '}'
+ { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
+ | dereferencable T_OBJECT_OPERATOR member_name argument_list
+ { $$ = zend_ast_create(ZEND_AST_METHOD_CALL, $1, $3, $4); }
+ | function_call { $$ = $1; }
;
-reference_variable:
- reference_variable '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
- | reference_variable '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); }
- | compound_variable { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
+variable:
+ callable_variable
+ { $$ = $1; }
+ | static_member
+ { $$ = $1; }
+ | dereferencable T_OBJECT_OPERATOR member_name
+ { $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); }
;
-
-compound_variable:
+simple_variable:
T_VARIABLE { $$ = $1; }
| '$' '{' expr '}' { $$ = $3; }
+ | '$' simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $2); }
;
-dim_offset:
- /* empty */ { $$.op_type = IS_UNUSED; }
- | expr { $$ = $1; }
-;
-
-
-object_property:
- object_dim_list { $$ = $1; }
- | variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); } { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
-;
-
-object_dim_list:
- object_dim_list '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
- | object_dim_list '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); }
- | variable_name { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
-;
-
-variable_name:
+static_member:
+ class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
+ { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
+ | variable_class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
+ { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
+;
+
+new_variable:
+ simple_variable
+ { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
+ | new_variable '[' optional_expr ']'
+ { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
+ | new_variable '{' expr '}'
+ { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
+ | new_variable T_OBJECT_OPERATOR member_name
+ { $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); }
+ | class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
+ { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
+ | new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable
+ { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
+;
+
+member_name:
T_STRING { $$ = $1; }
| '{' expr '}' { $$ = $2; }
-;
-
-simple_indirect_reference:
- '$' { Z_LVAL($$.u.constant) = 1; }
- | simple_indirect_reference '$' { Z_LVAL($$.u.constant)++; }
+ | simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
;
assignment_list:
assignment_list ',' assignment_list_element
+ { $$ = zend_ast_list_add($1, $3); }
| assignment_list_element
+ { $$ = zend_ast_create_list(1, ZEND_AST_LIST, $1); }
;
-
assignment_list_element:
- variable { zend_do_add_list_element(&$1 TSRMLS_CC); }
- | T_LIST '(' { zend_do_new_list_begin(TSRMLS_C); } assignment_list ')' { zend_do_new_list_end(TSRMLS_C); }
- | /* empty */ { zend_do_add_list_element(NULL TSRMLS_CC); }
+ variable { $$ = $1; }
+ | T_LIST '(' assignment_list ')' { $$ = $3; }
+ | /* empty */ { $$ = NULL; }
;
array_pair_list:
- /* empty */ { zend_do_init_array(&$$, NULL, NULL, 0 TSRMLS_CC); zend_do_end_array(&$$, &$$ TSRMLS_CC); }
- | non_empty_array_pair_list possible_comma { zend_do_end_array(&$$, &$1 TSRMLS_CC); }
+ /* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_ARRAY); }
+ | non_empty_array_pair_list possible_comma { $$ = $1; }
;
non_empty_array_pair_list:
- non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr { zend_do_add_array_element(&$$, &$5, &$3, 0 TSRMLS_CC); }
- | non_empty_array_pair_list ',' expr { zend_do_add_array_element(&$$, &$3, NULL, 0 TSRMLS_CC); }
- | expr T_DOUBLE_ARROW expr { zend_do_init_array(&$$, &$3, &$1, 0 TSRMLS_CC); }
- | expr { zend_do_init_array(&$$, &$1, NULL, 0 TSRMLS_CC); }
- | non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable { zend_do_add_array_element(&$$, &$6, &$3, 1 TSRMLS_CC); }
- | non_empty_array_pair_list ',' '&' w_variable { zend_do_add_array_element(&$$, &$4, NULL, 1 TSRMLS_CC); }
- | expr T_DOUBLE_ARROW '&' w_variable { zend_do_init_array(&$$, &$4, &$1, 1 TSRMLS_CC); }
- | '&' w_variable { zend_do_init_array(&$$, &$2, NULL, 1 TSRMLS_CC); }
+ non_empty_array_pair_list ',' array_pair
+ { $$ = zend_ast_list_add($1, $3); }
+ | array_pair
+ { $$ = zend_ast_create_list(1, ZEND_AST_ARRAY, $1); }
;
-encaps_list:
- encaps_list encaps_var { zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$1, &$2 TSRMLS_CC); }
- | encaps_list T_ENCAPSED_AND_WHITESPACE { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); }
- | encaps_var { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, NULL, &$1 TSRMLS_CC); }
- | T_ENCAPSED_AND_WHITESPACE encaps_var { zend_do_add_string(&$$, NULL, &$1 TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$$, &$2 TSRMLS_CC); }
+array_pair:
+ expr T_DOUBLE_ARROW expr
+ { $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, $1); }
+ | expr { $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $1, NULL); }
+ | expr T_DOUBLE_ARROW '&' variable
+ { $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $4, $1); }
+ | '&' variable
+ { $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $2, NULL); }
;
-
+encaps_list:
+ encaps_list encaps_var
+ { $$ = zend_ast_list_add($1, $2); }
+ | encaps_list T_ENCAPSED_AND_WHITESPACE
+ { $$ = zend_ast_list_add($1, $2); }
+ | encaps_var
+ { $$ = zend_ast_create_list(1, ZEND_AST_ENCAPS_LIST, $1); }
+ | T_ENCAPSED_AND_WHITESPACE encaps_var
+ { $$ = zend_ast_create_list(2, ZEND_AST_ENCAPS_LIST, $1, $2); }
+;
encaps_var:
- T_VARIABLE { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
- | T_VARIABLE '[' { zend_do_begin_variable_parse(TSRMLS_C); } encaps_var_offset ']' { fetch_array_begin(&$$, &$1, &$4 TSRMLS_CC); }
- | T_VARIABLE T_OBJECT_OPERATOR T_STRING { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$2, &$1, 1 TSRMLS_CC); zend_do_fetch_property(&$$, &$2, &$3 TSRMLS_CC); }
- | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$2, 1 TSRMLS_CC); }
- | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_begin(&$$, &$2, &$4 TSRMLS_CC); }
+ T_VARIABLE
+ { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
+ | T_VARIABLE '[' encaps_var_offset ']'
+ { $$ = zend_ast_create(ZEND_AST_DIM,
+ zend_ast_create(ZEND_AST_VAR, $1), $3); }
+ | T_VARIABLE T_OBJECT_OPERATOR T_STRING
+ { $$ = zend_ast_create(ZEND_AST_PROP,
+ zend_ast_create(ZEND_AST_VAR, $1), $3); }
+ | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
+ { $$ = zend_ast_create(ZEND_AST_VAR, $2); }
+ | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}'
+ { $$ = zend_ast_create(ZEND_AST_VAR, $2); }
+ | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
+ { $$ = zend_ast_create(ZEND_AST_DIM,
+ zend_ast_create(ZEND_AST_VAR, $2), $4); }
| T_CURLY_OPEN variable '}' { $$ = $2; }
;
-
encaps_var_offset:
T_STRING { $$ = $1; }
| T_NUM_STRING { $$ = $1; }
- | T_VARIABLE { fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
+ | T_VARIABLE { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
;
internal_functions_in_yacc:
T_ISSET '(' isset_variables ')' { $$ = $3; }
- | T_EMPTY '(' variable ')' { zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); }
- | T_EMPTY '(' expr_without_variable ')' { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$3 TSRMLS_CC); }
- | T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); }
- | T_INCLUDE_ONCE expr { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); }
- | T_EVAL '(' expr ')' { zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); }
- | T_REQUIRE expr { zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); }
- | T_REQUIRE_ONCE expr { zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC); }
+ | T_EMPTY '(' expr ')' { $$ = zend_ast_create(ZEND_AST_EMPTY, $3); }
+ | T_INCLUDE expr
+ { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE, $2); }
+ | T_INCLUDE_ONCE expr
+ { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE_ONCE, $2); }
+ | T_EVAL '(' expr ')'
+ { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_EVAL, $3); }
+ | T_REQUIRE expr
+ { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE, $2); }
+ | T_REQUIRE_ONCE expr
+ { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE_ONCE, $2); }
;
isset_variables:
- isset_variable { $$ = $1; }
- | isset_variables ',' { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } isset_variable { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
+ isset_variable { $$ = $1; }
+ | isset_variables ',' isset_variable
+ { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); }
;
isset_variable:
- variable { zend_do_isset_or_isempty(ZEND_ISSET, &$$, &$1 TSRMLS_CC); }
- | expr_without_variable { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use isset() on the result of an expression (you can use \"null !== expression\" instead)"); }
-;
-
-class_constant:
- class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); }
- | variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); }
-;
-
-static_class_name_scalar:
- class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS { zend_do_resolve_class_name(&$$, &$1, 1 TSRMLS_CC); }
+ expr { $$ = zend_ast_create(ZEND_AST_ISSET, $1); }
;
class_name_scalar:
- class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS { zend_do_resolve_class_name(&$$, &$1, 0 TSRMLS_CC); }
+ class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS
+ { $$ = zend_ast_create(ZEND_AST_RESOLVE_CLASS_NAME, $1); }
;
%%
diff --git a/Zend/zend_language_scanner.c b/Zend/zend_language_scanner.c
index 8858e8be9e..5bd2798cde 100644
--- a/Zend/zend_language_scanner.c
+++ b/Zend/zend_language_scanner.c
@@ -128,7 +128,7 @@ BEGIN_EXTERN_C()
static size_t encoding_filter_script_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
{
const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
- assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
+ ZEND_ASSERT(internal_encoding);
return zend_multibyte_encoding_converter(to, to_length, from, from_length, internal_encoding, LANG_SCNG(script_encoding) TSRMLS_CC);
}
@@ -146,7 +146,7 @@ LANG_SCNG(script_encoding), zend_multibyte_encoding_utf8 TSRMLS_CC);
static size_t encoding_filter_intermediate_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
{
const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
- assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
+ ZEND_ASSERT(internal_encoding);
return zend_multibyte_encoding_converter(to, to_length, from, from_length,
internal_encoding, zend_multibyte_encoding_utf8 TSRMLS_CC);
}
@@ -535,9 +535,9 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
file_path = file_handle->filename;
}
- compiled_filename = STR_INIT(file_path, strlen(file_path), 0);
+ compiled_filename = zend_string_init(file_path, strlen(file_path), 0);
zend_set_compiled_filename(compiled_filename TSRMLS_CC);
- STR_RELEASE(compiled_filename);
+ zend_string_release(compiled_filename);
if (CG(start_lineno)) {
CG(zend_lineno) = CG(start_lineno);
@@ -558,19 +558,15 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
zend_lex_state original_lex_state;
zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
zend_op_array *original_active_op_array = CG(active_op_array);
- zend_op_array *retval=NULL;
int compiler_result;
zend_bool compilation_successful=0;
- znode retval_znode;
+ zval retval_zv;
zend_bool original_in_compilation = CG(in_compilation);
- retval_znode.op_type = IS_CONST;
- ZVAL_LONG(&retval_znode.u.constant, 1);
+ ZVAL_LONG(&retval_zv, 1);
zend_save_lexical_state(&original_lex_state TSRMLS_CC);
- retval = op_array; /* success oriented */
-
if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) {
if (type==ZEND_REQUIRE) {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
@@ -585,27 +581,31 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
CG(active_op_array) = op_array;
zend_stack_push(&CG(context_stack), (void *) &CG(context));
zend_init_compiler_context(TSRMLS_C);
+ CG(ast_arena) = zend_arena_create(1024 * 32);
compiler_result = zendparse(TSRMLS_C);
- zend_do_return(&retval_znode, 0 TSRMLS_CC);
- CG(in_compilation) = original_in_compilation;
if (compiler_result != 0) { /* parser error */
zend_bailout();
}
+ zend_compile_top_stmt(CG(ast) TSRMLS_CC);
+ zend_ast_destroy(CG(ast));
+ zend_arena_destroy(CG(ast_arena));
+ zend_do_end_compilation(TSRMLS_C);
+ zend_emit_final_return(&retval_zv TSRMLS_CC);
+ CG(in_compilation) = original_in_compilation;
compilation_successful=1;
}
- if (retval) {
- CG(active_op_array) = original_active_op_array;
- if (compilation_successful) {
- pass_two(op_array TSRMLS_CC);
- zend_release_labels(0 TSRMLS_CC);
- } else {
- efree(op_array);
- retval = NULL;
- }
+ CG(active_op_array) = original_active_op_array;
+ if (compilation_successful) {
+ pass_two(op_array TSRMLS_CC);
+ zend_release_labels(0 TSRMLS_CC);
+ } else {
+ efree_size(op_array, sizeof(zend_op_array));
+ op_array = NULL;
}
+
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
- return retval;
+ return op_array;
}
@@ -656,7 +656,7 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_D
/* enforce ZEND_MMAP_AHEAD trailing NULLs for flex... */
old_len = Z_STRLEN_P(str);
- Z_STR_P(str) = STR_REALLOC(Z_STR_P(str), old_len + ZEND_MMAP_AHEAD, 0);
+ Z_STR_P(str) = zend_string_realloc(Z_STR_P(str), old_len + ZEND_MMAP_AHEAD, 0);
Z_TYPE_INFO_P(str) = IS_STRING_EX;
memset(Z_STRVAL_P(str) + old_len, 0, ZEND_MMAP_AHEAD + 1);
@@ -685,9 +685,9 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_D
yy_scan_buffer(buf, size TSRMLS_CC);
- new_compiled_filename = STR_INIT(filename, strlen(filename), 0);
+ new_compiled_filename = zend_string_init(filename, strlen(filename), 0);
zend_set_compiled_filename(new_compiled_filename TSRMLS_CC);
- STR_RELEASE(new_compiled_filename);
+ zend_string_release(new_compiled_filename);
CG(zend_lineno) = 1;
CG(increment_lineno) = 0;
RESET_DOC_COMMENT();
@@ -720,63 +720,50 @@ ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D)
zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
{
zend_lex_state original_lex_state;
- zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
- zend_op_array *original_active_op_array = CG(active_op_array);
- zend_op_array *retval;
+ zend_op_array *op_array = NULL;
zval tmp;
- int compiler_result;
zend_bool original_in_compilation = CG(in_compilation);
if (Z_STRLEN_P(source_string)==0) {
- efree(op_array);
return NULL;
}
- CG(in_compilation) = 1;
-
ZVAL_DUP(&tmp, source_string);
convert_to_string(&tmp);
source_string = &tmp;
-
+
+ CG(in_compilation) = 1;
zend_save_lexical_state(&original_lex_state TSRMLS_CC);
- if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC)==FAILURE) {
- efree(op_array);
- retval = NULL;
- } else {
- zend_bool orig_interactive = CG(interactive);
-
- CG(interactive) = 0;
- init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
- CG(interactive) = orig_interactive;
- CG(active_op_array) = op_array;
- zend_stack_push(&CG(context_stack), (void *) &CG(context));
- zend_init_compiler_context(TSRMLS_C);
+ if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC) == SUCCESS) {
+ CG(ast) = NULL;
+ CG(ast_arena) = zend_arena_create(1024 * 32);
BEGIN(ST_IN_SCRIPTING);
- compiler_result = zendparse(TSRMLS_C);
-
- if (SCNG(script_filtered)) {
- efree(SCNG(script_filtered));
- SCNG(script_filtered) = NULL;
- }
- if (compiler_result != 0) {
- CG(active_op_array) = original_active_op_array;
- CG(unclean_shutdown)=1;
- destroy_op_array(op_array TSRMLS_CC);
- efree(op_array);
- retval = NULL;
- } else {
- zend_do_return(NULL, 0 TSRMLS_CC);
- CG(active_op_array) = original_active_op_array;
+ if (!zendparse(TSRMLS_C)) {
+ zend_op_array *original_active_op_array = CG(active_op_array);
+ op_array = emalloc(sizeof(zend_op_array));
+ init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
+ CG(active_op_array) = op_array;
+
+ zend_stack_push(&CG(context_stack), (void *) &CG(context));
+ zend_init_compiler_context(TSRMLS_C);
+ zend_compile_top_stmt(CG(ast) TSRMLS_CC);
+ zend_do_end_compilation(TSRMLS_C);
+ zend_emit_final_return(NULL TSRMLS_CC);
pass_two(op_array TSRMLS_CC);
zend_release_labels(0 TSRMLS_CC);
- retval = op_array;
+
+ CG(active_op_array) = original_active_op_array;
}
+
+ zend_ast_destroy(CG(ast));
+ zend_arena_destroy(CG(ast_arena));
}
+
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
zval_dtor(&tmp);
CG(in_compilation) = original_in_compilation;
- return retval;
+ return op_array;
}
@@ -858,7 +845,7 @@ ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter
SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start));
SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start));
SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start));
- SCNG(yy_limit) = new_yy_start + (SCNG(yy_limit) - SCNG(yy_start));
+ SCNG(yy_limit) = new_yy_start + length;
SCNG(yy_start) = new_yy_start;
}
@@ -876,15 +863,6 @@ ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter
ZVAL_STRINGL(zendlval, yytext, yyleng); \
}
-// TODO: some extensions might need content, but we don't copy it intentional ???
-#if 0
-# define DUMMY_STRINGL(zendlval, yytext, yyleng) \
- ZVAL_STRINGL(zendlval, yytext, yyleng)
-#else
-# define DUMMY_STRINGL(zendlval, yytext, yyleng) \
- ZVAL_EMPTY_STRING(zendlval)
-#endif
-
static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type TSRMLS_DC)
{
register char *s, *t;
@@ -957,7 +935,7 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
hex_buf[1] = *(++s);
Z_STRLEN_P(zendlval)--;
}
- *t++ = (char) strtol(hex_buf, NULL, 16);
+ *t++ = (char) ZEND_STRTOL(hex_buf, NULL, 16);
} else {
*t++ = '\\';
*t++ = *s;
@@ -978,7 +956,7 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
Z_STRLEN_P(zendlval)--;
}
}
- *t++ = (char) strtol(octal_buf, NULL, 8);
+ *t++ = (char) ZEND_STRTOL(octal_buf, NULL, 8);
} else {
*t++ = '\\';
*t++ = *s;
@@ -1002,7 +980,7 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
s = Z_STRVAL_P(zendlval);
SCNG(output_filter)(&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval) TSRMLS_CC);
zval_ptr_dtor(zendlval);
- ZVAL_STRINGL(zendlval, str, sz);
+ ZVAL_STRINGL(zendlval, (char *) str, sz);
efree(str);
}
}
@@ -1016,7 +994,7 @@ restart:
yymore_restart:
-#line 1020 "Zend/zend_language_scanner.c"
+#line 998 "Zend/zend_language_scanner.c"
{
YYCTYPE yych;
unsigned int yyaccept = 0;
@@ -1115,7 +1093,7 @@ yyc_INITIAL:
yy3:
YYDEBUG(3, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1779 "Zend/zend_language_scanner.l"
+#line 1663 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
return 0;
@@ -1176,7 +1154,7 @@ inline_html:
HANDLE_NEWLINES(yytext, yyleng);
return T_INLINE_HTML;
}
-#line 1180 "Zend/zend_language_scanner.c"
+#line 1158 "Zend/zend_language_scanner.c"
yy4:
YYDEBUG(4, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1194,34 +1172,32 @@ yy5:
yy6:
YYDEBUG(6, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1769 "Zend/zend_language_scanner.l"
+#line 1654 "Zend/zend_language_scanner.l"
{
if (CG(short_tags)) {
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG;
} else {
goto inline_char_handler;
}
}
-#line 1208 "Zend/zend_language_scanner.c"
+#line 1185 "Zend/zend_language_scanner.c"
yy7:
YYDEBUG(7, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) == '=') goto yy43;
YYDEBUG(8, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1750 "Zend/zend_language_scanner.l"
+#line 1637 "Zend/zend_language_scanner.l"
{
if (CG(asp_tags)) {
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG;
} else {
goto inline_char_handler;
}
}
-#line 1225 "Zend/zend_language_scanner.c"
+#line 1201 "Zend/zend_language_scanner.c"
yy9:
YYDEBUG(9, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1407,7 +1383,7 @@ yy35:
++YYCURSOR;
YYDEBUG(38, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1716 "Zend/zend_language_scanner.l"
+#line 1606 "Zend/zend_language_scanner.l"
{
YYCTYPE *bracket = (YYCTYPE*)zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1));
@@ -1418,11 +1394,10 @@ yy35:
}
HANDLE_NEWLINES(yytext, yyleng);
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG;
}
-#line 1426 "Zend/zend_language_scanner.c"
+#line 1401 "Zend/zend_language_scanner.c"
yy39:
YYDEBUG(39, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1449,29 +1424,27 @@ yy43:
++YYCURSOR;
YYDEBUG(44, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1732 "Zend/zend_language_scanner.l"
+#line 1621 "Zend/zend_language_scanner.l"
{
if (CG(asp_tags)) {
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG_WITH_ECHO;
} else {
goto inline_char_handler;
}
}
-#line 1463 "Zend/zend_language_scanner.c"
+#line 1437 "Zend/zend_language_scanner.c"
yy45:
YYDEBUG(45, *YYCURSOR);
++YYCURSOR;
YYDEBUG(46, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1743 "Zend/zend_language_scanner.l"
+#line 1631 "Zend/zend_language_scanner.l"
{
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG_WITH_ECHO;
}
-#line 1475 "Zend/zend_language_scanner.c"
+#line 1448 "Zend/zend_language_scanner.c"
yy47:
YYDEBUG(47, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1498,14 +1471,13 @@ yy50:
yy51:
YYDEBUG(51, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1761 "Zend/zend_language_scanner.l"
+#line 1647 "Zend/zend_language_scanner.l"
{
- DUMMY_STRINGL(zendlval, yytext, yyleng);
HANDLE_NEWLINE(yytext[yyleng-1]);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG;
}
-#line 1509 "Zend/zend_language_scanner.c"
+#line 1481 "Zend/zend_language_scanner.c"
yy52:
YYDEBUG(52, *YYCURSOR);
++YYCURSOR;
@@ -1576,7 +1548,7 @@ yyc_ST_BACKQUOTE:
yy56:
YYDEBUG(56, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2222 "Zend/zend_language_scanner.l"
+#line 2106 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
return 0;
@@ -1617,7 +1589,7 @@ yy56:
zend_scan_escape_string(zendlval, yytext, yyleng, '`' TSRMLS_CC);
return T_ENCAPSED_AND_WHITESPACE;
}
-#line 1621 "Zend/zend_language_scanner.c"
+#line 1593 "Zend/zend_language_scanner.c"
yy57:
YYDEBUG(57, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1628,12 +1600,12 @@ yy58:
++YYCURSOR;
YYDEBUG(59, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2166 "Zend/zend_language_scanner.l"
+#line 2050 "Zend/zend_language_scanner.l"
{
BEGIN(ST_IN_SCRIPTING);
return '`';
}
-#line 1637 "Zend/zend_language_scanner.c"
+#line 1609 "Zend/zend_language_scanner.c"
yy60:
YYDEBUG(60, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1643,14 +1615,14 @@ yy61:
++YYCURSOR;
YYDEBUG(62, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2153 "Zend/zend_language_scanner.l"
+#line 2037 "Zend/zend_language_scanner.l"
{
- Z_LVAL_P(zendlval) = (long) '{';
+ Z_LVAL_P(zendlval) = (zend_long) '{';
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
yyless(1);
return T_CURLY_OPEN;
}
-#line 1654 "Zend/zend_language_scanner.c"
+#line 1626 "Zend/zend_language_scanner.c"
yy63:
YYDEBUG(63, *YYCURSOR);
yyaccept = 0;
@@ -1666,23 +1638,23 @@ yy63:
yy65:
YYDEBUG(65, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1860 "Zend/zend_language_scanner.l"
+#line 1744 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
return T_VARIABLE;
}
-#line 1675 "Zend/zend_language_scanner.c"
+#line 1647 "Zend/zend_language_scanner.c"
yy66:
YYDEBUG(66, *YYCURSOR);
++YYCURSOR;
YYDEBUG(67, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1483 "Zend/zend_language_scanner.l"
+#line 1460 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
return T_DOLLAR_OPEN_CURLY_BRACES;
}
-#line 1686 "Zend/zend_language_scanner.c"
+#line 1658 "Zend/zend_language_scanner.c"
yy68:
YYDEBUG(68, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1696,14 +1668,14 @@ yy70:
++YYCURSOR;
YYDEBUG(71, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1853 "Zend/zend_language_scanner.l"
+#line 1737 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
return T_VARIABLE;
}
-#line 1707 "Zend/zend_language_scanner.c"
+#line 1679 "Zend/zend_language_scanner.c"
yy72:
YYDEBUG(72, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1721,14 +1693,14 @@ yy73:
++YYCURSOR;
YYDEBUG(74, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1844 "Zend/zend_language_scanner.l"
+#line 1728 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
return T_VARIABLE;
}
-#line 1732 "Zend/zend_language_scanner.c"
+#line 1704 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_DOUBLE_QUOTES:
@@ -1796,7 +1768,7 @@ yy77:
yy78:
YYDEBUG(78, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2172 "Zend/zend_language_scanner.l"
+#line 2056 "Zend/zend_language_scanner.l"
{
if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) {
YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1;
@@ -1845,7 +1817,7 @@ double_quotes_scan_done:
zend_scan_escape_string(zendlval, yytext, yyleng, '"' TSRMLS_CC);
return T_ENCAPSED_AND_WHITESPACE;
}
-#line 1849 "Zend/zend_language_scanner.c"
+#line 1821 "Zend/zend_language_scanner.c"
yy79:
YYDEBUG(79, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1856,12 +1828,12 @@ yy80:
++YYCURSOR;
YYDEBUG(81, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2161 "Zend/zend_language_scanner.l"
+#line 2045 "Zend/zend_language_scanner.l"
{
BEGIN(ST_IN_SCRIPTING);
return '"';
}
-#line 1865 "Zend/zend_language_scanner.c"
+#line 1837 "Zend/zend_language_scanner.c"
yy82:
YYDEBUG(82, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1871,14 +1843,14 @@ yy83:
++YYCURSOR;
YYDEBUG(84, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2153 "Zend/zend_language_scanner.l"
+#line 2037 "Zend/zend_language_scanner.l"
{
- Z_LVAL_P(zendlval) = (long) '{';
+ Z_LVAL_P(zendlval) = (zend_long) '{';
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
yyless(1);
return T_CURLY_OPEN;
}
-#line 1882 "Zend/zend_language_scanner.c"
+#line 1854 "Zend/zend_language_scanner.c"
yy85:
YYDEBUG(85, *YYCURSOR);
yyaccept = 0;
@@ -1894,23 +1866,23 @@ yy85:
yy87:
YYDEBUG(87, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1860 "Zend/zend_language_scanner.l"
+#line 1744 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
return T_VARIABLE;
}
-#line 1903 "Zend/zend_language_scanner.c"
+#line 1875 "Zend/zend_language_scanner.c"
yy88:
YYDEBUG(88, *YYCURSOR);
++YYCURSOR;
YYDEBUG(89, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1483 "Zend/zend_language_scanner.l"
+#line 1460 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
return T_DOLLAR_OPEN_CURLY_BRACES;
}
-#line 1914 "Zend/zend_language_scanner.c"
+#line 1886 "Zend/zend_language_scanner.c"
yy90:
YYDEBUG(90, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1924,14 +1896,14 @@ yy92:
++YYCURSOR;
YYDEBUG(93, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1853 "Zend/zend_language_scanner.l"
+#line 1737 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
return T_VARIABLE;
}
-#line 1935 "Zend/zend_language_scanner.c"
+#line 1907 "Zend/zend_language_scanner.c"
yy94:
YYDEBUG(94, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1949,14 +1921,14 @@ yy95:
++YYCURSOR;
YYDEBUG(96, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1844 "Zend/zend_language_scanner.l"
+#line 1728 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
return T_VARIABLE;
}
-#line 1960 "Zend/zend_language_scanner.c"
+#line 1932 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_END_HEREDOC:
@@ -1967,7 +1939,7 @@ yyc_ST_END_HEREDOC:
++YYCURSOR;
YYDEBUG(100, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2139 "Zend/zend_language_scanner.l"
+#line 2023 "Zend/zend_language_scanner.l"
{
zend_heredoc_label *heredoc_label = zend_ptr_stack_pop(&SCNG(heredoc_label_stack));
@@ -1980,7 +1952,7 @@ yyc_ST_END_HEREDOC:
BEGIN(ST_IN_SCRIPTING);
return T_END_HEREDOC;
}
-#line 1984 "Zend/zend_language_scanner.c"
+#line 1956 "Zend/zend_language_scanner.c"
/* *********************************** */
yyc_ST_HEREDOC:
{
@@ -2042,7 +2014,7 @@ yy103:
yy104:
YYDEBUG(104, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2264 "Zend/zend_language_scanner.l"
+#line 2148 "Zend/zend_language_scanner.l"
{
int newline = 0;
@@ -2115,7 +2087,7 @@ heredoc_scan_done:
zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0 TSRMLS_CC);
return T_ENCAPSED_AND_WHITESPACE;
}
-#line 2119 "Zend/zend_language_scanner.c"
+#line 2091 "Zend/zend_language_scanner.c"
yy105:
YYDEBUG(105, *YYCURSOR);
yych = *++YYCURSOR;
@@ -2130,14 +2102,14 @@ yy107:
++YYCURSOR;
YYDEBUG(108, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2153 "Zend/zend_language_scanner.l"
+#line 2037 "Zend/zend_language_scanner.l"
{
- Z_LVAL_P(zendlval) = (long) '{';
+ Z_LVAL_P(zendlval) = (zend_long) '{';
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
yyless(1);
return T_CURLY_OPEN;
}
-#line 2141 "Zend/zend_language_scanner.c"
+#line 2113 "Zend/zend_language_scanner.c"
yy109:
YYDEBUG(109, *YYCURSOR);
yyaccept = 0;
@@ -2153,23 +2125,23 @@ yy109:
yy111:
YYDEBUG(111, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1860 "Zend/zend_language_scanner.l"
+#line 1744 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
return T_VARIABLE;
}
-#line 2162 "Zend/zend_language_scanner.c"
+#line 2134 "Zend/zend_language_scanner.c"
yy112:
YYDEBUG(112, *YYCURSOR);
++YYCURSOR;
YYDEBUG(113, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1483 "Zend/zend_language_scanner.l"
+#line 1460 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
return T_DOLLAR_OPEN_CURLY_BRACES;
}
-#line 2173 "Zend/zend_language_scanner.c"
+#line 2145 "Zend/zend_language_scanner.c"
yy114:
YYDEBUG(114, *YYCURSOR);
yych = *++YYCURSOR;
@@ -2183,14 +2155,14 @@ yy116:
++YYCURSOR;
YYDEBUG(117, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1853 "Zend/zend_language_scanner.l"
+#line 1737 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
return T_VARIABLE;
}
-#line 2194 "Zend/zend_language_scanner.c"
+#line 2166 "Zend/zend_language_scanner.c"
yy118:
YYDEBUG(118, *YYCURSOR);
yych = *++YYCURSOR;
@@ -2208,14 +2180,14 @@ yy119:
++YYCURSOR;
YYDEBUG(120, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1844 "Zend/zend_language_scanner.l"
+#line 1728 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
return T_VARIABLE;
}
-#line 2219 "Zend/zend_language_scanner.c"
+#line 2191 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_IN_SCRIPTING:
@@ -2398,12 +2370,12 @@ yy123:
yy124:
YYDEBUG(124, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1882 "Zend/zend_language_scanner.l"
+#line 1767 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, yytext, yyleng);
return T_STRING;
}
-#line 2407 "Zend/zend_language_scanner.c"
+#line 2379 "Zend/zend_language_scanner.c"
yy125:
YYDEBUG(125, *YYCURSOR);
yych = *++YYCURSOR;
@@ -2635,11 +2607,11 @@ yy138:
yy139:
YYDEBUG(139, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1472 "Zend/zend_language_scanner.l"
+#line 1449 "Zend/zend_language_scanner.l"
{
return yytext[0];
}
-#line 2643 "Zend/zend_language_scanner.c"
+#line 2615 "Zend/zend_language_scanner.c"
yy140:
YYDEBUG(140, *YYCURSOR);
++YYCURSOR;
@@ -2648,13 +2620,12 @@ yy140:
yy141:
YYDEBUG(141, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1194 "Zend/zend_language_scanner.l"
+#line 1172 "Zend/zend_language_scanner.l"
{
- DUMMY_STRINGL(zendlval, yytext, yyleng);
HANDLE_NEWLINES(yytext, yyleng);
return T_WHITESPACE;
}
-#line 2658 "Zend/zend_language_scanner.c"
+#line 2629 "Zend/zend_language_scanner.c"
yy142:
YYDEBUG(142, *YYCURSOR);
yych = *++YYCURSOR;
@@ -2665,11 +2636,11 @@ yy143:
++YYCURSOR;
YYDEBUG(144, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1220 "Zend/zend_language_scanner.l"
+#line 1197 "Zend/zend_language_scanner.l"
{
return T_NS_SEPARATOR;
}
-#line 2673 "Zend/zend_language_scanner.c"
+#line 2644 "Zend/zend_language_scanner.c"
yy145:
YYDEBUG(145, *YYCURSOR);
yyaccept = 1;
@@ -2903,18 +2874,18 @@ yy168:
++YYCURSOR;
YYDEBUG(169, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1477 "Zend/zend_language_scanner.l"
+#line 1454 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
return '{';
}
-#line 2912 "Zend/zend_language_scanner.c"
+#line 2883 "Zend/zend_language_scanner.c"
yy170:
YYDEBUG(170, *YYCURSOR);
++YYCURSOR;
YYDEBUG(171, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1489 "Zend/zend_language_scanner.l"
+#line 1466 "Zend/zend_language_scanner.l"
{
RESET_DOC_COMMENT();
if (!zend_stack_is_empty(&SCNG(state_stack))) {
@@ -2922,7 +2893,7 @@ yy170:
}
return '}';
}
-#line 2926 "Zend/zend_language_scanner.c"
+#line 2897 "Zend/zend_language_scanner.c"
yy172:
YYDEBUG(172, *YYCURSOR);
yyaccept = 2;
@@ -2950,13 +2921,13 @@ yy172:
yy173:
YYDEBUG(173, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1537 "Zend/zend_language_scanner.l"
+#line 1514 "Zend/zend_language_scanner.l"
{
if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
- ZVAL_LONG(zendlval, strtol(yytext, NULL, 0));
+ ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, NULL, 0));
} else {
errno = 0;
- ZVAL_LONG(zendlval, strtol(yytext, NULL, 0));
+ ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, NULL, 0));
if (errno == ERANGE) { /* Overflow */
if (yytext[0] == '0') { /* octal overflow */
ZVAL_DOUBLE(zendlval, zend_oct_strtod(yytext, NULL));
@@ -2968,7 +2939,7 @@ yy173:
}
return T_LNUMBER;
}
-#line 2972 "Zend/zend_language_scanner.c"
+#line 2943 "Zend/zend_language_scanner.c"
yy174:
YYDEBUG(174, *YYCURSOR);
yyaccept = 2;
@@ -2996,7 +2967,7 @@ yy176:
yy177:
YYDEBUG(177, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1888 "Zend/zend_language_scanner.l"
+#line 1773 "Zend/zend_language_scanner.l"
{
while (YYCURSOR < YYLIMIT) {
switch (*YYCURSOR++) {
@@ -3030,14 +3001,14 @@ yy177:
return T_COMMENT;
}
-#line 3034 "Zend/zend_language_scanner.c"
+#line 3005 "Zend/zend_language_scanner.c"
yy178:
YYDEBUG(178, *YYCURSOR);
++YYCURSOR;
yy179:
YYDEBUG(179, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1974 "Zend/zend_language_scanner.l"
+#line 1857 "Zend/zend_language_scanner.l"
{
register char *s, *t;
char *end;
@@ -3059,6 +3030,7 @@ yy179:
/* Unclosed single quotes; treat similar to double quotes, but without a separate token
* for ' (unrecognized by parser), instead of old flex fallback to "Unexpected character..."
* rule, which continued in ST_IN_SCRIPTING state after the quote */
+ ZVAL_NULL(zendlval);
return T_ENCAPSED_AND_WHITESPACE;
}
}
@@ -3105,14 +3077,14 @@ yy179:
}
return T_CONSTANT_ENCAPSED_STRING;
}
-#line 3109 "Zend/zend_language_scanner.c"
+#line 3081 "Zend/zend_language_scanner.c"
yy180:
YYDEBUG(180, *YYCURSOR);
++YYCURSOR;
yy181:
YYDEBUG(181, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2043 "Zend/zend_language_scanner.l"
+#line 1927 "Zend/zend_language_scanner.l"
{
int bprefix = (yytext[0] != '"') ? 1 : 0;
@@ -3153,24 +3125,24 @@ yy181:
BEGIN(ST_DOUBLE_QUOTES);
return '"';
}
-#line 3157 "Zend/zend_language_scanner.c"
+#line 3129 "Zend/zend_language_scanner.c"
yy182:
YYDEBUG(182, *YYCURSOR);
++YYCURSOR;
YYDEBUG(183, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2133 "Zend/zend_language_scanner.l"
+#line 2017 "Zend/zend_language_scanner.l"
{
BEGIN(ST_BACKQUOTE);
return '`';
}
-#line 3168 "Zend/zend_language_scanner.c"
+#line 3140 "Zend/zend_language_scanner.c"
yy184:
YYDEBUG(184, *YYCURSOR);
++YYCURSOR;
YYDEBUG(185, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2395 "Zend/zend_language_scanner.l"
+#line 2279 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
return 0;
@@ -3179,7 +3151,7 @@ yy184:
zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
goto restart;
}
-#line 3183 "Zend/zend_language_scanner.c"
+#line 3155 "Zend/zend_language_scanner.c"
yy186:
YYDEBUG(186, *YYCURSOR);
++YYCURSOR;
@@ -3206,12 +3178,12 @@ yy188:
yy190:
YYDEBUG(190, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1592 "Zend/zend_language_scanner.l"
+#line 1569 "Zend/zend_language_scanner.l"
{
ZVAL_DOUBLE(zendlval, zend_strtod(yytext, NULL));
return T_DNUMBER;
}
-#line 3215 "Zend/zend_language_scanner.c"
+#line 3187 "Zend/zend_language_scanner.c"
yy191:
YYDEBUG(191, *YYCURSOR);
yyaccept = 2;
@@ -3303,7 +3275,7 @@ yy200:
}
YYDEBUG(202, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1514 "Zend/zend_language_scanner.l"
+#line 1491 "Zend/zend_language_scanner.l"
{
char *bin = yytext + 2; /* Skip "0b" */
int len = yyleng - 2;
@@ -3314,11 +3286,11 @@ yy200:
--len;
}
- if (len < SIZEOF_LONG * 8) {
+ if (len < SIZEOF_ZEND_LONG * 8) {
if (len == 0) {
ZVAL_LONG(zendlval, 0);
} else {
- ZVAL_LONG(zendlval, strtol(bin, NULL, 2));
+ ZVAL_LONG(zendlval, ZEND_STRTOL(bin, NULL, 2));
}
return T_LNUMBER;
} else {
@@ -3326,7 +3298,7 @@ yy200:
return T_DNUMBER;
}
}
-#line 3330 "Zend/zend_language_scanner.c"
+#line 3302 "Zend/zend_language_scanner.c"
yy203:
YYDEBUG(203, *YYCURSOR);
++YYCURSOR;
@@ -3338,7 +3310,7 @@ yy203:
}
YYDEBUG(205, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1555 "Zend/zend_language_scanner.l"
+#line 1532 "Zend/zend_language_scanner.l"
{
char *hex = yytext + 2; /* Skip "0x" */
int len = yyleng - 2;
@@ -3349,11 +3321,11 @@ yy203:
len--;
}
- if (len < SIZEOF_LONG * 2 || (len == SIZEOF_LONG * 2 && *hex <= '7')) {
+ if (len < SIZEOF_ZEND_LONG * 2 || (len == SIZEOF_ZEND_LONG * 2 && *hex <= '7')) {
if (len == 0) {
ZVAL_LONG(zendlval, 0);
} else {
- ZVAL_LONG(zendlval, strtol(hex, NULL, 16));
+ ZVAL_LONG(zendlval, ZEND_STRTOL(hex, NULL, 16));
}
return T_LNUMBER;
} else {
@@ -3361,7 +3333,7 @@ yy203:
return T_DNUMBER;
}
}
-#line 3365 "Zend/zend_language_scanner.c"
+#line 3337 "Zend/zend_language_scanner.c"
yy206:
YYDEBUG(206, *YYCURSOR);
++YYCURSOR;
@@ -3370,13 +3342,12 @@ yy206:
yy207:
YYDEBUG(207, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1955 "Zend/zend_language_scanner.l"
+#line 1840 "Zend/zend_language_scanner.l"
{
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(INITIAL);
return T_CLOSE_TAG; /* implicit ';' at php-end tag */
}
-#line 3380 "Zend/zend_language_scanner.c"
+#line 3351 "Zend/zend_language_scanner.c"
yy208:
YYDEBUG(208, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3410,12 +3381,12 @@ yy210:
yy212:
YYDEBUG(212, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1860 "Zend/zend_language_scanner.l"
+#line 1744 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
return T_VARIABLE;
}
-#line 3419 "Zend/zend_language_scanner.c"
+#line 3390 "Zend/zend_language_scanner.c"
yy213:
YYDEBUG(213, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3429,11 +3400,11 @@ yy214:
}
YYDEBUG(215, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1460 "Zend/zend_language_scanner.l"
+#line 1437 "Zend/zend_language_scanner.l"
{
return T_LOGICAL_XOR;
}
-#line 3437 "Zend/zend_language_scanner.c"
+#line 3408 "Zend/zend_language_scanner.c"
yy216:
YYDEBUG(216, *YYCURSOR);
++YYCURSOR;
@@ -3442,61 +3413,61 @@ yy216:
}
YYDEBUG(217, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1452 "Zend/zend_language_scanner.l"
+#line 1429 "Zend/zend_language_scanner.l"
{
return T_LOGICAL_OR;
}
-#line 3450 "Zend/zend_language_scanner.c"
+#line 3421 "Zend/zend_language_scanner.c"
yy218:
YYDEBUG(218, *YYCURSOR);
++YYCURSOR;
YYDEBUG(219, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1440 "Zend/zend_language_scanner.l"
+#line 1417 "Zend/zend_language_scanner.l"
{
return T_XOR_EQUAL;
}
-#line 3460 "Zend/zend_language_scanner.c"
+#line 3431 "Zend/zend_language_scanner.c"
yy220:
YYDEBUG(220, *YYCURSOR);
++YYCURSOR;
YYDEBUG(221, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1444 "Zend/zend_language_scanner.l"
+#line 1421 "Zend/zend_language_scanner.l"
{
return T_BOOLEAN_OR;
}
-#line 3470 "Zend/zend_language_scanner.c"
+#line 3441 "Zend/zend_language_scanner.c"
yy222:
YYDEBUG(222, *YYCURSOR);
++YYCURSOR;
YYDEBUG(223, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1436 "Zend/zend_language_scanner.l"
+#line 1413 "Zend/zend_language_scanner.l"
{
return T_OR_EQUAL;
}
-#line 3480 "Zend/zend_language_scanner.c"
+#line 3451 "Zend/zend_language_scanner.c"
yy224:
YYDEBUG(224, *YYCURSOR);
++YYCURSOR;
YYDEBUG(225, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1448 "Zend/zend_language_scanner.l"
+#line 1425 "Zend/zend_language_scanner.l"
{
return T_BOOLEAN_AND;
}
-#line 3490 "Zend/zend_language_scanner.c"
+#line 3461 "Zend/zend_language_scanner.c"
yy226:
YYDEBUG(226, *YYCURSOR);
++YYCURSOR;
YYDEBUG(227, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1432 "Zend/zend_language_scanner.l"
+#line 1409 "Zend/zend_language_scanner.l"
{
return T_AND_EQUAL;
}
-#line 3500 "Zend/zend_language_scanner.c"
+#line 3471 "Zend/zend_language_scanner.c"
yy228:
YYDEBUG(228, *YYCURSOR);
++YYCURSOR;
@@ -3505,28 +3476,27 @@ yy228:
yy229:
YYDEBUG(229, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1962 "Zend/zend_language_scanner.l"
+#line 1846 "Zend/zend_language_scanner.l"
{
if (CG(asp_tags)) {
BEGIN(INITIAL);
- DUMMY_STRINGL(zendlval, yytext, yyleng);
return T_CLOSE_TAG; /* implicit ';' at php-end tag */
} else {
yyless(1);
return yytext[0];
}
}
-#line 3520 "Zend/zend_language_scanner.c"
+#line 3490 "Zend/zend_language_scanner.c"
yy230:
YYDEBUG(230, *YYCURSOR);
++YYCURSOR;
YYDEBUG(231, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1420 "Zend/zend_language_scanner.l"
+#line 1397 "Zend/zend_language_scanner.l"
{
return T_MOD_EQUAL;
}
-#line 3530 "Zend/zend_language_scanner.c"
+#line 3500 "Zend/zend_language_scanner.c"
yy232:
YYDEBUG(232, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3544,7 +3514,7 @@ yy234:
yy235:
YYDEBUG(235, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1922 "Zend/zend_language_scanner.l"
+#line 1807 "Zend/zend_language_scanner.l"
{
int doc_com;
@@ -3571,13 +3541,13 @@ yy235:
HANDLE_NEWLINES(yytext, yyleng);
if (doc_com) {
- CG(doc_comment) = STR_INIT(yytext, yyleng, 0);
+ CG(doc_comment) = zend_string_init(yytext, yyleng, 0);
return T_DOC_COMMENT;
}
return T_COMMENT;
}
-#line 3581 "Zend/zend_language_scanner.c"
+#line 3551 "Zend/zend_language_scanner.c"
yy236:
YYDEBUG(236, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3587,11 +3557,11 @@ yy237:
++YYCURSOR;
YYDEBUG(238, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1412 "Zend/zend_language_scanner.l"
+#line 1389 "Zend/zend_language_scanner.l"
{
return T_DIV_EQUAL;
}
-#line 3595 "Zend/zend_language_scanner.c"
+#line 3565 "Zend/zend_language_scanner.c"
yy239:
YYDEBUG(239, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3615,62 +3585,62 @@ yy242:
if ((yych = *YYCURSOR) == '=') goto yy246;
YYDEBUG(243, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1404 "Zend/zend_language_scanner.l"
+#line 1381 "Zend/zend_language_scanner.l"
{
return T_POW;
}
-#line 3623 "Zend/zend_language_scanner.c"
+#line 3593 "Zend/zend_language_scanner.c"
yy244:
YYDEBUG(244, *YYCURSOR);
++YYCURSOR;
YYDEBUG(245, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1400 "Zend/zend_language_scanner.l"
+#line 1377 "Zend/zend_language_scanner.l"
{
return T_MUL_EQUAL;
}
-#line 3633 "Zend/zend_language_scanner.c"
+#line 3603 "Zend/zend_language_scanner.c"
yy246:
YYDEBUG(246, *YYCURSOR);
++YYCURSOR;
YYDEBUG(247, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1408 "Zend/zend_language_scanner.l"
+#line 1385 "Zend/zend_language_scanner.l"
{
return T_POW_EQUAL;
}
-#line 3643 "Zend/zend_language_scanner.c"
+#line 3613 "Zend/zend_language_scanner.c"
yy248:
YYDEBUG(248, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) == '=') goto yy252;
YYDEBUG(249, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1468 "Zend/zend_language_scanner.l"
+#line 1445 "Zend/zend_language_scanner.l"
{
return T_SR;
}
-#line 3654 "Zend/zend_language_scanner.c"
+#line 3624 "Zend/zend_language_scanner.c"
yy250:
YYDEBUG(250, *YYCURSOR);
++YYCURSOR;
YYDEBUG(251, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1388 "Zend/zend_language_scanner.l"
+#line 1365 "Zend/zend_language_scanner.l"
{
return T_IS_GREATER_OR_EQUAL;
}
-#line 3664 "Zend/zend_language_scanner.c"
+#line 3634 "Zend/zend_language_scanner.c"
yy252:
YYDEBUG(252, *YYCURSOR);
++YYCURSOR;
YYDEBUG(253, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1428 "Zend/zend_language_scanner.l"
+#line 1405 "Zend/zend_language_scanner.l"
{
return T_SR_EQUAL;
}
-#line 3674 "Zend/zend_language_scanner.c"
+#line 3644 "Zend/zend_language_scanner.c"
yy254:
YYDEBUG(254, *YYCURSOR);
yyaccept = 5;
@@ -3681,11 +3651,11 @@ yy254:
yy255:
YYDEBUG(255, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1464 "Zend/zend_language_scanner.l"
+#line 1441 "Zend/zend_language_scanner.l"
{
return T_SL;
}
-#line 3689 "Zend/zend_language_scanner.c"
+#line 3659 "Zend/zend_language_scanner.c"
yy256:
YYDEBUG(256, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3697,22 +3667,22 @@ yy257:
++YYCURSOR;
YYDEBUG(258, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1384 "Zend/zend_language_scanner.l"
+#line 1361 "Zend/zend_language_scanner.l"
{
return T_IS_SMALLER_OR_EQUAL;
}
-#line 3705 "Zend/zend_language_scanner.c"
+#line 3675 "Zend/zend_language_scanner.c"
yy259:
YYDEBUG(259, *YYCURSOR);
++YYCURSOR;
yy260:
YYDEBUG(260, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1380 "Zend/zend_language_scanner.l"
+#line 1357 "Zend/zend_language_scanner.l"
{
return T_IS_NOT_EQUAL;
}
-#line 3716 "Zend/zend_language_scanner.c"
+#line 3686 "Zend/zend_language_scanner.c"
yy261:
YYDEBUG(261, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3763,11 +3733,11 @@ yy268:
++YYCURSOR;
YYDEBUG(269, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1424 "Zend/zend_language_scanner.l"
+#line 1401 "Zend/zend_language_scanner.l"
{
return T_SL_EQUAL;
}
-#line 3771 "Zend/zend_language_scanner.c"
+#line 3741 "Zend/zend_language_scanner.c"
yy270:
YYDEBUG(270, *YYCURSOR);
++YYCURSOR;
@@ -3872,7 +3842,7 @@ yy279:
yy280:
YYDEBUG(280, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2085 "Zend/zend_language_scanner.l"
+#line 1969 "Zend/zend_language_scanner.l"
{
char *s;
int bprefix = (yytext[0] != '<') ? 1 : 0;
@@ -3919,7 +3889,7 @@ yy280:
return T_START_HEREDOC;
}
-#line 3923 "Zend/zend_language_scanner.c"
+#line 3893 "Zend/zend_language_scanner.c"
yy281:
YYDEBUG(281, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3959,31 +3929,31 @@ yy284:
++YYCURSOR;
YYDEBUG(286, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1372 "Zend/zend_language_scanner.l"
+#line 1349 "Zend/zend_language_scanner.l"
{
return T_IS_NOT_IDENTICAL;
}
-#line 3967 "Zend/zend_language_scanner.c"
+#line 3937 "Zend/zend_language_scanner.c"
yy287:
YYDEBUG(287, *YYCURSOR);
++YYCURSOR;
YYDEBUG(288, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1392 "Zend/zend_language_scanner.l"
+#line 1369 "Zend/zend_language_scanner.l"
{
return T_PLUS_EQUAL;
}
-#line 3977 "Zend/zend_language_scanner.c"
+#line 3947 "Zend/zend_language_scanner.c"
yy289:
YYDEBUG(289, *YYCURSOR);
++YYCURSOR;
YYDEBUG(290, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1360 "Zend/zend_language_scanner.l"
+#line 1337 "Zend/zend_language_scanner.l"
{
return T_INC;
}
-#line 3987 "Zend/zend_language_scanner.c"
+#line 3957 "Zend/zend_language_scanner.c"
yy291:
YYDEBUG(291, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4002,42 +3972,42 @@ yy293:
}
YYDEBUG(294, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1348 "Zend/zend_language_scanner.l"
+#line 1325 "Zend/zend_language_scanner.l"
{
return T_LIST;
}
-#line 4010 "Zend/zend_language_scanner.c"
+#line 3980 "Zend/zend_language_scanner.c"
yy295:
YYDEBUG(295, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) == '=') goto yy299;
YYDEBUG(296, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1376 "Zend/zend_language_scanner.l"
+#line 1353 "Zend/zend_language_scanner.l"
{
return T_IS_EQUAL;
}
-#line 4021 "Zend/zend_language_scanner.c"
+#line 3991 "Zend/zend_language_scanner.c"
yy297:
YYDEBUG(297, *YYCURSOR);
++YYCURSOR;
YYDEBUG(298, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1344 "Zend/zend_language_scanner.l"
+#line 1321 "Zend/zend_language_scanner.l"
{
return T_DOUBLE_ARROW;
}
-#line 4031 "Zend/zend_language_scanner.c"
+#line 4001 "Zend/zend_language_scanner.c"
yy299:
YYDEBUG(299, *YYCURSOR);
++YYCURSOR;
YYDEBUG(300, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1368 "Zend/zend_language_scanner.l"
+#line 1345 "Zend/zend_language_scanner.l"
{
return T_IS_IDENTICAL;
}
-#line 4041 "Zend/zend_language_scanner.c"
+#line 4011 "Zend/zend_language_scanner.c"
yy301:
YYDEBUG(301, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4167,16 +4137,11 @@ yy317:
}
YYDEBUG(320, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1707 "Zend/zend_language_scanner.l"
+#line 1602 "Zend/zend_language_scanner.l"
{
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- ZVAL_DUP(zendlval, &CG(current_namespace));
- } else {
- ZVAL_EMPTY_STRING(zendlval);
- }
return T_NS_C;
}
-#line 4180 "Zend/zend_language_scanner.c"
+#line 4145 "Zend/zend_language_scanner.c"
yy321:
YYDEBUG(321, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4196,32 +4161,11 @@ yy322:
}
YYDEBUG(325, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1682 "Zend/zend_language_scanner.l"
+#line 1598 "Zend/zend_language_scanner.l"
{
- zend_string *filename = zend_get_compiled_filename(TSRMLS_C);
- zend_string *dirname;
-
- if (!filename) {
- filename = STR_EMPTY_ALLOC();
- }
-
- dirname = STR_INIT(filename->val, filename->len, 0);
- zend_dirname(dirname->val, dirname->len);
-
- if (strcmp(dirname->val, ".") == 0) {
- dirname = STR_REALLOC(dirname, MAXPATHLEN, 0);
-#if HAVE_GETCWD
- VCWD_GETCWD(dirname->val, MAXPATHLEN);
-#elif HAVE_GETWD
- VCWD_GETWD(dirname->val);
-#endif
- }
-
- dirname->len = strlen(dirname->val);
- ZVAL_STR(zendlval, dirname);
return T_DIR;
}
-#line 4225 "Zend/zend_language_scanner.c"
+#line 4169 "Zend/zend_language_scanner.c"
yy326:
YYDEBUG(326, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4246,12 +4190,11 @@ yy328:
}
YYDEBUG(331, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1666 "Zend/zend_language_scanner.l"
+#line 1590 "Zend/zend_language_scanner.l"
{
- ZVAL_LONG(zendlval, CG(zend_lineno));
return T_LINE;
}
-#line 4255 "Zend/zend_language_scanner.c"
+#line 4198 "Zend/zend_language_scanner.c"
yy332:
YYDEBUG(332, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4286,39 +4229,11 @@ yy336:
}
YYDEBUG(339, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1634 "Zend/zend_language_scanner.l"
+#line 1586 "Zend/zend_language_scanner.l"
{
- if (CG(active_class_entry)) {
- int len = 0;
-
- if (CG(active_class_entry)->name) {
- len += CG(active_class_entry)->name->len;
- }
- if (CG(active_op_array) && CG(active_op_array)->function_name) {
- len += sizeof("::")-1;
- len += CG(active_op_array)->function_name->len;
- }
- ZVAL_NEW_STR(zendlval, STR_ALLOC(len, 0));
- len = 0;
- if (CG(active_class_entry)->name) {
- memcpy(Z_STRVAL_P(zendlval), CG(active_class_entry)->name->val, CG(active_class_entry)->name->len);
- len += CG(active_class_entry)->name->len;
- }
- if (CG(active_op_array) && CG(active_op_array)->function_name) {
- memcpy(Z_STRVAL_P(zendlval) + len, "::", sizeof("::")-1);
- len += sizeof("::")-1;
- memcpy(Z_STRVAL_P(zendlval) + len, CG(active_op_array)->function_name->val, CG(active_op_array)->function_name->len);
- len += CG(active_op_array)->function_name->len;
- }
- Z_STRVAL_P(zendlval)[len] = 0;
- } else if (CG(active_op_array) && CG(active_op_array)->function_name) {
- ZVAL_STR(zendlval, STR_COPY(CG(active_op_array)->function_name));
- } else {
- ZVAL_EMPTY_STRING(zendlval);
- }
return T_METHOD_C;
}
-#line 4322 "Zend/zend_language_scanner.c"
+#line 4237 "Zend/zend_language_scanner.c"
yy340:
YYDEBUG(340, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4369,17 +4284,11 @@ yy347:
}
YYDEBUG(350, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1624 "Zend/zend_language_scanner.l"
+#line 1582 "Zend/zend_language_scanner.l"
{
- zend_op_array *op_array = CG(active_op_array);
- if (op_array && op_array->function_name) {
- ZVAL_STR(zendlval, STR_COPY(op_array->function_name));
- } else {
- ZVAL_EMPTY_STRING(zendlval);
- }
return T_FUNC_C;
}
-#line 4383 "Zend/zend_language_scanner.c"
+#line 4292 "Zend/zend_language_scanner.c"
yy351:
YYDEBUG(351, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4399,18 +4308,11 @@ yy352:
}
YYDEBUG(355, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1671 "Zend/zend_language_scanner.l"
+#line 1594 "Zend/zend_language_scanner.l"
{
- zend_string *filename = zend_get_compiled_filename(TSRMLS_C);
-
- if (!filename) {
- ZVAL_EMPTY_STRING(zendlval);
- } else {
- ZVAL_STR(zendlval, STR_COPY(filename));
- }
return T_FILE;
}
-#line 4414 "Zend/zend_language_scanner.c"
+#line 4316 "Zend/zend_language_scanner.c"
yy356:
YYDEBUG(356, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4440,17 +4342,11 @@ yy359:
}
YYDEBUG(362, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1614 "Zend/zend_language_scanner.l"
+#line 1578 "Zend/zend_language_scanner.l"
{
- zend_class_entry *ce = CG(active_class_entry);
- if (ce && ce->name && ZEND_ACC_TRAIT == (ce->ce_flags & ZEND_ACC_TRAIT)) {
- ZVAL_STR(zendlval, STR_COPY(ce->name));
- } else {
- ZVAL_EMPTY_STRING(zendlval);
- }
return T_TRAIT_C;
}
-#line 4454 "Zend/zend_language_scanner.c"
+#line 4350 "Zend/zend_language_scanner.c"
yy363:
YYDEBUG(363, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4480,24 +4376,11 @@ yy366:
}
YYDEBUG(369, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1597 "Zend/zend_language_scanner.l"
+#line 1574 "Zend/zend_language_scanner.l"
{
- zend_class_entry *ce = CG(active_class_entry);
- if (ce && ZEND_ACC_TRAIT == (ce->ce_flags & ZEND_ACC_TRAIT)) {
- /* We create a special __CLASS__ constant that is going to be resolved
- at run-time */
- ZVAL_STRINGL(zendlval, "__CLASS__", sizeof("__CLASS__") - 1);
- Z_TYPE_INFO_P(zendlval) = IS_CONSTANT_EX;
- } else {
- if (ce && ce->name) {
- ZVAL_STR(zendlval, STR_COPY(ce->name));
- } else {
- ZVAL_EMPTY_STRING(zendlval);
- }
- }
return T_CLASS_C;
}
-#line 4501 "Zend/zend_language_scanner.c"
+#line 4384 "Zend/zend_language_scanner.c"
yy370:
YYDEBUG(370, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4559,11 +4442,11 @@ yy381:
}
YYDEBUG(382, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1312 "Zend/zend_language_scanner.l"
+#line 1289 "Zend/zend_language_scanner.l"
{
return T_HALT_COMPILER;
}
-#line 4567 "Zend/zend_language_scanner.c"
+#line 4450 "Zend/zend_language_scanner.c"
yy383:
YYDEBUG(383, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4583,11 +4466,11 @@ yy385:
}
YYDEBUG(386, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1292 "Zend/zend_language_scanner.l"
+#line 1269 "Zend/zend_language_scanner.l"
{
return T_USE;
}
-#line 4591 "Zend/zend_language_scanner.c"
+#line 4474 "Zend/zend_language_scanner.c"
yy387:
YYDEBUG(387, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4606,11 +4489,11 @@ yy389:
}
YYDEBUG(390, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1340 "Zend/zend_language_scanner.l"
+#line 1317 "Zend/zend_language_scanner.l"
{
return T_UNSET;
}
-#line 4614 "Zend/zend_language_scanner.c"
+#line 4497 "Zend/zend_language_scanner.c"
yy391:
YYDEBUG(391, *YYCURSOR);
++YYCURSOR;
@@ -4782,11 +4665,11 @@ yy406:
++YYCURSOR;
YYDEBUG(408, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1240 "Zend/zend_language_scanner.l"
+#line 1217 "Zend/zend_language_scanner.l"
{
return T_INT_CAST;
}
-#line 4790 "Zend/zend_language_scanner.c"
+#line 4673 "Zend/zend_language_scanner.c"
yy409:
YYDEBUG(409, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4830,11 +4713,11 @@ yy414:
++YYCURSOR;
YYDEBUG(417, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1244 "Zend/zend_language_scanner.l"
+#line 1221 "Zend/zend_language_scanner.l"
{
return T_DOUBLE_CAST;
}
-#line 4838 "Zend/zend_language_scanner.c"
+#line 4721 "Zend/zend_language_scanner.c"
yy418:
YYDEBUG(418, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4904,11 +4787,11 @@ yy428:
++YYCURSOR;
YYDEBUG(431, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1248 "Zend/zend_language_scanner.l"
+#line 1225 "Zend/zend_language_scanner.l"
{
return T_STRING_CAST;
}
-#line 4912 "Zend/zend_language_scanner.c"
+#line 4795 "Zend/zend_language_scanner.c"
yy432:
YYDEBUG(432, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4941,11 +4824,11 @@ yy435:
++YYCURSOR;
YYDEBUG(438, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1252 "Zend/zend_language_scanner.l"
+#line 1229 "Zend/zend_language_scanner.l"
{
return T_ARRAY_CAST;
}
-#line 4949 "Zend/zend_language_scanner.c"
+#line 4832 "Zend/zend_language_scanner.c"
yy439:
YYDEBUG(439, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4983,11 +4866,11 @@ yy443:
++YYCURSOR;
YYDEBUG(446, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1256 "Zend/zend_language_scanner.l"
+#line 1233 "Zend/zend_language_scanner.l"
{
return T_OBJECT_CAST;
}
-#line 4991 "Zend/zend_language_scanner.c"
+#line 4874 "Zend/zend_language_scanner.c"
yy447:
YYDEBUG(447, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5028,11 +4911,11 @@ yy452:
++YYCURSOR;
YYDEBUG(454, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1260 "Zend/zend_language_scanner.l"
+#line 1237 "Zend/zend_language_scanner.l"
{
return T_BOOL_CAST;
}
-#line 5036 "Zend/zend_language_scanner.c"
+#line 4919 "Zend/zend_language_scanner.c"
yy455:
YYDEBUG(455, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5092,11 +4975,11 @@ yy463:
++YYCURSOR;
YYDEBUG(466, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1264 "Zend/zend_language_scanner.l"
+#line 1241 "Zend/zend_language_scanner.l"
{
return T_UNSET_CAST;
}
-#line 5100 "Zend/zend_language_scanner.c"
+#line 4983 "Zend/zend_language_scanner.c"
yy467:
YYDEBUG(467, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5110,11 +4993,11 @@ yy468:
}
YYDEBUG(469, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1236 "Zend/zend_language_scanner.l"
+#line 1213 "Zend/zend_language_scanner.l"
{
return T_VAR;
}
-#line 5118 "Zend/zend_language_scanner.c"
+#line 5001 "Zend/zend_language_scanner.c"
yy470:
YYDEBUG(470, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5134,11 +5017,11 @@ yy472:
}
YYDEBUG(473, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1228 "Zend/zend_language_scanner.l"
+#line 1205 "Zend/zend_language_scanner.l"
{
return T_NEW;
}
-#line 5142 "Zend/zend_language_scanner.c"
+#line 5025 "Zend/zend_language_scanner.c"
yy474:
YYDEBUG(474, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5177,11 +5060,11 @@ yy480:
}
YYDEBUG(481, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1288 "Zend/zend_language_scanner.l"
+#line 1265 "Zend/zend_language_scanner.l"
{
return T_NAMESPACE;
}
-#line 5185 "Zend/zend_language_scanner.c"
+#line 5068 "Zend/zend_language_scanner.c"
yy482:
YYDEBUG(482, *YYCURSOR);
yyaccept = 3;
@@ -5203,11 +5086,11 @@ yy484:
++YYCURSOR;
YYDEBUG(485, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1416 "Zend/zend_language_scanner.l"
+#line 1393 "Zend/zend_language_scanner.l"
{
return T_CONCAT_EQUAL;
}
-#line 5211 "Zend/zend_language_scanner.c"
+#line 5094 "Zend/zend_language_scanner.c"
yy486:
YYDEBUG(486, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5216,21 +5099,21 @@ yy486:
++YYCURSOR;
YYDEBUG(488, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1224 "Zend/zend_language_scanner.l"
+#line 1201 "Zend/zend_language_scanner.l"
{
return T_ELLIPSIS;
}
-#line 5224 "Zend/zend_language_scanner.c"
+#line 5107 "Zend/zend_language_scanner.c"
yy489:
YYDEBUG(489, *YYCURSOR);
++YYCURSOR;
YYDEBUG(490, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1216 "Zend/zend_language_scanner.l"
+#line 1193 "Zend/zend_language_scanner.l"
{
return T_PAAMAYIM_NEKUDOTAYIM;
}
-#line 5234 "Zend/zend_language_scanner.c"
+#line 5117 "Zend/zend_language_scanner.c"
yy491:
YYDEBUG(491, *YYCURSOR);
++YYCURSOR;
@@ -5252,32 +5135,32 @@ yy493:
++YYCURSOR;
YYDEBUG(494, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1396 "Zend/zend_language_scanner.l"
+#line 1373 "Zend/zend_language_scanner.l"
{
return T_MINUS_EQUAL;
}
-#line 5260 "Zend/zend_language_scanner.c"
+#line 5143 "Zend/zend_language_scanner.c"
yy495:
YYDEBUG(495, *YYCURSOR);
++YYCURSOR;
YYDEBUG(496, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1364 "Zend/zend_language_scanner.l"
+#line 1341 "Zend/zend_language_scanner.l"
{
return T_DEC;
}
-#line 5270 "Zend/zend_language_scanner.c"
+#line 5153 "Zend/zend_language_scanner.c"
yy497:
YYDEBUG(497, *YYCURSOR);
++YYCURSOR;
YYDEBUG(498, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1189 "Zend/zend_language_scanner.l"
+#line 1167 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
return T_OBJECT_OPERATOR;
}
-#line 5281 "Zend/zend_language_scanner.c"
+#line 5164 "Zend/zend_language_scanner.c"
yy499:
YYDEBUG(499, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5322,11 +5205,11 @@ yy504:
}
YYDEBUG(505, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1336 "Zend/zend_language_scanner.l"
+#line 1313 "Zend/zend_language_scanner.l"
{
return T_PUBLIC;
}
-#line 5330 "Zend/zend_language_scanner.c"
+#line 5213 "Zend/zend_language_scanner.c"
yy506:
YYDEBUG(506, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5381,11 +5264,11 @@ yy513:
}
YYDEBUG(514, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1332 "Zend/zend_language_scanner.l"
+#line 1309 "Zend/zend_language_scanner.l"
{
return T_PROTECTED;
}
-#line 5389 "Zend/zend_language_scanner.c"
+#line 5272 "Zend/zend_language_scanner.c"
yy515:
YYDEBUG(515, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5415,11 +5298,11 @@ yy519:
}
YYDEBUG(520, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1328 "Zend/zend_language_scanner.l"
+#line 1305 "Zend/zend_language_scanner.l"
{
return T_PRIVATE;
}
-#line 5423 "Zend/zend_language_scanner.c"
+#line 5306 "Zend/zend_language_scanner.c"
yy521:
YYDEBUG(521, *YYCURSOR);
++YYCURSOR;
@@ -5428,11 +5311,11 @@ yy521:
}
YYDEBUG(522, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1165 "Zend/zend_language_scanner.l"
+#line 1143 "Zend/zend_language_scanner.l"
{
return T_PRINT;
}
-#line 5436 "Zend/zend_language_scanner.c"
+#line 5319 "Zend/zend_language_scanner.c"
yy523:
YYDEBUG(523, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5457,11 +5340,11 @@ yy526:
}
YYDEBUG(527, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1157 "Zend/zend_language_scanner.l"
+#line 1135 "Zend/zend_language_scanner.l"
{
return T_GOTO;
}
-#line 5465 "Zend/zend_language_scanner.c"
+#line 5348 "Zend/zend_language_scanner.c"
yy528:
YYDEBUG(528, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5485,11 +5368,11 @@ yy531:
}
YYDEBUG(532, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1300 "Zend/zend_language_scanner.l"
+#line 1277 "Zend/zend_language_scanner.l"
{
return T_GLOBAL;
}
-#line 5493 "Zend/zend_language_scanner.c"
+#line 5376 "Zend/zend_language_scanner.c"
yy533:
YYDEBUG(533, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5526,11 +5409,11 @@ yy539:
}
YYDEBUG(540, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1149 "Zend/zend_language_scanner.l"
+#line 1127 "Zend/zend_language_scanner.l"
{
return T_BREAK;
}
-#line 5534 "Zend/zend_language_scanner.c"
+#line 5417 "Zend/zend_language_scanner.c"
yy541:
YYDEBUG(541, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5570,11 +5453,11 @@ yy547:
}
YYDEBUG(548, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1133 "Zend/zend_language_scanner.l"
+#line 1111 "Zend/zend_language_scanner.l"
{
return T_SWITCH;
}
-#line 5578 "Zend/zend_language_scanner.c"
+#line 5461 "Zend/zend_language_scanner.c"
yy549:
YYDEBUG(549, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5598,11 +5481,11 @@ yy552:
}
YYDEBUG(553, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1316 "Zend/zend_language_scanner.l"
+#line 1293 "Zend/zend_language_scanner.l"
{
return T_STATIC;
}
-#line 5606 "Zend/zend_language_scanner.c"
+#line 5489 "Zend/zend_language_scanner.c"
yy554:
YYDEBUG(554, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5629,11 +5512,11 @@ yy557:
}
YYDEBUG(558, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1129 "Zend/zend_language_scanner.l"
+#line 1107 "Zend/zend_language_scanner.l"
{
return T_AS;
}
-#line 5637 "Zend/zend_language_scanner.c"
+#line 5520 "Zend/zend_language_scanner.c"
yy559:
YYDEBUG(559, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5652,11 +5535,11 @@ yy561:
}
YYDEBUG(562, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1352 "Zend/zend_language_scanner.l"
+#line 1329 "Zend/zend_language_scanner.l"
{
return T_ARRAY;
}
-#line 5660 "Zend/zend_language_scanner.c"
+#line 5543 "Zend/zend_language_scanner.c"
yy563:
YYDEBUG(563, *YYCURSOR);
++YYCURSOR;
@@ -5665,11 +5548,11 @@ yy563:
}
YYDEBUG(564, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1456 "Zend/zend_language_scanner.l"
+#line 1433 "Zend/zend_language_scanner.l"
{
return T_LOGICAL_AND;
}
-#line 5673 "Zend/zend_language_scanner.c"
+#line 5556 "Zend/zend_language_scanner.c"
yy565:
YYDEBUG(565, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5703,11 +5586,11 @@ yy570:
}
YYDEBUG(571, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1320 "Zend/zend_language_scanner.l"
+#line 1297 "Zend/zend_language_scanner.l"
{
return T_ABSTRACT;
}
-#line 5711 "Zend/zend_language_scanner.c"
+#line 5594 "Zend/zend_language_scanner.c"
yy572:
YYDEBUG(572, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5731,11 +5614,11 @@ yy575:
}
YYDEBUG(576, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1089 "Zend/zend_language_scanner.l"
+#line 1067 "Zend/zend_language_scanner.l"
{
return T_WHILE;
}
-#line 5739 "Zend/zend_language_scanner.c"
+#line 5622 "Zend/zend_language_scanner.c"
yy577:
YYDEBUG(577, *YYCURSOR);
++YYCURSOR;
@@ -5744,11 +5627,11 @@ yy577:
}
YYDEBUG(578, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1073 "Zend/zend_language_scanner.l"
+#line 1051 "Zend/zend_language_scanner.l"
{
return T_IF;
}
-#line 5752 "Zend/zend_language_scanner.c"
+#line 5635 "Zend/zend_language_scanner.c"
yy579:
YYDEBUG(579, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5800,11 +5683,11 @@ yy584:
}
YYDEBUG(585, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1304 "Zend/zend_language_scanner.l"
+#line 1281 "Zend/zend_language_scanner.l"
{
return T_ISSET;
}
-#line 5808 "Zend/zend_language_scanner.c"
+#line 5691 "Zend/zend_language_scanner.c"
yy586:
YYDEBUG(586, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5858,11 +5741,11 @@ yy592:
yy593:
YYDEBUG(593, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1272 "Zend/zend_language_scanner.l"
+#line 1249 "Zend/zend_language_scanner.l"
{
return T_INCLUDE;
}
-#line 5866 "Zend/zend_language_scanner.c"
+#line 5749 "Zend/zend_language_scanner.c"
yy594:
YYDEBUG(594, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5891,11 +5774,11 @@ yy598:
}
YYDEBUG(599, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1276 "Zend/zend_language_scanner.l"
+#line 1253 "Zend/zend_language_scanner.l"
{
return T_INCLUDE_ONCE;
}
-#line 5899 "Zend/zend_language_scanner.c"
+#line 5782 "Zend/zend_language_scanner.c"
yy600:
YYDEBUG(600, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5929,11 +5812,11 @@ yy605:
}
YYDEBUG(606, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1173 "Zend/zend_language_scanner.l"
+#line 1151 "Zend/zend_language_scanner.l"
{
return T_INTERFACE;
}
-#line 5937 "Zend/zend_language_scanner.c"
+#line 5820 "Zend/zend_language_scanner.c"
yy607:
YYDEBUG(607, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5983,11 +5866,11 @@ yy613:
}
YYDEBUG(614, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1296 "Zend/zend_language_scanner.l"
+#line 1273 "Zend/zend_language_scanner.l"
{
return T_INSTEADOF;
}
-#line 5991 "Zend/zend_language_scanner.c"
+#line 5874 "Zend/zend_language_scanner.c"
yy615:
YYDEBUG(615, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6016,11 +5899,11 @@ yy619:
}
YYDEBUG(620, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1125 "Zend/zend_language_scanner.l"
+#line 1103 "Zend/zend_language_scanner.l"
{
return T_INSTANCEOF;
}
-#line 6024 "Zend/zend_language_scanner.c"
+#line 5907 "Zend/zend_language_scanner.c"
yy621:
YYDEBUG(621, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6064,11 +5947,11 @@ yy628:
}
YYDEBUG(629, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1185 "Zend/zend_language_scanner.l"
+#line 1163 "Zend/zend_language_scanner.l"
{
return T_IMPLEMENTS;
}
-#line 6072 "Zend/zend_language_scanner.c"
+#line 5955 "Zend/zend_language_scanner.c"
yy630:
YYDEBUG(630, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6096,11 +5979,11 @@ yy631:
}
YYDEBUG(633, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1057 "Zend/zend_language_scanner.l"
+#line 1035 "Zend/zend_language_scanner.l"
{
return T_TRY;
}
-#line 6104 "Zend/zend_language_scanner.c"
+#line 5987 "Zend/zend_language_scanner.c"
yy634:
YYDEBUG(634, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6119,11 +6002,11 @@ yy636:
}
YYDEBUG(637, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1177 "Zend/zend_language_scanner.l"
+#line 1155 "Zend/zend_language_scanner.l"
{
return T_TRAIT;
}
-#line 6127 "Zend/zend_language_scanner.c"
+#line 6010 "Zend/zend_language_scanner.c"
yy638:
YYDEBUG(638, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6142,11 +6025,11 @@ yy640:
}
YYDEBUG(641, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1069 "Zend/zend_language_scanner.l"
+#line 1047 "Zend/zend_language_scanner.l"
{
return T_THROW;
}
-#line 6150 "Zend/zend_language_scanner.c"
+#line 6033 "Zend/zend_language_scanner.c"
yy642:
YYDEBUG(642, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6170,11 +6053,11 @@ yy645:
}
YYDEBUG(646, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1053 "Zend/zend_language_scanner.l"
+#line 1031 "Zend/zend_language_scanner.l"
{
return T_YIELD;
}
-#line 6178 "Zend/zend_language_scanner.c"
+#line 6061 "Zend/zend_language_scanner.c"
yy647:
YYDEBUG(647, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6235,11 +6118,11 @@ yy653:
yy654:
YYDEBUG(654, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1280 "Zend/zend_language_scanner.l"
+#line 1257 "Zend/zend_language_scanner.l"
{
return T_REQUIRE;
}
-#line 6243 "Zend/zend_language_scanner.c"
+#line 6126 "Zend/zend_language_scanner.c"
yy655:
YYDEBUG(655, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6268,11 +6151,11 @@ yy659:
}
YYDEBUG(660, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1284 "Zend/zend_language_scanner.l"
+#line 1261 "Zend/zend_language_scanner.l"
{
return T_REQUIRE_ONCE;
}
-#line 6276 "Zend/zend_language_scanner.c"
+#line 6159 "Zend/zend_language_scanner.c"
yy661:
YYDEBUG(661, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6291,11 +6174,11 @@ yy663:
}
YYDEBUG(664, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1049 "Zend/zend_language_scanner.l"
+#line 1027 "Zend/zend_language_scanner.l"
{
return T_RETURN;
}
-#line 6299 "Zend/zend_language_scanner.c"
+#line 6182 "Zend/zend_language_scanner.c"
yy665:
YYDEBUG(665, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6385,11 +6268,11 @@ yy674:
}
YYDEBUG(675, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1153 "Zend/zend_language_scanner.l"
+#line 1131 "Zend/zend_language_scanner.l"
{
return T_CONTINUE;
}
-#line 6393 "Zend/zend_language_scanner.c"
+#line 6276 "Zend/zend_language_scanner.c"
yy676:
YYDEBUG(676, *YYCURSOR);
++YYCURSOR;
@@ -6398,11 +6281,11 @@ yy676:
}
YYDEBUG(677, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1045 "Zend/zend_language_scanner.l"
+#line 1023 "Zend/zend_language_scanner.l"
{
return T_CONST;
}
-#line 6406 "Zend/zend_language_scanner.c"
+#line 6289 "Zend/zend_language_scanner.c"
yy678:
YYDEBUG(678, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6427,11 +6310,11 @@ yy681:
}
YYDEBUG(682, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1232 "Zend/zend_language_scanner.l"
+#line 1209 "Zend/zend_language_scanner.l"
{
return T_CLONE;
}
-#line 6435 "Zend/zend_language_scanner.c"
+#line 6318 "Zend/zend_language_scanner.c"
yy683:
YYDEBUG(683, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6445,11 +6328,11 @@ yy684:
}
YYDEBUG(685, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1169 "Zend/zend_language_scanner.l"
+#line 1147 "Zend/zend_language_scanner.l"
{
return T_CLASS;
}
-#line 6453 "Zend/zend_language_scanner.c"
+#line 6336 "Zend/zend_language_scanner.c"
yy686:
YYDEBUG(686, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6495,11 +6378,11 @@ yy693:
}
YYDEBUG(694, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1356 "Zend/zend_language_scanner.l"
+#line 1333 "Zend/zend_language_scanner.l"
{
return T_CALLABLE;
}
-#line 6503 "Zend/zend_language_scanner.c"
+#line 6386 "Zend/zend_language_scanner.c"
yy695:
YYDEBUG(695, *YYCURSOR);
++YYCURSOR;
@@ -6508,11 +6391,11 @@ yy695:
}
YYDEBUG(696, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1141 "Zend/zend_language_scanner.l"
+#line 1119 "Zend/zend_language_scanner.l"
{
return T_CASE;
}
-#line 6516 "Zend/zend_language_scanner.c"
+#line 6399 "Zend/zend_language_scanner.c"
yy697:
YYDEBUG(697, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6526,11 +6409,11 @@ yy698:
}
YYDEBUG(699, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1061 "Zend/zend_language_scanner.l"
+#line 1039 "Zend/zend_language_scanner.l"
{
return T_CATCH;
}
-#line 6534 "Zend/zend_language_scanner.c"
+#line 6417 "Zend/zend_language_scanner.c"
yy700:
YYDEBUG(700, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6581,11 +6464,11 @@ yy708:
}
YYDEBUG(709, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1041 "Zend/zend_language_scanner.l"
+#line 1019 "Zend/zend_language_scanner.l"
{
return T_FUNCTION;
}
-#line 6589 "Zend/zend_language_scanner.c"
+#line 6472 "Zend/zend_language_scanner.c"
yy710:
YYDEBUG(710, *YYCURSOR);
++YYCURSOR;
@@ -6609,11 +6492,11 @@ yy710:
yy711:
YYDEBUG(711, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1101 "Zend/zend_language_scanner.l"
+#line 1079 "Zend/zend_language_scanner.l"
{
return T_FOR;
}
-#line 6617 "Zend/zend_language_scanner.c"
+#line 6500 "Zend/zend_language_scanner.c"
yy712:
YYDEBUG(712, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6637,11 +6520,11 @@ yy715:
}
YYDEBUG(716, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1109 "Zend/zend_language_scanner.l"
+#line 1087 "Zend/zend_language_scanner.l"
{
return T_FOREACH;
}
-#line 6645 "Zend/zend_language_scanner.c"
+#line 6528 "Zend/zend_language_scanner.c"
yy717:
YYDEBUG(717, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6675,11 +6558,11 @@ yy719:
yy720:
YYDEBUG(720, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1324 "Zend/zend_language_scanner.l"
+#line 1301 "Zend/zend_language_scanner.l"
{
return T_FINAL;
}
-#line 6683 "Zend/zend_language_scanner.c"
+#line 6566 "Zend/zend_language_scanner.c"
yy721:
YYDEBUG(721, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6693,11 +6576,11 @@ yy722:
}
YYDEBUG(723, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1065 "Zend/zend_language_scanner.l"
+#line 1043 "Zend/zend_language_scanner.l"
{
return T_FINALLY;
}
-#line 6701 "Zend/zend_language_scanner.c"
+#line 6584 "Zend/zend_language_scanner.c"
yy724:
YYDEBUG(724, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6728,11 +6611,11 @@ yy726:
}
YYDEBUG(727, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1097 "Zend/zend_language_scanner.l"
+#line 1075 "Zend/zend_language_scanner.l"
{
return T_DO;
}
-#line 6736 "Zend/zend_language_scanner.c"
+#line 6619 "Zend/zend_language_scanner.c"
yy728:
YYDEBUG(728, *YYCURSOR);
++YYCURSOR;
@@ -6741,11 +6624,11 @@ yy728:
}
YYDEBUG(729, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1037 "Zend/zend_language_scanner.l"
+#line 1015 "Zend/zend_language_scanner.l"
{
return T_EXIT;
}
-#line 6749 "Zend/zend_language_scanner.c"
+#line 6632 "Zend/zend_language_scanner.c"
yy730:
YYDEBUG(730, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6780,11 +6663,11 @@ yy735:
}
YYDEBUG(736, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1145 "Zend/zend_language_scanner.l"
+#line 1123 "Zend/zend_language_scanner.l"
{
return T_DEFAULT;
}
-#line 6788 "Zend/zend_language_scanner.c"
+#line 6671 "Zend/zend_language_scanner.c"
yy737:
YYDEBUG(737, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6808,11 +6691,11 @@ yy740:
}
YYDEBUG(741, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1117 "Zend/zend_language_scanner.l"
+#line 1095 "Zend/zend_language_scanner.l"
{
return T_DECLARE;
}
-#line 6816 "Zend/zend_language_scanner.c"
+#line 6699 "Zend/zend_language_scanner.c"
yy742:
YYDEBUG(742, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6892,11 +6775,11 @@ yy753:
}
YYDEBUG(754, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1181 "Zend/zend_language_scanner.l"
+#line 1159 "Zend/zend_language_scanner.l"
{
return T_EXTENDS;
}
-#line 6900 "Zend/zend_language_scanner.c"
+#line 6783 "Zend/zend_language_scanner.c"
yy755:
YYDEBUG(755, *YYCURSOR);
++YYCURSOR;
@@ -6905,11 +6788,11 @@ yy755:
}
YYDEBUG(756, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1033 "Zend/zend_language_scanner.l"
+#line 1011 "Zend/zend_language_scanner.l"
{
return T_EXIT;
}
-#line 6913 "Zend/zend_language_scanner.c"
+#line 6796 "Zend/zend_language_scanner.c"
yy757:
YYDEBUG(757, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6923,11 +6806,11 @@ yy758:
}
YYDEBUG(759, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1268 "Zend/zend_language_scanner.l"
+#line 1245 "Zend/zend_language_scanner.l"
{
return T_EVAL;
}
-#line 6931 "Zend/zend_language_scanner.c"
+#line 6814 "Zend/zend_language_scanner.c"
yy760:
YYDEBUG(760, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6997,11 +6880,11 @@ yy769:
}
YYDEBUG(770, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1093 "Zend/zend_language_scanner.l"
+#line 1071 "Zend/zend_language_scanner.l"
{
return T_ENDWHILE;
}
-#line 7005 "Zend/zend_language_scanner.c"
+#line 6888 "Zend/zend_language_scanner.c"
yy771:
YYDEBUG(771, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7030,11 +6913,11 @@ yy775:
}
YYDEBUG(776, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1137 "Zend/zend_language_scanner.l"
+#line 1115 "Zend/zend_language_scanner.l"
{
return T_ENDSWITCH;
}
-#line 7038 "Zend/zend_language_scanner.c"
+#line 6921 "Zend/zend_language_scanner.c"
yy777:
YYDEBUG(777, *YYCURSOR);
++YYCURSOR;
@@ -7043,11 +6926,11 @@ yy777:
}
YYDEBUG(778, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1081 "Zend/zend_language_scanner.l"
+#line 1059 "Zend/zend_language_scanner.l"
{
return T_ENDIF;
}
-#line 7051 "Zend/zend_language_scanner.c"
+#line 6934 "Zend/zend_language_scanner.c"
yy779:
YYDEBUG(779, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7076,11 +6959,11 @@ yy780:
yy781:
YYDEBUG(781, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1105 "Zend/zend_language_scanner.l"
+#line 1083 "Zend/zend_language_scanner.l"
{
return T_ENDFOR;
}
-#line 7084 "Zend/zend_language_scanner.c"
+#line 6967 "Zend/zend_language_scanner.c"
yy782:
YYDEBUG(782, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7104,11 +6987,11 @@ yy785:
}
YYDEBUG(786, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1113 "Zend/zend_language_scanner.l"
+#line 1091 "Zend/zend_language_scanner.l"
{
return T_ENDFOREACH;
}
-#line 7112 "Zend/zend_language_scanner.c"
+#line 6995 "Zend/zend_language_scanner.c"
yy787:
YYDEBUG(787, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7142,11 +7025,11 @@ yy792:
}
YYDEBUG(793, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1121 "Zend/zend_language_scanner.l"
+#line 1099 "Zend/zend_language_scanner.l"
{
return T_ENDDECLARE;
}
-#line 7150 "Zend/zend_language_scanner.c"
+#line 7033 "Zend/zend_language_scanner.c"
yy794:
YYDEBUG(794, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7165,11 +7048,11 @@ yy796:
}
YYDEBUG(797, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1308 "Zend/zend_language_scanner.l"
+#line 1285 "Zend/zend_language_scanner.l"
{
return T_EMPTY;
}
-#line 7173 "Zend/zend_language_scanner.c"
+#line 7056 "Zend/zend_language_scanner.c"
yy798:
YYDEBUG(798, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7198,11 +7081,11 @@ yy799:
yy800:
YYDEBUG(800, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1085 "Zend/zend_language_scanner.l"
+#line 1063 "Zend/zend_language_scanner.l"
{
return T_ELSE;
}
-#line 7206 "Zend/zend_language_scanner.c"
+#line 7089 "Zend/zend_language_scanner.c"
yy801:
YYDEBUG(801, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7216,11 +7099,11 @@ yy802:
}
YYDEBUG(803, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1077 "Zend/zend_language_scanner.l"
+#line 1055 "Zend/zend_language_scanner.l"
{
return T_ELSEIF;
}
-#line 7224 "Zend/zend_language_scanner.c"
+#line 7107 "Zend/zend_language_scanner.c"
yy804:
YYDEBUG(804, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7234,11 +7117,11 @@ yy805:
}
YYDEBUG(806, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1161 "Zend/zend_language_scanner.l"
+#line 1139 "Zend/zend_language_scanner.l"
{
return T_ECHO;
}
-#line 7242 "Zend/zend_language_scanner.c"
+#line 7125 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_LOOKING_FOR_PROPERTY:
@@ -7311,13 +7194,12 @@ yy809:
yy810:
YYDEBUG(810, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1194 "Zend/zend_language_scanner.l"
+#line 1172 "Zend/zend_language_scanner.l"
{
- DUMMY_STRINGL(zendlval, yytext, yyleng);
HANDLE_NEWLINES(yytext, yyleng);
return T_WHITESPACE;
}
-#line 7321 "Zend/zend_language_scanner.c"
+#line 7203 "Zend/zend_language_scanner.c"
yy811:
YYDEBUG(811, *YYCURSOR);
++YYCURSOR;
@@ -7325,13 +7207,13 @@ yy811:
yy812:
YYDEBUG(812, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1210 "Zend/zend_language_scanner.l"
+#line 1187 "Zend/zend_language_scanner.l"
{
yyless(0);
yy_pop_state(TSRMLS_C);
goto restart;
}
-#line 7335 "Zend/zend_language_scanner.c"
+#line 7217 "Zend/zend_language_scanner.c"
yy813:
YYDEBUG(813, *YYCURSOR);
++YYCURSOR;
@@ -7340,13 +7222,13 @@ yy813:
yy814:
YYDEBUG(814, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1204 "Zend/zend_language_scanner.l"
+#line 1181 "Zend/zend_language_scanner.l"
{
yy_pop_state(TSRMLS_C);
zend_copy_value(zendlval, yytext, yyleng);
return T_STRING;
}
-#line 7350 "Zend/zend_language_scanner.c"
+#line 7232 "Zend/zend_language_scanner.c"
yy815:
YYDEBUG(815, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7367,11 +7249,11 @@ yy818:
++YYCURSOR;
YYDEBUG(819, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1200 "Zend/zend_language_scanner.l"
+#line 1177 "Zend/zend_language_scanner.l"
{
return T_OBJECT_OPERATOR;
}
-#line 7375 "Zend/zend_language_scanner.c"
+#line 7257 "Zend/zend_language_scanner.c"
yy820:
YYDEBUG(820, *YYCURSOR);
++YYCURSOR;
@@ -7456,14 +7338,14 @@ yy824:
yy825:
YYDEBUG(825, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1507 "Zend/zend_language_scanner.l"
+#line 1484 "Zend/zend_language_scanner.l"
{
yyless(0);
yy_pop_state(TSRMLS_C);
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
goto restart;
}
-#line 7467 "Zend/zend_language_scanner.c"
+#line 7349 "Zend/zend_language_scanner.c"
yy826:
YYDEBUG(826, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7488,7 +7370,7 @@ yy830:
++YYCURSOR;
YYDEBUG(831, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1498 "Zend/zend_language_scanner.l"
+#line 1475 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
zend_copy_value(zendlval, yytext, yyleng);
@@ -7496,7 +7378,7 @@ yy830:
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
return T_STRING_VARNAME;
}
-#line 7500 "Zend/zend_language_scanner.c"
+#line 7382 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_NOWDOC:
@@ -7507,7 +7389,7 @@ yyc_ST_NOWDOC:
++YYCURSOR;
YYDEBUG(835, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2338 "Zend/zend_language_scanner.l"
+#line 2222 "Zend/zend_language_scanner.l"
{
int newline = 0;
@@ -7563,7 +7445,7 @@ nowdoc_scan_done:
HANDLE_NEWLINES(yytext, yyleng - newline);
return T_ENCAPSED_AND_WHITESPACE;
}
-#line 7567 "Zend/zend_language_scanner.c"
+#line 7449 "Zend/zend_language_scanner.c"
/* *********************************** */
yyc_ST_VAR_OFFSET:
{
@@ -7670,16 +7552,16 @@ yy838:
yy839:
YYDEBUG(839, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1578 "Zend/zend_language_scanner.l"
+#line 1555 "Zend/zend_language_scanner.l"
{ /* Offset could be treated as a long */
if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) {
- ZVAL_LONG(zendlval, strtol(yytext, NULL, 10));
+ ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, NULL, 10));
} else {
ZVAL_STRINGL(zendlval, yytext, yyleng);
}
return T_NUM_STRING;
}
-#line 7683 "Zend/zend_language_scanner.c"
+#line 7565 "Zend/zend_language_scanner.c"
yy840:
YYDEBUG(840, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7699,23 +7581,23 @@ yy841:
yy842:
YYDEBUG(842, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1870 "Zend/zend_language_scanner.l"
+#line 1754 "Zend/zend_language_scanner.l"
{
/* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */
return yytext[0];
}
-#line 7708 "Zend/zend_language_scanner.c"
+#line 7590 "Zend/zend_language_scanner.c"
yy843:
YYDEBUG(843, *YYCURSOR);
++YYCURSOR;
YYDEBUG(844, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1865 "Zend/zend_language_scanner.l"
+#line 1749 "Zend/zend_language_scanner.l"
{
yy_pop_state(TSRMLS_C);
return ']';
}
-#line 7719 "Zend/zend_language_scanner.c"
+#line 7601 "Zend/zend_language_scanner.c"
yy845:
YYDEBUG(845, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7725,14 +7607,15 @@ yy846:
++YYCURSOR;
YYDEBUG(847, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1875 "Zend/zend_language_scanner.l"
+#line 1759 "Zend/zend_language_scanner.l"
{
/* Invalid rule to return a more explicit parse error with proper line number */
yyless(0);
yy_pop_state(TSRMLS_C);
+ ZVAL_NULL(zendlval);
return T_ENCAPSED_AND_WHITESPACE;
}
-#line 7736 "Zend/zend_language_scanner.c"
+#line 7619 "Zend/zend_language_scanner.c"
yy848:
YYDEBUG(848, *YYCURSOR);
++YYCURSOR;
@@ -7741,18 +7624,18 @@ yy848:
yy849:
YYDEBUG(849, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1882 "Zend/zend_language_scanner.l"
+#line 1767 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, yytext, yyleng);
return T_STRING;
}
-#line 7750 "Zend/zend_language_scanner.c"
+#line 7633 "Zend/zend_language_scanner.c"
yy850:
YYDEBUG(850, *YYCURSOR);
++YYCURSOR;
YYDEBUG(851, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2395 "Zend/zend_language_scanner.l"
+#line 2279 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
return 0;
@@ -7761,7 +7644,7 @@ yy850:
zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
goto restart;
}
-#line 7765 "Zend/zend_language_scanner.c"
+#line 7648 "Zend/zend_language_scanner.c"
yy852:
YYDEBUG(852, *YYCURSOR);
++YYCURSOR;
@@ -7797,12 +7680,12 @@ yy854:
yy856:
YYDEBUG(856, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1860 "Zend/zend_language_scanner.l"
+#line 1744 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
return T_VARIABLE;
}
-#line 7806 "Zend/zend_language_scanner.c"
+#line 7689 "Zend/zend_language_scanner.c"
yy857:
YYDEBUG(857, *YYCURSOR);
++YYCURSOR;
@@ -7842,12 +7725,12 @@ yy862:
yy864:
YYDEBUG(864, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1587 "Zend/zend_language_scanner.l"
+#line 1564 "Zend/zend_language_scanner.l"
{ /* Offset must be treated as a string */
ZVAL_STRINGL(zendlval, yytext, yyleng);
return T_NUM_STRING;
}
-#line 7851 "Zend/zend_language_scanner.c"
+#line 7734 "Zend/zend_language_scanner.c"
yy865:
YYDEBUG(865, *YYCURSOR);
++YYCURSOR;
@@ -7870,6 +7753,6 @@ yy867:
goto yy864;
}
}
-#line 2404 "Zend/zend_language_scanner.l"
+#line 2288 "Zend/zend_language_scanner.l"
}
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index b5100860c1..bcc341e8a1 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -126,7 +126,7 @@ BEGIN_EXTERN_C()
static size_t encoding_filter_script_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
{
const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
- assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
+ ZEND_ASSERT(internal_encoding);
return zend_multibyte_encoding_converter(to, to_length, from, from_length, internal_encoding, LANG_SCNG(script_encoding) TSRMLS_CC);
}
@@ -144,7 +144,7 @@ LANG_SCNG(script_encoding), zend_multibyte_encoding_utf8 TSRMLS_CC);
static size_t encoding_filter_intermediate_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
{
const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
- assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
+ ZEND_ASSERT(internal_encoding);
return zend_multibyte_encoding_converter(to, to_length, from, from_length,
internal_encoding, zend_multibyte_encoding_utf8 TSRMLS_CC);
}
@@ -533,9 +533,9 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
file_path = file_handle->filename;
}
- compiled_filename = STR_INIT(file_path, strlen(file_path), 0);
+ compiled_filename = zend_string_init(file_path, strlen(file_path), 0);
zend_set_compiled_filename(compiled_filename TSRMLS_CC);
- STR_RELEASE(compiled_filename);
+ zend_string_release(compiled_filename);
if (CG(start_lineno)) {
CG(zend_lineno) = CG(start_lineno);
@@ -556,19 +556,15 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
zend_lex_state original_lex_state;
zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
zend_op_array *original_active_op_array = CG(active_op_array);
- zend_op_array *retval=NULL;
int compiler_result;
zend_bool compilation_successful=0;
- znode retval_znode;
+ zval retval_zv;
zend_bool original_in_compilation = CG(in_compilation);
- retval_znode.op_type = IS_CONST;
- ZVAL_LONG(&retval_znode.u.constant, 1);
+ ZVAL_LONG(&retval_zv, 1);
zend_save_lexical_state(&original_lex_state TSRMLS_CC);
- retval = op_array; /* success oriented */
-
if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) {
if (type==ZEND_REQUIRE) {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
@@ -583,27 +579,31 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
CG(active_op_array) = op_array;
zend_stack_push(&CG(context_stack), (void *) &CG(context));
zend_init_compiler_context(TSRMLS_C);
+ CG(ast_arena) = zend_arena_create(1024 * 32);
compiler_result = zendparse(TSRMLS_C);
- zend_do_return(&retval_znode, 0 TSRMLS_CC);
- CG(in_compilation) = original_in_compilation;
if (compiler_result != 0) { /* parser error */
zend_bailout();
}
+ zend_compile_top_stmt(CG(ast) TSRMLS_CC);
+ zend_ast_destroy(CG(ast));
+ zend_arena_destroy(CG(ast_arena));
+ zend_do_end_compilation(TSRMLS_C);
+ zend_emit_final_return(&retval_zv TSRMLS_CC);
+ CG(in_compilation) = original_in_compilation;
compilation_successful=1;
}
- if (retval) {
- CG(active_op_array) = original_active_op_array;
- if (compilation_successful) {
- pass_two(op_array TSRMLS_CC);
- zend_release_labels(0 TSRMLS_CC);
- } else {
- efree(op_array);
- retval = NULL;
- }
+ CG(active_op_array) = original_active_op_array;
+ if (compilation_successful) {
+ pass_two(op_array TSRMLS_CC);
+ zend_release_labels(0 TSRMLS_CC);
+ } else {
+ efree_size(op_array, sizeof(zend_op_array));
+ op_array = NULL;
}
+
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
- return retval;
+ return op_array;
}
@@ -654,7 +654,7 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_D
/* enforce ZEND_MMAP_AHEAD trailing NULLs for flex... */
old_len = Z_STRLEN_P(str);
- Z_STR_P(str) = STR_REALLOC(Z_STR_P(str), old_len + ZEND_MMAP_AHEAD, 0);
+ Z_STR_P(str) = zend_string_realloc(Z_STR_P(str), old_len + ZEND_MMAP_AHEAD, 0);
Z_TYPE_INFO_P(str) = IS_STRING_EX;
memset(Z_STRVAL_P(str) + old_len, 0, ZEND_MMAP_AHEAD + 1);
@@ -683,9 +683,9 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_D
yy_scan_buffer(buf, size TSRMLS_CC);
- new_compiled_filename = STR_INIT(filename, strlen(filename), 0);
+ new_compiled_filename = zend_string_init(filename, strlen(filename), 0);
zend_set_compiled_filename(new_compiled_filename TSRMLS_CC);
- STR_RELEASE(new_compiled_filename);
+ zend_string_release(new_compiled_filename);
CG(zend_lineno) = 1;
CG(increment_lineno) = 0;
RESET_DOC_COMMENT();
@@ -718,63 +718,50 @@ ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D)
zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
{
zend_lex_state original_lex_state;
- zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
- zend_op_array *original_active_op_array = CG(active_op_array);
- zend_op_array *retval;
+ zend_op_array *op_array = NULL;
zval tmp;
- int compiler_result;
zend_bool original_in_compilation = CG(in_compilation);
if (Z_STRLEN_P(source_string)==0) {
- efree(op_array);
return NULL;
}
- CG(in_compilation) = 1;
-
ZVAL_DUP(&tmp, source_string);
convert_to_string(&tmp);
source_string = &tmp;
-
+
+ CG(in_compilation) = 1;
zend_save_lexical_state(&original_lex_state TSRMLS_CC);
- if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC)==FAILURE) {
- efree(op_array);
- retval = NULL;
- } else {
- zend_bool orig_interactive = CG(interactive);
-
- CG(interactive) = 0;
- init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
- CG(interactive) = orig_interactive;
- CG(active_op_array) = op_array;
- zend_stack_push(&CG(context_stack), (void *) &CG(context));
- zend_init_compiler_context(TSRMLS_C);
+ if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC) == SUCCESS) {
+ CG(ast) = NULL;
+ CG(ast_arena) = zend_arena_create(1024 * 32);
BEGIN(ST_IN_SCRIPTING);
- compiler_result = zendparse(TSRMLS_C);
- if (SCNG(script_filtered)) {
- efree(SCNG(script_filtered));
- SCNG(script_filtered) = NULL;
- }
-
- if (compiler_result != 0) {
- CG(active_op_array) = original_active_op_array;
- CG(unclean_shutdown)=1;
- destroy_op_array(op_array TSRMLS_CC);
- efree(op_array);
- retval = NULL;
- } else {
- zend_do_return(NULL, 0 TSRMLS_CC);
- CG(active_op_array) = original_active_op_array;
+ if (!zendparse(TSRMLS_C)) {
+ zend_op_array *original_active_op_array = CG(active_op_array);
+ op_array = emalloc(sizeof(zend_op_array));
+ init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
+ CG(active_op_array) = op_array;
+
+ zend_stack_push(&CG(context_stack), (void *) &CG(context));
+ zend_init_compiler_context(TSRMLS_C);
+ zend_compile_top_stmt(CG(ast) TSRMLS_CC);
+ zend_do_end_compilation(TSRMLS_C);
+ zend_emit_final_return(NULL TSRMLS_CC);
pass_two(op_array TSRMLS_CC);
zend_release_labels(0 TSRMLS_CC);
- retval = op_array;
+
+ CG(active_op_array) = original_active_op_array;
}
+
+ zend_ast_destroy(CG(ast));
+ zend_arena_destroy(CG(ast_arena));
}
+
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
zval_dtor(&tmp);
CG(in_compilation) = original_in_compilation;
- return retval;
+ return op_array;
}
@@ -856,7 +843,7 @@ ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter
SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start));
SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start));
SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start));
- SCNG(yy_limit) = new_yy_start + (SCNG(yy_limit) - SCNG(yy_start));
+ SCNG(yy_limit) = new_yy_start + length;
SCNG(yy_start) = new_yy_start;
}
@@ -874,15 +861,6 @@ ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter
ZVAL_STRINGL(zendlval, yytext, yyleng); \
}
-// TODO: some extensions might need content, but we don't copy it intentional ???
-#if 0
-# define DUMMY_STRINGL(zendlval, yytext, yyleng) \
- ZVAL_STRINGL(zendlval, yytext, yyleng)
-#else
-# define DUMMY_STRINGL(zendlval, yytext, yyleng) \
- ZVAL_EMPTY_STRING(zendlval)
-#endif
-
static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type TSRMLS_DC)
{
register char *s, *t;
@@ -955,7 +933,7 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
hex_buf[1] = *(++s);
Z_STRLEN_P(zendlval)--;
}
- *t++ = (char) strtol(hex_buf, NULL, 16);
+ *t++ = (char) ZEND_STRTOL(hex_buf, NULL, 16);
} else {
*t++ = '\\';
*t++ = *s;
@@ -976,7 +954,7 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
Z_STRLEN_P(zendlval)--;
}
}
- *t++ = (char) strtol(octal_buf, NULL, 8);
+ *t++ = (char) ZEND_STRTOL(octal_buf, NULL, 8);
} else {
*t++ = '\\';
*t++ = *s;
@@ -1000,7 +978,7 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
s = Z_STRVAL_P(zendlval);
SCNG(output_filter)(&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval) TSRMLS_CC);
zval_ptr_dtor(zendlval);
- ZVAL_STRINGL(zendlval, str, sz);
+ ZVAL_STRINGL(zendlval, (char *) str, sz);
efree(str);
}
}
@@ -1192,7 +1170,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
<ST_IN_SCRIPTING,ST_LOOKING_FOR_PROPERTY>{WHITESPACE}+ {
- DUMMY_STRINGL(zendlval, yytext, yyleng);
HANDLE_NEWLINES(yytext, yyleng);
return T_WHITESPACE;
}
@@ -1521,11 +1498,11 @@ NEWLINE ("\r"|"\n"|"\r\n")
--len;
}
- if (len < SIZEOF_LONG * 8) {
+ if (len < SIZEOF_ZEND_LONG * 8) {
if (len == 0) {
ZVAL_LONG(zendlval, 0);
} else {
- ZVAL_LONG(zendlval, strtol(bin, NULL, 2));
+ ZVAL_LONG(zendlval, ZEND_STRTOL(bin, NULL, 2));
}
return T_LNUMBER;
} else {
@@ -1536,10 +1513,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
<ST_IN_SCRIPTING>{LNUM} {
if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
- ZVAL_LONG(zendlval, strtol(yytext, NULL, 0));
+ ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, NULL, 0));
} else {
errno = 0;
- ZVAL_LONG(zendlval, strtol(yytext, NULL, 0));
+ ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, NULL, 0));
if (errno == ERANGE) { /* Overflow */
if (yytext[0] == '0') { /* octal overflow */
ZVAL_DOUBLE(zendlval, zend_oct_strtod(yytext, NULL));
@@ -1562,11 +1539,11 @@ NEWLINE ("\r"|"\n"|"\r\n")
len--;
}
- if (len < SIZEOF_LONG * 2 || (len == SIZEOF_LONG * 2 && *hex <= '7')) {
+ if (len < SIZEOF_ZEND_LONG * 2 || (len == SIZEOF_ZEND_LONG * 2 && *hex <= '7')) {
if (len == 0) {
ZVAL_LONG(zendlval, 0);
} else {
- ZVAL_LONG(zendlval, strtol(hex, NULL, 16));
+ ZVAL_LONG(zendlval, ZEND_STRTOL(hex, NULL, 16));
}
return T_LNUMBER;
} else {
@@ -1577,7 +1554,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
<ST_VAR_OFFSET>[0]|([1-9][0-9]*) { /* Offset could be treated as a long */
if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) {
- ZVAL_LONG(zendlval, strtol(yytext, NULL, 10));
+ ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, NULL, 10));
} else {
ZVAL_STRINGL(zendlval, yytext, yyleng);
}
@@ -1595,121 +1572,34 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
<ST_IN_SCRIPTING>"__CLASS__" {
- zend_class_entry *ce = CG(active_class_entry);
- if (ce && ZEND_ACC_TRAIT == (ce->ce_flags & ZEND_ACC_TRAIT)) {
- /* We create a special __CLASS__ constant that is going to be resolved
- at run-time */
- ZVAL_STRINGL(zendlval, "__CLASS__", sizeof("__CLASS__") - 1);
- Z_TYPE_INFO_P(zendlval) = IS_CONSTANT_EX;
- } else {
- if (ce && ce->name) {
- ZVAL_STR(zendlval, STR_COPY(ce->name));
- } else {
- ZVAL_EMPTY_STRING(zendlval);
- }
- }
return T_CLASS_C;
}
<ST_IN_SCRIPTING>"__TRAIT__" {
- zend_class_entry *ce = CG(active_class_entry);
- if (ce && ce->name && ZEND_ACC_TRAIT == (ce->ce_flags & ZEND_ACC_TRAIT)) {
- ZVAL_STR(zendlval, STR_COPY(ce->name));
- } else {
- ZVAL_EMPTY_STRING(zendlval);
- }
return T_TRAIT_C;
}
<ST_IN_SCRIPTING>"__FUNCTION__" {
- zend_op_array *op_array = CG(active_op_array);
- if (op_array && op_array->function_name) {
- ZVAL_STR(zendlval, STR_COPY(op_array->function_name));
- } else {
- ZVAL_EMPTY_STRING(zendlval);
- }
return T_FUNC_C;
}
<ST_IN_SCRIPTING>"__METHOD__" {
- if (CG(active_class_entry)) {
- int len = 0;
-
- if (CG(active_class_entry)->name) {
- len += CG(active_class_entry)->name->len;
- }
- if (CG(active_op_array) && CG(active_op_array)->function_name) {
- len += sizeof("::")-1;
- len += CG(active_op_array)->function_name->len;
- }
- ZVAL_NEW_STR(zendlval, STR_ALLOC(len, 0));
- len = 0;
- if (CG(active_class_entry)->name) {
- memcpy(Z_STRVAL_P(zendlval), CG(active_class_entry)->name->val, CG(active_class_entry)->name->len);
- len += CG(active_class_entry)->name->len;
- }
- if (CG(active_op_array) && CG(active_op_array)->function_name) {
- memcpy(Z_STRVAL_P(zendlval) + len, "::", sizeof("::")-1);
- len += sizeof("::")-1;
- memcpy(Z_STRVAL_P(zendlval) + len, CG(active_op_array)->function_name->val, CG(active_op_array)->function_name->len);
- len += CG(active_op_array)->function_name->len;
- }
- Z_STRVAL_P(zendlval)[len] = 0;
- } else if (CG(active_op_array) && CG(active_op_array)->function_name) {
- ZVAL_STR(zendlval, STR_COPY(CG(active_op_array)->function_name));
- } else {
- ZVAL_EMPTY_STRING(zendlval);
- }
return T_METHOD_C;
}
<ST_IN_SCRIPTING>"__LINE__" {
- ZVAL_LONG(zendlval, CG(zend_lineno));
return T_LINE;
}
<ST_IN_SCRIPTING>"__FILE__" {
- zend_string *filename = zend_get_compiled_filename(TSRMLS_C);
-
- if (!filename) {
- ZVAL_EMPTY_STRING(zendlval);
- } else {
- ZVAL_STR(zendlval, STR_COPY(filename));
- }
return T_FILE;
}
<ST_IN_SCRIPTING>"__DIR__" {
- zend_string *filename = zend_get_compiled_filename(TSRMLS_C);
- zend_string *dirname;
-
- if (!filename) {
- filename = STR_EMPTY_ALLOC();
- }
-
- dirname = STR_INIT(filename->val, filename->len, 0);
- zend_dirname(dirname->val, dirname->len);
-
- if (strcmp(dirname->val, ".") == 0) {
- dirname = STR_REALLOC(dirname, MAXPATHLEN, 0);
-#if HAVE_GETCWD
- VCWD_GETCWD(dirname->val, MAXPATHLEN);
-#elif HAVE_GETWD
- VCWD_GETWD(dirname->val);
-#endif
- }
-
- dirname->len = strlen(dirname->val);
- ZVAL_STR(zendlval, dirname);
return T_DIR;
}
<ST_IN_SCRIPTING>"__NAMESPACE__" {
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- ZVAL_DUP(zendlval, &CG(current_namespace));
- } else {
- ZVAL_EMPTY_STRING(zendlval);
- }
return T_NS_C;
}
@@ -1723,7 +1613,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
HANDLE_NEWLINES(yytext, yyleng);
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG;
}
@@ -1731,7 +1620,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
<INITIAL>"<%=" {
if (CG(asp_tags)) {
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG_WITH_ECHO;
} else {
@@ -1741,7 +1629,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
<INITIAL>"<?=" {
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG_WITH_ECHO;
}
@@ -1749,7 +1636,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
<INITIAL>"<%" {
if (CG(asp_tags)) {
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG;
} else {
@@ -1759,7 +1645,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
<INITIAL>"<?php"([ \t]|{NEWLINE}) {
- DUMMY_STRINGL(zendlval, yytext, yyleng);
HANDLE_NEWLINE(yytext[yyleng-1]);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG;
@@ -1768,7 +1653,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
<INITIAL>"<?" {
if (CG(short_tags)) {
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG;
} else {
@@ -1876,6 +1760,7 @@ inline_html:
/* Invalid rule to return a more explicit parse error with proper line number */
yyless(0);
yy_pop_state(TSRMLS_C);
+ ZVAL_NULL(zendlval);
return T_ENCAPSED_AND_WHITESPACE;
}
@@ -1945,7 +1830,7 @@ inline_html:
HANDLE_NEWLINES(yytext, yyleng);
if (doc_com) {
- CG(doc_comment) = STR_INIT(yytext, yyleng, 0);
+ CG(doc_comment) = zend_string_init(yytext, yyleng, 0);
return T_DOC_COMMENT;
}
@@ -1953,7 +1838,6 @@ inline_html:
}
<ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? {
- DUMMY_STRINGL(zendlval, yytext, yyleng);
BEGIN(INITIAL);
return T_CLOSE_TAG; /* implicit ';' at php-end tag */
}
@@ -1962,7 +1846,6 @@ inline_html:
<ST_IN_SCRIPTING>"%>"{NEWLINE}? {
if (CG(asp_tags)) {
BEGIN(INITIAL);
- DUMMY_STRINGL(zendlval, yytext, yyleng);
return T_CLOSE_TAG; /* implicit ';' at php-end tag */
} else {
yyless(1);
@@ -1992,6 +1875,7 @@ inline_html:
/* Unclosed single quotes; treat similar to double quotes, but without a separate token
* for ' (unrecognized by parser), instead of old flex fallback to "Unexpected character..."
* rule, which continued in ST_IN_SCRIPTING state after the quote */
+ ZVAL_NULL(zendlval);
return T_ENCAPSED_AND_WHITESPACE;
}
}
@@ -2151,7 +2035,7 @@ inline_html:
<ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"{$" {
- Z_LVAL_P(zendlval) = (long) '{';
+ Z_LVAL_P(zendlval) = (zend_long) '{';
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
yyless(1);
return T_CURLY_OPEN;
diff --git a/Zend/zend_list.c b/Zend/zend_list.c
index bb340ae490..d8141f8664 100644
--- a/Zend/zend_list.c
+++ b/Zend/zend_list.c
@@ -169,7 +169,7 @@ void list_entry_destructor(zval *zv)
zend_resource_dtor(res TSRMLS_CC);
}
- efree(res);
+ efree_size(res, sizeof(zend_resource));
}
void plist_entry_destructor(zval *zv)
diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c
index ad74bd56cb..0fb49abf5b 100644
--- a/Zend/zend_llist.c
+++ b/Zend/zend_llist.c
@@ -126,32 +126,26 @@ ZEND_API void zend_llist_clean(zend_llist *l)
}
-ZEND_API void *zend_llist_remove_tail(zend_llist *l)
+ZEND_API void zend_llist_remove_tail(zend_llist *l)
{
- zend_llist_element *old_tail;
- void *data;
-
- if ((old_tail = l->tail)) {
- if (old_tail->prev) {
- old_tail->prev->next = NULL;
- } else {
- l->head = NULL;
- }
-
- data = old_tail->data;
-
- l->tail = old_tail->prev;
- if (l->dtor) {
- l->dtor(data);
- }
- pefree(old_tail, l->persistent);
-
- --l->count;
+ zend_llist_element *old_tail = l->tail;
+ if (!old_tail) {
+ return;
+ }
- return data;
+ if (old_tail->prev) {
+ old_tail->prev->next = NULL;
+ } else {
+ l->head = NULL;
}
- return NULL;
+ l->tail = old_tail->prev;
+ --l->count;
+
+ if (l->dtor) {
+ l->dtor(old_tail->data);
+ }
+ pefree(old_tail, l->persistent);
}
diff --git a/Zend/zend_llist.h b/Zend/zend_llist.h
index b05ece8077..602884c27d 100644
--- a/Zend/zend_llist.h
+++ b/Zend/zend_llist.h
@@ -53,7 +53,7 @@ ZEND_API void zend_llist_prepend_element(zend_llist *l, void *element);
ZEND_API void zend_llist_del_element(zend_llist *l, void *element, int (*compare)(void *element1, void *element2));
ZEND_API void zend_llist_destroy(zend_llist *l);
ZEND_API void zend_llist_clean(zend_llist *l);
-ZEND_API void *zend_llist_remove_tail(zend_llist *l);
+ZEND_API void zend_llist_remove_tail(zend_llist *l);
ZEND_API void zend_llist_copy(zend_llist *dst, zend_llist *src);
ZEND_API void zend_llist_apply(zend_llist *l, llist_apply_func_t func TSRMLS_DC);
ZEND_API void zend_llist_apply_with_del(zend_llist *l, int (*func)(void *data));
diff --git a/Zend/zend_long.h b/Zend/zend_long.h
new file mode 100644
index 0000000000..153b4d24f2
--- /dev/null
+++ b/Zend/zend_long.h
@@ -0,0 +1,122 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Anatol Belski <ab@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+
+#ifndef ZEND_LONG_H
+#define ZEND_LONG_H
+
+#include "main/php_stdint.h"
+
+/* This is the heart of the whole int64 enablement in zval. */
+#if defined(__X86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)
+# define ZEND_ENABLE_ZVAL_LONG64 1
+#endif
+
+/* Integer types. */
+#ifdef ZEND_ENABLE_ZVAL_LONG64
+typedef int64_t zend_long;
+typedef uint64_t zend_ulong;
+typedef int64_t zend_off_t;
+# define ZEND_LONG_MAX INT64_MAX
+# define ZEND_LONG_MIN INT64_MIN
+# define ZEND_ULONG_MAX UINT64_MAX
+# ifdef _WIN64
+# define Z_L(i) i##i64
+# define Z_UL(i) i##Ui64
+# else
+# define Z_L(i) i##LL
+# define Z_UL(i) i##ULL
+# endif
+# define SIZEOF_ZEND_LONG 8
+#else
+typedef int32_t zend_long;
+typedef uint32_t zend_ulong;
+typedef int32_t zend_off_t;
+# define ZEND_LONG_MAX INT32_MAX
+# define ZEND_LONG_MIN INT32_MIN
+# define ZEND_ULONG_MAX UINT32_MAX
+# define Z_L(i) INT32_C(i)
+# define Z_UL(i) UINT32_C(i)
+# define SIZEOF_ZEND_LONG 4
+#endif
+
+
+/* Conversion macros. */
+#define ZEND_LTOA_BUF_LEN 65
+
+#ifdef ZEND_ENABLE_ZVAL_LONG64
+# define ZEND_LONG_FMT "%" PRId64
+# define ZEND_ULONG_FMT "%" PRIu64
+# define ZEND_LONG_FMT_SPEC PRId64
+# define ZEND_ULONG_FMT_SPEC PRIu64
+# ifdef PHP_WIN32
+# define ZEND_LTOA(i, s, len) _i64toa_s((i), (s), (len), 10)
+# define ZEND_ATOL(i, s) i = _atoi64((s))
+# define ZEND_STRTOL(s0, s1, base) _strtoi64((s0), (s1), (base))
+# define ZEND_STRTOUL(s0, s1, base) _strtoui64((s0), (s1), (base))
+# define ZEND_STRTOL_PTR _strtoi64
+# define ZEND_STRTOUL_PTR _strtoui64
+# define ZEND_ABS _abs64
+# else
+# define ZEND_LTOA(i, s, len) \
+ do { \
+ int st = snprintf((s), (len), ZEND_LONG_FMT, (i)); \
+ (s)[st] = '\0'; \
+ } while (0)
+# define ZEND_ATOL(i, s) (i) = atoll((s))
+# define ZEND_STRTOL(s0, s1, base) strtoll((s0), (s1), (base))
+# define ZEND_STRTOUL(s0, s1, base) strtoull((s0), (s1), (base))
+# define ZEND_STRTOL_PTR strtoll
+# define ZEND_STRTOUL_PTR strtoull
+# define ZEND_ABS imaxabs
+# endif
+#else
+# define ZEND_STRTOL(s0, s1, base) strtol((s0), (s1), (base))
+# define ZEND_STRTOUL(s0, s1, base) strtoul((s0), (s1), (base))
+# define ZEND_LONG_FMT "%" PRId32
+# define ZEND_ULONG_FMT "%" PRIu32
+# define ZEND_LONG_FMT_SPEC PRId32
+# define ZEND_ULONG_FMT_SPEC PRIu32
+# ifdef PHP_WIN32
+# define ZEND_LTOA(i, s, len) _ltoa_s((i), (s), (len), 10)
+# define ZEND_ATOL(i, s) i = atol((s))
+# else
+# define ZEND_LTOA(i, s, len) \
+ do { \
+ int st = snprintf((s), (len), ZEND_LONG_FMT, (i)); \
+ (s)[st] = '\0'; \
+ } while (0)
+# define ZEND_ATOL(i, s) (i) = atol((s))
+# endif
+# define ZEND_STRTOL_PTR strtol
+# define ZEND_STRTOUL_PTR strtoul
+# define ZEND_ABS abs
+#endif
+
+
+#endif /* ZEND_LONG_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index 74dc7d1452..11744c2699 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -22,7 +22,7 @@
#if defined(__i386__) && defined(__GNUC__)
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
- long __tmpvar; \
+ zend_long __tmpvar; \
__asm__ ("imul %3,%0\n" \
"adc $0,%1" \
: "=r"(__tmpvar),"=r"(usedval) \
@@ -34,7 +34,7 @@
#elif defined(__x86_64__) && defined(__GNUC__)
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
- long __tmpvar; \
+ zend_long __tmpvar; \
__asm__ ("imul %3,%0\n" \
"adc $0,%1" \
: "=r"(__tmpvar),"=r"(usedval) \
@@ -46,7 +46,7 @@
#elif defined(__arm__) && defined(__GNUC__)
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
- long __tmpvar; \
+ zend_long __tmpvar; \
__asm__("smull %0, %1, %2, %3\n" \
"sub %1, %1, %0, asr #31" \
: "=r"(__tmpvar), "=r"(usedval) \
@@ -58,7 +58,7 @@
#elif defined(__aarch64__) && defined(__GNUC__)
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
- long __tmpvar; \
+ zend_long __tmpvar; \
__asm__("mul %0, %2, %3\n" \
"smulh %1, %2, %3\n" \
"sub %1, %1, %0, asr #63\n" \
@@ -68,11 +68,24 @@
else (lval) = __tmpvar; \
} while (0)
-#elif SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64)
+#elif defined(ZEND_WIN32)
+
+#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
+ zend_long __lres = (a) * (b); \
+ long double __dres = (long double)(a) * (long double)(b); \
+ long double __delta = (long double) __lres - __dres; \
+ if ( ((usedval) = (( __dres + __delta ) != __dres))) { \
+ (dval) = __dres; \
+ } else { \
+ (lval) = __lres; \
+ } \
+} while (0)
+
+#elif SIZEOF_ZEND_LONG == 4 && defined(HAVE_ZEND_LONG64)
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
zend_long64 __result = (zend_long64) (a) * (zend_long64) (b); \
- if (__result > LONG_MAX || __result < LONG_MIN) { \
+ if (__result > ZEND_LONG_MAX || __result < ZEND_LONG_MIN) { \
(dval) = (double) __result; \
(usedval) = 1; \
} else { \
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index d7d8bf0a52..f831d2fadd 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -159,7 +159,7 @@ ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC
*is_temp = 1;
ALLOC_HASHTABLE(ht);
*ht = *Z_ARRVAL(retval);
- efree(Z_ARR(retval));
+ efree_size(Z_ARR(retval), sizeof(zend_array));
return ht;
} else {
*is_temp = 0;
@@ -385,9 +385,9 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui
}
/* }}} */
-ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC) /* {{{ */
+ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_string *member, int silent TSRMLS_DC) /* {{{ */
{
- return zend_get_property_info_quick(ce, Z_STR_P(member), silent, NULL TSRMLS_CC);
+ return zend_get_property_info_quick(ce, member, silent, NULL TSRMLS_CC);
}
/* }}} */
@@ -397,16 +397,16 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf
const char *class_name = NULL;
const char *prop_name;
zend_string *member;
- int prop_name_len;
+ size_t prop_name_len;
if (prop_info_name->val[0] == 0) {
- zend_unmangle_property_name_ex(prop_info_name->val, prop_info_name->len, &class_name, &prop_name, &prop_name_len);
- member = STR_INIT(prop_name, prop_name_len, 0);
+ zend_unmangle_property_name_ex(prop_info_name, &class_name, &prop_name, &prop_name_len);
+ member = zend_string_init(prop_name, prop_name_len, 0);
} else {
- member = STR_COPY(prop_info_name);
+ member = zend_string_copy(prop_info_name);
}
property_info = zend_get_property_info_quick(zobj->ce, member, 1, NULL TSRMLS_CC);
- STR_RELEASE(member);
+ zend_string_release(member);
if (!property_info) {
return FAILURE;
}
@@ -423,7 +423,7 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf
}
/* }}} */
-static long *zend_get_property_guard(zend_object *zobj, zend_property_info *property_info, zval *member) /* {{{ */
+static zend_long *zend_get_property_guard(zend_object *zobj, zend_property_info *property_info, zval *member) /* {{{ */
{
zend_property_info info;
zval stub, *guard;
@@ -434,10 +434,12 @@ static long *zend_get_property_guard(zend_object *zobj, zend_property_info *prop
info.name = Z_STR_P(member);
} else if(property_info->name->val[0] == '\0'){
const char *class_name = NULL, *prop_name = NULL;
- zend_unmangle_property_name(property_info->name->val, property_info->name->len, &class_name, &prop_name);
+ size_t prop_name_len;
+ zend_unmangle_property_name_ex(property_info->name, &class_name,
+ &prop_name, &prop_name_len);
if (class_name) {
/* use unmangled name for protected properties */
- str = info.name = STR_INIT(prop_name, strlen(prop_name), 0);
+ str = info.name = zend_string_init(prop_name, prop_name_len, 0);
property_info = &info;
}
}
@@ -446,7 +448,7 @@ static long *zend_get_property_guard(zend_object *zobj, zend_property_info *prop
zend_hash_init(zobj->guards, 8, NULL, NULL, 0);
} else if ((guard = zend_hash_find(zobj->guards, property_info->name)) != NULL) {
if (str) {
- STR_RELEASE(str);
+ zend_string_release(str);
}
return &Z_LVAL_P(guard);
}
@@ -454,7 +456,7 @@ static long *zend_get_property_guard(zend_object *zobj, zend_property_info *prop
ZVAL_LONG(&stub, 0);
guard = zend_hash_add_new(zobj->guards, property_info->name, &stub);
if (str) {
- STR_RELEASE(str);
+ zend_string_release(str);
}
return &Z_LVAL_P(guard);
}
@@ -501,7 +503,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
/* magic get */
if (zobj->ce->__get) {
- long *guard = zend_get_property_guard(zobj, property_info, member);
+ zend_long *guard = zend_get_property_guard(zobj, property_info, member);
if (!((*guard) & IN_GET)) {
zval tmp_object;
@@ -635,7 +637,7 @@ found:
/* magic set */
if (zobj->ce->__set) {
- long *guard = zend_get_property_guard(zobj, property_info, member);
+ zend_long *guard = zend_get_property_guard(zobj, property_info, member);
if (!((*guard) & IN_SET)) {
zval tmp_object;
@@ -659,12 +661,12 @@ found:
}
}
} else if (EXPECTED(property_info != NULL)) {
+ zval tmp;
+
write_std_property:
- /* if we assign referenced variable, we should separate it */
if (Z_REFCOUNTED_P(value)) {
if (Z_ISREF_P(value)) {
- zval tmp;
-
+ /* if we assign referenced variable, we should separate it */
ZVAL_DUP(&tmp, Z_REFVAL_P(value));
value = &tmp;
} else {
@@ -778,7 +780,7 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type,
zval tmp_member;
zval *retval, tmp;
zend_property_info *property_info;
- long *guard;
+ zend_long *guard;
zobj = Z_OBJ_P(object);
@@ -875,7 +877,7 @@ static void zend_std_unset_property(zval *object, zval *member, void **cache_slo
/* magic unset */
if (zobj->ce->__unset) {
- long *guard = zend_get_property_guard(zobj, property_info, member);
+ zend_long *guard = zend_get_property_guard(zobj, property_info, member);
if (!((*guard) & IN_UNSET)) {
zval tmp_object;
@@ -951,7 +953,7 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
zval_ptr_dtor(&method_name);
/* destruct the function also, then - we have allocated it in get_method */
- efree(func);
+ efree_size(func, sizeof(zend_internal_function));
}
/* }}} */
@@ -1046,9 +1048,9 @@ static inline union _zend_function *zend_get_user_call_function(zend_class_entry
//??? keep compatibility for "\0" characters
//??? see: Zend/tests/bug46238.phpt
if (UNEXPECTED(strlen(method_name->val) != method_name->len)) {
- call_user_call->function_name = STR_INIT(method_name->val, strlen(method_name->val), 0);
+ call_user_call->function_name = zend_string_init(method_name->val, strlen(method_name->val), 0);
} else {
- call_user_call->function_name = STR_COPY(method_name);
+ call_user_call->function_name = zend_string_copy(method_name);
}
return (union _zend_function *)call_user_call;
@@ -1168,7 +1170,7 @@ ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{
zval_ptr_dtor(&method_name);
/* destruct the function also, then - we have allocated it in get_method */
- efree(func);
+ efree_size(func, sizeof(zend_internal_function));
}
/* }}} */
@@ -1185,9 +1187,9 @@ static inline union _zend_function *zend_get_user_callstatic_function(zend_class
//??? keep compatibility for "\0" characters
//??? see: Zend/tests/bug46238.phpt
if (UNEXPECTED(strlen(method_name->val) != method_name->len)) {
- callstatic_user_call->function_name = STR_INIT(method_name->val, strlen(method_name->val), 0);
+ callstatic_user_call->function_name = zend_string_init(method_name->val, strlen(method_name->val), 0);
} else {
- callstatic_user_call->function_name = STR_COPY(method_name);
+ callstatic_user_call->function_name = zend_string_copy(method_name);
}
return (zend_function *)callstatic_user_call;
@@ -1205,7 +1207,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
if (EXPECTED(key != NULL)) {
lc_function_name = Z_STR_P(key);
} else {
- lc_function_name = STR_ALLOC(function_name->len, 0);
+ lc_function_name = zend_string_alloc(function_name->len, 0);
zend_str_tolower_copy(lc_function_name->val, function_name->val, function_name->len);
}
@@ -1226,7 +1228,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
fbc = Z_FUNC_P(func);
} else {
if (UNEXPECTED(!key)) {
- STR_FREE(lc_function_name);
+ zend_string_free(lc_function_name);
}
if (ce->__call &&
Z_OBJ(EG(This)) &&
@@ -1278,7 +1280,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
}
if (UNEXPECTED(!key)) {
- STR_FREE(lc_function_name);
+ zend_string_free(lc_function_name);
}
return fbc;
@@ -1485,7 +1487,7 @@ found:
result = 0;
if ((has_set_exists != 2) && zobj->ce->__isset) {
- long *guard = zend_get_property_guard(zobj, property_info, member);
+ zend_long *guard = zend_get_property_guard(zobj, property_info, member);
if (!((*guard) & IN_ISSET)) {
zval rv;
@@ -1546,7 +1548,7 @@ zend_string* zend_std_object_get_class_name(const zend_object *zobj, int parent
ce = zobj->ce;
}
- return STR_COPY(ce->name);
+ return zend_string_copy(ce->name);
}
/* }}} */
diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h
index ac3d962071..bc8500c3ec 100644
--- a/Zend/zend_object_handlers.h
+++ b/Zend/zend_object_handlers.h
@@ -106,7 +106,7 @@ typedef int (*zend_object_cast_t)(zval *readobj, zval *retval, int type TSRMLS_D
/* updates *count to hold the number of elements present and returns SUCCESS.
* Returns FAILURE if the object does not have any sense of overloaded dimensions */
-typedef int (*zend_object_count_elements_t)(zval *object, long *count TSRMLS_DC);
+typedef int (*zend_object_count_elements_t)(zval *object, zend_long *count TSRMLS_DC);
typedef int (*zend_object_get_closure_t)(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zend_object **obj_ptr TSRMLS_DC);
@@ -159,7 +159,7 @@ ZEND_API union _zend_function *zend_std_get_static_method(zend_class_entry *ce,
ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, zend_bool silent, void **cache_slot TSRMLS_DC);
ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name, void **cache_slot TSRMLS_DC);
ZEND_API union _zend_function *zend_std_get_constructor(zend_object *object TSRMLS_DC);
-ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC);
+ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_string *member, int silent TSRMLS_DC);
ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC);
ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC);
ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC);
diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c
index af0070c5fb..40d37b3d36 100644
--- a/Zend/zend_objects.c
+++ b/Zend/zend_objects.c
@@ -149,12 +149,12 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o
}
if (old_object->properties) {
zval *prop, new_prop;
- ulong num_key;
+ zend_ulong num_key;
zend_string *key;
if (!new_object->properties) {
ALLOC_HASHTABLE(new_object->properties);
- zend_hash_init(new_object->properties, 8, NULL, ZVAL_PTR_DTOR, 0);
+ zend_hash_init(new_object->properties, zend_hash_num_elements(old_object->properties), NULL, ZVAL_PTR_DTOR, 0);
}
ZEND_HASH_FOREACH_KEY_VAL(old_object->properties, num_key, key, prop) {
diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c
index c1b2f3ba6e..50930df20d 100644
--- a/Zend/zend_objects_API.c
+++ b/Zend/zend_objects_API.c
@@ -25,7 +25,7 @@
#include "zend_API.h"
#include "zend_objects_API.h"
-ZEND_API void zend_objects_store_init(zend_objects_store *objects, zend_uint init_size)
+ZEND_API void zend_objects_store_init(zend_objects_store *objects, uint32_t init_size)
{
objects->object_buckets = (zend_object **) emalloc(init_size * sizeof(zend_object*));
objects->top = 1; /* Skip 0 so that handles are true */
@@ -42,7 +42,7 @@ ZEND_API void zend_objects_store_destroy(zend_objects_store *objects)
ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC)
{
- zend_uint i;
+ uint32_t i;
for (i = 1; i < objects->top ; i++) {
zend_object *obj = objects->object_buckets[i];
@@ -60,7 +60,7 @@ ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TS
ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects TSRMLS_DC)
{
- zend_uint i;
+ uint32_t i;
if (!objects->object_buckets) {
return;
@@ -76,7 +76,7 @@ ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects TSR
ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects TSRMLS_DC)
{
- zend_uint i;
+ uint32_t i;
/* Free object properties but don't free object their selves */
for (i = objects->top - 1; i > 0 ; i--) {
@@ -134,7 +134,7 @@ ZEND_API void zend_objects_store_put(zend_object *object TSRMLS_DC)
ZEND_API void zend_objects_store_free(zend_object *object TSRMLS_DC) /* {{{ */
{
- zend_uint handle = object->handle;
+ uint32_t handle = object->handle;
void *ptr = ((char*)object) - object->handlers->offset;
GC_REMOVE_FROM_BUFFER(object);
@@ -169,7 +169,7 @@ ZEND_API void zend_objects_store_del(zend_object *object TSRMLS_DC) /* {{{ */
}
if (GC_REFCOUNT(object) == 0) {
- zend_uint handle = object->handle;
+ uint32_t handle = object->handle;
void *ptr;
EG(objects_store).object_buckets[handle] = SET_OBJ_INVALID(object);
diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h
index 4d6afe6842..df22a26cc9 100644
--- a/Zend/zend_objects_API.h
+++ b/Zend/zend_objects_API.h
@@ -48,14 +48,14 @@
typedef struct _zend_objects_store {
zend_object **object_buckets;
- zend_uint top;
- zend_uint size;
+ uint32_t top;
+ uint32_t size;
int free_list_head;
} zend_objects_store;
/* Global store handling functions */
BEGIN_EXTERN_C()
-ZEND_API void zend_objects_store_init(zend_objects_store *objects, zend_uint init_size);
+ZEND_API void zend_objects_store_init(zend_objects_store *objects, uint32_t init_size);
ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC);
ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects TSRMLS_DC);
ZEND_API void zend_objects_store_destroy(zend_objects_store *objects);
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 8309599521..d57721e58b 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -43,7 +43,7 @@ static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend
}
}
-static void op_array_alloc_ops(zend_op_array *op_array, zend_uint size)
+static void op_array_alloc_ops(zend_op_array *op_array, uint32_t size)
{
op_array->opcodes = erealloc(op_array->opcodes, size * sizeof(zend_op));
}
@@ -52,14 +52,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
{
op_array->type = type;
- if (CG(interactive)) {
- /* We must avoid a realloc() on the op_array in interactive mode, since pointers to constants
- * will become invalid
- */
- initial_ops_size = INITIAL_INTERACTIVE_OP_ARRAY_SIZE;
- }
-
- op_array->refcount = (zend_uint *) emalloc(sizeof(zend_uint));
+ op_array->refcount = (uint32_t *) emalloc(sizeof(uint32_t));
*op_array->refcount = 1;
op_array->last = 0;
op_array->opcodes = NULL;
@@ -79,6 +72,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->required_num_args = 0;
op_array->scope = NULL;
+ op_array->prototype = NULL;
op_array->brk_cont_array = NULL;
op_array->try_catch_array = NULL;
@@ -86,11 +80,10 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->static_variables = NULL;
op_array->last_try_catch = 0;
- op_array->has_finally_block = 0;
op_array->this_var = -1;
- op_array->fn_flags = CG(interactive)?ZEND_ACC_INTERACTIVE:0;
+ op_array->fn_flags = 0;
op_array->early_binding = -1;
@@ -113,7 +106,7 @@ ZEND_API void destroy_zend_function(zend_function *function TSRMLS_DC)
break;
case ZEND_INTERNAL_FUNCTION:
if (function->common.function_name) {
- STR_RELEASE(function->common.function_name);
+ zend_string_release(function->common.function_name);
}
/* do nothing */
break;
@@ -129,7 +122,7 @@ ZEND_API void zend_function_dtor(zval *zv)
if (function->type == ZEND_INTERNAL_FUNCTION) {
pefree(function, 1);
} else if (!function->common.function_name) {
- efree(function);
+ efree_size(function, sizeof(zend_op_array));
}
}
@@ -198,16 +191,16 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce)
while (ce->trait_aliases[i]) {
if (ce->trait_aliases[i]->trait_method) {
if (ce->trait_aliases[i]->trait_method->method_name) {
- STR_RELEASE(ce->trait_aliases[i]->trait_method->method_name);
+ zend_string_release(ce->trait_aliases[i]->trait_method->method_name);
}
if (ce->trait_aliases[i]->trait_method->class_name) {
- STR_RELEASE(ce->trait_aliases[i]->trait_method->class_name);
+ zend_string_release(ce->trait_aliases[i]->trait_method->class_name);
}
efree(ce->trait_aliases[i]->trait_method);
}
if (ce->trait_aliases[i]->alias) {
- STR_RELEASE(ce->trait_aliases[i]->alias);
+ zend_string_release(ce->trait_aliases[i]->alias);
}
efree(ce->trait_aliases[i]);
@@ -221,8 +214,8 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce)
size_t i = 0;
while (ce->trait_precedences[i]) {
- STR_RELEASE(ce->trait_precedences[i]->trait_method->method_name);
- STR_RELEASE(ce->trait_precedences[i]->trait_method->class_name);
+ zend_string_release(ce->trait_precedences[i]->trait_method->method_name);
+ zend_string_release(ce->trait_precedences[i]->trait_method->class_name);
efree(ce->trait_precedences[i]->trait_method);
if (ce->trait_precedences[i]->exclude_from_classes) {
@@ -266,14 +259,14 @@ ZEND_API void destroy_zend_class(zval *zv)
efree(ce->default_static_members_table);
}
zend_hash_destroy(&ce->properties_info);
- STR_RELEASE(ce->name);
+ zend_string_release(ce->name);
zend_hash_destroy(&ce->function_table);
zend_hash_destroy(&ce->constants_table);
if (ce->num_interfaces > 0 && ce->interfaces) {
efree(ce->interfaces);
}
if (ce->info.user.doc_comment) {
- STR_RELEASE(ce->info.user.doc_comment);
+ zend_string_release(ce->info.user.doc_comment);
}
_destroy_zend_class_traits_info(ce);
@@ -299,7 +292,7 @@ ZEND_API void destroy_zend_class(zval *zv)
free(ce->default_static_members_table);
}
zend_hash_destroy(&ce->properties_info);
- STR_RELEASE(ce->name);
+ zend_string_release(ce->name);
zend_hash_destroy(&ce->function_table);
zend_hash_destroy(&ce->constants_table);
if (ce->num_interfaces > 0) {
@@ -321,7 +314,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
{
zval *literal = op_array->literals;
zval *end;
- zend_uint i;
+ uint32_t i;
if (op_array->static_variables) {
zend_hash_destroy(op_array->static_variables);
@@ -336,13 +329,13 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
return;
}
- efree(op_array->refcount);
+ efree_size(op_array->refcount, sizeof(*(op_array->refcount)));
if (op_array->vars) {
i = op_array->last_var;
while (i > 0) {
i--;
- STR_RELEASE(op_array->vars[i]);
+ zend_string_release(op_array->vars[i]);
}
efree(op_array->vars);
}
@@ -350,7 +343,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
if (literal) {
end = literal + op_array->last_literal;
while (literal < end) {
- zval_dtor(literal);
+ zval_ptr_dtor_nogc(literal);
literal++;
}
efree(op_array->literals);
@@ -358,10 +351,10 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
efree(op_array->opcodes);
if (op_array->function_name) {
- STR_RELEASE(op_array->function_name);
+ zend_string_release(op_array->function_name);
}
if (op_array->doc_comment) {
- STR_RELEASE(op_array->doc_comment);
+ zend_string_release(op_array->doc_comment);
}
if (op_array->brk_cont_array) {
efree(op_array->brk_cont_array);
@@ -392,16 +385,10 @@ void init_op(zend_op *op TSRMLS_DC)
zend_op *get_next_op(zend_op_array *op_array TSRMLS_DC)
{
- zend_uint next_op_num = op_array->last++;
+ uint32_t next_op_num = op_array->last++;
zend_op *next_op;
if (next_op_num >= CG(context).opcodes_size) {
- if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) {
- /* we messed up */
- zend_printf("Ran out of opcode space!\n"
- "You should probably consider writing this huge script into a file!\n");
- zend_bailout();
- }
CG(context).opcodes_size *= 4;
op_array_alloc_ops(op_array, CG(context).opcodes_size);
}
@@ -455,9 +442,9 @@ static void zend_extension_op_array_handler(zend_extension *extension, zend_op_a
}
}
-static void zend_check_finally_breakout(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC)
+static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num, uint32_t dst_num TSRMLS_DC)
{
- zend_uint i;
+ int i;
for (i = 0; i < op_array->last_try_catch; i++) {
if ((op_num < op_array->try_catch_array[i].finally_op ||
@@ -480,10 +467,10 @@ static void zend_check_finally_breakout(zend_op_array *op_array, zend_uint op_nu
}
}
-static void zend_adjust_fast_call(zend_op_array *op_array, zend_uint fast_call, zend_uint start, zend_uint end TSRMLS_DC)
+static void zend_adjust_fast_call(zend_op_array *op_array, uint32_t fast_call, uint32_t start, uint32_t end TSRMLS_DC)
{
int i;
- zend_uint op_num = 0;
+ uint32_t op_num = 0;
for (i = 0; i < op_array->last_try_catch; i++) {
if (op_array->try_catch_array[i].finally_op > start
@@ -501,10 +488,10 @@ static void zend_adjust_fast_call(zend_op_array *op_array, zend_uint fast_call,
}
}
-static void zend_resolve_fast_call(zend_op_array *op_array, zend_uint fast_call, zend_uint op_num TSRMLS_DC)
+static void zend_resolve_fast_call(zend_op_array *op_array, uint32_t fast_call, uint32_t op_num TSRMLS_DC)
{
int i;
- zend_uint finally_op_num = 0;
+ uint32_t finally_op_num = 0;
for (i = 0; i < op_array->last_try_catch; i++) {
if (op_num >= op_array->try_catch_array[i].finally_op
@@ -523,13 +510,13 @@ static void zend_resolve_fast_call(zend_op_array *op_array, zend_uint fast_call,
}
}
-static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC)
+static void zend_resolve_finally_call(zend_op_array *op_array, uint32_t op_num, uint32_t dst_num TSRMLS_DC)
{
- zend_uint start_op;
+ uint32_t start_op;
zend_op *opline;
- zend_uint i = op_array->last_try_catch;
+ uint32_t i = op_array->last_try_catch;
- if (dst_num != (zend_uint)-1) {
+ if (dst_num != (uint32_t)-1) {
zend_check_finally_breakout(op_array, op_num, dst_num TSRMLS_CC);
}
@@ -601,10 +588,10 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num,
}
}
-static void zend_resolve_finally_ret(zend_op_array *op_array, zend_uint op_num TSRMLS_DC)
+static void zend_resolve_finally_ret(zend_op_array *op_array, uint32_t op_num TSRMLS_DC)
{
int i;
- zend_uint catch_op_num = 0, finally_op_num = 0;
+ uint32_t catch_op_num = 0, finally_op_num = 0;
for (i = 0; i < op_array->last_try_catch; i++) {
if (op_array->try_catch_array[i].try_op > op_num) {
@@ -631,7 +618,7 @@ static void zend_resolve_finally_ret(zend_op_array *op_array, zend_uint op_num T
static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC)
{
- zend_uint i, j;
+ uint32_t i, j;
zend_op *opline;
for (i = 0, j = op_array->last; i < j; i++) {
@@ -640,7 +627,7 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC)
case ZEND_RETURN:
case ZEND_RETURN_BY_REF:
case ZEND_GENERATOR_RETURN:
- zend_resolve_finally_call(op_array, i, (zend_uint)-1 TSRMLS_CC);
+ zend_resolve_finally_call(op_array, i, (uint32_t)-1 TSRMLS_CC);
break;
case ZEND_BRK:
case ZEND_CONT:
@@ -662,7 +649,7 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC)
}
case ZEND_GOTO:
if (Z_TYPE(op_array->literals[opline->op2.constant]) != IS_LONG) {
- zend_uint num = opline->op2.constant;
+ uint32_t num = opline->op2.constant;
opline->op2.zv = &op_array->literals[opline->op2.constant];
zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC);
opline->op2.constant = num;
@@ -690,7 +677,7 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
if (!ZEND_USER_CODE(op_array->type)) {
return 0;
}
- if (op_array->has_finally_block) {
+ if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
zend_resolve_finally_calls(op_array TSRMLS_CC);
}
if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
@@ -700,15 +687,15 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array TSRMLS_CC);
}
- if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).vars_size != op_array->last_var) {
+ if (CG(context).vars_size != op_array->last_var) {
op_array->vars = (zend_string**) erealloc(op_array->vars, sizeof(zend_string*)*op_array->last_var);
CG(context).vars_size = op_array->last_var;
}
- if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).opcodes_size != op_array->last) {
+ if (CG(context).opcodes_size != op_array->last) {
op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last);
CG(context).opcodes_size = op_array->last;
}
- if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).literals_size != op_array->last_literal) {
+ if (CG(context).literals_size != op_array->last_literal) {
op_array->literals = (zval*)erealloc(op_array->literals, sizeof(zval) * op_array->last_literal);
CG(context).literals_size = op_array->last_literal;
}
@@ -718,20 +705,20 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
if (opline->op1_type == IS_CONST) {
opline->op1.zv = &op_array->literals[opline->op1.constant];
} else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
- opline->op1.var = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->op1.var);
+ opline->op1.var = (uint32_t)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->op1.var);
}
if (opline->op2_type == IS_CONST) {
opline->op2.zv = &op_array->literals[opline->op2.constant];
} else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
- opline->op2.var = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->op2.var);
+ opline->op2.var = (uint32_t)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->op2.var);
}
if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
- opline->result.var = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->result.var);
+ opline->result.var = (uint32_t)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->result.var);
}
switch (opline->opcode) {
case ZEND_DECLARE_INHERITED_CLASS:
case ZEND_DECLARE_INHERITED_CLASS_DELAYED:
- opline->extended_value = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->extended_value);
+ opline->extended_value = (uint32_t)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->extended_value);
break;
case ZEND_GOTO:
if (Z_TYPE_P(opline->op2.zv) != IS_LONG) {
@@ -751,7 +738,6 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
case ZEND_JMP_SET:
- case ZEND_JMP_SET_VAR:
case ZEND_NEW:
case ZEND_FE_RESET:
case ZEND_FE_FETCH:
@@ -795,13 +781,10 @@ ZEND_API unary_op_type get_unary_op(int opcode)
switch (opcode) {
case ZEND_BW_NOT:
return (unary_op_type) bitwise_not_function;
- break;
case ZEND_BOOL_NOT:
return (unary_op_type) boolean_not_function;
- break;
default:
return (unary_op_type) NULL;
- break;
}
}
@@ -811,74 +794,54 @@ ZEND_API binary_op_type get_binary_op(int opcode)
case ZEND_ADD:
case ZEND_ASSIGN_ADD:
return (binary_op_type) add_function;
- break;
case ZEND_SUB:
case ZEND_ASSIGN_SUB:
return (binary_op_type) sub_function;
- break;
case ZEND_MUL:
case ZEND_ASSIGN_MUL:
return (binary_op_type) mul_function;
- break;
case ZEND_POW:
return (binary_op_type) pow_function;
- break;
case ZEND_DIV:
case ZEND_ASSIGN_DIV:
return (binary_op_type) div_function;
- break;
case ZEND_MOD:
case ZEND_ASSIGN_MOD:
return (binary_op_type) mod_function;
- break;
case ZEND_SL:
case ZEND_ASSIGN_SL:
return (binary_op_type) shift_left_function;
- break;
case ZEND_SR:
case ZEND_ASSIGN_SR:
return (binary_op_type) shift_right_function;
- break;
case ZEND_CONCAT:
case ZEND_ASSIGN_CONCAT:
return (binary_op_type) concat_function;
- break;
case ZEND_IS_IDENTICAL:
return (binary_op_type) is_identical_function;
- break;
case ZEND_IS_NOT_IDENTICAL:
return (binary_op_type) is_not_identical_function;
- break;
case ZEND_IS_EQUAL:
return (binary_op_type) is_equal_function;
- break;
case ZEND_IS_NOT_EQUAL:
return (binary_op_type) is_not_equal_function;
- break;
case ZEND_IS_SMALLER:
return (binary_op_type) is_smaller_function;
- break;
case ZEND_IS_SMALLER_OR_EQUAL:
return (binary_op_type) is_smaller_or_equal_function;
- break;
case ZEND_BW_OR:
case ZEND_ASSIGN_BW_OR:
return (binary_op_type) bitwise_or_function;
- break;
case ZEND_BW_AND:
case ZEND_ASSIGN_BW_AND:
return (binary_op_type) bitwise_and_function;
- break;
case ZEND_BW_XOR:
case ZEND_ASSIGN_BW_XOR:
return (binary_op_type) bitwise_xor_function;
- break;
case ZEND_BOOL_XOR:
return (binary_op_type) boolean_xor_function;
- break;
default:
return (binary_op_type) NULL;
- break;
}
}
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index ce47c26854..5dbe1bd90d 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -86,7 +86,7 @@ ZEND_API int zend_atoi(const char *str, int str_len) /* {{{ */
if (!str_len) {
str_len = strlen(str);
}
- retval = strtol(str, NULL, 0);
+ retval = ZEND_STRTOL(str, NULL, 0);
if (str_len>0) {
switch (str[str_len-1]) {
case 'g':
@@ -107,14 +107,14 @@ ZEND_API int zend_atoi(const char *str, int str_len) /* {{{ */
}
/* }}} */
-ZEND_API long zend_atol(const char *str, int str_len) /* {{{ */
+ZEND_API zend_long zend_atol(const char *str, int str_len) /* {{{ */
{
- long retval;
+ zend_long retval;
if (!str_len) {
str_len = strlen(str);
}
- retval = strtol(str, NULL, 0);
+ retval = ZEND_STRTOL(str, NULL, 0);
if (str_len>0) {
switch (str[str_len-1]) {
case 'g':
@@ -135,52 +135,6 @@ ZEND_API long zend_atol(const char *str, int str_len) /* {{{ */
}
/* }}} */
-ZEND_API double zend_string_to_double(const char *number, zend_uint length) /* {{{ */
-{
- double divisor = 10.0;
- double result = 0.0;
- double exponent;
- const char *end = number+length;
- const char *digit = number;
-
- if (!length) {
- return result;
- }
-
- while (digit < end) {
- if ((*digit <= '9' && *digit >= '0')) {
- result *= 10;
- result += *digit - '0';
- } else if (*digit == '.') {
- digit++;
- break;
- } else if (toupper(*digit) == 'E') {
- exponent = (double) atoi(digit+1);
- result *= pow(10.0, exponent);
- return result;
- } else {
- return result;
- }
- digit++;
- }
-
- while (digit < end) {
- if ((*digit <= '9' && *digit >= '0')) {
- result += (*digit - '0') / divisor;
- divisor *= 10;
- } else if (toupper(*digit) == 'E') {
- exponent = (double) atoi(digit+1);
- result *= pow(10.0, exponent);
- return result;
- } else {
- return result;
- }
- digit++;
- }
- return result;
-}
-/* }}} */
-
ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC) /* {{{ */
{
try_again:
@@ -201,7 +155,7 @@ try_again:
if ((Z_TYPE_INFO_P(op)=is_numeric_string(str->val, str->len, &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
ZVAL_LONG(op, 0);
}
- STR_RELEASE(str);
+ zend_string_release(str);
break;
}
case IS_NULL:
@@ -213,7 +167,7 @@ try_again:
break;
case IS_RESOURCE:
{
- long l = Z_RES_HANDLE_P(op);
+ zend_long l = Z_RES_HANDLE_P(op);
zval_ptr_dtor(op);
ZVAL_LONG(op, l);
}
@@ -283,7 +237,7 @@ try_again:
ZVAL_LONG(&holder, zend_dval_to_lval(Z_DVAL_P(op)));\
break; \
case IS_STRING: \
- ZVAL_LONG(&holder, strtol(Z_STRVAL_P(op), NULL, 10));\
+ ZVAL_LONG(&holder, ZEND_STRTOL(Z_STRVAL_P(op), NULL, 10));\
break; \
case IS_ARRAY: \
ZVAL_LONG(&holder, zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
@@ -378,7 +332,7 @@ ZEND_API void convert_to_long(zval *op) /* {{{ */
ZEND_API void convert_to_long_base(zval *op, int base) /* {{{ */
{
- long tmp;
+ zend_long tmp;
switch (Z_TYPE_P(op)) {
case IS_NULL:
@@ -389,7 +343,7 @@ ZEND_API void convert_to_long_base(zval *op, int base) /* {{{ */
ZVAL_LONG(op, 1);
break;
case IS_RESOURCE: {
- long l = Z_RES_HANDLE_P(op);
+ zend_long l = Z_RES_HANDLE_P(op);
zval_ptr_dtor(op);
ZVAL_LONG(op, l);
}
@@ -405,8 +359,8 @@ ZEND_API void convert_to_long_base(zval *op, int base) /* {{{ */
{
zend_string *str = Z_STR_P(op);
- ZVAL_LONG(op, strtol(str->val, NULL, base));
- STR_RELEASE(str);
+ ZVAL_LONG(op, ZEND_STRTOL(str->val, NULL, base));
+ zend_string_release(str);
}
break;
case IS_ARRAY:
@@ -464,7 +418,7 @@ ZEND_API void convert_to_double(zval *op) /* {{{ */
zend_string *str = Z_STR_P(op);
ZVAL_DOUBLE(op, zend_strtod(str->val, NULL));
- STR_RELEASE(str);
+ zend_string_release(str);
}
break;
case IS_ARRAY:
@@ -527,7 +481,7 @@ ZEND_API void convert_to_boolean(zval *op) /* {{{ */
ZVAL_BOOL(op, 0);
break;
case IS_RESOURCE: {
- long l = (Z_RES_HANDLE_P(op) ? 1 : 0);
+ zend_long l = (Z_RES_HANDLE_P(op) ? 1 : 0);
zval_ptr_dtor(op);
ZVAL_BOOL(op, l);
@@ -549,7 +503,7 @@ ZEND_API void convert_to_boolean(zval *op) /* {{{ */
} else {
ZVAL_BOOL(op, 1);
}
- STR_RELEASE(str);
+ zend_string_release(str);
}
break;
case IS_ARRAY:
@@ -586,6 +540,7 @@ ZEND_API void _convert_to_cstring(zval *op ZEND_FILE_LINE_DC) /* {{{ */
ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
{
switch (Z_TYPE_P(op)) {
+ case IS_UNDEF:
case IS_NULL:
case IS_FALSE: {
TSRMLS_FETCH();
@@ -593,14 +548,14 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
break;
}
case IS_TRUE:
- ZVAL_NEW_STR(op, STR_INIT("1", 1, 0));
+ ZVAL_NEW_STR(op, zend_string_init("1", 1, 0));
break;
case IS_STRING:
break;
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
- int len = snprintf(buf, sizeof(buf), "Resource id #%ld", Z_RES_HANDLE_P(op));
- ZVAL_NEW_STR(op, STR_INIT(buf, len, 0));
+ int len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT, Z_RES_HANDLE_P(op));
+ ZVAL_NEW_STR(op, zend_string_init(buf, len, 0));
break;
}
case IS_LONG: {
@@ -620,7 +575,7 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
case IS_ARRAY:
zend_error(E_NOTICE, "Array to string conversion");
zval_dtor(op);
- ZVAL_NEW_STR(op, STR_INIT("Array", sizeof("Array")-1, 0));
+ ZVAL_NEW_STR(op, zend_string_init("Array", sizeof("Array")-1, 0));
break;
case IS_OBJECT: {
zval dst;
@@ -634,7 +589,7 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
} else {
zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name->val);
zval_dtor(op);
- ZVAL_NEW_STR(op, STR_INIT("Object", sizeof("Object")-1, 0));
+ ZVAL_NEW_STR(op, zend_string_init("Object", sizeof("Object")-1, 0));
}
break;
}
@@ -716,7 +671,7 @@ ZEND_API void convert_to_object(zval *op) /* {{{ */
memcpy(properties, Z_ARRVAL_P(op), sizeof(HashTable));
object_and_properties_init(op, zend_standard_class_def, properties);
if (--GC_REFCOUNT(arr) == 0) {
- efree(arr);
+ efree_size(arr, sizeof(zend_array));
}
break;
}
@@ -784,7 +739,7 @@ ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */
}
/* }}} */
-ZEND_API long _zval_get_long_func(zval *op TSRMLS_DC) /* {{{ */
+ZEND_API zend_long _zval_get_long_func(zval *op TSRMLS_DC) /* {{{ */
{
try_again:
switch (Z_TYPE_P(op)) {
@@ -800,7 +755,7 @@ try_again:
case IS_DOUBLE:
return zend_dval_to_lval(Z_DVAL_P(op));
case IS_STRING:
- return strtol(Z_STRVAL_P(op), NULL, 10);
+ return ZEND_STRTOL(Z_STRVAL_P(op), NULL, 10);
case IS_ARRAY:
return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1 : 0;
case IS_OBJECT:
@@ -868,19 +823,20 @@ ZEND_API zend_string *_zval_get_string_func(zval *op TSRMLS_DC) /* {{{ */
{
try_again:
switch (Z_TYPE_P(op)) {
+ case IS_UNDEF:
case IS_NULL:
case IS_FALSE:
return STR_EMPTY_ALLOC();
case IS_STRING:
- return STR_COPY(Z_STR_P(op));
+ return zend_string_copy(Z_STR_P(op));
case IS_TRUE:
- return STR_INIT("1", 1, 0);
+ return zend_string_init("1", 1, 0);
case IS_RESOURCE: {
char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
int len;
- len = snprintf(buf, sizeof(buf), "Resource id #%ld", Z_RES_HANDLE_P(op));
- return STR_INIT(buf, len, 0);
+ len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT, Z_RES_HANDLE_P(op));
+ return zend_string_init(buf, len, 0);
}
case IS_LONG: {
return zend_long_to_str(Z_LVAL_P(op));
@@ -890,7 +846,7 @@ try_again:
}
case IS_ARRAY:
zend_error(E_NOTICE, "Array to string conversion");
- return STR_INIT("Array", sizeof("Array")-1, 0);
+ return zend_string_init("Array", sizeof("Array")-1, 0);
case IS_OBJECT: {
zval tmp;
if (Z_OBJ_HT_P(op)->cast_object) {
@@ -926,7 +882,7 @@ ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
while (1) {
switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
case TYPE_PAIR(IS_LONG, IS_LONG): {
- long lval = Z_LVAL_P(op1) + Z_LVAL_P(op2);
+ zend_long lval = Z_LVAL_P(op1) + Z_LVAL_P(op2);
/* check for overflow by comparing sign bits */
if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
@@ -990,7 +946,7 @@ ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
while (1) {
switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
case TYPE_PAIR(IS_LONG, IS_LONG): {
- long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2);
+ zend_long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2);
/* check for overflow by comparing sign bits */
if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
@@ -1043,7 +999,7 @@ ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
while (1) {
switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
case TYPE_PAIR(IS_LONG, IS_LONG): {
- long overflow;
+ zend_long overflow;
ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
@@ -1091,7 +1047,7 @@ ZEND_API int pow_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
case TYPE_PAIR(IS_LONG, IS_LONG):
if (Z_LVAL_P(op2) >= 0) {
- long l1 = 1, l2 = Z_LVAL_P(op1), i = Z_LVAL_P(op2);
+ zend_long l1 = 1, l2 = Z_LVAL_P(op1), i = Z_LVAL_P(op2);
if (i == 0) {
ZVAL_LONG(result, 1L);
@@ -1102,7 +1058,7 @@ ZEND_API int pow_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
}
while (i >= 1) {
- long overflow;
+ zend_long overflow;
double dval = 0.0;
if (i % 2) {
@@ -1182,9 +1138,9 @@ ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
zend_error(E_WARNING, "Division by zero");
ZVAL_BOOL(result, 0);
return FAILURE; /* division by zero */
- } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN) {
+ } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN) {
/* Prevent overflow error/crash */
- ZVAL_DOUBLE(result, (double) LONG_MIN / -1);
+ ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1);
return SUCCESS;
}
if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
@@ -1244,7 +1200,7 @@ ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
+ zend_long op1_lval;
if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MOD);
@@ -1276,7 +1232,7 @@ ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
+ zend_long op1_lval;
if ((Z_TYPE_P(op1) != IS_FALSE && Z_TYPE_P(op1) != IS_TRUE) ||
(Z_TYPE_P(op2) != IS_FALSE && Z_TYPE_P(op2) != IS_TRUE)) {
@@ -1324,10 +1280,10 @@ ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
return SUCCESS;
case IS_STRING: {
- int i;
+ size_t i;
zval op1_copy = *op1;
- ZVAL_NEW_STR(result, STR_ALLOC(Z_STRLEN(op1_copy), 0));
+ ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN(op1_copy), 0));
for (i = 0; i < Z_STRLEN(op1_copy); i++) {
Z_STRVAL_P(result)[i] = ~Z_STRVAL(op1_copy)[i];
}
@@ -1346,12 +1302,12 @@ ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
+ zend_long op1_lval;
if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
zval *longer, *shorter;
zend_string *str;
- int i;
+ size_t i;
if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
longer = op1;
@@ -1361,13 +1317,13 @@ ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /
shorter = op1;
}
- str = STR_ALLOC(Z_STRLEN_P(longer), 0);
+ str = zend_string_alloc(Z_STRLEN_P(longer), 0);
for (i = 0; i < Z_STRLEN_P(shorter); i++) {
str->val[i] = Z_STRVAL_P(longer)[i] | Z_STRVAL_P(shorter)[i];
}
memcpy(str->val + i, Z_STRVAL_P(longer) + i, Z_STRLEN_P(longer) - i + 1);
if (result==op1) {
- STR_RELEASE(Z_STR_P(result));
+ zend_string_release(Z_STR_P(result));
}
ZVAL_NEW_STR(result, str);
return SUCCESS;
@@ -1391,12 +1347,12 @@ ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /
ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
+ zend_long op1_lval;
if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
zval *longer, *shorter;
zend_string *str;
- int i;
+ size_t i;
if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
longer = op1;
@@ -1406,13 +1362,13 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
shorter = op1;
}
- str = STR_ALLOC(Z_STRLEN_P(shorter), 0);
+ str = zend_string_alloc(Z_STRLEN_P(shorter), 0);
for (i = 0; i < Z_STRLEN_P(shorter); i++) {
str->val[i] = Z_STRVAL_P(shorter)[i] & Z_STRVAL_P(longer)[i];
}
str->val[i] = 0;
if (result==op1) {
- STR_RELEASE(Z_STR_P(result));
+ zend_string_release(Z_STR_P(result));
}
ZVAL_NEW_STR(result, str);
return SUCCESS;
@@ -1436,12 +1392,12 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
+ zend_long op1_lval;
if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
zval *longer, *shorter;
zend_string *str;
- int i;
+ size_t i;
if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
longer = op1;
@@ -1451,13 +1407,13 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
shorter = op1;
}
- str = STR_ALLOC(Z_STRLEN_P(shorter), 0);
+ str = zend_string_alloc(Z_STRLEN_P(shorter), 0);
for (i = 0; i < Z_STRLEN_P(shorter); i++) {
str->val[i] = Z_STRVAL_P(shorter)[i] ^ Z_STRVAL_P(longer)[i];
}
str->val[i] = 0;
if (result==op1) {
- STR_RELEASE(Z_STR_P(result));
+ zend_string_release(Z_STR_P(result));
}
ZVAL_NEW_STR(result, str);
return SUCCESS;
@@ -1481,7 +1437,7 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
+ zend_long op1_lval;
if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SL);
@@ -1513,7 +1469,7 @@ ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /
ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
+ zend_long op1_lval;
if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SR);
@@ -1545,8 +1501,8 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
/* must support result==op1 */
ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
- int length = Z_STRLEN_P(op1) + 1;
- zend_string *buf = STR_REALLOC(Z_STR_P(op1), length, 0);
+ size_t length = Z_STRLEN_P(op1) + 1;
+ zend_string *buf = zend_string_realloc(Z_STR_P(op1), length, 0);
buf->val[length - 1] = (char) Z_LVAL_P(op2);
buf->val[length] = 0;
@@ -1558,9 +1514,9 @@ ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2)
/* must support result==op1 */
ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
- int op1_len = Z_STRLEN_P(op1);
- int length = op1_len + Z_STRLEN_P(op2);
- zend_string *buf = STR_REALLOC(Z_STR_P(op1), length, 0);
+ size_t op1_len = Z_STRLEN_P(op1);
+ size_t length = op1_len + Z_STRLEN_P(op2);
+ zend_string *buf = zend_string_realloc(Z_STR_P(op1), length, 0);
memcpy(buf->val + op1_len, Z_STRVAL_P(op2), Z_STRLEN_P(op2));
buf->val[length] = 0;
@@ -1599,29 +1555,33 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
op2 = &op2_copy;
}
- if (result==op1 && !IS_INTERNED(Z_STR_P(op1))) { /* special case, perform operations on result */
- uint op1_len = Z_STRLEN_P(op1);
- uint op2_len = Z_STRLEN_P(op2);
- uint res_len = op1_len + op2_len;
+ {
+ size_t op1_len = Z_STRLEN_P(op1);
+ size_t op2_len = Z_STRLEN_P(op2);
+ size_t result_len = op1_len + op2_len;
+ zend_string *result_str;
- if (Z_STRLEN_P(result) < 0 || (int) (op1_len + op2_len) < 0) {
- ZVAL_EMPTY_STRING(result);
- zend_error(E_ERROR, "String size overflow");
+ if (op1_len > SIZE_MAX - op2_len) {
+ zend_error_noreturn(E_ERROR, "String size overflow");
}
- Z_STR_P(result) = STR_REALLOC(Z_STR_P(result), res_len, 0 );
- Z_TYPE_INFO_P(result) = IS_STRING_EX;
- memcpy(Z_STRVAL_P(result) + op1_len, Z_STRVAL_P(op2), op2_len);
- Z_STRVAL_P(result)[res_len]=0;
- } else {
- int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
- zend_string *buf = STR_ALLOC(length, 0);
+ if (result == op1 && !IS_INTERNED(Z_STR_P(result))) {
+ /* special case, perform operations on result */
+ result_str = zend_string_realloc(Z_STR_P(result), result_len, 0);
+ } else {
+ result_str = zend_string_alloc(result_len, 0);
+ memcpy(result_str->val, Z_STRVAL_P(op1), op1_len);
+ }
+
+ /* This has to happen first to account for the cases where result == op1 == op2 and
+ * the realloc is done. In this case this line will also update Z_STRVAL_P(op2) to
+ * point to the new string. The first op2_len bytes of result will still be the same. */
+ ZVAL_NEW_STR(result, result_str);
- memcpy(buf->val, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
- memcpy(buf->val + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
- buf->val[length] = 0;
- ZVAL_NEW_STR(result, buf);
+ memcpy(result_str->val + op1_len, Z_STRVAL_P(op2), op2_len);
+ result_str->val[result_len] = '\0';
}
+
if (UNEXPECTED(use_copy1)) {
zval_dtor(op1);
}
@@ -1643,8 +1603,8 @@ ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend
ZVAL_LONG(result, zend_binary_strcmp(str1->val, str1->len, str2->val, str2->len));
}
- STR_RELEASE(str1);
- STR_RELEASE(str2);
+ zend_string_release(str1);
+ zend_string_release(str2);
return SUCCESS;
}
/* }}} */
@@ -1664,8 +1624,8 @@ ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_D
ZVAL_LONG(result, zend_binary_strcmp(str1->val, str1->len, str2->val, str2->len));
- STR_RELEASE(str1);
- STR_RELEASE(str2);
+ zend_string_release(str1);
+ zend_string_release(str2);
}
return SUCCESS;
}
@@ -1686,8 +1646,8 @@ ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSR
ZVAL_LONG(result, zend_binary_strcasecmp_l(str1->val, str1->len, str2->val, str1->len));
- STR_RELEASE(str1);
- STR_RELEASE(str2);
+ zend_string_release(str1);
+ zend_string_release(str2);
}
return SUCCESS;
}
@@ -1701,8 +1661,8 @@ ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 T
ZVAL_LONG(result, strcoll(str1->val, str2->val));
- STR_RELEASE(str1);
- STR_RELEASE(str2);
+ zend_string_release(str1);
+ zend_string_release(str2);
return SUCCESS;
}
/* }}} */
@@ -2037,7 +1997,7 @@ ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSR
ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC) /* {{{ */
{
- zend_uint i;
+ uint32_t i;
for (i=0; i<instance_ce->num_interfaces; i++) {
if (instanceof_function(instance_ce->interfaces[i], ce TSRMLS_CC)) {
@@ -2070,31 +2030,31 @@ ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, cons
static void increment_string(zval *str) /* {{{ */
{
int carry=0;
- int pos=Z_STRLEN_P(str)-1;
+ size_t pos=Z_STRLEN_P(str)-1;
char *s;
zend_string *t;
int last=0; /* Shut up the compiler warning */
int ch;
if (Z_STRLEN_P(str) == 0) {
- STR_RELEASE(Z_STR_P(str));
- Z_STR_P(str) = STR_INIT("1", sizeof("1")-1, 0);
+ zend_string_release(Z_STR_P(str));
+ Z_STR_P(str) = zend_string_init("1", sizeof("1")-1, 0);
Z_TYPE_INFO_P(str) = IS_STRING_EX;
return;
}
if (IS_INTERNED(Z_STR_P(str))) {
- Z_STR_P(str) = STR_INIT(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
+ Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
Z_TYPE_INFO_P(str) = IS_STRING_EX;
} else if (Z_REFCOUNT_P(str) > 1) {
Z_DELREF_P(str);
- Z_STR_P(str) = STR_INIT(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
+ Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
} else {
- STR_FORGET_HASH_VAL(Z_STR_P(str));
+ zend_string_forget_hash_val(Z_STR_P(str));
}
s = Z_STRVAL_P(str);
- while (pos >= 0) {
+ do {
ch = s[pos];
if (ch >= 'a' && ch <= 'z') {
if (ch == 'z') {
@@ -2130,11 +2090,10 @@ static void increment_string(zval *str) /* {{{ */
if (carry == 0) {
break;
}
- pos--;
- }
+ } while (pos-- > 0);
if (carry) {
- t = STR_ALLOC(Z_STRLEN_P(str)+1, 0);
+ t = zend_string_alloc(Z_STRLEN_P(str)+1, 0);
memcpy(t->val + 1, Z_STRVAL_P(str), Z_STRLEN_P(str));
t->val[Z_STRLEN_P(str) + 1] = '\0';
switch (last) {
@@ -2148,7 +2107,7 @@ static void increment_string(zval *str) /* {{{ */
t->val[0] = 'a';
break;
}
- STR_FREE(Z_STR_P(str));
+ zend_string_free(Z_STR_P(str));
ZVAL_NEW_STR(str, t);
}
}
@@ -2159,7 +2118,7 @@ ZEND_API int increment_function(zval *op1) /* {{{ */
try_again:
switch (Z_TYPE_P(op1)) {
case IS_LONG:
- if (Z_LVAL_P(op1) == LONG_MAX) {
+ if (Z_LVAL_P(op1) == ZEND_LONG_MAX) {
/* switch to double */
double d = (double)Z_LVAL_P(op1);
ZVAL_DOUBLE(op1, d+1);
@@ -2174,13 +2133,13 @@ try_again:
ZVAL_LONG(op1, 1);
break;
case IS_STRING: {
- long lval;
+ zend_long lval;
double dval;
switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
case IS_LONG:
- STR_RELEASE(Z_STR_P(op1));
- if (lval == LONG_MAX) {
+ zend_string_release(Z_STR_P(op1));
+ if (lval == ZEND_LONG_MAX) {
/* switch to double */
double d = (double)lval;
ZVAL_DOUBLE(op1, d+1);
@@ -2189,7 +2148,7 @@ try_again:
}
break;
case IS_DOUBLE:
- STR_RELEASE(Z_STR_P(op1));
+ zend_string_release(Z_STR_P(op1));
ZVAL_DOUBLE(op1, dval+1);
break;
default:
@@ -2224,13 +2183,13 @@ try_again:
ZEND_API int decrement_function(zval *op1) /* {{{ */
{
- long lval;
+ zend_long lval;
double dval;
try_again:
switch (Z_TYPE_P(op1)) {
case IS_LONG:
- if (Z_LVAL_P(op1) == LONG_MIN) {
+ if (Z_LVAL_P(op1) == ZEND_LONG_MIN) {
double d = (double)Z_LVAL_P(op1);
ZVAL_DOUBLE(op1, d-1);
} else {
@@ -2242,14 +2201,14 @@ try_again:
break;
case IS_STRING: /* Like perl we only support string increment */
if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
- STR_RELEASE(Z_STR_P(op1));
+ zend_string_release(Z_STR_P(op1));
ZVAL_LONG(op1, -1);
break;
}
switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
case IS_LONG:
- STR_RELEASE(Z_STR_P(op1));
- if (lval == LONG_MIN) {
+ zend_string_release(Z_STR_P(op1));
+ if (lval == ZEND_LONG_MIN) {
double d = (double)lval;
ZVAL_DOUBLE(op1, d-1);
} else {
@@ -2257,7 +2216,7 @@ try_again:
}
break;
case IS_DOUBLE:
- STR_RELEASE(Z_STR_P(op1));
+ zend_string_release(Z_STR_P(op1));
ZVAL_DOUBLE(op1, dval - 1);
break;
}
@@ -2301,7 +2260,7 @@ ZEND_API void zend_update_current_locale(void) /* {{{ */
/* }}} */
#endif
-ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length) /* {{{ */
+ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, size_t length) /* {{{ */
{
register unsigned char *str = (unsigned char*)source;
register unsigned char *result = (unsigned char*)dest;
@@ -2316,13 +2275,13 @@ ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned in
}
/* }}} */
-ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length) /* {{{ */
+ZEND_API char *zend_str_tolower_dup(const char *source, size_t length) /* {{{ */
{
return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
}
/* }}} */
-ZEND_API void zend_str_tolower(char *str, unsigned int length) /* {{{ */
+ZEND_API void zend_str_tolower(char *str, size_t length) /* {{{ */
{
register unsigned char *p = (unsigned char*)str;
register unsigned char *end = p + length;
@@ -2334,7 +2293,7 @@ ZEND_API void zend_str_tolower(char *str, unsigned int length) /* {{{ */
}
/* }}} */
-ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
+ZEND_API int zend_binary_strcmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
{
int retval;
@@ -2343,14 +2302,14 @@ ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint
}
retval = memcmp(s1, s2, MIN(len1, len2));
if (!retval) {
- return (len1 - len2);
+ return (int)(len1 - len2);
} else {
return retval;
}
}
/* }}} */
-ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
+ZEND_API int zend_binary_strncmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
{
int retval;
@@ -2359,16 +2318,16 @@ ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint
}
retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
if (!retval) {
- return (MIN(length, len1) - MIN(length, len2));
+ return (int)(MIN(length, len1) - MIN(length, len2));
} else {
return retval;
}
}
/* }}} */
-ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
+ZEND_API int zend_binary_strcasecmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
{
- int len;
+ size_t len;
int c1, c2;
if (s1 == s2) {
@@ -2384,13 +2343,13 @@ ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, u
}
}
- return len1 - len2;
+ return (int)(len1 - len2);
}
/* }}} */
-ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
+ZEND_API int zend_binary_strncasecmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
{
- int len;
+ size_t len;
int c1, c2;
if (s1 == s2) {
@@ -2405,13 +2364,13 @@ ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2,
}
}
- return MIN(length, len1) - MIN(length, len2);
+ return (int)(MIN(length, len1) - MIN(length, len2));
}
/* }}} */
-ZEND_API int zend_binary_strcasecmp_l(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
+ZEND_API int zend_binary_strcasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
{
- int len;
+ size_t len;
int c1, c2;
if (s1 == s2) {
@@ -2427,13 +2386,13 @@ ZEND_API int zend_binary_strcasecmp_l(const char *s1, uint len1, const char *s2,
}
}
- return len1 - len2;
+ return (int)(len1 - len2);
}
/* }}} */
-ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
+ZEND_API int zend_binary_strncasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
{
- int len;
+ size_t len;
int c1, c2;
if (s1 == s2) {
@@ -2448,7 +2407,7 @@ ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2
}
}
- return MIN(length, len1) - MIN(length, len2);
+ return (int)(MIN(length, len1) - MIN(length, len2));
}
/* }}} */
@@ -2480,12 +2439,12 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
{
int ret1, ret2;
int oflow1, oflow2;
- long lval1 = 0, lval2 = 0;
+ zend_long lval1 = 0, lval2 = 0;
double dval1 = 0.0, dval2 = 0.0;
if ((ret1=is_numeric_string_ex(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0, &oflow1)) &&
(ret2=is_numeric_string_ex(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0, &oflow2))) {
-#if ULONG_MAX == 0xFFFFFFFF
+#if ZEND_ULONG_MAX == 0xFFFFFFFF
if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. &&
((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/)
|| (oflow1 == -1 && dval1 < -9007199254740991.))) {
@@ -2582,16 +2541,16 @@ ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
}
/* }}} */
-ZEND_API zend_string *zend_long_to_str(long num) /* {{{ */
+ZEND_API zend_string *zend_long_to_str(zend_long num) /* {{{ */
{
char buf[MAX_LENGTH_OF_LONG + 1];
char *res;
- _zend_print_signed_to_buf(buf + sizeof(buf) - 1, num, unsigned long, res);
- return STR_INIT(res, buf + sizeof(buf) - 1 - res, 0);
+ _zend_print_signed_to_buf(buf + sizeof(buf) - 1, num, zend_ulong, res);
+ return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
}
/* }}} */
-ZEND_API zend_uchar is_numeric_str_function(const zend_string *str, long *lval, double *dval) {
+ZEND_API zend_uchar is_numeric_str_function(const zend_string *str, zend_long *lval, double *dval) {
return is_numeric_string_ex(str->val, str->len, lval, dval, -1, NULL);
}
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index f168af7ce8..256429dddb 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -41,7 +41,7 @@
#include "ext/bcmath/libbcmath/src/bcmath.h"
#endif
-#define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
+#define LONG_SIGN_MASK (((zend_long)1) << (8*sizeof(zend_long)-1))
BEGIN_EXTERN_C()
ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
@@ -72,18 +72,18 @@ ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, cons
END_EXTERN_C()
#if ZEND_DVAL_TO_LVAL_CAST_OK
-static zend_always_inline long zend_dval_to_lval(double d)
+static zend_always_inline zend_long zend_dval_to_lval(double d)
{
if (EXPECTED(zend_finite(d)) && EXPECTED(!zend_isnan(d))) {
- return (long)d;
+ return (zend_long)d;
} else {
return 0;
}
}
-#elif SIZEOF_LONG == 4
-static zend_always_inline long zend_dval_to_lval(double d)
+#elif SIZEOF_ZEND_LONG == 4
+static zend_always_inline zend_long zend_dval_to_lval(double d)
{
- if (d > LONG_MAX || d < LONG_MIN) {
+ if (d > ZEND_LONG_MAX || d < ZEND_LONG_MIN) {
double two_pow_32 = pow(2., 32.),
dmod;
@@ -93,17 +93,17 @@ static zend_always_inline long zend_dval_to_lval(double d)
* to simulate rounding towards 0 of the negative number */
dmod = ceil(dmod) + two_pow_32;
}
- return (long)(unsigned long)dmod;
+ return (zend_long)(zend_ulong)dmod;
} else if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
return 0;
}
- return (long)d;
+ return (zend_long)d;
}
#else
-static zend_always_inline long zend_dval_to_lval(double d)
+static zend_always_inline zend_long zend_dval_to_lval(double d)
{
- /* >= as (double)LONG_MAX is outside signed range */
- if (d >= LONG_MAX || d < LONG_MIN) {
+ /* >= as (double)ZEND_LONG_MAX is outside signed range */
+ if (d >= ZEND_LONG_MAX || d < ZEND_LONG_MIN) {
double two_pow_64 = pow(2., 64.),
dmod;
@@ -113,11 +113,11 @@ static zend_always_inline long zend_dval_to_lval(double d)
* fractional part, hence dmod does not have one either */
dmod += two_pow_64;
}
- return (long)(unsigned long)dmod;
+ return (zend_long)(zend_ulong)dmod;
} else if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
return 0;
}
- return (long)d;
+ return (zend_long)d;
}
#endif
/* }}} */
@@ -138,9 +138,9 @@ static zend_always_inline long zend_dval_to_lval(double d)
*
* This variant also gives information if a string that represents an integer
* could not be represented as such due to overflow. It writes 1 to oflow_info
- * if the integer is larger than LONG_MAX and -1 if it's smaller than LONG_MIN.
+ * if the integer is larger than ZEND_LONG_MAX and -1 if it's smaller than ZEND_LONG_MIN.
*/
-static inline zend_uchar is_numeric_string_ex(const char *str, int length, long *lval, double *dval, int allow_errors, int *oflow_info)
+static inline zend_uchar is_numeric_string_ex(const char *str, size_t length, zend_long *lval, double *dval, int allow_errors, int *oflow_info)
{
const char *ptr;
int base = 10, digits = 0, dp_or_e = 0;
@@ -213,7 +213,7 @@ check_digits:
dp_or_e = -1;
goto process_double;
}
- } else if (!(digits < SIZEOF_LONG * 2 || (digits == SIZEOF_LONG * 2 && ptr[-digits] <= '7'))) {
+ } else if (!(digits < SIZEOF_ZEND_LONG * 2 || (digits == SIZEOF_ZEND_LONG * 2 && ptr[-digits] <= '7'))) {
if (dval) {
local_dval = zend_hex_strtod(str, &ptr);
}
@@ -264,7 +264,7 @@ process_double:
}
if (lval) {
- *lval = strtol(str, NULL, base);
+ *lval = ZEND_STRTOL(str, NULL, base);
}
return IS_LONG;
@@ -277,23 +277,27 @@ process_double:
}
}
-static inline zend_uchar is_numeric_string(const char *str, int length, long *lval, double *dval, int allow_errors) {
+static inline zend_uchar is_numeric_string(const char *str, size_t length, zend_long *lval, double *dval, int allow_errors) {
return is_numeric_string_ex(str, length, lval, dval, allow_errors, NULL);
}
-ZEND_API zend_uchar is_numeric_str_function(const zend_string *str, long *lval, double *dval);
+ZEND_API zend_uchar is_numeric_str_function(const zend_string *str, zend_long *lval, double *dval);
static inline const char *
-zend_memnstr(const char *haystack, const char *needle, int needle_len, char *end)
+zend_memnstr(const char *haystack, const char *needle, size_t needle_len, char *end)
{
const char *p = haystack;
const char ne = needle[needle_len-1];
+ ptrdiff_t off_p;
+ size_t off_s;
if (needle_len == 1) {
return (char *)memchr(p, *needle, (end-p));
}
- if (needle_len > end-haystack) {
+ off_p = end - haystack;
+ off_s = (off_p > 0) ? (size_t)off_p : 0;
+ if (needle_len > off_s) {
return NULL;
}
@@ -351,18 +355,18 @@ ZEND_API void multi_convert_to_long_ex(int argc, ...);
ZEND_API void multi_convert_to_double_ex(int argc, ...);
ZEND_API void multi_convert_to_string_ex(int argc, ...);
-ZEND_API long _zval_get_long_func(zval *op TSRMLS_DC);
+ZEND_API zend_long _zval_get_long_func(zval *op TSRMLS_DC);
ZEND_API double _zval_get_double_func(zval *op TSRMLS_DC);
ZEND_API zend_string *_zval_get_string_func(zval *op TSRMLS_DC);
-static zend_always_inline long _zval_get_long(zval *op TSRMLS_DC) {
+static zend_always_inline zend_long _zval_get_long(zval *op TSRMLS_DC) {
return Z_TYPE_P(op) == IS_LONG ? Z_LVAL_P(op) : _zval_get_long_func(op TSRMLS_CC);
}
static zend_always_inline double _zval_get_double(zval *op TSRMLS_DC) {
return Z_TYPE_P(op) == IS_DOUBLE ? Z_DVAL_P(op) : _zval_get_double_func(op TSRMLS_CC);
}
static zend_always_inline zend_string *_zval_get_string(zval *op TSRMLS_DC) {
- return Z_TYPE_P(op) == IS_STRING ? STR_COPY(Z_STR_P(op)) : _zval_get_string_func(op TSRMLS_CC);
+ return Z_TYPE_P(op) == IS_STRING ? zend_string_copy(Z_STR_P(op)) : _zval_get_string_func(op TSRMLS_CC);
}
#define zval_get_long(op) _zval_get_long((op) TSRMLS_CC)
@@ -374,8 +378,6 @@ ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2
#define convert_to_cstring(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_cstring((op) ZEND_FILE_LINE_CC); }
#define convert_to_string(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); }
-ZEND_API double zend_string_to_double(const char *number, zend_uint length);
-
ZEND_API int zval_is_true(zval *op);
ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
@@ -386,20 +388,20 @@ ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSR
ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
#endif
-ZEND_API void zend_str_tolower(char *str, unsigned int length);
-ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length);
-ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length);
+ZEND_API void zend_str_tolower(char *str, size_t length);
+ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, size_t length);
+ZEND_API char *zend_str_tolower_dup(const char *source, size_t length);
ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2);
ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3);
ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2);
ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3);
-ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2);
-ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length);
-ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2);
-ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length);
-ZEND_API int zend_binary_strcasecmp_l(const char *s1, uint len1, const char *s2, uint len2);
-ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2, uint len2, uint length);
+ZEND_API int zend_binary_strcmp(const char *s1, size_t len1, const char *s2, size_t len2);
+ZEND_API int zend_binary_strncmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length);
+ZEND_API int zend_binary_strcasecmp(const char *s1, size_t len1, const char *s2, size_t len2);
+ZEND_API int zend_binary_strncasecmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length);
+ZEND_API int zend_binary_strcasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2);
+ZEND_API int zend_binary_strncasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2, size_t length);
ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2);
ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC);
@@ -407,7 +409,7 @@ ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC);
ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC);
ZEND_API int zend_atoi(const char *str, int str_len);
-ZEND_API long zend_atol(const char *str, int str_len);
+ZEND_API zend_long zend_atol(const char *str, int str_len);
ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC);
END_EXTERN_C()
@@ -515,9 +517,9 @@ static zend_always_inline int fast_increment_function(zval *op1)
"n"(ZVAL_OFFSETOF_TYPE)
: "cc");
#else
- if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MAX)) {
+ if (UNEXPECTED(Z_LVAL_P(op1) == ZEND_LONG_MAX)) {
/* switch to double */
- ZVAL_DOUBLE(op1, (double)LONG_MAX + 1.0);
+ ZVAL_DOUBLE(op1, (double)ZEND_LONG_MAX + 1.0);
} else {
Z_LVAL_P(op1)++;
}
@@ -557,9 +559,9 @@ static zend_always_inline int fast_decrement_function(zval *op1)
"n"(ZVAL_OFFSETOF_TYPE)
: "cc");
#else
- if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MIN)) {
+ if (UNEXPECTED(Z_LVAL_P(op1) == ZEND_LONG_MIN)) {
/* switch to double */
- ZVAL_DOUBLE(op1, (double)LONG_MIN - 1.0);
+ ZVAL_DOUBLE(op1, (double)ZEND_LONG_MIN - 1.0);
} else {
Z_LVAL_P(op1)--;
}
@@ -737,7 +739,7 @@ static zend_always_inline int fast_mul_function(zval *result, zval *op1, zval *o
{
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
- long overflow;
+ zend_long overflow;
ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow);
Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
@@ -767,9 +769,9 @@ static zend_always_inline int fast_div_function(zval *result, zval *op1, zval *o
zend_error(E_WARNING, "Division by zero");
ZVAL_BOOL(result, 0);
return FAILURE;
- } else if (UNEXPECTED(Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN)) {
+ } else if (UNEXPECTED(Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN)) {
/* Prevent overflow error/crash */
- ZVAL_DOUBLE(result, (double) LONG_MIN / -1);
+ ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1);
} else if (EXPECTED(Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0)) {
/* integer */
ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
@@ -818,7 +820,7 @@ static zend_always_inline int fast_mod_function(zval *result, zval *op1, zval *o
ZVAL_BOOL(result, 0);
return FAILURE;
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
- /* Prevent overflow error/crash if op1==LONG_MIN */
+ /* Prevent overflow error/crash if op1==ZEND_LONG_MIN */
ZVAL_LONG(result, 0);
return SUCCESS;
}
@@ -1045,14 +1047,14 @@ static zend_always_inline void fast_is_not_identical_function(zval *result, zval
/* buf points to the END of the buffer */
#define _zend_print_signed_to_buf(buf, num, vartype, result) do { \
if (num < 0) { \
- _zend_print_unsigned_to_buf((buf), -(vartype)(num), vartype, (result)); \
+ _zend_print_unsigned_to_buf((buf), (~((vartype)(num)) + 1), vartype, (result)); \
*--(result) = '-'; \
} else { \
_zend_print_unsigned_to_buf((buf), (num), vartype, (result)); \
} \
} while (0)
-ZEND_API zend_string *zend_long_to_str(long num);
+ZEND_API zend_string *zend_long_to_str(zend_long num);
#endif
diff --git a/Zend/zend_qsort.c b/Zend/zend_qsort.c
index ea577e1c07..a27a3c281f 100644
--- a/Zend/zend_qsort.c
+++ b/Zend/zend_qsort.c
@@ -74,7 +74,7 @@ ZEND_API void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_
end = end_stack[loop];
while (begin < end) {
- offset = (end - begin) >> 1;
+ offset = (end - begin) >> Z_L(1);
_zend_qsort_swap(begin, begin + (offset - (offset % siz)), siz);
seg1 = begin + siz;
diff --git a/Zend/zend_static_allocator.c b/Zend/zend_static_allocator.c
index 71338d211e..049d29f6a2 100644
--- a/Zend/zend_static_allocator.c
+++ b/Zend/zend_static_allocator.c
@@ -22,13 +22,13 @@
/* Not checking emalloc() and erealloc() return values as they are supposed to bailout */
-inline static void block_init(Block *block, zend_uint block_size)
+inline static void block_init(Block *block, uint32_t block_size)
{
block->pos = block->bp = (char *) emalloc(block_size);
block->end = block->bp + block_size;
}
-inline static char *block_allocate(Block *block, zend_uint size)
+inline static char *block_allocate(Block *block, uint32_t size)
{
char *retval = block->pos;
if ((block->pos += size) >= block->end) {
@@ -50,7 +50,7 @@ void static_allocator_init(StaticAllocator *sa)
sa->current_block = 0;
}
-char *static_allocator_allocate(StaticAllocator *sa, zend_uint size)
+char *static_allocator_allocate(StaticAllocator *sa, uint32_t size)
{
char *retval;
@@ -67,7 +67,7 @@ char *static_allocator_allocate(StaticAllocator *sa, zend_uint size)
void static_allocator_destroy(StaticAllocator *sa)
{
- zend_uint i;
+ uint32_t i;
for (i=0; i<sa->num_blocks; i++) {
block_free(&sa->Blocks[i]);
diff --git a/Zend/zend_static_allocator.h b/Zend/zend_static_allocator.h
index 7516065707..cd9b0ff583 100644
--- a/Zend/zend_static_allocator.h
+++ b/Zend/zend_static_allocator.h
@@ -24,7 +24,7 @@
#define ALLOCATOR_BLOCK_SIZE 400000
/* Temporary */
-typedef unsigned int zend_uint;
+typedef unsigned int uint32_t;
#define emalloc(s) malloc(s)
#define efree(p) free(p)
@@ -36,12 +36,12 @@ typedef struct _Block {
typedef struct _StaticAllocator {
Block *Blocks;
- zend_uint num_blocks;
- zend_uint current_block;
+ uint32_t num_blocks;
+ uint32_t current_block;
} StaticAllocator;
void static_allocator_init(StaticAllocator *sa);
-char *static_allocator_allocate(StaticAllocator *sa, zend_uint size);
+char *static_allocator_allocate(StaticAllocator *sa, uint32_t size);
void static_allocator_destroy(StaticAllocator *sa);
#endif /* ZEND_STATIC_ALLOCATOR_H */
diff --git a/Zend/zend_stream.c b/Zend/zend_stream.c
index 6d306b337e..f67f59af4a 100644
--- a/Zend/zend_stream.c
+++ b/Zend/zend_stream.c
@@ -24,9 +24,8 @@
#include "zend.h"
#include "zend_compile.h"
+#include "zend_stream.h"
-#include <sys/types.h>
-#include <sys/stat.h>
#if HAVE_MMAP
# if HAVE_UNISTD_H
# include <unistd.h>
@@ -64,8 +63,8 @@ static void zend_stream_stdio_closer(void *handle TSRMLS_DC) /* {{{ */
static size_t zend_stream_stdio_fsizer(void *handle TSRMLS_DC) /* {{{ */
{
- struct stat buf;
- if (handle && fstat(fileno((FILE*)handle), &buf) == 0) {
+ zend_stat_t buf;
+ if (handle && zend_fstat(fileno((FILE*)handle), &buf) == 0) {
#ifdef S_ISREG
if (!S_ISREG(buf.st_mode)) {
return 0;
@@ -106,7 +105,7 @@ static inline int zend_stream_is_mmap(zend_file_handle *file_handle) { /* {{{ */
static size_t zend_stream_fsize(zend_file_handle *file_handle TSRMLS_DC) /* {{{ */
{
- struct stat buf;
+ zend_stat_t buf;
if (zend_stream_is_mmap(file_handle)) {
return file_handle->handle.stream.mmap.len;
@@ -114,7 +113,7 @@ static size_t zend_stream_fsize(zend_file_handle *file_handle TSRMLS_DC) /* {{{
if (file_handle->type == ZEND_HANDLE_STREAM || file_handle->type == ZEND_HANDLE_MAPPED) {
return file_handle->handle.stream.fsizer(file_handle->handle.stream.handle TSRMLS_CC);
}
- if (file_handle->handle.fp && fstat(fileno(file_handle->handle.fp), &buf) == 0) {
+ if (file_handle->handle.fp && zend_fstat(fileno(file_handle->handle.fp), &buf) == 0) {
#ifdef S_ISREG
if (!S_ISREG(buf.st_mode)) {
return 0;
@@ -237,7 +236,7 @@ ZEND_API int zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t
/* *buf[size] is zeroed automatically by the kernel */
*buf = mmap(0, size + ZEND_MMAP_AHEAD, PROT_READ, MAP_PRIVATE, fileno(file_handle->handle.fp), 0);
if (*buf != MAP_FAILED) {
- long offset = ftell(file_handle->handle.fp);
+ zend_long offset = ftell(file_handle->handle.fp);
file_handle->handle.stream.mmap.map = *buf;
if (offset != -1) {
diff --git a/Zend/zend_stream.h b/Zend/zend_stream.h
index 5306b496f9..84dc2e00b8 100644
--- a/Zend/zend_stream.h
+++ b/Zend/zend_stream.h
@@ -24,6 +24,9 @@
#ifndef ZEND_STREAM_H
#define ZEND_STREAM_H
+#include <sys/types.h>
+#include <sys/stat.h>
+
/* Lightweight stream implementation for the ZE scanners.
* These functions are private to the engine.
* */
@@ -60,14 +63,14 @@ typedef struct _zend_stream {
} zend_stream;
typedef struct _zend_file_handle {
- zend_stream_type type;
- const char *filename;
- char *opened_path;
union {
int fd;
FILE *fp;
zend_stream stream;
} handle;
+ const char *filename;
+ char *opened_path;
+ zend_stream_type type;
zend_bool free_filename;
} zend_file_handle;
@@ -78,4 +81,20 @@ ZEND_API void zend_file_handle_dtor(zend_file_handle *fh TSRMLS_DC);
ZEND_API int zend_compare_file_handles(zend_file_handle *fh1, zend_file_handle *fh2);
END_EXTERN_C()
+#ifdef _WIN64
+# define zend_fseek _fseeki64
+# define zend_ftell _ftelli64
+# define zend_lseek _lseeki64
+# define zend_fstat _fstat64
+# define zend_stat _stat64
+typedef struct __stat64 zend_stat_t;
+#else
+# define zend_fseek fseek
+# define zend_ftell ftell
+# define zend_lseek lseek
+# define zend_fstat fstat
+# define zend_stat stat
+typedef struct stat zend_stat_t;
+#endif
+
#endif
diff --git a/Zend/zend_string.c b/Zend/zend_string.c
index 2a415454ce..a9148f2c4a 100644
--- a/Zend/zend_string.c
+++ b/Zend/zend_string.c
@@ -29,17 +29,19 @@ static zend_string *zend_new_interned_string_int(zend_string *str TSRMLS_DC);
static void zend_interned_strings_snapshot_int(TSRMLS_D);
static void zend_interned_strings_restore_int(TSRMLS_D);
-ZEND_API zend_ulong zend_hash_func(const char *str, uint len)
+ZEND_API zend_ulong zend_hash_func(const char *str, size_t len)
{
return zend_inline_hash_func(str, len);
}
+#ifndef ZTS
static void _str_dtor(zval *zv)
{
zend_string *str = Z_STR_P(zv);
GC_FLAGS(str) &= ~IS_STR_INTERNED;
GC_REFCOUNT(str) = 1;
}
+#endif
void zend_interned_strings_init(TSRMLS_D)
{
@@ -50,17 +52,17 @@ void zend_interned_strings_init(TSRMLS_D)
CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
CG(interned_strings).arData = (Bucket*) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket), 1);
- CG(interned_strings).arHash = (zend_uint*) pecalloc(CG(interned_strings).nTableSize, sizeof(zend_uint), 1);
- memset(CG(interned_strings).arHash, INVALID_IDX, CG(interned_strings).nTableSize * sizeof(zend_uint));
+ CG(interned_strings).arHash = (uint32_t*) pecalloc(CG(interned_strings).nTableSize, sizeof(uint32_t), 1);
+ memset(CG(interned_strings).arHash, INVALID_IDX, CG(interned_strings).nTableSize * sizeof(uint32_t));
/* interned empty string */
- str = STR_ALLOC(sizeof("")-1, 1);
+ str = zend_string_alloc(sizeof("")-1, 1);
str->val[0] = '\000';
CG(empty_string) = zend_new_interned_string_int(str TSRMLS_CC);
#else
- str = STR_ALLOC(sizeof("")-1, 1);
+ str = zend_string_alloc(sizeof("")-1, 1);
str->val[0] = '\000';
- STR_HASH_VAL(str);
+ zend_string_hash_val(str);
str->gc.u.v.flags |= IS_STR_INTERNED;
CG(empty_string) = str;
#endif
@@ -85,7 +87,7 @@ void zend_interned_strings_dtor(TSRMLS_D)
static zend_string *zend_new_interned_string_int(zend_string *str TSRMLS_DC)
{
#ifndef ZTS
- ulong h;
+ zend_ulong h;
uint nIndex;
uint idx;
Bucket *p;
@@ -94,14 +96,14 @@ static zend_string *zend_new_interned_string_int(zend_string *str TSRMLS_DC)
return str;
}
- h = STR_HASH_VAL(str);
+ h = zend_string_hash_val(str);
nIndex = h & CG(interned_strings).nTableMask;
idx = CG(interned_strings).arHash[nIndex];
while (idx != INVALID_IDX) {
p = CG(interned_strings).arData + idx;
if ((p->h == h) && (p->key->len == str->len)) {
if (!memcmp(p->key->val, str->val, str->len)) {
- STR_RELEASE(str);
+ zend_string_release(str);
return p->key;
}
}
@@ -114,7 +116,7 @@ static zend_string *zend_new_interned_string_int(zend_string *str TSRMLS_DC)
if (CG(interned_strings).nNumUsed >= CG(interned_strings).nTableSize) {
if ((CG(interned_strings).nTableSize << 1) > 0) { /* Let's double the table size */
Bucket *d = (Bucket *) perealloc_recoverable(CG(interned_strings).arData, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket), 1);
- zend_uint *h = (zend_uint *) perealloc_recoverable(CG(interned_strings).arHash, (CG(interned_strings).nTableSize << 1) * sizeof(zend_uint), 1);
+ uint32_t *h = (uint32_t *) perealloc_recoverable(CG(interned_strings).arHash, (CG(interned_strings).nTableSize << 1) * sizeof(uint32_t), 1);
if (d && h) {
HANDLE_BLOCK_INTERRUPTIONS();
@@ -182,7 +184,7 @@ static void zend_interned_strings_restore_int(TSRMLS_D)
GC_FLAGS(p->key) &= ~IS_STR_INTERNED;
GC_REFCOUNT(p->key) = 1;
- STR_FREE(p->key);
+ zend_string_free(p->key);
nIndex = p->h & CG(interned_strings).nTableMask;
if (CG(interned_strings).arHash[nIndex] == idx) {
diff --git a/Zend/zend_string.h b/Zend/zend_string.h
index ef0116b938..a2b5fb932e 100644
--- a/Zend/zend_string.h
+++ b/Zend/zend_string.h
@@ -29,7 +29,7 @@ ZEND_API extern zend_string *(*zend_new_interned_string)(zend_string *str TSRMLS
ZEND_API extern void (*zend_interned_strings_snapshot)(TSRMLS_D);
ZEND_API extern void (*zend_interned_strings_restore)(TSRMLS_D);
-ZEND_API zend_ulong zend_hash_func(const char *str, uint len);
+ZEND_API zend_ulong zend_hash_func(const char *str, size_t len);
void zend_interned_strings_init(TSRMLS_D);
void zend_interned_strings_dtor(TSRMLS_D);
@@ -37,21 +37,6 @@ END_EXTERN_C()
#define IS_INTERNED(s) (GC_FLAGS(s) & IS_STR_INTERNED)
-#define STR_HASH_VAL(s) zend_str_hash_val(s)
-#define STR_FORGET_HASH_VAL(s) zend_str_forget_hash_val(s)
-
-#define STR_REFCOUNT(s) zend_str_refcount(s)
-#define STR_ADDREF(s) zend_str_addref(s)
-#define STR_DELREF(s) zend_str_delref(s)
-#define STR_ALLOC(len, persistent) zend_str_alloc(len, persistent)
-#define STR_SAFE_ALLOC(n, m, l, p) zend_str_safe_alloc(n, m, l, p)
-#define STR_INIT(str, len, persistent) zend_str_init(str, len, persistent)
-#define STR_COPY(s) zend_str_copy(s)
-#define STR_DUP(s, persistent) zend_str_dup(s, persistent)
-#define STR_REALLOC(s, len, persistent) zend_str_realloc(s, len, persistent)
-#define STR_SAFE_REALLOC(s, n, m, l, p) zend_str_safe_realloc(s, n, m, l, p)
-#define STR_FREE(s) zend_str_free(s)
-#define STR_RELEASE(s) zend_str_release(s)
#define STR_EMPTY_ALLOC() CG(empty_string)
#define _STR_HEADER_SIZE XtOffsetOf(zend_string, val)
@@ -70,7 +55,7 @@ END_EXTERN_C()
#define STR_ALLOCA_FREE(str, use_heap) free_alloca(str, use_heap)
-static zend_always_inline zend_ulong zend_str_hash_val(zend_string *s)
+static zend_always_inline zend_ulong zend_string_hash_val(zend_string *s)
{
if (!s->h) {
s->h = zend_hash_func(s->val, s->len);
@@ -78,12 +63,12 @@ static zend_always_inline zend_ulong zend_str_hash_val(zend_string *s)
return s->h;
}
-static zend_always_inline void zend_str_forget_hash_val(zend_string *s)
+static zend_always_inline void zend_string_forget_hash_val(zend_string *s)
{
s->h = 0;
}
-static zend_always_inline zend_uint zend_str_refcount(zend_string *s)
+static zend_always_inline uint32_t zend_string_refcount(zend_string *s)
{
if (!IS_INTERNED(s)) {
return GC_REFCOUNT(s);
@@ -91,7 +76,7 @@ static zend_always_inline zend_uint zend_str_refcount(zend_string *s)
return 1;
}
-static zend_always_inline zend_uint zend_str_addref(zend_string *s)
+static zend_always_inline uint32_t zend_string_addref(zend_string *s)
{
if (!IS_INTERNED(s)) {
return ++GC_REFCOUNT(s);
@@ -99,7 +84,7 @@ static zend_always_inline zend_uint zend_str_addref(zend_string *s)
return 1;
}
-static zend_always_inline zend_uint zend_str_delref(zend_string *s)
+static zend_always_inline uint32_t zend_string_delref(zend_string *s)
{
if (!IS_INTERNED(s)) {
return --GC_REFCOUNT(s);
@@ -107,7 +92,7 @@ static zend_always_inline zend_uint zend_str_delref(zend_string *s)
return 1;
}
-static zend_always_inline zend_string *zend_str_alloc(int len, int persistent)
+static zend_always_inline zend_string *zend_string_alloc(size_t len, int persistent)
{
zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), persistent);
@@ -125,7 +110,7 @@ static zend_always_inline zend_string *zend_str_alloc(int len, int persistent)
return ret;
}
-static zend_always_inline zend_string *zend_str_safe_alloc(size_t n, size_t m, size_t l, int persistent)
+static zend_always_inline zend_string *zend_string_safe_alloc(size_t n, size_t m, size_t l, int persistent)
{
zend_string *ret = (zend_string *)safe_pemalloc(n, m, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + l + 1), persistent);
@@ -143,87 +128,98 @@ static zend_always_inline zend_string *zend_str_safe_alloc(size_t n, size_t m, s
return ret;
}
-static zend_always_inline zend_string *zend_str_init(const char *str, int len, int persistent)
+static zend_always_inline zend_string *zend_string_init(const char *str, size_t len, int persistent)
{
- zend_string *ret = STR_ALLOC(len, persistent);
+ zend_string *ret = zend_string_alloc(len, persistent);
memcpy(ret->val, str, len);
ret->val[len] = '\0';
return ret;
}
-static zend_always_inline zend_string *zend_str_copy(zend_string *s)
+static zend_always_inline zend_string *zend_string_copy(zend_string *s)
{
if (!IS_INTERNED(s)) {
- STR_ADDREF(s);
+ zend_string_addref(s);
}
return s;
}
-static zend_always_inline zend_string *zend_str_dup(zend_string *s, int persistent)
+static zend_always_inline zend_string *zend_string_dup(zend_string *s, int persistent)
{
if (IS_INTERNED(s)) {
return s;
} else {
- return STR_INIT(s->val, s->len, persistent);
+ return zend_string_init(s->val, s->len, persistent);
}
}
-static zend_always_inline zend_string *zend_str_realloc(zend_string *s, int len, int persistent)
+static zend_always_inline zend_string *zend_string_realloc(zend_string *s, size_t len, int persistent)
{
zend_string *ret;
if (IS_INTERNED(s)) {
- ret = STR_ALLOC(len, persistent);
+ ret = zend_string_alloc(len, persistent);
memcpy(ret->val, s->val, (len > s->len ? s->len : len) + 1);
- } else if (EXPECTED(STR_REFCOUNT(s) == 1)) {
+ } else if (EXPECTED(zend_string_refcount(s) == 1)) {
ret = (zend_string *)perealloc(s, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), persistent);
ret->len = len;
- STR_FORGET_HASH_VAL(ret);
+ zend_string_forget_hash_val(ret);
} else {
- ret = STR_ALLOC(len, persistent);
+ ret = zend_string_alloc(len, persistent);
memcpy(ret->val, s->val, (len > s->len ? s->len : len) + 1);
- STR_DELREF(s);
+ zend_string_delref(s);
}
return ret;
}
-static zend_always_inline zend_string *zend_str_safe_realloc(zend_string *s, size_t n, size_t m, size_t l, int persistent)
+static zend_always_inline zend_string *zend_string_safe_realloc(zend_string *s, size_t n, size_t m, size_t l, int persistent)
{
zend_string *ret;
if (IS_INTERNED(s)) {
- ret = STR_SAFE_ALLOC(n, m, l, persistent);
+ ret = zend_string_safe_alloc(n, m, l, persistent);
memcpy(ret->val, s->val, ((n * m) + l > (size_t)s->len ? (size_t)s->len : ((n * m) + l)) + 1);
- } else if (STR_REFCOUNT(s) == 1) {
+ } else if (zend_string_refcount(s) == 1) {
ret = (zend_string *)safe_perealloc(s, n, m, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + l + 1), persistent);
ret->len = (n * m) + l;
- STR_FORGET_HASH_VAL(ret);
+ zend_string_forget_hash_val(ret);
} else {
- ret = STR_SAFE_ALLOC(n, m, l, persistent);
+ ret = zend_string_safe_alloc(n, m, l, persistent);
memcpy(ret->val, s->val, ((n * m) + l > (size_t)s->len ? (size_t)s->len : ((n * m) + l)) + 1);
- STR_DELREF(s);
+ zend_string_delref(s);
}
return ret;
}
-static zend_always_inline void zend_str_free(zend_string *s)
+static zend_always_inline void zend_string_free(zend_string *s)
{
if (!IS_INTERNED(s)) {
- ZEND_ASSERT(STR_REFCOUNT(s) <= 1);
+ ZEND_ASSERT(zend_string_refcount(s) <= 1);
pefree(s, GC_FLAGS(s) & IS_STR_PERSISTENT);
}
}
-static zend_always_inline void zend_str_release(zend_string *s)
+static zend_always_inline void zend_string_release(zend_string *s)
{
if (!IS_INTERNED(s)) {
- if (STR_DELREF(s) == 0) {
+ if (zend_string_delref(s) == 0) {
pefree(s, GC_FLAGS(s) & IS_STR_PERSISTENT);
}
}
}
+static zend_always_inline zend_bool zend_string_equals(zend_string *s1, zend_string *s2)
+{
+ return s1 == s2 || (s1->len == s2->len && !memcmp(s1->val, s2->val, s1->len));
+}
+
+#define zend_string_equals_literal_ci(str, c) \
+ ((str)->len == sizeof(c) - 1 && !zend_binary_strcasecmp((str)->val, (str)->len, (c), sizeof(c) - 1))
+
+#define zend_string_equals_literal(str, literal) \
+ ((str)->len == sizeof(literal)-1 && !memcmp((str)->val, literal, sizeof(literal) - 1))
+
/*
* DJBX33A (Daniel J. Bernstein, Times 33 with Addition)
*
@@ -257,9 +253,9 @@ static zend_always_inline void zend_str_release(zend_string *s)
* -- Ralf S. Engelschall <rse@engelschall.com>
*/
-static inline ulong zend_inline_hash_func(const char *str, uint len)
+static inline zend_ulong zend_inline_hash_func(const char *str, size_t len)
{
- register ulong hash = 5381;
+ register zend_ulong hash = Z_UL(5381);
/* variant with the hash unrolled eight times */
for (; len >= 8; len -= 8) {
diff --git a/Zend/zend_ts_hash.c b/Zend/zend_ts_hash.c
index f6523574ae..b289ae17c9 100644
--- a/Zend/zend_ts_hash.c
+++ b/Zend/zend_ts_hash.c
@@ -110,7 +110,7 @@ ZEND_API zval *_zend_ts_hash_add_or_update(TsHashTable *ht, zend_string *key, zv
return retval;
}
-ZEND_API zval *_zend_ts_hash_index_update_or_next_insert(TsHashTable *ht, ulong h, zval *pData, int flag ZEND_FILE_LINE_DC)
+ZEND_API zval *_zend_ts_hash_index_update_or_next_insert(TsHashTable *ht, zend_ulong h, zval *pData, int flag ZEND_FILE_LINE_DC)
{
zval *retval;
@@ -187,7 +187,7 @@ ZEND_API int zend_ts_hash_del(TsHashTable *ht, zend_string *key)
return retval;
}
-ZEND_API int zend_ts_hash_index_del(TsHashTable *ht, ulong h)
+ZEND_API int zend_ts_hash_index_del(TsHashTable *ht, zend_ulong h)
{
int retval;
@@ -209,7 +209,7 @@ ZEND_API zval *zend_ts_hash_find(TsHashTable *ht, zend_string *key)
return retval;
}
-ZEND_API zval *zend_ts_hash_index_find(TsHashTable *ht, ulong h)
+ZEND_API zval *zend_ts_hash_index_find(TsHashTable *ht, zend_ulong h)
{
zval *retval;
@@ -231,7 +231,7 @@ ZEND_API int zend_ts_hash_exists(TsHashTable *ht, zend_string *key)
return retval;
}
-ZEND_API int zend_ts_hash_index_exists(TsHashTable *ht, ulong h)
+ZEND_API int zend_ts_hash_index_exists(TsHashTable *ht, zend_ulong h)
{
int retval;
diff --git a/Zend/zend_ts_hash.h b/Zend/zend_ts_hash.h
index fcf8c3cda1..0adedff437 100644
--- a/Zend/zend_ts_hash.h
+++ b/Zend/zend_ts_hash.h
@@ -25,7 +25,7 @@
typedef struct _zend_ts_hashtable {
HashTable hash;
- zend_uint reader;
+ uint32_t reader;
#ifdef ZTS
MUTEX_T mx_reader;
MUTEX_T mx_writer;
@@ -55,7 +55,7 @@ ZEND_API zval *_zend_ts_hash_add_or_update(TsHashTable *ht, zend_string *key, zv
#define zend_ts_hash_add(ht, key, pData) \
_zend_ts_hash_add_or_update(ht, key, pData, HASH_ADD ZEND_FILE_LINE_CC)
-ZEND_API zval *_zend_ts_hash_index_update_or_next_insert(TsHashTable *ht, ulong h, zval *pData, int flag ZEND_FILE_LINE_DC);
+ZEND_API zval *_zend_ts_hash_index_update_or_next_insert(TsHashTable *ht, zend_ulong h, zval *pData, int flag ZEND_FILE_LINE_DC);
#define zend_ts_hash_index_update(ht, h, pData) \
_zend_ts_hash_index_update_or_next_insert(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_CC)
#define zend_ts_hash_next_index_insert(ht, pData) \
@@ -73,15 +73,15 @@ ZEND_API void zend_ts_hash_reverse_apply(TsHashTable *ht, apply_func_t apply_fun
/* Deletes */
ZEND_API int zend_ts_hash_del(TsHashTable *ht, zend_string *key);
-ZEND_API int zend_ts_hash_index_del(TsHashTable *ht, ulong h);
+ZEND_API int zend_ts_hash_index_del(TsHashTable *ht, zend_ulong h);
/* Data retreival */
ZEND_API zval *zend_ts_hash_find(TsHashTable *ht, zend_string *key);
-ZEND_API zval *zend_ts_hash_index_find(TsHashTable *ht, ulong);
+ZEND_API zval *zend_ts_hash_index_find(TsHashTable *ht, zend_ulong);
/* Misc */
ZEND_API int zend_ts_hash_exists(TsHashTable *ht, zend_string *key);
-ZEND_API int zend_ts_hash_index_exists(TsHashTable *ht, ulong h);
+ZEND_API int zend_ts_hash_index_exists(TsHashTable *ht, zend_ulong h);
/* Copying, merging and sorting */
ZEND_API void zend_ts_hash_copy(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor);
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index 232fcbadc1..d3d1a6ecf8 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -22,6 +22,8 @@
#ifndef ZEND_TYPES_H
#define ZEND_TYPES_H
+#include "zend_long.h"
+
#ifdef WORDS_BIGENDIAN
# define ZEND_ENDIAN_LOHI(lo, hi) hi; lo;
# define ZEND_ENDIAN_LOHI_3(lo, mi, hi) hi; mi; lo;
@@ -40,9 +42,20 @@
typedef unsigned char zend_bool;
typedef unsigned char zend_uchar;
-typedef unsigned int zend_uint;
-typedef unsigned long zend_ulong;
-typedef unsigned short zend_ushort;
+
+#ifdef ZEND_ENABLE_ZVAL_LONG64
+# ifdef ZEND_WIN32
+# define ZEND_SIZE_MAX _UI64_MAX
+# else
+# define ZEND_SIZE_MAX SIZE_MAX
+# endif
+#else
+# if defined(ZEND_WIN32)
+# define ZEND_SIZE_MAX _UI32_MAX
+# else
+# define ZEND_SIZE_MAX SIZE_MAX
+# endif
+#endif
#define HAVE_ZEND_LONG64
#ifdef ZEND_WIN32
@@ -58,12 +71,13 @@ typedef unsigned long long zend_ulong64;
# undef HAVE_ZEND_LONG64
#endif
-#ifdef _WIN64
-typedef __int64 zend_intptr_t;
-typedef unsigned __int64 zend_uintptr_t;
+/* XXX this won't work on X32 platform */
+#ifdef ZEND_ENABLE_ZVAL_LONG64
+typedef int64_t zend_intptr_t;
+typedef uint64_t zend_uintptr_t;
#else
-typedef long zend_intptr_t;
-typedef unsigned long zend_uintptr_t;
+typedef int32_t zend_intptr_t;
+typedef uint32_t zend_uintptr_t;
#endif
typedef struct _zend_object_handlers zend_object_handlers;
@@ -87,7 +101,7 @@ typedef void (*dtor_func_t)(zval *pDest);
typedef void (*copy_ctor_func_t)(zval *pElement);
typedef union _zend_value {
- long lval; /* long value */
+ zend_long lval; /* long value */
double dval; /* double value */
zend_refcounted *counted;
zend_string *str;
@@ -112,33 +126,34 @@ struct _zval_struct {
zend_uchar const_flags,
zend_uchar reserved) /* various IS_VAR flags */
} v;
- zend_uint type_info;
+ uint32_t type_info;
} u1;
union {
- zend_uint var_flags;
- zend_uint next; /* hash collision chain */
- zend_uint str_offset; /* string offset */
- zend_uint cache_slot; /* literal cache slot */
+ uint32_t var_flags;
+ uint32_t next; /* hash collision chain */
+ uint32_t cache_slot; /* literal cache slot */
+ uint32_t lineno; /* line number (for ast nodes) */
+ uint32_t silence_num; /* BEGIN_SILENCE op number */
} u2;
};
struct _zend_refcounted {
- zend_uint refcount; /* reference counter 32-bit */
+ uint32_t refcount; /* reference counter 32-bit */
union {
struct {
ZEND_ENDIAN_LOHI_3(
zend_uchar type,
zend_uchar flags, /* used for strings & objects */
- zend_ushort gc_info) /* keeps GC root number (or 0) and color */
+ uint16_t gc_info) /* keeps GC root number (or 0) and color */
} v;
- zend_uint type_info;
+ uint32_t type_info;
} u;
};
struct _zend_string {
zend_refcounted gc;
zend_ulong h; /* hash value */
- int len;
+ size_t len;
char val[1];
};
@@ -149,23 +164,23 @@ typedef struct _Bucket {
} Bucket;
typedef struct _HashTable {
- zend_uint nTableSize;
- zend_uint nTableMask;
- zend_uint nNumUsed;
- zend_uint nNumOfElements;
- long nNextFreeElement;
+ uint32_t nTableSize;
+ uint32_t nTableMask;
+ uint32_t nNumUsed;
+ uint32_t nNumOfElements;
+ zend_long nNextFreeElement;
Bucket *arData;
- zend_uint *arHash;
+ uint32_t *arHash;
dtor_func_t pDestructor;
- zend_uint nInternalPointer;
+ uint32_t nInternalPointer;
union {
struct {
ZEND_ENDIAN_LOHI_3(
zend_uchar flags,
zend_uchar nApplyCount,
- zend_ushort reserve)
+ uint16_t reserve)
} v;
- zend_uint flags;
+ uint32_t flags;
} u;
} HashTable;
@@ -176,7 +191,7 @@ struct _zend_array {
struct _zend_object {
zend_refcounted gc;
- zend_uint handle; // TODO: may be removed ???
+ uint32_t handle; // TODO: may be removed ???
zend_class_entry *ce;
const zend_object_handlers *handlers;
HashTable *properties;
@@ -186,7 +201,7 @@ struct _zend_object {
struct _zend_resource {
zend_refcounted gc;
- long handle; // TODO: may be removed ???
+ zend_long handle; // TODO: may be removed ???
int type;
void *ptr;
};
@@ -224,7 +239,6 @@ struct _zend_ast_ref {
/* internal types */
#define IS_INDIRECT 15
-#define IS_STR_OFFSET 16
#define IS_PTR 17
static inline zend_uchar zval_get_type(const zval* pz) {
@@ -505,10 +519,10 @@ static inline zend_uchar zval_get_type(const zval* pz) {
IS_STRING_EX; \
} while (0)
-#define ZVAL_INT_STR(z, s) do { \
- zval *__z = (z); \
- zend_string *__s = (s); \
- Z_STR_P(__z) = __s; \
+#define ZVAL_INTERNED_STR(z, s) do { \
+ zval *__z = (z); \
+ zend_string *__s = (s); \
+ Z_STR_P(__z) = __s; \
Z_TYPE_INFO_P(__z) = IS_INTERNED_STRING_EX; \
} while (0)
@@ -558,26 +572,26 @@ static inline zend_uchar zval_get_type(const zval* pz) {
#define ZVAL_NEW_RES(z, h, p, t) do { \
zend_resource *_res = emalloc(sizeof(zend_resource)); \
- zval *__z; \
+ zval *__z; \
GC_REFCOUNT(_res) = 1; \
GC_TYPE_INFO(_res) = IS_RESOURCE; \
_res->handle = (h); \
_res->type = (t); \
_res->ptr = (p); \
- __z = (z); \
+ __z = (z); \
Z_RES_P(__z) = _res; \
Z_TYPE_INFO_P(__z) = IS_RESOURCE_EX; \
} while (0)
#define ZVAL_NEW_PERSISTENT_RES(z, h, p, t) do { \
zend_resource *_res = malloc(sizeof(zend_resource)); \
- zval *__z; \
+ zval *__z; \
GC_REFCOUNT(_res) = 1; \
GC_TYPE_INFO(_res) = IS_RESOURCE; \
_res->handle = (h); \
_res->type = (t); \
_res->ptr = (p); \
- __z = (z); \
+ __z = (z); \
Z_RES_P(__z) = _res; \
Z_TYPE_INFO_P(__z) = IS_RESOURCE_EX; \
} while (0)
@@ -636,19 +650,6 @@ static inline zend_uchar zval_get_type(const zval* pz) {
Z_TYPE_INFO_P(z) = IS_PTR; \
} while (0)
-
-#define Z_STR_OFFSET_STR(zval) Z_INDIRECT(zval)
-#define Z_STR_OFFSET_STR_P(zval_p) Z_STR_OFFSET_STR(*(zval_p))
-
-#define Z_STR_OFFSET_IDX(zval) (zval).u2.str_offset
-#define Z_STR_OFFSET_IDX_P(zval_p) Z_STR_OFFSET_IDX(*(zval_p))
-
-#define ZVAL_STR_OFFSET(z, s, i) do { \
- Z_STR_OFFSET_STR_P(z) = (s); \
- Z_STR_OFFSET_IDX_P(z) = (i); \
- Z_TYPE_INFO_P(z) = IS_STR_OFFSET; \
- } while (0)
-
#endif /* ZEND_TYPES_H */
/*
diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c
index 9f76d9f812..3e68a38487 100644
--- a/Zend/zend_variables.c
+++ b/Zend/zend_variables.c
@@ -34,7 +34,7 @@ ZEND_API void _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC)
case IS_CONSTANT: {
zend_string *str = (zend_string*)p;
CHECK_ZVAL_STRING_REL(str);
- STR_RELEASE(str);
+ zend_string_release(str);
break;
}
case IS_ARRAY: {
@@ -46,15 +46,15 @@ ZEND_API void _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC)
GC_TYPE(arr) = IS_NULL;
GC_REMOVE_FROM_BUFFER(arr);
zend_hash_destroy(&arr->ht);
- efree(arr);
+ efree_size(arr, sizeof(zend_array));
}
break;
}
case IS_CONSTANT_AST: {
zend_ast_ref *ast = (zend_ast_ref*)p;
- zend_ast_destroy(ast->ast);
- efree(ast);
+ zend_ast_destroy_and_free(ast->ast);
+ efree_size(ast, sizeof(zend_ast_ref));
break;
}
case IS_OBJECT: {
@@ -78,7 +78,7 @@ ZEND_API void _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC)
zend_reference *ref = (zend_reference*)p;
if (--GC_REFCOUNT(ref) == 0) {
zval_ptr_dtor(&ref->val);
- efree(ref);
+ efree_size(ref, sizeof(zend_reference));
}
break;
}
@@ -94,7 +94,7 @@ ZEND_API void _zval_dtor_func_for_ptr(zend_refcounted *p ZEND_FILE_LINE_DC)
case IS_CONSTANT: {
zend_string *str = (zend_string*)p;
CHECK_ZVAL_STRING_REL(str);
- STR_FREE(str);
+ zend_string_free(str);
break;
}
case IS_ARRAY: {
@@ -106,15 +106,15 @@ ZEND_API void _zval_dtor_func_for_ptr(zend_refcounted *p ZEND_FILE_LINE_DC)
GC_TYPE(arr) = IS_NULL;
GC_REMOVE_FROM_BUFFER(arr);
zend_hash_destroy(&arr->ht);
- efree(arr);
+ efree_size(arr, sizeof(zend_array));
}
break;
}
case IS_CONSTANT_AST: {
zend_ast_ref *ast = (zend_ast_ref*)p;
- zend_ast_destroy(ast->ast);
- efree(ast);
+ zend_ast_destroy_and_free(ast->ast);
+ efree_size(ast, sizeof(zend_ast_ref));
break;
}
case IS_OBJECT: {
@@ -136,7 +136,7 @@ ZEND_API void _zval_dtor_func_for_ptr(zend_refcounted *p ZEND_FILE_LINE_DC)
zend_reference *ref = (zend_reference*)p;
zval_ptr_dtor(&ref->val);
- efree(ref);
+ efree_size(ref, sizeof(zend_reference));
break;
}
default:
@@ -150,7 +150,7 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
case IS_STRING:
case IS_CONSTANT:
CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue));
- STR_RELEASE(Z_STR_P(zvalue));
+ zend_string_release(Z_STR_P(zvalue));
break;
case IS_ARRAY:
case IS_CONSTANT_AST:
@@ -181,7 +181,7 @@ ZEND_API void _zval_internal_dtor_for_ptr(zval *zvalue ZEND_FILE_LINE_DC)
case IS_STRING:
case IS_CONSTANT:
CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue));
- STR_FREE(Z_STR_P(zvalue));
+ zend_string_free(Z_STR_P(zvalue));
break;
case IS_ARRAY:
case IS_CONSTANT_AST:
@@ -234,7 +234,7 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
case IS_CONSTANT:
case IS_STRING:
CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue));
- Z_STR_P(zvalue) = STR_DUP(Z_STR_P(zvalue), 0);
+ Z_STR_P(zvalue) = zend_string_dup(Z_STR_P(zvalue), 0);
break;
case IS_ARRAY: {
HashTable *ht;
diff --git a/Zend/zend_variables.h b/Zend/zend_variables.h
index c55ce233a5..538d2a5566 100644
--- a/Zend/zend_variables.h
+++ b/Zend/zend_variables.h
@@ -36,6 +36,13 @@ static zend_always_inline void _zval_dtor(zval *zvalue ZEND_FILE_LINE_DC)
_zval_dtor_func(Z_COUNTED_P(zvalue) ZEND_FILE_LINE_RELAY_CC);
}
+static zend_always_inline void _zval_ptr_dtor_nogc(zval *zval_ptr ZEND_FILE_LINE_DC)
+{
+ if (Z_REFCOUNTED_P(zval_ptr) && !Z_DELREF_P(zval_ptr)) {
+ _zval_dtor_func_for_ptr(Z_COUNTED_P(zval_ptr) ZEND_FILE_LINE_CC);
+ }
+}
+
ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC);
#define zval_copy_ctor_func(zv) _zval_copy_ctor_func(zv ZEND_FILE_LINE_CC)
@@ -98,6 +105,7 @@ ZEND_API void _zval_dtor_wrapper(zval *zvalue);
#define zval_opt_copy_ctor_no_imm(zvalue) _zval_opt_copy_ctor_no_imm((zvalue) ZEND_FILE_LINE_CC)
#define zval_dtor(zvalue) _zval_dtor((zvalue) ZEND_FILE_LINE_CC)
#define zval_ptr_dtor(zval_ptr) _zval_ptr_dtor((zval_ptr) ZEND_FILE_LINE_CC)
+#define zval_ptr_dtor_nogc(zval_ptr) _zval_ptr_dtor_nogc((zval_ptr) ZEND_FILE_LINE_CC)
#define zval_internal_dtor(zvalue) _zval_internal_dtor((zvalue) ZEND_FILE_LINE_CC)
#define zval_internal_ptr_dtor(zvalue) _zval_internal_ptr_dtor((zvalue) ZEND_FILE_LINE_CC)
#define zval_dtor_wrapper _zval_dtor_wrapper
diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c
index ab3d0d7c49..665829d685 100644
--- a/Zend/zend_virtual_cwd.c
+++ b/Zend/zend_virtual_cwd.c
@@ -178,7 +178,7 @@ static int php_check_dots(const char *element, int n)
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )
typedef struct {
- unsigned long ReparseTag;
+ zend_ulong ReparseTag;
unsigned short ReparseDataLength;
unsigned short Reserved;
union {
@@ -187,7 +187,7 @@ typedef struct {
unsigned short SubstituteNameLength;
unsigned short PrintNameOffset;
unsigned short PrintNameLength;
- unsigned long Flags;
+ zend_ulong Flags;
wchar_t ReparseTarget[1];
} SymbolicLinkReparseBuffer;
struct {
@@ -291,7 +291,7 @@ CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len){
}
/* }}} */
-CWD_API int php_sys_stat_ex(const char *path, struct stat *buf, int lstat) /* {{{ */
+CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{{ */
{
WIN32_FILE_ATTRIBUTE_DATA data;
__int64 t;
@@ -299,7 +299,7 @@ CWD_API int php_sys_stat_ex(const char *path, struct stat *buf, int lstat) /* {{
ALLOCA_FLAG(use_heap_large);
if (!GetFileAttributesEx(path, GetFileExInfoStandard, &data)) {
- return stat(path, buf);
+ return zend_stat(path, buf);
}
if (path_len >= 1 && path[1] == ':') {
@@ -407,7 +407,7 @@ CWD_API int php_sys_stat_ex(const char *path, struct stat *buf, int lstat) /* {{
static int php_is_dir_ok(const cwd_state *state) /* {{{ */
{
- struct stat buf;
+ zend_stat_t buf;
if (php_sys_stat(state->cwd, &buf) == 0 && S_ISDIR(buf.st_mode))
return (0);
@@ -418,7 +418,7 @@ static int php_is_dir_ok(const cwd_state *state) /* {{{ */
static int php_is_file_ok(const cwd_state *state) /* {{{ */
{
- struct stat buf;
+ zend_stat_t buf;
if (php_sys_stat(state->cwd, &buf) == 0 && S_ISREG(buf.st_mode))
return (0);
@@ -582,9 +582,9 @@ CWD_API char *virtual_getcwd(char *buf, size_t size TSRMLS_DC) /* {{{ */
/* }}} */
#ifdef PHP_WIN32
-static inline unsigned long realpath_cache_key(const char *path, int path_len TSRMLS_DC) /* {{{ */
+static inline zend_ulong realpath_cache_key(const char *path, int path_len TSRMLS_DC) /* {{{ */
{
- register unsigned long h;
+ register zend_ulong h;
char *bucket_key_start = tsrm_win32_get_path_sid_key(path TSRMLS_CC);
char *bucket_key = (char *)bucket_key_start;
const char *e = bucket_key + strlen(bucket_key);
@@ -593,8 +593,8 @@ static inline unsigned long realpath_cache_key(const char *path, int path_len TS
return 0;
}
- for (h = 2166136261U; bucket_key < e;) {
- h *= 16777619;
+ for (h = Z_UL(2166136261); bucket_key < e;) {
+ h *= Z_UL(16777619);
h ^= *bucket_key++;
}
HeapFree(GetProcessHeap(), 0, (LPVOID)bucket_key_start);
@@ -602,13 +602,13 @@ static inline unsigned long realpath_cache_key(const char *path, int path_len TS
}
/* }}} */
#else
-static inline unsigned long realpath_cache_key(const char *path, int path_len) /* {{{ */
+static inline zend_ulong realpath_cache_key(const char *path, int path_len) /* {{{ */
{
- register unsigned long h;
+ register zend_ulong h;
const char *e = path + path_len;
- for (h = 2166136261U; path < e;) {
- h *= 16777619;
+ for (h = Z_UL(2166136261); path < e;) {
+ h *= Z_UL(16777619);
h ^= *path++;
}
@@ -637,11 +637,11 @@ CWD_API void realpath_cache_clean(TSRMLS_D) /* {{{ */
CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC) /* {{{ */
{
#ifdef PHP_WIN32
- unsigned long key = realpath_cache_key(path, path_len TSRMLS_CC);
+ zend_ulong key = realpath_cache_key(path, path_len TSRMLS_CC);
#else
- unsigned long key = realpath_cache_key(path, path_len);
+ zend_ulong key = realpath_cache_key(path, path_len);
#endif
- unsigned long n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
+ zend_ulong n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
realpath_cache_bucket **bucket = &CWDG(realpath_cache)[n];
while (*bucket != NULL) {
@@ -668,7 +668,7 @@ CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC) /* {{{
static inline void realpath_cache_add(const char *path, int path_len, const char *realpath, int realpath_len, int is_dir, time_t t TSRMLS_DC) /* {{{ */
{
- long size = sizeof(realpath_cache_bucket) + path_len + 1;
+ zend_long size = sizeof(realpath_cache_bucket) + path_len + 1;
int same = 1;
if (realpath_len != path_len ||
@@ -679,7 +679,7 @@ static inline void realpath_cache_add(const char *path, int path_len, const char
if (CWDG(realpath_cache_size) + size <= CWDG(realpath_cache_size_limit)) {
realpath_cache_bucket *bucket = malloc(size);
- unsigned long n;
+ zend_ulong n;
if (bucket == NULL) {
return;
@@ -719,12 +719,12 @@ static inline void realpath_cache_add(const char *path, int path_len, const char
static inline realpath_cache_bucket* realpath_cache_find(const char *path, int path_len, time_t t TSRMLS_DC) /* {{{ */
{
#ifdef PHP_WIN32
- unsigned long key = realpath_cache_key(path, path_len TSRMLS_CC);
+ zend_ulong key = realpath_cache_key(path, path_len TSRMLS_CC);
#else
- unsigned long key = realpath_cache_key(path, path_len);
+ zend_ulong key = realpath_cache_key(path, path_len);
#endif
- unsigned long n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
+ zend_ulong n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
realpath_cache_bucket **bucket = &CWDG(realpath_cache)[n];
while (*bucket != NULL) {
@@ -756,12 +756,12 @@ CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, int path_
}
/* }}} */
-CWD_API int realpath_cache_size(TSRMLS_D)
+CWD_API zend_long realpath_cache_size(TSRMLS_D)
{
return CWDG(realpath_cache_size);
}
-CWD_API int realpath_cache_max_buckets(TSRMLS_D)
+CWD_API zend_long realpath_cache_max_buckets(TSRMLS_D)
{
return (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
}
@@ -784,7 +784,7 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
HANDLE hFind;
ALLOCA_FLAG(use_heap_large)
#else
- struct stat st;
+ zend_stat_t st;
#endif
realpath_cache_bucket *bucket;
char *tmp;
@@ -1739,7 +1739,7 @@ CWD_API int virtual_rename(const char *oldname, const char *newname TSRMLS_DC) /
}
/* }}} */
-CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC) /* {{{ */
+CWD_API int virtual_stat(const char *path, zend_stat_t *buf TSRMLS_DC) /* {{{ */
{
cwd_state new_state;
int retval;
@@ -1757,7 +1757,7 @@ CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC) /* {{{ */
}
/* }}} */
-CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC) /* {{{ */
+CWD_API int virtual_lstat(const char *path, zend_stat_t *buf TSRMLS_DC) /* {{{ */
{
cwd_state new_state;
int retval;
diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h
index b0df0ad310..3c432de9ad 100644
--- a/Zend/zend_virtual_cwd.h
+++ b/Zend/zend_virtual_cwd.h
@@ -130,7 +130,7 @@ typedef unsigned short mode_t;
#endif
#ifdef TSRM_WIN32
-CWD_API int php_sys_stat_ex(const char *path, struct stat *buf, int lstat);
+CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat);
# define php_sys_stat(path, buf) php_sys_stat_ex(path, buf, 0)
# define php_sys_lstat(path, buf) php_sys_stat_ex(path, buf, 1)
CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len);
@@ -164,8 +164,8 @@ CWD_API FILE *virtual_fopen(const char *path, const char *mode TSRMLS_DC);
CWD_API int virtual_open(const char *path TSRMLS_DC, int flags, ...);
CWD_API int virtual_creat(const char *path, mode_t mode TSRMLS_DC);
CWD_API int virtual_rename(const char *oldname, const char *newname TSRMLS_DC);
-CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC);
-CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC);
+CWD_API int virtual_stat(const char *path, zend_stat_t *buf TSRMLS_DC);
+CWD_API int virtual_lstat(const char *path, zend_stat_t *buf TSRMLS_DC);
CWD_API int virtual_unlink(const char *path TSRMLS_DC);
CWD_API int virtual_mkdir(const char *pathname, mode_t mode TSRMLS_DC);
CWD_API int virtual_rmdir(const char *pathname TSRMLS_DC);
@@ -211,27 +211,27 @@ CWD_API char *tsrm_realpath(const char *path, char *real_path TSRMLS_DC);
#define REALPATH_CACHE_SIZE 0 /* disabled while php.ini isn't loaded */
typedef struct _realpath_cache_bucket {
- unsigned long key;
+ zend_ulong key;
char *path;
- int path_len;
char *realpath;
+ struct _realpath_cache_bucket *next;
+ time_t expires;
+ int path_len;
int realpath_len;
int is_dir;
- time_t expires;
#ifdef PHP_WIN32
unsigned char is_rvalid;
unsigned char is_readable;
unsigned char is_wvalid;
unsigned char is_writable;
#endif
- struct _realpath_cache_bucket *next;
} realpath_cache_bucket;
typedef struct _virtual_cwd_globals {
cwd_state cwd;
- long realpath_cache_size;
- long realpath_cache_size_limit;
- long realpath_cache_ttl;
+ zend_long realpath_cache_size;
+ zend_long realpath_cache_size_limit;
+ zend_long realpath_cache_ttl;
realpath_cache_bucket *realpath_cache[1024];
} virtual_cwd_globals;
@@ -246,8 +246,8 @@ extern virtual_cwd_globals cwd_globals;
CWD_API void realpath_cache_clean(TSRMLS_D);
CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC);
CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, int path_len, time_t t TSRMLS_DC);
-CWD_API int realpath_cache_size(TSRMLS_D);
-CWD_API int realpath_cache_max_buckets(TSRMLS_D);
+CWD_API zend_long realpath_cache_size(TSRMLS_D);
+CWD_API zend_long realpath_cache_max_buckets(TSRMLS_D);
CWD_API realpath_cache_bucket** realpath_cache_get_buckets(TSRMLS_D);
/* The actual macros to be used in programs using TSRM
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 7749197a74..a3ae246579 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -335,7 +335,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
zval *value;
int have_get_ptr = 0;
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -430,7 +430,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (OP1_TYPE == IS_VAR && !OP1_FREE) {
@@ -445,7 +445,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -497,7 +497,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU
value = GET_OP2_ZVAL_PTR(BP_VAR_R);
var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -692,7 +692,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
retval = EX_VAR(opline->result.var);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -784,7 +784,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
retval = EX_VAR(opline->result.var);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -867,6 +867,10 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY)
SAVE_OPLINE();
var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
fast_increment_function(var_ptr);
if (RETURN_VALUE_USED(opline)) {
@@ -875,9 +879,6 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY)
ZEND_VM_NEXT_OPCODE();
}
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
if (RETURN_VALUE_USED(opline)) {
ZVAL_NULL(EX_VAR(opline->result.var));
@@ -922,6 +923,10 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY)
SAVE_OPLINE();
var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
fast_decrement_function(var_ptr);
if (RETURN_VALUE_USED(opline)) {
@@ -930,9 +935,6 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY)
ZEND_VM_NEXT_OPCODE();
}
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
if (RETURN_VALUE_USED(opline)) {
ZVAL_NULL(EX_VAR(opline->result.var));
@@ -977,15 +979,16 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
SAVE_OPLINE();
var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
fast_increment_function(var_ptr);
ZEND_VM_NEXT_OPCODE();
}
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
ZVAL_NULL(EX_VAR(opline->result.var));
FREE_OP1_VAR_PTR();
@@ -1031,15 +1034,16 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
SAVE_OPLINE();
var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
fast_decrement_function(var_ptr);
ZEND_VM_NEXT_OPCODE();
}
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
ZVAL_NULL(EX_VAR(opline->result.var));
FREE_OP1_VAR_PTR();
@@ -1116,7 +1120,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -1131,7 +1135,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (OP1_TYPE != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
FREE_OP1();
CHECK_EXCEPTION();
@@ -1154,8 +1158,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -1175,8 +1178,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -1198,7 +1200,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
}
if (OP1_TYPE != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -1279,7 +1281,7 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
SAVE_OPLINE();
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (EXPECTED(opline->extended_value == 0)) {
@@ -1288,7 +1290,7 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
}
FREE_OP2();
- if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1305,12 +1307,12 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
SAVE_OPLINE();
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1318,7 +1320,7 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, VAR|CV, CONST|TMP|VAR|CV)
+ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -1333,7 +1335,7 @@ ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, VAR|CV, CONST|TMP|VAR|CV)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
+ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUSED|CV)
{
USE_OPLINE
zval *container;
@@ -1342,12 +1344,15 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
- if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP2();
@@ -1374,12 +1379,12 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV)
SAVE_OPLINE();
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_UNSET);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1387,7 +1392,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
+ZEND_VM_HELPER(zend_fetch_property_address_read_helper, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
USE_OPLINE
zend_free_op free_op1;
@@ -1420,7 +1425,7 @@ ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
+ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_property_address_read_helper);
}
@@ -1436,13 +1441,13 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1461,12 +1466,12 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1474,7 +1479,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
+ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
USE_OPLINE
zend_free_op free_op1;
@@ -1506,7 +1511,7 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
+ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
USE_OPLINE
zval *container;
@@ -1520,12 +1525,15 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1546,12 +1554,12 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1592,7 +1600,7 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
property_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -1613,7 +1621,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
SAVE_OPLINE();
object_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
@@ -1631,35 +1639,30 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
zval *dim = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
zval *variable_ptr;
- zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, OP2_TYPE TSRMLS_CC);
+ variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, OP2_TYPE TSRMLS_CC);
FREE_OP2();
-
- value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
- if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
- if (IS_TMP_FREE(free_op_data1)) {
- zval_dtor(value);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- FREE_OP_VAR_PTR(free_op_data2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ if (UNEXPECTED(variable_ptr != NULL)) {
+ zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
} else {
- if ((opline+1)->op1_type == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if ((opline+1)->op1_type == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
+ variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
} else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_IF_VAR(free_op_data1);
+ FREE_OP_IF_VAR(free_op_data1);
}
FREE_OP1_VAR_PTR();
/* assign_dim has two opcodes! */
@@ -1676,12 +1679,10 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV)
zval *variable_ptr;
SAVE_OPLINE();
- value = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ value = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, OP2_TYPE, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
if (IS_OP2_TMP_FREE()) {
zval_dtor(value);
}
@@ -1689,13 +1690,7 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV)
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- if (OP2_TYPE == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if (OP2_TYPE == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
- } else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
+ value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
@@ -1744,8 +1739,8 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
UNEXPECTED(!Z_ISREF_P(variable_ptr))) {
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
}
- if ((OP2_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) ||
- (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET))) {
+ if ((OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) ||
+ (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == NULL))) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
}
if ((OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) ||
@@ -1809,7 +1804,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
EG(scope) = EX(scope);
if (UNEXPECTED(EG(exception) != NULL)) {
- zend_op *opline = EX(opline);
+ const zend_op *opline = EX(opline);
zend_throw_exception_internal(NULL TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(EX_VAR(opline->result.var));
@@ -1823,7 +1818,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
} else if (frame_kind == VM_FRAME_NESTED_CODE) {
zend_detach_symbol_table(execute_data);
destroy_op_array(&EX(func)->op_array TSRMLS_CC);
- efree(EX(func));
+ efree_size(EX(func), sizeof(zend_op_array));
EG(current_execute_data) = EX(prev_execute_data);
zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
@@ -2382,7 +2377,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
zend_function *fbc;
zval *function_name, *func;
- if (OP2_TYPE == IS_CONST) {
+ if (OP2_TYPE == IS_CONST && Z_TYPE_P(opline->op2.zv) == IS_STRING) {
function_name = (zval*)(opline->op2.zv+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
@@ -2412,21 +2407,22 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
ZVAL_DEREF(function_name);
if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
if (Z_STRVAL_P(function_name)[0] == '\\') {
- lcname = STR_ALLOC(Z_STRLEN_P(function_name) - 1, 0);
+ lcname = zend_string_alloc(Z_STRLEN_P(function_name) - 1, 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name) + 1, Z_STRLEN_P(function_name) - 1);
} else {
- lcname = STR_ALLOC(Z_STRLEN_P(function_name), 0);
+ lcname = zend_string_alloc(Z_STRLEN_P(function_name), 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name), Z_STRLEN_P(function_name));
}
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
}
- STR_FREE(lcname);
+ zend_string_free(lcname);
FREE_OP2();
+
fbc = Z_FUNC_P(func);
called_scope = NULL;
object = NULL;
- } else if (OP2_TYPE != IS_CONST && OP2_TYPE != IS_TMP_VAR &&
+ } else if (OP2_TYPE != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
@@ -2437,11 +2433,10 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
fbc->common.prototype = (zend_function*)Z_OBJ_P(function_name_ptr);
- } else {
+ } else if (OP2_TYPE == IS_CV) {
FREE_OP2();
}
- } else if (OP2_TYPE != IS_CONST &&
- EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
+ } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
zval *obj;
zval *method;
@@ -2671,7 +2666,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
EG(current_execute_data) = call;
if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
- zend_uint i;
+ uint32_t i;
zval *p = ZEND_CALL_ARG(call, 1);
for (i = 0; i < call->num_args; ++i) {
@@ -2768,7 +2763,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
zend_vm_stack_free_call_frame(call TSRMLS_CC);
if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
- STR_RELEASE(fbc->common.function_name);
+ zend_string_release(fbc->common.function_name);
}
efree(fbc);
@@ -2874,7 +2869,7 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
retval_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
}
@@ -3077,10 +3072,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
(Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) &&
- ((!Z_REFCOUNTED_P(varptr) && Z_TYPE_P(varptr) != IS_STRING) ||
- Z_ISREF_P(varptr) ||
- Z_TYPE_P(varptr) == IS_OBJECT ||
- (Z_REFCOUNTED_P(varptr) && Z_REFCOUNT_P(varptr) == 1))) {
+ (Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) {
ZVAL_MAKE_REF(varptr);
if (OP1_TYPE == IS_CV) {
@@ -3113,7 +3105,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
SAVE_OPLINE();
varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(varptr) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(varptr == NULL)) {
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
}
@@ -3186,7 +3178,7 @@ ZEND_VM_C_LABEL(send_again):
zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht) TSRMLS_CC);
if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
- int i;
+ uint32_t i;
int separate = 0;
/* check if any of arguments are going to be passed by reference */
@@ -3352,7 +3344,7 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY)
EX(call)->called_scope = NULL;
EX(call)->object = NULL;
} else {
- zend_uint arg_num = 1;
+ uint32_t arg_num = 1;
HashTable *ht = Z_ARRVAL_P(args);
zval *arg, *param, tmp;
@@ -3360,7 +3352,7 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY)
zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht) TSRMLS_CC);
if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
- zend_uint i;
+ uint32_t i;
int separate = 0;
/* check if any of arguments are going to be passed by reference */
@@ -3530,7 +3522,7 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY)
ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
{
USE_OPLINE
- zend_uint arg_num = opline->op1.num;
+ uint32_t arg_num = opline->op1.num;
SAVE_OPLINE();
if (UNEXPECTED(arg_num > EX(num_args))) {
@@ -3549,7 +3541,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
{
USE_OPLINE
- zend_uint arg_num = opline->op1.num;
+ uint32_t arg_num = opline->op1.num;
zval *param;
SAVE_OPLINE();
@@ -3577,8 +3569,8 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
{
USE_OPLINE
- zend_uint arg_num = opline->op1.num;
- zend_uint arg_count = EX(num_args);
+ uint32_t arg_num = opline->op1.num;
+ uint32_t arg_count = EX(num_args);
zval *params;
SAVE_OPLINE();
@@ -3892,7 +3884,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
} else if (Z_STRLEN_P(opline->op2.zv) == sizeof("class")-1 && memcmp(Z_STRVAL_P(opline->op2.zv), "class", sizeof("class") - 1) == 0) {
/* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
ZVAL_STR(EX_VAR(opline->result.var), ce->name);
- STR_ADDREF(ce->name);
+ zend_string_addref(ce->name);
} else {
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
@@ -3912,7 +3904,7 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS
if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -3941,7 +3933,7 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS
zend_free_op free_op2;
zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
ZEND_VM_C_LABEL(add_again):
switch (Z_TYPE_P(offset)) {
@@ -3993,7 +3985,7 @@ ZEND_VM_C_LABEL(str_index):
ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|UNUSED|CV)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -4162,9 +4154,9 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
zend_file_handle file_handle;
char *resolved_path;
- resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+ resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename) TSRMLS_CC);
if (resolved_path) {
- failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, strlen(resolved_path));
+ failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path));
} else {
resolved_path = Z_STRVAL_P(inc_filename);
}
@@ -4177,7 +4169,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
file_handle.opened_path = estrdup(resolved_path);
}
- if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path))) {
+ if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) {
new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
@@ -4242,7 +4234,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
}
destroy_op_array(new_op_array TSRMLS_CC);
- efree(new_op_array);
+ efree_size(new_op_array, sizeof(zend_op_array));
if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
HANDLE_EXCEPTION();
@@ -4332,10 +4324,13 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zend_free_op free_op1, free_op2;
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (OP1_TYPE != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -4414,7 +4409,6 @@ ZEND_VM_C_LABEL(numeric_index_dim):
FREE_OP2();
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -4435,7 +4429,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
- if (OP1_TYPE == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
@@ -4472,17 +4466,15 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
ZVAL_DEREF(array_ptr);
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL_NOREF(array_ptr);
+ SEPARATE_ARRAY(array_ptr);
array_ref = array_ptr;
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
ZVAL_NEW_REF(array_ptr, array_ptr);
array_ref = array_ptr;
array_ptr = Z_REFVAL_P(array_ptr);
}
- } else if (Z_IMMUTABLE_P(array_ptr)) {
+ } else if (Z_IMMUTABLE_P(array_ptr) || Z_REFCOUNT_P(array_ptr) > 1) {
zval_copy_ctor(array_ptr);
- } else {
- SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -4493,9 +4485,6 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
ce = Z_OBJCE_P(array_ptr);
if (!ce || ce->get_iterator == NULL) {
- if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL_NOREF(array_ptr);
- }
Z_ADDREF_P(array_ptr);
}
array_ref = array_ptr;
@@ -4542,15 +4531,23 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
}
ZVAL_DUP(&tmp, array_ref);
array_ptr = array_ref = &tmp;
- } else if (OP1_TYPE == IS_CV) {
+ } else if (OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) {
if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) {
ZVAL_UNREF(array_ref);
array_ptr = array_ref;
}
- if (Z_IMMUTABLE_P(array_ptr)) {
+ if (Z_IMMUTABLE_P(array_ptr) ||
+ (Z_ISREF_P(array_ref) &&
+ Z_REFCOUNTED_P(array_ptr) &&
+ Z_REFCOUNT_P(array_ptr) > 1)) {
+ if (!Z_IMMUTABLE_P(array_ptr)) {
+ Z_DELREF_P(array_ptr);
+ }
zval_copy_ctor(array_ptr);
}
- Z_ADDREF_P(array_ref);
+ if (OP1_TYPE == IS_CV) {
+ Z_ADDREF_P(array_ref);
+ }
}
}
}
@@ -4600,25 +4597,37 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- zend_hash_internal_pointer_reset(fe_ht);
- if (ce) {
- zend_object *zobj = Z_OBJ_P(array_ptr);
- while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
- zend_string *str_key;
- ulong int_key;
- zend_uchar key_type;
-
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
- if (key_type != HASH_KEY_NON_EXISTENT &&
- (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS)) {
- break;
+ HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
+ HashPosition pos = 0;
+ Bucket *p;
+
+ while (1) {
+ if (pos >= fe_ht->nNumUsed) {
+ is_empty = 1;
+ if (OP1_TYPE == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+ FREE_OP1_VAR_PTR();
}
- zend_hash_move_forward(fe_ht);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ p = fe_ht->arData + pos;
+ if (Z_TYPE(p->val) == IS_UNDEF ||
+ (Z_TYPE(p->val) == IS_INDIRECT &&
+ Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
+ pos++;
+ continue;
+ }
+ if (!ce ||
+ !p->key ||
+ zend_check_property_access(Z_OBJ_P(array_ptr), p->key TSRMLS_CC) == SUCCESS) {
+ break;
}
+ pos++;
}
- is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+2)->op1.var));
+ fe_ht->nInternalPointer = pos;
+ ptr->pos = pos;
+ ptr->ht = fe_ht;
+ ptr->h = fe_ht->arData[pos].h;
+ is_empty = 0;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
@@ -4642,8 +4651,9 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
zval *array, *array_ref;
zval *value;
HashTable *fe_ht;
- zend_object_iterator *iter = NULL;
- zval *key = NULL;
+ HashPointer *ptr;
+ HashPosition pos;
+ Bucket *p;
array = array_ref = EX_VAR(opline->op1.var);
if (Z_ISREF_P(array)) {
@@ -4653,81 +4663,182 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
zval_copy_ctor(array);
}
}
- if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
- key = EX_VAR((opline+1)->result.var);
- }
SAVE_OPLINE();
- switch (zend_iterator_unwrap(array, &iter TSRMLS_CC)) {
- default:
- case ZEND_ITER_INVALID:
- zend_error(E_WARNING, "Invalid argument supplied for foreach()");
+ if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) {
+ fe_ht = Z_ARRVAL_P(array);
+ ptr = (HashPointer*)EX_VAR((opline+1)->op1.var);
+ pos = ptr->pos;
+ if (UNEXPECTED(pos == INVALID_IDX)) {
+ /* reached end of iteration */
ZEND_VM_JMP(opline->op2.jmp_addr);
-
- case ZEND_ITER_PLAIN_OBJECT: {
- zend_object *zobj = Z_OBJ_P(array);
- int key_type;
- zend_string *str_key;
- zend_ulong int_key;
-
- fe_ht = Z_OBJPROP_P(array);
- zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
+ } else if (UNEXPECTED(ptr->ht != fe_ht)) {
+ ptr->ht = fe_ht;
+ pos = 0;
+ } else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) {
+ if (fe_ht->u.flags & HASH_FLAG_PACKED) {
+ pos = ptr->h;
+ } else {
+ pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask];
+ while (pos != INVALID_IDX) {
+ if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) {
+ break;
+ }
+ pos = Z_NEXT(fe_ht->arData[pos].val);
+ }
+ }
+ }
+ while (1) {
+ if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
+ /* reached end of iteration */
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ p = fe_ht->arData + pos;
+ value = &p->val;
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
+ continue;
+ } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
+ value = Z_INDIRECT_P(value);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
+ continue;
+ }
+ }
+ if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ ZVAL_MAKE_REF(value);
+ Z_ADDREF_P(value);
+ ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
+ } else {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
+ if (!p->key) {
+ ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h);
+ } else if (IS_INTERNED(p->key)) {
+ ZVAL_INTERNED_STR(EX_VAR((opline+1)->result.var), p->key);
+ } else {
+ ZVAL_NEW_STR(EX_VAR((opline+1)->result.var), p->key);
+ GC_REFCOUNT(p->key)++;
+ }
+ }
+ break;
+ }
+ do {
+ pos++;
+ if (pos >= fe_ht->nNumUsed) {
+ fe_ht->nInternalPointer = ptr->pos = INVALID_IDX;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ p = fe_ht->arData + pos;
+ } while (Z_TYPE(p->val) == IS_UNDEF ||
+ (Z_TYPE(p->val) == IS_INDIRECT &&
+ Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF));
+ fe_ht->nInternalPointer = ptr->pos = pos;
+ ptr->h = fe_ht->arData[pos].h;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) {
+ zend_object_iterator *iter;
+
+ if ((iter = zend_iterator_unwrap(array TSRMLS_CC)) == NULL) {
+ /* plain object */
+ zend_object *zobj = Z_OBJ_P(array);
+
+ fe_ht = Z_OBJPROP_P(array);
+ ptr = (HashPointer*)EX_VAR((opline+1)->op1.var);
+ pos = ptr->pos;
+ if (pos == INVALID_IDX) {
+ /* reached end of iteration */
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ } else if (UNEXPECTED(ptr->ht != fe_ht)) {
+ ptr->ht = fe_ht;
+ pos = 0;
+ } else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) {
+ if (fe_ht->u.flags & HASH_FLAG_PACKED) {
+ pos = ptr->h;
+ } else {
+ pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask];
+ while (pos != INVALID_IDX) {
+ if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) {
+ break;
+ }
+ pos = Z_NEXT(fe_ht->arData[pos].val);
+ }
+ }
+ }
while (1) {
- if ((value = zend_hash_get_current_data(fe_ht)) == NULL) {
+ if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
/* reached end of iteration */
ZEND_VM_JMP(opline->op2.jmp_addr);
}
- if (Z_TYPE_P(value) == IS_INDIRECT) {
+ p = fe_ht->arData + pos;
+ value = &p->val;
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
+ continue;
+ } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
value = Z_INDIRECT_P(value);
- if (Z_TYPE_P(value) == IS_UNDEF) {
- zend_hash_move_forward(fe_ht);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
continue;
}
}
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
-
- zend_hash_move_forward(fe_ht);
- if (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ if (UNEXPECTED(!p->key)) {
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
+ ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h);
+ }
+ break;
+ } else if (zend_check_property_access(zobj, p->key TSRMLS_CC) == SUCCESS) {
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
+ if (p->key->val[0]) {
+ if (IS_INTERNED(p->key)) {
+ ZVAL_INTERNED_STR(EX_VAR((opline+1)->result.var), p->key);
+ } else {
+ ZVAL_NEW_STR(EX_VAR((opline+1)->result.var), p->key);
+ GC_REFCOUNT(p->key)++;
+ }
+ } else {
+ const char *class_name, *prop_name;
+ size_t prop_name_len;
+ zend_unmangle_property_name_ex(
+ p->key, &class_name, &prop_name, &prop_name_len);
+ ZVAL_STRINGL(EX_VAR((opline+1)->result.var), prop_name, prop_name_len);
+ }
+ }
break;
}
+ pos++;
}
-
- 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->val, str_key->len, &class_name, &prop_name, &prop_name_len
- );
- ZVAL_STRINGL(key, prop_name, prop_name_len);
- }
- }
-
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- break;
- }
-
- case ZEND_ITER_PLAIN_ARRAY:
- fe_ht = Z_ARRVAL_P(array);
- zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- if ((value = zend_hash_get_current_data(fe_ht)) == NULL) {
- /* reached end of iteration */
- ZEND_VM_JMP(opline->op2.jmp_addr);
- }
- if (key) {
- zend_hash_get_current_key_zval(fe_ht, key);
+ if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ ZVAL_MAKE_REF(value);
+ Z_ADDREF_P(value);
+ ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
+ } else {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
}
- zend_hash_move_forward(fe_ht);
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- break;
-
- case ZEND_ITER_OBJECT:
+ do {
+ pos++;
+ if (pos >= fe_ht->nNumUsed) {
+ fe_ht->nInternalPointer = ptr->pos = INVALID_IDX;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ p = fe_ht->arData + pos;
+ } while (Z_TYPE(p->val) == IS_UNDEF ||
+ (Z_TYPE(p->val) == IS_INDIRECT &&
+ Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) ||
+ (EXPECTED(p->key != NULL) &&
+ zend_check_property_access(zobj, p->key TSRMLS_CC) == FAILURE));
+ fe_ht->nInternalPointer = ptr->pos = pos;
+ ptr->h = fe_ht->arData[pos].h;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
/* !iter happens from exception */
if (iter && ++iter->index > 0) {
/* This could cause an endless loop if index becomes zero again.
@@ -4756,31 +4867,31 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
/* failure in get_current_data */
ZEND_VM_JMP(opline->op2.jmp_addr);
}
- if (key) {
+ if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ ZVAL_MAKE_REF(value);
+ Z_ADDREF_P(value);
+ ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
+ } else {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
if (iter->funcs->get_current_key) {
- iter->funcs->get_current_key(iter, key TSRMLS_CC);
+ iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var) TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(array_ref);
HANDLE_EXCEPTION();
}
} else {
- ZVAL_LONG(key, iter->index);
+ ZVAL_LONG(EX_VAR((opline+1)->result.var), iter->index);
}
}
- break;
- }
-
- if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
- ZVAL_MAKE_REF(value);
- Z_ADDREF_P(value);
- ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ }
} else {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ zend_error(E_WARNING, "Invalid argument supplied for foreach()");
+ ZEND_VM_JMP(opline->op2.jmp_addr);
}
-
- CHECK_EXCEPTION();
- ZEND_VM_INC_OPCODE();
- ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
@@ -4863,13 +4974,13 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
+ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -4956,7 +5067,7 @@ ZEND_VM_C_LABEL(num_index_prop):
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -4972,12 +5083,12 @@ ZEND_VM_C_LABEL(num_index_prop):
FREE_OP2();
ZVAL_BOOL(EX_VAR(opline->result.var), result);
- FREE_OP1_IF_VAR();
+ FREE_OP1();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
+ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -5005,7 +5116,7 @@ ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|C
FREE_OP2();
ZVAL_BOOL(EX_VAR(opline->result.var), result);
- FREE_OP1_IF_VAR();
+ FREE_OP1();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -5040,6 +5151,7 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting));
if (Z_TYPE(EX(old_error_reporting)) == IS_UNDEF) {
ZVAL_LONG(&EX(old_error_reporting), EG(error_reporting));
+ EX(old_error_reporting).u2.silence_num = opline->op2.num;
}
if (EG(error_reporting)) {
@@ -5060,15 +5172,10 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
}
if (EXPECTED(zend_hash_str_add_ptr(EG(modified_ini_directives), "error_reporting", sizeof("error_reporting")-1, EG(error_reporting_ini_entry)) != NULL)) {
EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value;
- EG(error_reporting_ini_entry)->orig_value_length = EG(error_reporting_ini_entry)->value_length;
EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable;
EG(error_reporting_ini_entry)->modified = 1;
}
- } else if (EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value) {
- efree(EG(error_reporting_ini_entry)->value);
}
- EG(error_reporting_ini_entry)->value = estrndup("0", sizeof("0")-1);
- EG(error_reporting_ini_entry)->value_length = sizeof("0")-1;
} while (0);
}
CHECK_EXCEPTION();
@@ -5085,26 +5192,15 @@ ZEND_VM_HANDLER(142, ZEND_RAISE_ABSTRACT_ERROR, ANY, ANY)
ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY)
{
USE_OPLINE
- char buf[MAX_LENGTH_OF_LONG + 1];
- char *res;
SAVE_OPLINE();
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) {
EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var));
- _zend_print_signed_to_buf(buf + sizeof(buf) - 1, EG(error_reporting), unsigned long, res);
- if (EXPECTED(EG(error_reporting_ini_entry) != NULL)) {
- if (EXPECTED(EG(error_reporting_ini_entry)->modified &&
- EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value)) {
- efree(EG(error_reporting_ini_entry)->value);
- }
- EG(error_reporting_ini_entry)->value_length = buf + sizeof(buf) - 1 - res;
- EG(error_reporting_ini_entry)->value = estrndup(res, EG(error_reporting_ini_entry)->value_length);
- }
}
-//??? if (EX(old_error_reporting) == EX_VAR(opline->op1.var)) {
-//??? EX(old_error_reporting) = NULL;
-//??? }
- CHECK_EXCEPTION();
+ if (Z_TYPE(EX(old_error_reporting)) != IS_UNDEF &&
+ EX(old_error_reporting).u2.silence_num == opline->op2.num) {
+ ZVAL_UNDEF(&EX(old_error_reporting));
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -5113,10 +5209,15 @@ ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY)
USE_OPLINE
zend_free_op free_op1;
zval *value;
+ int is_ref = 0;
SAVE_OPLINE();
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && Z_ISREF_P(value)) {
+ is_ref = 1;
+ value = Z_REFVAL_P(value);
+ }
if (i_zend_is_true(value TSRMLS_CC)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
if (OP1_TYPE == IS_CONST) {
@@ -5125,6 +5226,9 @@ ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY)
}
} else if (OP1_TYPE == IS_CV) {
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
+ } else if (OP1_TYPE == IS_VAR && is_ref) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
+ FREE_OP1();
}
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -5134,7 +5238,7 @@ ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(158, ZEND_JMP_SET_VAR, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
{
USE_OPLINE
zend_free_op free_op1;
@@ -5143,7 +5247,10 @@ ZEND_VM_HANDLER(158, ZEND_JMP_SET_VAR, CONST|TMP|VAR|CV, ANY)
SAVE_OPLINE();
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
- if (i_zend_is_true(value TSRMLS_CC)) {
+ if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && Z_ISREF_P(value)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value));
+ FREE_OP1();
+ } else {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
if (OP1_TYPE == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
@@ -5152,50 +5259,6 @@ ZEND_VM_HANDLER(158, ZEND_JMP_SET_VAR, CONST|TMP|VAR|CV, ANY)
} else if (OP1_TYPE == IS_CV) {
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
- ZEND_VM_JMP(opline->op2.jmp_addr);
- }
-
- FREE_OP1();
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
-}
-
-ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
-{
- USE_OPLINE
- zend_free_op free_op1;
- zval *value;
-
- SAVE_OPLINE();
- value = GET_OP1_ZVAL_PTR(BP_VAR_R);
-
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (OP1_TYPE == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
- zval_copy_ctor_func(EX_VAR(opline->result.var));
- }
- } else if (OP1_TYPE == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
-ZEND_VM_HANDLER(157, ZEND_QM_ASSIGN_VAR, CONST|TMP|VAR|CV, ANY)
-{
- USE_OPLINE
- zend_free_op free_op1;
- zval *value;
-
- SAVE_OPLINE();
- value = GET_OP1_ZVAL_PTR(BP_VAR_R);
-
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (OP1_TYPE == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
- zval_copy_ctor_func(EX_VAR(opline->result.var));
- }
- } else if (OP1_TYPE == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
ZEND_VM_NEXT_OPCODE();
}
@@ -5390,9 +5453,9 @@ ZEND_VM_HANDLER(155, ZEND_BIND_TRAITS, ANY, ANY)
ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
{
- zend_uint op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes;
+ uint32_t op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes;
int i;
- zend_uint catch_op_num = 0, finally_op_num = 0, finally_op_end = 0;
+ uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0;
for (i = 0; i < EX(func)->op_array.last_try_catch; i++) {
if (EX(func)->op_array.try_catch_array[i].try_op > op_num) {
@@ -5461,15 +5524,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
/* restore previous error_reporting value */
if (!EG(error_reporting) && Z_TYPE(EX(old_error_reporting)) != IS_UNDEF && Z_LVAL(EX(old_error_reporting)) != 0) {
- zval restored_error_reporting;
- zend_string *key;
-
- ZVAL_LONG(&restored_error_reporting, Z_LVAL(EX(old_error_reporting)));
- convert_to_string(&restored_error_reporting);
- key = STR_INIT("error_reporting", sizeof("error_reporting")-1, 0);
- zend_alter_ini_entry_ex(key, Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC);
- STR_FREE(key);
- zval_dtor(&restored_error_reporting);
+ EG(error_reporting) = Z_LVAL(EX(old_error_reporting));
}
ZVAL_UNDEF(&EX(old_error_reporting));
@@ -5566,7 +5621,7 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
}
}
c.flags = CONST_CS; /* non persistent, case sensetive */
- c.name = STR_DUP(Z_STR_P(name), 0);
+ c.name = zend_string_dup(Z_STR_P(name), 0);
c.module_number = PHP_USER_CONSTANT;
if (zend_register_constant(&c TSRMLS_CC) == FAILURE) {
@@ -5661,7 +5716,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
} else {
zval *value_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -5877,15 +5932,17 @@ ZEND_VM_HANDLER(121, ZEND_STRLEN, CONST|TMP|VAR|CV, ANY)
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
zend_string *str = zval_get_string(value);
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- STR_RELEASE(str);
+ zend_string_release(str);
} else if (Z_TYPE_P(value) == IS_OBJECT) {
zend_string *str;
+ zval tmp;
- if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) {
+ ZVAL_COPY(&tmp, value);
+ if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) {
ZEND_VM_C_GOTO(strlen_error);
}
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- STR_RELEASE(str);
+ zval_dtor(&tmp);
} else {
ZEND_VM_C_LABEL(strlen_error):
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
@@ -5940,8 +5997,8 @@ ZEND_VM_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMP|VAR|CV, ANY)
} else {
ZVAL_FALSE(EX_VAR(opline->result.var));
}
+ break;
EMPTY_SWITCH_DEFAULT_CASE()
-
}
FREE_OP1();
CHECK_EXCEPTION();
@@ -5951,11 +6008,9 @@ ZEND_VM_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMP|VAR|CV, ANY)
ZEND_VM_HANDLER(122, ZEND_DEFINED, CONST, ANY)
{
USE_OPLINE
- zval *name;
zend_constant *c;
SAVE_OPLINE();
- name = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ZVAL_TRUE(EX_VAR(opline->result.var));
} else if ((c = zend_quick_get_constant(opline->op1.zv, 0 TSRMLS_CC)) == NULL) {
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index c2e59c1441..1a2defd584 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -306,7 +306,7 @@ static zend_uchar zend_user_opcodes[256] = {0,
241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
};
-static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op);
+static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);
#undef OPLINE
@@ -316,7 +316,7 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* o
#undef SAVE_OPLINE
#define OPLINE EX(opline)
#define DCL_OPLINE
-#define USE_OPLINE zend_op *opline = EX(opline);
+#define USE_OPLINE const zend_op *opline = EX(opline);
#define LOAD_OPLINE()
#define SAVE_OPLINE()
#undef CHECK_EXCEPTION
@@ -325,7 +325,6 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* o
#define CHECK_EXCEPTION() LOAD_OPLINE()
#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()
#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()
-#define LOAD_REGS()
#define ZEND_VM_CONTINUE() return 0
#define ZEND_VM_RETURN() return -1
#define ZEND_VM_ENTER() return 1
@@ -340,7 +339,6 @@ ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC)
- LOAD_REGS();
LOAD_OPLINE();
while (1) {
@@ -420,7 +418,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
EG(scope) = EX(scope);
if (UNEXPECTED(EG(exception) != NULL)) {
- zend_op *opline = EX(opline);
+ const zend_op *opline = EX(opline);
zend_throw_exception_internal(NULL TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(EX_VAR(opline->result.var));
@@ -434,7 +432,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
} else if (frame_kind == VM_FRAME_NESTED_CODE) {
zend_detach_symbol_table(execute_data);
destroy_op_array(&EX(func)->op_array TSRMLS_CC);
- efree(EX(func));
+ efree_size(EX(func), sizeof(zend_op_array));
EG(current_execute_data) = EX(prev_execute_data);
zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
@@ -564,7 +562,7 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EG(current_execute_data) = call;
if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
- zend_uint i;
+ uint32_t i;
zval *p = ZEND_CALL_ARG(call, 1);
for (i = 0; i < call->num_args; ++i) {
@@ -661,7 +659,7 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_vm_stack_free_call_frame(call TSRMLS_CC);
if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
- STR_RELEASE(fbc->common.function_name);
+ zend_string_release(fbc->common.function_name);
}
efree(fbc);
@@ -738,7 +736,7 @@ send_again:
zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht) TSRMLS_CC);
if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
- int i;
+ uint32_t i;
int separate = 0;
/* check if any of arguments are going to be passed by reference */
@@ -904,7 +902,7 @@ static int ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EX(call)->called_scope = NULL;
EX(call)->object = NULL;
} else {
- zend_uint arg_num = 1;
+ uint32_t arg_num = 1;
HashTable *ht = Z_ARRVAL_P(args);
zval *arg, *param, tmp;
@@ -912,7 +910,7 @@ static int ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht) TSRMLS_CC);
if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
- zend_uint i;
+ uint32_t i;
int separate = 0;
/* check if any of arguments are going to be passed by reference */
@@ -1003,7 +1001,7 @@ static int ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zend_uint arg_num = opline->op1.num;
+ uint32_t arg_num = opline->op1.num;
SAVE_OPLINE();
if (UNEXPECTED(arg_num > EX(num_args))) {
@@ -1022,8 +1020,8 @@ static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zend_uint arg_num = opline->op1.num;
- zend_uint arg_count = EX(num_args);
+ uint32_t arg_num = opline->op1.num;
+ uint32_t arg_count = EX(num_args);
zval *params;
SAVE_OPLINE();
@@ -1113,6 +1111,7 @@ static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting));
if (Z_TYPE(EX(old_error_reporting)) == IS_UNDEF) {
ZVAL_LONG(&EX(old_error_reporting), EG(error_reporting));
+ EX(old_error_reporting).u2.silence_num = opline->op2.num;
}
if (EG(error_reporting)) {
@@ -1133,15 +1132,10 @@ static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
}
if (EXPECTED(zend_hash_str_add_ptr(EG(modified_ini_directives), "error_reporting", sizeof("error_reporting")-1, EG(error_reporting_ini_entry)) != NULL)) {
EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value;
- EG(error_reporting_ini_entry)->orig_value_length = EG(error_reporting_ini_entry)->value_length;
EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable;
EG(error_reporting_ini_entry)->modified = 1;
}
- } else if (EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value) {
- efree(EG(error_reporting_ini_entry)->value);
}
- EG(error_reporting_ini_entry)->value = estrndup("0", sizeof("0")-1);
- EG(error_reporting_ini_entry)->value_length = sizeof("0")-1;
} while (0);
}
CHECK_EXCEPTION();
@@ -1297,9 +1291,9 @@ static int ZEND_FASTCALL ZEND_BIND_TRAITS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_uint op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes;
+ uint32_t op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes;
int i;
- zend_uint catch_op_num = 0, finally_op_num = 0, finally_op_end = 0;
+ uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0;
for (i = 0; i < EX(func)->op_array.last_try_catch; i++) {
if (EX(func)->op_array.try_catch_array[i].try_op > op_num) {
@@ -1368,15 +1362,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
/* restore previous error_reporting value */
if (!EG(error_reporting) && Z_TYPE(EX(old_error_reporting)) != IS_UNDEF && Z_LVAL(EX(old_error_reporting)) != 0) {
- zval restored_error_reporting;
- zend_string *key;
-
- ZVAL_LONG(&restored_error_reporting, Z_LVAL(EX(old_error_reporting)));
- convert_to_string(&restored_error_reporting);
- key = STR_INIT("error_reporting", sizeof("error_reporting")-1, 0);
- zend_alter_ini_entry_ex(key, Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC);
- STR_FREE(key);
- zval_dtor(&restored_error_reporting);
+ EG(error_reporting) = Z_LVAL(EX(old_error_reporting));
}
ZVAL_UNDEF(&EX(old_error_reporting));
@@ -1553,7 +1539,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
zend_function *fbc;
zval *function_name, *func;
- if (IS_CONST == IS_CONST) {
+ if (IS_CONST == IS_CONST && Z_TYPE_P(opline->op2.zv) == IS_STRING) {
function_name = (zval*)(opline->op2.zv+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
@@ -1583,21 +1569,21 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
ZVAL_DEREF(function_name);
if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
if (Z_STRVAL_P(function_name)[0] == '\\') {
- lcname = STR_ALLOC(Z_STRLEN_P(function_name) - 1, 0);
+ lcname = zend_string_alloc(Z_STRLEN_P(function_name) - 1, 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name) + 1, Z_STRLEN_P(function_name) - 1);
} else {
- lcname = STR_ALLOC(Z_STRLEN_P(function_name), 0);
+ lcname = zend_string_alloc(Z_STRLEN_P(function_name), 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name), Z_STRLEN_P(function_name));
}
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
}
- STR_FREE(lcname);
+ zend_string_free(lcname);
fbc = Z_FUNC_P(func);
called_scope = NULL;
object = NULL;
- } else if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR &&
+ } else if (IS_CONST != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
@@ -1608,11 +1594,10 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
fbc->common.prototype = (zend_function*)Z_OBJ_P(function_name_ptr);
- } else {
+ } else if (IS_CONST == IS_CV) {
}
- } else if (IS_CONST != IS_CONST &&
- EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
+ } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
zval *obj;
zval *method;
@@ -1738,7 +1723,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER
static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zend_uint arg_num = opline->op1.num;
+ uint32_t arg_num = opline->op1.num;
zval *param;
SAVE_OPLINE();
@@ -1882,7 +1867,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
zend_function *fbc;
zval *function_name, *func;
- if (IS_TMP_VAR == IS_CONST) {
+ if (IS_TMP_VAR == IS_CONST && Z_TYPE_P(opline->op2.zv) == IS_STRING) {
function_name = (zval*)(opline->op2.zv+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
@@ -1912,21 +1897,22 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
ZVAL_DEREF(function_name);
if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
if (Z_STRVAL_P(function_name)[0] == '\\') {
- lcname = STR_ALLOC(Z_STRLEN_P(function_name) - 1, 0);
+ lcname = zend_string_alloc(Z_STRLEN_P(function_name) - 1, 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name) + 1, Z_STRLEN_P(function_name) - 1);
} else {
- lcname = STR_ALLOC(Z_STRLEN_P(function_name), 0);
+ lcname = zend_string_alloc(Z_STRLEN_P(function_name), 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name), Z_STRLEN_P(function_name));
}
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
}
- STR_FREE(lcname);
+ zend_string_free(lcname);
zval_dtor(free_op2.var);
+
fbc = Z_FUNC_P(func);
called_scope = NULL;
object = NULL;
- } else if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR &&
+ } else if (IS_TMP_VAR != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
@@ -1937,11 +1923,10 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
fbc->common.prototype = (zend_function*)Z_OBJ_P(function_name_ptr);
- } else {
+ } else if (IS_TMP_VAR == IS_CV) {
zval_dtor(free_op2.var);
}
- } else if (IS_TMP_VAR != IS_CONST &&
- EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
+ } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
zval *obj;
zval *method;
@@ -2056,7 +2041,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
zend_function *fbc;
zval *function_name, *func;
- if (IS_VAR == IS_CONST) {
+ if (IS_VAR == IS_CONST && Z_TYPE_P(opline->op2.zv) == IS_STRING) {
function_name = (zval*)(opline->op2.zv+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
@@ -2086,21 +2071,22 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
ZVAL_DEREF(function_name);
if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
if (Z_STRVAL_P(function_name)[0] == '\\') {
- lcname = STR_ALLOC(Z_STRLEN_P(function_name) - 1, 0);
+ lcname = zend_string_alloc(Z_STRLEN_P(function_name) - 1, 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name) + 1, Z_STRLEN_P(function_name) - 1);
} else {
- lcname = STR_ALLOC(Z_STRLEN_P(function_name), 0);
+ lcname = zend_string_alloc(Z_STRLEN_P(function_name), 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name), Z_STRLEN_P(function_name));
}
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
}
- STR_FREE(lcname);
+ zend_string_free(lcname);
zval_ptr_dtor_nogc(free_op2.var);
+
fbc = Z_FUNC_P(func);
called_scope = NULL;
object = NULL;
- } else if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR &&
+ } else if (IS_VAR != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
@@ -2111,11 +2097,10 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
fbc->common.prototype = (zend_function*)Z_OBJ_P(function_name_ptr);
- } else {
+ } else if (IS_VAR == IS_CV) {
zval_ptr_dtor_nogc(free_op2.var);
}
- } else if (IS_VAR != IS_CONST &&
- EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
+ } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
zval *obj;
zval *method;
@@ -2268,7 +2253,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
zend_function *fbc;
zval *function_name, *func;
- if (IS_CV == IS_CONST) {
+ if (IS_CV == IS_CONST && Z_TYPE_P(opline->op2.zv) == IS_STRING) {
function_name = (zval*)(opline->op2.zv+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
@@ -2298,21 +2283,21 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
ZVAL_DEREF(function_name);
if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
if (Z_STRVAL_P(function_name)[0] == '\\') {
- lcname = STR_ALLOC(Z_STRLEN_P(function_name) - 1, 0);
+ lcname = zend_string_alloc(Z_STRLEN_P(function_name) - 1, 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name) + 1, Z_STRLEN_P(function_name) - 1);
} else {
- lcname = STR_ALLOC(Z_STRLEN_P(function_name), 0);
+ lcname = zend_string_alloc(Z_STRLEN_P(function_name), 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name), Z_STRLEN_P(function_name));
}
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
}
- STR_FREE(lcname);
+ zend_string_free(lcname);
fbc = Z_FUNC_P(func);
called_scope = NULL;
object = NULL;
- } else if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR &&
+ } else if (IS_CV != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
@@ -2323,11 +2308,10 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
fbc->common.prototype = (zend_function*)Z_OBJ_P(function_name_ptr);
- } else {
+ } else if (IS_CV == IS_CV) {
}
- } else if (IS_CV != IS_CONST &&
- EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
+ } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
zval *obj;
zval *method;
@@ -2669,7 +2653,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
retval_ptr = NULL;
- if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_STR_OFFSET)) {
+ if (IS_CONST == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
}
@@ -2976,9 +2960,9 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
zend_file_handle file_handle;
char *resolved_path;
- resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+ resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename) TSRMLS_CC);
if (resolved_path) {
- failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, strlen(resolved_path));
+ failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path));
} else {
resolved_path = Z_STRVAL_P(inc_filename);
}
@@ -2991,7 +2975,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
file_handle.opened_path = estrdup(resolved_path);
}
- if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path))) {
+ if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) {
new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
@@ -3056,7 +3040,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
}
destroy_op_array(new_op_array TSRMLS_CC);
- efree(new_op_array);
+ efree_size(new_op_array, sizeof(zend_op_array));
if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
HANDLE_EXCEPTION();
@@ -3086,17 +3070,15 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
ZVAL_DEREF(array_ptr);
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL_NOREF(array_ptr);
+ SEPARATE_ARRAY(array_ptr);
array_ref = array_ptr;
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
ZVAL_NEW_REF(array_ptr, array_ptr);
array_ref = array_ptr;
array_ptr = Z_REFVAL_P(array_ptr);
}
- } else if (Z_IMMUTABLE_P(array_ptr)) {
+ } else if (Z_IMMUTABLE_P(array_ptr) || Z_REFCOUNT_P(array_ptr) > 1) {
zval_copy_ctor(array_ptr);
- } else {
- SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -3107,9 +3089,6 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
ce = Z_OBJCE_P(array_ptr);
if (!ce || ce->get_iterator == NULL) {
- if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL_NOREF(array_ptr);
- }
Z_ADDREF_P(array_ptr);
}
array_ref = array_ptr;
@@ -3156,15 +3135,23 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
}
ZVAL_DUP(&tmp, array_ref);
array_ptr = array_ref = &tmp;
- } else if (IS_CONST == IS_CV) {
+ } else if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) {
ZVAL_UNREF(array_ref);
array_ptr = array_ref;
}
- if (Z_IMMUTABLE_P(array_ptr)) {
+ if (Z_IMMUTABLE_P(array_ptr) ||
+ (Z_ISREF_P(array_ref) &&
+ Z_REFCOUNTED_P(array_ptr) &&
+ Z_REFCOUNT_P(array_ptr) > 1)) {
+ if (!Z_IMMUTABLE_P(array_ptr)) {
+ Z_DELREF_P(array_ptr);
+ }
zval_copy_ctor(array_ptr);
}
- Z_ADDREF_P(array_ref);
+ if (IS_CONST == IS_CV) {
+ Z_ADDREF_P(array_ref);
+ }
}
}
}
@@ -3214,25 +3201,37 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- zend_hash_internal_pointer_reset(fe_ht);
- if (ce) {
- zend_object *zobj = Z_OBJ_P(array_ptr);
- while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
- zend_string *str_key;
- ulong int_key;
- zend_uchar key_type;
-
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
- if (key_type != HASH_KEY_NON_EXISTENT &&
- (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS)) {
- break;
+ HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
+ HashPosition pos = 0;
+ Bucket *p;
+
+ while (1) {
+ if (pos >= fe_ht->nNumUsed) {
+ is_empty = 1;
+ if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+
}
- zend_hash_move_forward(fe_ht);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ p = fe_ht->arData + pos;
+ if (Z_TYPE(p->val) == IS_UNDEF ||
+ (Z_TYPE(p->val) == IS_INDIRECT &&
+ Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
+ pos++;
+ continue;
+ }
+ if (!ce ||
+ !p->key ||
+ zend_check_property_access(Z_OBJ_P(array_ptr), p->key TSRMLS_CC) == SUCCESS) {
+ break;
}
+ pos++;
}
- is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+2)->op1.var));
+ fe_ht->nInternalPointer = pos;
+ ptr->pos = pos;
+ ptr->ht = fe_ht;
+ ptr->h = fe_ht->arData[pos].h;
+ is_empty = 0;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
@@ -3276,10 +3275,15 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR
USE_OPLINE
zval *value;
+ int is_ref = 0;
SAVE_OPLINE();
value = opline->op1.zv;
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(value)) {
+ is_ref = 1;
+ value = Z_REFVAL_P(value);
+ }
if (i_zend_is_true(value TSRMLS_CC)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
if (IS_CONST == IS_CONST) {
@@ -3288,6 +3292,9 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR
}
} else if (IS_CONST == IS_CV) {
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
+ } else if (IS_CONST == IS_VAR && is_ref) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
+
}
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -3296,7 +3303,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -3305,7 +3312,10 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE
SAVE_OPLINE();
value = opline->op1.zv;
- if (i_zend_is_true(value TSRMLS_CC)) {
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(value)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value));
+
+ } else {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
if (IS_CONST == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
@@ -3314,49 +3324,6 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE
} else if (IS_CONST == IS_CV) {
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
- ZEND_VM_JMP(opline->op2.jmp_addr);
- }
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
-
- zval *value;
-
- SAVE_OPLINE();
- value = opline->op1.zv;
-
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (IS_CONST == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
- zval_copy_ctor_func(EX_VAR(opline->result.var));
- }
- } else if (IS_CONST == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
-
- zval *value;
-
- SAVE_OPLINE();
- value = opline->op1.zv;
-
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (IS_CONST == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
- zval_copy_ctor_func(EX_VAR(opline->result.var));
- }
- } else if (IS_CONST == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
ZEND_VM_NEXT_OPCODE();
}
@@ -3379,15 +3346,17 @@ static int ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
zend_string *str = zval_get_string(value);
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- STR_RELEASE(str);
+ zend_string_release(str);
} else if (Z_TYPE_P(value) == IS_OBJECT) {
zend_string *str;
+ zval tmp;
- if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) {
+ ZVAL_COPY(&tmp, value);
+ if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) {
goto strlen_error;
}
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- STR_RELEASE(str);
+ zval_dtor(&tmp);
} else {
strlen_error:
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
@@ -3442,8 +3411,8 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER
} else {
ZVAL_FALSE(EX_VAR(opline->result.var));
}
+ break;
EMPTY_SWITCH_DEFAULT_CASE()
-
}
CHECK_EXCEPTION();
@@ -3453,11 +3422,9 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER
static int ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *name;
zend_constant *c;
SAVE_OPLINE();
- name = opline->op1.zv;
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ZVAL_TRUE(EX_VAR(opline->result.var));
} else if ((c = zend_quick_get_constant(opline->op1.zv, 0 TSRMLS_CC)) == NULL) {
@@ -3761,7 +3728,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -3776,7 +3743,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_CONST != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
CHECK_EXCEPTION();
@@ -3799,8 +3766,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -3820,8 +3786,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -3843,7 +3808,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
}
if (IS_CONST != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -3915,6 +3880,157 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
+
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ container = NULL;
+ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ }
+ zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
+ if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+
+ } else {
+ if (IS_CONST == IS_UNUSED) {
+ zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
+ }
+ container = opline->op1.zv;
+ zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
+
+
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = opline->op2.zv;
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = opline->op2.zv;
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ /* Behave like FETCH_OBJ_W */
+ zend_free_op free_op1;
+ zval *property;
+
+ SAVE_OPLINE();
+ property = opline->op2.zv;
+ container = NULL;
+
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
+ }
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
+
+ if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ return zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ }
+}
+
static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -4196,7 +4312,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
} else if (Z_STRLEN_P(opline->op2.zv) == sizeof("class")-1 && memcmp(Z_STRVAL_P(opline->op2.zv), "class", sizeof("class") - 1) == 0) {
/* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
ZVAL_STR(EX_VAR(opline->result.var), ce->name);
- STR_ADDREF(ce->name);
+ zend_string_addref(ce->name);
} else {
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
@@ -4216,7 +4332,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_O
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
- if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -4245,7 +4361,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_O
zval *offset = opline->op2.zv;
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -4297,7 +4413,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -4477,6 +4593,151 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+ int result;
+ zend_ulong hval;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = opline->op2.zv;
+
+ if (Z_TYPE_P(container) == IS_ARRAY) {
+ HashTable *ht = Z_ARRVAL_P(container);
+ zval *value;
+ zend_string *str;
+
+isset_again:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CONST != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index_prop;
+ }
+ }
+str_index_prop:
+ value = zend_hash_find_ind(ht, str);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_NULL:
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ case IS_FALSE:
+ hval = 0;
+ goto num_index_prop;
+ case IS_TRUE:
+ hval = 1;
+ goto num_index_prop;
+ case IS_RESOURCE:
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ case IS_REFERENCE:
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ value = NULL;
+ break;
+ }
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ /* > IS_NULL means not IS_UNDEF and not IS_NULL */
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
+ }
+ } else if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_dimension) {
+ result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */
+ zval tmp;
+
+ result = 0;
+ if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
+ if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_DUP(&tmp, offset);
+ convert_to_long(&tmp);
+ offset = &tmp;
+ }
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
+ if ((opline->extended_value & ZEND_ISSET) ||
+ Z_STRVAL_P(container)[offset->value.lval] != '0') {
+ result = 1;
+ }
+ }
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+ int result;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = opline->op2.zv;
+
+ if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_property) {
+ result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -4499,7 +4760,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
}
}
c.flags = CONST_CS; /* non persistent, case sensetive */
- c.name = STR_DUP(Z_STR_P(name), 0);
+ c.name = zend_string_dup(Z_STR_P(name), 0);
c.module_number = PHP_USER_CONSTANT;
if (zend_register_constant(&c TSRMLS_CC) == FAILURE) {
@@ -4550,7 +4811,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE
} else {
zval *value_ptr = NULL;
- if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -4947,6 +5208,159 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HA
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op2;
+ zval *container;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
+ zval_dtor(free_op2.var);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+ zend_free_op free_op1, free_op2;
+
+ SAVE_OPLINE();
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ container = NULL;
+ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ }
+ zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
+ if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+ zval_dtor(free_op2.var);
+
+ } else {
+ if (IS_TMP_VAR == IS_UNUSED) {
+ zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
+ }
+ container = opline->op1.zv;
+ zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
+ zval_dtor(free_op2.var);
+
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_dtor(free_op2.var);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_dtor(free_op2.var);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ /* Behave like FETCH_OBJ_W */
+ zend_free_op free_op1, free_op2;
+ zval *property;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+ container = NULL;
+
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
+ }
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
+ zval_dtor(free_op2.var);
+ if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ return zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ }
+}
+
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -5131,7 +5545,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
- if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -5160,7 +5574,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC
zend_free_op free_op2;
zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -5212,7 +5626,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -5240,6 +5654,153 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HAN
}
}
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op2;
+ zval *container;
+ int result;
+ zend_ulong hval;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_ARRAY) {
+ HashTable *ht = Z_ARRVAL_P(container);
+ zval *value;
+ zend_string *str;
+
+isset_again:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_TMP_VAR != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index_prop;
+ }
+ }
+str_index_prop:
+ value = zend_hash_find_ind(ht, str);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_NULL:
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ case IS_FALSE:
+ hval = 0;
+ goto num_index_prop;
+ case IS_TRUE:
+ hval = 1;
+ goto num_index_prop;
+ case IS_RESOURCE:
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ case IS_REFERENCE:
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ value = NULL;
+ break;
+ }
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ /* > IS_NULL means not IS_UNDEF and not IS_NULL */
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
+ }
+ } else if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_dimension) {
+ result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */
+ zval tmp;
+
+ result = 0;
+ if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
+ if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_DUP(&tmp, offset);
+ convert_to_long(&tmp);
+ offset = &tmp;
+ }
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
+ if ((opline->extended_value & ZEND_ISSET) ||
+ Z_STRVAL_P(container)[offset->value.lval] != '0') {
+ result = 1;
+ }
+ }
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ zval_dtor(free_op2.var);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op2;
+ zval *container;
+ int result;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_property) {
+ result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ zval_dtor(free_op2.var);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -5280,7 +5841,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_
} else {
zval *value_ptr = NULL;
- if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -5676,7 +6237,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -5691,7 +6252,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_CONST != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
CHECK_EXCEPTION();
@@ -5714,8 +6275,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -5735,8 +6295,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -5758,7 +6317,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
}
if (IS_CONST != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -5830,6 +6389,159 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HA
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op2;
+ zval *container;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
+ zval_ptr_dtor_nogc(free_op2.var);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+ zend_free_op free_op1, free_op2;
+
+ SAVE_OPLINE();
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ container = NULL;
+ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ }
+ zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
+ if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+ zval_ptr_dtor_nogc(free_op2.var);
+
+ } else {
+ if (IS_VAR == IS_UNUSED) {
+ zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
+ }
+ container = opline->op1.zv;
+ zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
+ zval_ptr_dtor_nogc(free_op2.var);
+
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_ptr_dtor_nogc(free_op2.var);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_ptr_dtor_nogc(free_op2.var);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ /* Behave like FETCH_OBJ_W */
+ zend_free_op free_op1, free_op2;
+ zval *property;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+ container = NULL;
+
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
+ }
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
+ zval_ptr_dtor_nogc(free_op2.var);
+ if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ return zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ }
+}
+
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -6014,7 +6726,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
- if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -6043,7 +6755,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC
zend_free_op free_op2;
zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -6095,7 +6807,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -6275,6 +6987,153 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op2;
+ zval *container;
+ int result;
+ zend_ulong hval;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_ARRAY) {
+ HashTable *ht = Z_ARRVAL_P(container);
+ zval *value;
+ zend_string *str;
+
+isset_again:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_VAR != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index_prop;
+ }
+ }
+str_index_prop:
+ value = zend_hash_find_ind(ht, str);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_NULL:
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ case IS_FALSE:
+ hval = 0;
+ goto num_index_prop;
+ case IS_TRUE:
+ hval = 1;
+ goto num_index_prop;
+ case IS_RESOURCE:
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ case IS_REFERENCE:
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ value = NULL;
+ break;
+ }
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ /* > IS_NULL means not IS_UNDEF and not IS_NULL */
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
+ }
+ } else if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_dimension) {
+ result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */
+ zval tmp;
+
+ result = 0;
+ if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
+ if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_DUP(&tmp, offset);
+ convert_to_long(&tmp);
+ offset = &tmp;
+ }
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
+ if ((opline->extended_value & ZEND_ISSET) ||
+ Z_STRVAL_P(container)[offset->value.lval] != '0') {
+ result = 1;
+ }
+ }
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ zval_ptr_dtor_nogc(free_op2.var);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op2;
+ zval *container;
+ int result;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_property) {
+ result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ zval_ptr_dtor_nogc(free_op2.var);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -6315,7 +7174,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_
} else {
zval *value_ptr = NULL;
- if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -6436,7 +7295,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -6451,7 +7310,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_CONST != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
CHECK_EXCEPTION();
@@ -6474,8 +7333,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -6495,8 +7353,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -6518,7 +7375,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
}
if (IS_CONST != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -6573,6 +7430,41 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HA
return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ container = NULL;
+ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ }
+ zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
+ if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+
+ } else {
+ if (IS_UNUSED == IS_UNUSED) {
+ zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
+ }
+ container = opline->op1.zv;
+ zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
+
+
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -6699,7 +7591,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
- if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -6728,7 +7620,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_
zval *offset = NULL;
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -6780,7 +7672,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -7025,7 +7917,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL
} else {
zval *value_ptr = NULL;
- if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -7407,6 +8299,157 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAN
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
+
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ container = NULL;
+ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ }
+ zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
+ if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+
+ } else {
+ if (IS_CV == IS_UNUSED) {
+ zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
+ }
+ container = opline->op1.zv;
+ zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
+
+
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ /* Behave like FETCH_OBJ_W */
+ zend_free_op free_op1;
+ zval *property;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+ container = NULL;
+
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
+ }
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
+
+ if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ return zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ }
+}
+
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -7642,7 +8685,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
- if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -7671,7 +8714,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO
zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -7723,7 +8766,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -7751,6 +8794,151 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAND
}
}
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+ int result;
+ zend_ulong hval;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_ARRAY) {
+ HashTable *ht = Z_ARRVAL_P(container);
+ zval *value;
+ zend_string *str;
+
+isset_again:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CV != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index_prop;
+ }
+ }
+str_index_prop:
+ value = zend_hash_find_ind(ht, str);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_NULL:
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ case IS_FALSE:
+ hval = 0;
+ goto num_index_prop;
+ case IS_TRUE:
+ hval = 1;
+ goto num_index_prop;
+ case IS_RESOURCE:
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ case IS_REFERENCE:
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ value = NULL;
+ break;
+ }
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ /* > IS_NULL means not IS_UNDEF and not IS_NULL */
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
+ }
+ } else if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_dimension) {
+ result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */
+ zval tmp;
+
+ result = 0;
+ if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
+ if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_DUP(&tmp, offset);
+ convert_to_long(&tmp);
+ offset = &tmp;
+ }
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
+ if ((opline->extended_value & ZEND_ISSET) ||
+ Z_STRVAL_P(container)[offset->value.lval] != '0') {
+ result = 1;
+ }
+ }
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+ int result;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+ offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_property) {
+ result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -7791,7 +8979,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
} else {
zval *value_ptr = NULL;
- if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -8184,7 +9372,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
retval_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_STR_OFFSET)) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
}
@@ -8493,9 +9681,9 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
zend_file_handle file_handle;
char *resolved_path;
- resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+ resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename) TSRMLS_CC);
if (resolved_path) {
- failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, strlen(resolved_path));
+ failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path));
} else {
resolved_path = Z_STRVAL_P(inc_filename);
}
@@ -8508,7 +9696,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
file_handle.opened_path = estrdup(resolved_path);
}
- if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path))) {
+ if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) {
new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
@@ -8573,7 +9761,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
}
destroy_op_array(new_op_array TSRMLS_CC);
- efree(new_op_array);
+ efree_size(new_op_array, sizeof(zend_op_array));
if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
HANDLE_EXCEPTION();
@@ -8603,17 +9791,15 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
ZVAL_DEREF(array_ptr);
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL_NOREF(array_ptr);
+ SEPARATE_ARRAY(array_ptr);
array_ref = array_ptr;
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
ZVAL_NEW_REF(array_ptr, array_ptr);
array_ref = array_ptr;
array_ptr = Z_REFVAL_P(array_ptr);
}
- } else if (Z_IMMUTABLE_P(array_ptr)) {
+ } else if (Z_IMMUTABLE_P(array_ptr) || Z_REFCOUNT_P(array_ptr) > 1) {
zval_copy_ctor(array_ptr);
- } else {
- SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -8624,9 +9810,6 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
ce = Z_OBJCE_P(array_ptr);
if (!ce || ce->get_iterator == NULL) {
- if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL_NOREF(array_ptr);
- }
Z_ADDREF_P(array_ptr);
}
array_ref = array_ptr;
@@ -8673,15 +9856,23 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
ZVAL_DUP(&tmp, array_ref);
array_ptr = array_ref = &tmp;
- } else if (IS_TMP_VAR == IS_CV) {
+ } else if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) {
ZVAL_UNREF(array_ref);
array_ptr = array_ref;
}
- if (Z_IMMUTABLE_P(array_ptr)) {
+ if (Z_IMMUTABLE_P(array_ptr) ||
+ (Z_ISREF_P(array_ref) &&
+ Z_REFCOUNTED_P(array_ptr) &&
+ Z_REFCOUNT_P(array_ptr) > 1)) {
+ if (!Z_IMMUTABLE_P(array_ptr)) {
+ Z_DELREF_P(array_ptr);
+ }
zval_copy_ctor(array_ptr);
}
- Z_ADDREF_P(array_ref);
+ if (IS_TMP_VAR == IS_CV) {
+ Z_ADDREF_P(array_ref);
+ }
}
}
}
@@ -8731,25 +9922,37 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- zend_hash_internal_pointer_reset(fe_ht);
- if (ce) {
- zend_object *zobj = Z_OBJ_P(array_ptr);
- while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
- zend_string *str_key;
- ulong int_key;
- zend_uchar key_type;
-
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
- if (key_type != HASH_KEY_NON_EXISTENT &&
- (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS)) {
- break;
+ HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
+ HashPosition pos = 0;
+ Bucket *p;
+
+ while (1) {
+ if (pos >= fe_ht->nNumUsed) {
+ is_empty = 1;
+ if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+
}
- zend_hash_move_forward(fe_ht);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ p = fe_ht->arData + pos;
+ if (Z_TYPE(p->val) == IS_UNDEF ||
+ (Z_TYPE(p->val) == IS_INDIRECT &&
+ Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
+ pos++;
+ continue;
}
+ if (!ce ||
+ !p->key ||
+ zend_check_property_access(Z_OBJ_P(array_ptr), p->key TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ pos++;
}
- is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+2)->op1.var));
+ fe_ht->nInternalPointer = pos;
+ ptr->pos = pos;
+ ptr->ht = fe_ht;
+ ptr->h = fe_ht->arData[pos].h;
+ is_empty = 0;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
@@ -8791,26 +9994,15 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- char buf[MAX_LENGTH_OF_LONG + 1];
- char *res;
SAVE_OPLINE();
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) {
EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var));
- _zend_print_signed_to_buf(buf + sizeof(buf) - 1, EG(error_reporting), unsigned long, res);
- if (EXPECTED(EG(error_reporting_ini_entry) != NULL)) {
- if (EXPECTED(EG(error_reporting_ini_entry)->modified &&
- EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value)) {
- efree(EG(error_reporting_ini_entry)->value);
- }
- EG(error_reporting_ini_entry)->value_length = buf + sizeof(buf) - 1 - res;
- EG(error_reporting_ini_entry)->value = estrndup(res, EG(error_reporting_ini_entry)->value_length);
- }
}
-//??? if (EX(old_error_reporting) == EX_VAR(opline->op1.var)) {
-//??? EX(old_error_reporting) = NULL;
-//??? }
- CHECK_EXCEPTION();
+ if (Z_TYPE(EX(old_error_reporting)) != IS_UNDEF &&
+ EX(old_error_reporting).u2.silence_num == opline->op2.num) {
+ ZVAL_UNDEF(&EX(old_error_reporting));
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -8819,10 +10011,15 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS
USE_OPLINE
zend_free_op free_op1;
zval *value;
+ int is_ref = 0;
SAVE_OPLINE();
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) {
+ is_ref = 1;
+ value = Z_REFVAL_P(value);
+ }
if (i_zend_is_true(value TSRMLS_CC)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
if (IS_TMP_VAR == IS_CONST) {
@@ -8831,6 +10028,9 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
} else if (IS_TMP_VAR == IS_CV) {
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
+ } else if (IS_TMP_VAR == IS_VAR && is_ref) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
+ zval_dtor(free_op1.var);
}
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -8840,7 +10040,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zend_free_op free_op1;
@@ -8849,7 +10049,10 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_
SAVE_OPLINE();
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (i_zend_is_true(value TSRMLS_CC)) {
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value));
+ zval_dtor(free_op1.var);
+ } else {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
if (IS_TMP_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
@@ -8858,50 +10061,6 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_
} else if (IS_TMP_VAR == IS_CV) {
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
- ZEND_VM_JMP(opline->op2.jmp_addr);
- }
-
- zval_dtor(free_op1.var);
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
- zend_free_op free_op1;
- zval *value;
-
- SAVE_OPLINE();
- value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (IS_TMP_VAR == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
- zval_copy_ctor_func(EX_VAR(opline->result.var));
- }
- } else if (IS_TMP_VAR == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
- zend_free_op free_op1;
- zval *value;
-
- SAVE_OPLINE();
- value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (IS_TMP_VAR == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
- zval_copy_ctor_func(EX_VAR(opline->result.var));
- }
- } else if (IS_TMP_VAR == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
ZEND_VM_NEXT_OPCODE();
}
@@ -8945,15 +10104,17 @@ static int ZEND_FASTCALL ZEND_STRLEN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
zend_string *str = zval_get_string(value);
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- STR_RELEASE(str);
+ zend_string_release(str);
} else if (Z_TYPE_P(value) == IS_OBJECT) {
zend_string *str;
+ zval tmp;
- if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) {
+ ZVAL_COPY(&tmp, value);
+ if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) {
goto strlen_error;
}
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- STR_RELEASE(str);
+ zval_dtor(&tmp);
} else {
strlen_error:
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
@@ -9008,8 +10169,8 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A
} else {
ZVAL_FALSE(EX_VAR(opline->result.var));
}
+ break;
EMPTY_SWITCH_DEFAULT_CASE()
-
}
zval_dtor(free_op1.var);
CHECK_EXCEPTION();
@@ -9307,7 +10468,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -9322,7 +10483,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_TMP_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
zval_dtor(free_op1.var);
CHECK_EXCEPTION();
@@ -9345,8 +10506,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -9366,8 +10526,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -9389,7 +10548,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
}
if (IS_TMP_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -9461,6 +10620,157 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HA
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
+
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ container = NULL;
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ }
+ zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
+ if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+
+ } else {
+ if (IS_CONST == IS_UNUSED) {
+ zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
+ }
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
+
+ zval_dtor(free_op1.var);
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = opline->op2.zv;
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = opline->op2.zv;
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ /* Behave like FETCH_OBJ_W */
+ zend_free_op free_op1;
+ zval *property;
+
+ SAVE_OPLINE();
+ property = opline->op2.zv;
+ container = NULL;
+
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
+ }
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
+
+ if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ return zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ }
+}
+
static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -9616,7 +10926,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -9645,7 +10955,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC
zval *offset = opline->op2.zv;
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -9697,7 +11007,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -9877,6 +11187,151 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+ int result;
+ zend_ulong hval;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = opline->op2.zv;
+
+ if (Z_TYPE_P(container) == IS_ARRAY) {
+ HashTable *ht = Z_ARRVAL_P(container);
+ zval *value;
+ zend_string *str;
+
+isset_again:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CONST != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index_prop;
+ }
+ }
+str_index_prop:
+ value = zend_hash_find_ind(ht, str);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_NULL:
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ case IS_FALSE:
+ hval = 0;
+ goto num_index_prop;
+ case IS_TRUE:
+ hval = 1;
+ goto num_index_prop;
+ case IS_RESOURCE:
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ case IS_REFERENCE:
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ value = NULL;
+ break;
+ }
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ /* > IS_NULL means not IS_UNDEF and not IS_NULL */
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
+ }
+ } else if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_dimension) {
+ result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */
+ zval tmp;
+
+ result = 0;
+ if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
+ if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_DUP(&tmp, offset);
+ convert_to_long(&tmp);
+ offset = &tmp;
+ }
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
+ if ((opline->extended_value & ZEND_ISSET) ||
+ Z_STRVAL_P(container)[offset->value.lval] != '0') {
+ result = 1;
+ }
+ }
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+ int result;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = opline->op2.zv;
+
+ if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_property) {
+ result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -9917,7 +11372,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_
} else {
zval *value_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -10314,6 +11769,159 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAND
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1, free_op2;
+ zval *container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
+ zval_dtor(free_op2.var);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+ zend_free_op free_op1, free_op2;
+
+ SAVE_OPLINE();
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ container = NULL;
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ }
+ zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
+ if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+ zval_dtor(free_op2.var);
+
+ } else {
+ if (IS_TMP_VAR == IS_UNUSED) {
+ zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
+ }
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
+ zval_dtor(free_op2.var);
+ zval_dtor(free_op1.var);
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_dtor(free_op2.var);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_dtor(free_op2.var);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ /* Behave like FETCH_OBJ_W */
+ zend_free_op free_op1, free_op2;
+ zval *property;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+ container = NULL;
+
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
+ }
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
+ zval_dtor(free_op2.var);
+ if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ return zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ }
+}
+
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -10455,7 +12063,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -10484,7 +12092,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD
zend_free_op free_op2;
zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -10536,7 +12144,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -10564,6 +12172,153 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDL
}
}
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1, free_op2;
+ zval *container;
+ int result;
+ zend_ulong hval;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_ARRAY) {
+ HashTable *ht = Z_ARRVAL_P(container);
+ zval *value;
+ zend_string *str;
+
+isset_again:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_TMP_VAR != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index_prop;
+ }
+ }
+str_index_prop:
+ value = zend_hash_find_ind(ht, str);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_NULL:
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ case IS_FALSE:
+ hval = 0;
+ goto num_index_prop;
+ case IS_TRUE:
+ hval = 1;
+ goto num_index_prop;
+ case IS_RESOURCE:
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ case IS_REFERENCE:
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ value = NULL;
+ break;
+ }
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ /* > IS_NULL means not IS_UNDEF and not IS_NULL */
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
+ }
+ } else if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_dimension) {
+ result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */
+ zval tmp;
+
+ result = 0;
+ if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
+ if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_DUP(&tmp, offset);
+ convert_to_long(&tmp);
+ offset = &tmp;
+ }
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
+ if ((opline->extended_value & ZEND_ISSET) ||
+ Z_STRVAL_P(container)[offset->value.lval] != '0') {
+ result = 1;
+ }
+ }
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ zval_dtor(free_op2.var);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1, free_op2;
+ zval *container;
+ int result;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_property) {
+ result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ zval_dtor(free_op2.var);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -10604,7 +12359,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
} else {
zval *value_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -11000,7 +12755,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -11015,7 +12770,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_TMP_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
zval_dtor(free_op1.var);
CHECK_EXCEPTION();
@@ -11038,8 +12793,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -11059,8 +12813,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -11082,7 +12835,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
}
if (IS_TMP_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -11154,6 +12907,159 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAND
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1, free_op2;
+ zval *container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
+ zval_ptr_dtor_nogc(free_op2.var);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+ zend_free_op free_op1, free_op2;
+
+ SAVE_OPLINE();
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ container = NULL;
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ }
+ zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
+ if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+ zval_ptr_dtor_nogc(free_op2.var);
+
+ } else {
+ if (IS_VAR == IS_UNUSED) {
+ zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
+ }
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
+ zval_ptr_dtor_nogc(free_op2.var);
+ zval_dtor(free_op1.var);
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_ptr_dtor_nogc(free_op2.var);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_ptr_dtor_nogc(free_op2.var);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ /* Behave like FETCH_OBJ_W */
+ zend_free_op free_op1, free_op2;
+ zval *property;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+ container = NULL;
+
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
+ }
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
+ zval_ptr_dtor_nogc(free_op2.var);
+ if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ return zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ }
+}
+
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -11295,7 +13201,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -11324,7 +13230,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
zend_free_op free_op2;
zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -11376,7 +13282,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -11556,6 +13462,153 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1, free_op2;
+ zval *container;
+ int result;
+ zend_ulong hval;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_ARRAY) {
+ HashTable *ht = Z_ARRVAL_P(container);
+ zval *value;
+ zend_string *str;
+
+isset_again:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_VAR != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index_prop;
+ }
+ }
+str_index_prop:
+ value = zend_hash_find_ind(ht, str);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_NULL:
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ case IS_FALSE:
+ hval = 0;
+ goto num_index_prop;
+ case IS_TRUE:
+ hval = 1;
+ goto num_index_prop;
+ case IS_RESOURCE:
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ case IS_REFERENCE:
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ value = NULL;
+ break;
+ }
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ /* > IS_NULL means not IS_UNDEF and not IS_NULL */
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
+ }
+ } else if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_dimension) {
+ result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */
+ zval tmp;
+
+ result = 0;
+ if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
+ if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_DUP(&tmp, offset);
+ convert_to_long(&tmp);
+ offset = &tmp;
+ }
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
+ if ((opline->extended_value & ZEND_ISSET) ||
+ Z_STRVAL_P(container)[offset->value.lval] != '0') {
+ result = 1;
+ }
+ }
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ zval_ptr_dtor_nogc(free_op2.var);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1, free_op2;
+ zval *container;
+ int result;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_property) {
+ result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ zval_ptr_dtor_nogc(free_op2.var);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -11596,7 +13649,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
} else {
zval *value_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -11717,7 +13770,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -11732,7 +13785,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_TMP_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
zval_dtor(free_op1.var);
CHECK_EXCEPTION();
@@ -11755,8 +13808,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -11776,8 +13828,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -11799,7 +13850,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
}
if (IS_TMP_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -11854,6 +13905,41 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAND
return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ container = NULL;
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ }
+ zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
+ if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+
+ } else {
+ if (IS_UNUSED == IS_UNUSED) {
+ zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
+ }
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
+
+ zval_dtor(free_op1.var);
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -11864,7 +13950,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -11893,7 +13979,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
zval *offset = NULL;
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -11945,7 +14031,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -12165,7 +14251,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
} else {
zval *value_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -12547,6 +14633,157 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDL
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
+
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ container = NULL;
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ }
+ zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
+ if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+
+ } else {
+ if (IS_CV == IS_UNUSED) {
+ zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
+ }
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
+
+ zval_dtor(free_op1.var);
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } else {
+ zval *retval;
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ }
+
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *container;
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ /* Behave like FETCH_OBJ_W */
+ zend_free_op free_op1;
+ zval *property;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+ container = NULL;
+
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
+ }
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
+
+ if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ return zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ }
+}
+
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -12685,7 +14922,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -12714,7 +14951,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE
zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -12766,7 +15003,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -12794,6 +15031,151 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLE
}
}
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+ int result;
+ zend_ulong hval;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_ARRAY) {
+ HashTable *ht = Z_ARRVAL_P(container);
+ zval *value;
+ zend_string *str;
+
+isset_again:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CV != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index_prop;
+ }
+ }
+str_index_prop:
+ value = zend_hash_find_ind(ht, str);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_NULL:
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ case IS_FALSE:
+ hval = 0;
+ goto num_index_prop;
+ case IS_TRUE:
+ hval = 1;
+ goto num_index_prop;
+ case IS_RESOURCE:
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ case IS_REFERENCE:
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ value = NULL;
+ break;
+ }
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ /* > IS_NULL means not IS_UNDEF and not IS_NULL */
+ result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = (value == NULL || !i_zend_is_true(value TSRMLS_CC));
+ }
+ } else if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_dimension) {
+ result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else if (Z_TYPE_P(container) == IS_STRING) { /* string offsets */
+ zval tmp;
+
+ result = 0;
+ if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
+ if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_DUP(&tmp, offset);
+ convert_to_long(&tmp);
+ offset = &tmp;
+ }
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
+ if ((opline->extended_value & ZEND_ISSET) ||
+ Z_STRVAL_P(container)[offset->value.lval] != '0') {
+ result = 1;
+ }
+ }
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+ int result;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+
+ if (Z_TYPE_P(container) == IS_OBJECT) {
+ if (Z_OBJ_HT_P(container)->has_property) {
+ result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL) TSRMLS_CC);
+ } else {
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
+ }
+ if ((opline->extended_value & ZEND_ISSET) == 0) {
+ result = !result;
+ }
+ } else {
+ result = ((opline->extended_value & ZEND_ISSET) == 0);
+ }
+
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -12834,7 +15216,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
} else {
zval *value_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -12974,6 +15356,10 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
SAVE_OPLINE();
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
fast_increment_function(var_ptr);
if (RETURN_VALUE_USED(opline)) {
@@ -12982,9 +15368,6 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ZEND_VM_NEXT_OPCODE();
}
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
if (RETURN_VALUE_USED(opline)) {
ZVAL_NULL(EX_VAR(opline->result.var));
@@ -13029,6 +15412,10 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
SAVE_OPLINE();
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
fast_decrement_function(var_ptr);
if (RETURN_VALUE_USED(opline)) {
@@ -13037,9 +15424,6 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ZEND_VM_NEXT_OPCODE();
}
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
if (RETURN_VALUE_USED(opline)) {
ZVAL_NULL(EX_VAR(opline->result.var));
@@ -13084,15 +15468,16 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
SAVE_OPLINE();
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
fast_increment_function(var_ptr);
ZEND_VM_NEXT_OPCODE();
}
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
ZVAL_NULL(EX_VAR(opline->result.var));
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -13138,15 +15523,16 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
SAVE_OPLINE();
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
fast_decrement_function(var_ptr);
ZEND_VM_NEXT_OPCODE();
}
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
ZVAL_NULL(EX_VAR(opline->result.var));
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -13445,7 +15831,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
}
@@ -13542,10 +15928,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
(Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) &&
- ((!Z_REFCOUNTED_P(varptr) && Z_TYPE_P(varptr) != IS_STRING) ||
- Z_ISREF_P(varptr) ||
- Z_TYPE_P(varptr) == IS_OBJECT ||
- (Z_REFCOUNTED_P(varptr) && Z_REFCOUNT_P(varptr) == 1))) {
+ (Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) {
ZVAL_MAKE_REF(varptr);
if (IS_VAR == IS_CV) {
@@ -13578,7 +15961,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
SAVE_OPLINE();
varptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(varptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(varptr == NULL)) {
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
}
@@ -13933,9 +16316,9 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
zend_file_handle file_handle;
char *resolved_path;
- resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+ resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename) TSRMLS_CC);
if (resolved_path) {
- failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, strlen(resolved_path));
+ failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path));
} else {
resolved_path = Z_STRVAL_P(inc_filename);
}
@@ -13948,7 +16331,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
file_handle.opened_path = estrdup(resolved_path);
}
- if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path))) {
+ if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) {
new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
@@ -14013,7 +16396,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
}
destroy_op_array(new_op_array TSRMLS_CC);
- efree(new_op_array);
+ efree_size(new_op_array, sizeof(zend_op_array));
if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
HANDLE_EXCEPTION();
@@ -14043,17 +16426,15 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
ZVAL_DEREF(array_ptr);
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL_NOREF(array_ptr);
+ SEPARATE_ARRAY(array_ptr);
array_ref = array_ptr;
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
ZVAL_NEW_REF(array_ptr, array_ptr);
array_ref = array_ptr;
array_ptr = Z_REFVAL_P(array_ptr);
}
- } else if (Z_IMMUTABLE_P(array_ptr)) {
+ } else if (Z_IMMUTABLE_P(array_ptr) || Z_REFCOUNT_P(array_ptr) > 1) {
zval_copy_ctor(array_ptr);
- } else {
- SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -14064,9 +16445,6 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
ce = Z_OBJCE_P(array_ptr);
if (!ce || ce->get_iterator == NULL) {
- if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL_NOREF(array_ptr);
- }
Z_ADDREF_P(array_ptr);
}
array_ref = array_ptr;
@@ -14113,15 +16491,23 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
ZVAL_DUP(&tmp, array_ref);
array_ptr = array_ref = &tmp;
- } else if (IS_VAR == IS_CV) {
+ } else if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) {
ZVAL_UNREF(array_ref);
array_ptr = array_ref;
}
- if (Z_IMMUTABLE_P(array_ptr)) {
+ if (Z_IMMUTABLE_P(array_ptr) ||
+ (Z_ISREF_P(array_ref) &&
+ Z_REFCOUNTED_P(array_ptr) &&
+ Z_REFCOUNT_P(array_ptr) > 1)) {
+ if (!Z_IMMUTABLE_P(array_ptr)) {
+ Z_DELREF_P(array_ptr);
+ }
zval_copy_ctor(array_ptr);
}
- Z_ADDREF_P(array_ref);
+ if (IS_VAR == IS_CV) {
+ Z_ADDREF_P(array_ref);
+ }
}
}
}
@@ -14171,25 +16557,37 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- zend_hash_internal_pointer_reset(fe_ht);
- if (ce) {
- zend_object *zobj = Z_OBJ_P(array_ptr);
- while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
- zend_string *str_key;
- ulong int_key;
- zend_uchar key_type;
-
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
- if (key_type != HASH_KEY_NON_EXISTENT &&
- (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS)) {
- break;
+ HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
+ HashPosition pos = 0;
+ Bucket *p;
+
+ while (1) {
+ if (pos >= fe_ht->nNumUsed) {
+ is_empty = 1;
+ if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+ if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
}
- zend_hash_move_forward(fe_ht);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ p = fe_ht->arData + pos;
+ if (Z_TYPE(p->val) == IS_UNDEF ||
+ (Z_TYPE(p->val) == IS_INDIRECT &&
+ Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
+ pos++;
+ continue;
+ }
+ if (!ce ||
+ !p->key ||
+ zend_check_property_access(Z_OBJ_P(array_ptr), p->key TSRMLS_CC) == SUCCESS) {
+ break;
}
+ pos++;
}
- is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+2)->op1.var));
+ fe_ht->nInternalPointer = pos;
+ ptr->pos = pos;
+ ptr->ht = fe_ht;
+ ptr->h = fe_ht->arData[pos].h;
+ is_empty = 0;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
@@ -14213,8 +16611,9 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
zval *array, *array_ref;
zval *value;
HashTable *fe_ht;
- zend_object_iterator *iter = NULL;
- zval *key = NULL;
+ HashPointer *ptr;
+ HashPosition pos;
+ Bucket *p;
array = array_ref = EX_VAR(opline->op1.var);
if (Z_ISREF_P(array)) {
@@ -14224,81 +16623,182 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
zval_copy_ctor(array);
}
}
- if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
- key = EX_VAR((opline+1)->result.var);
- }
SAVE_OPLINE();
- switch (zend_iterator_unwrap(array, &iter TSRMLS_CC)) {
- default:
- case ZEND_ITER_INVALID:
- zend_error(E_WARNING, "Invalid argument supplied for foreach()");
+ if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) {
+ fe_ht = Z_ARRVAL_P(array);
+ ptr = (HashPointer*)EX_VAR((opline+1)->op1.var);
+ pos = ptr->pos;
+ if (UNEXPECTED(pos == INVALID_IDX)) {
+ /* reached end of iteration */
ZEND_VM_JMP(opline->op2.jmp_addr);
+ } else if (UNEXPECTED(ptr->ht != fe_ht)) {
+ ptr->ht = fe_ht;
+ pos = 0;
+ } else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) {
+ if (fe_ht->u.flags & HASH_FLAG_PACKED) {
+ pos = ptr->h;
+ } else {
+ pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask];
+ while (pos != INVALID_IDX) {
+ if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) {
+ break;
+ }
+ pos = Z_NEXT(fe_ht->arData[pos].val);
+ }
+ }
+ }
+ while (1) {
+ if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
+ /* reached end of iteration */
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ p = fe_ht->arData + pos;
+ value = &p->val;
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
+ continue;
+ } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
+ value = Z_INDIRECT_P(value);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
+ continue;
+ }
+ }
+ if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ ZVAL_MAKE_REF(value);
+ Z_ADDREF_P(value);
+ ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
+ } else {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
+ if (!p->key) {
+ ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h);
+ } else if (IS_INTERNED(p->key)) {
+ ZVAL_INTERNED_STR(EX_VAR((opline+1)->result.var), p->key);
+ } else {
+ ZVAL_NEW_STR(EX_VAR((opline+1)->result.var), p->key);
+ GC_REFCOUNT(p->key)++;
+ }
+ }
+ break;
+ }
+ do {
+ pos++;
+ if (pos >= fe_ht->nNumUsed) {
+ fe_ht->nInternalPointer = ptr->pos = INVALID_IDX;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ p = fe_ht->arData + pos;
+ } while (Z_TYPE(p->val) == IS_UNDEF ||
+ (Z_TYPE(p->val) == IS_INDIRECT &&
+ Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF));
+ fe_ht->nInternalPointer = ptr->pos = pos;
+ ptr->h = fe_ht->arData[pos].h;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) {
+ zend_object_iterator *iter;
- case ZEND_ITER_PLAIN_OBJECT: {
- zend_object *zobj = Z_OBJ_P(array);
- int key_type;
- zend_string *str_key;
- zend_ulong int_key;
+ if ((iter = zend_iterator_unwrap(array TSRMLS_CC)) == NULL) {
+ /* plain object */
+ zend_object *zobj = Z_OBJ_P(array);
- fe_ht = Z_OBJPROP_P(array);
- zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
+ fe_ht = Z_OBJPROP_P(array);
+ ptr = (HashPointer*)EX_VAR((opline+1)->op1.var);
+ pos = ptr->pos;
+ if (pos == INVALID_IDX) {
+ /* reached end of iteration */
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ } else if (UNEXPECTED(ptr->ht != fe_ht)) {
+ ptr->ht = fe_ht;
+ pos = 0;
+ } else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) {
+ if (fe_ht->u.flags & HASH_FLAG_PACKED) {
+ pos = ptr->h;
+ } else {
+ pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask];
+ while (pos != INVALID_IDX) {
+ if (fe_ht->arData[pos].h == ptr->h && pos == ptr->pos) {
+ break;
+ }
+ pos = Z_NEXT(fe_ht->arData[pos].val);
+ }
+ }
+ }
while (1) {
- if ((value = zend_hash_get_current_data(fe_ht)) == NULL) {
+ if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
/* reached end of iteration */
ZEND_VM_JMP(opline->op2.jmp_addr);
}
- if (Z_TYPE_P(value) == IS_INDIRECT) {
+ p = fe_ht->arData + pos;
+ value = &p->val;
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
+ continue;
+ } else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
value = Z_INDIRECT_P(value);
- if (Z_TYPE_P(value) == IS_UNDEF) {
- zend_hash_move_forward(fe_ht);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ pos++;
continue;
}
}
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
-
- zend_hash_move_forward(fe_ht);
- if (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ if (UNEXPECTED(!p->key)) {
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
+ ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h);
+ }
+ break;
+ } else if (zend_check_property_access(zobj, p->key TSRMLS_CC) == SUCCESS) {
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
+ if (p->key->val[0]) {
+ if (IS_INTERNED(p->key)) {
+ ZVAL_INTERNED_STR(EX_VAR((opline+1)->result.var), p->key);
+ } else {
+ ZVAL_NEW_STR(EX_VAR((opline+1)->result.var), p->key);
+ GC_REFCOUNT(p->key)++;
+ }
+ } else {
+ const char *class_name, *prop_name;
+ size_t prop_name_len;
+ zend_unmangle_property_name_ex(
+ p->key, &class_name, &prop_name, &prop_name_len);
+ ZVAL_STRINGL(EX_VAR((opline+1)->result.var), prop_name, prop_name_len);
+ }
+ }
break;
}
+ pos++;
}
-
- 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->val, str_key->len, &class_name, &prop_name, &prop_name_len
- );
- ZVAL_STRINGL(key, prop_name, prop_name_len);
- }
- }
-
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- break;
- }
-
- case ZEND_ITER_PLAIN_ARRAY:
- fe_ht = Z_ARRVAL_P(array);
- zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- if ((value = zend_hash_get_current_data(fe_ht)) == NULL) {
- /* reached end of iteration */
- ZEND_VM_JMP(opline->op2.jmp_addr);
- }
- if (key) {
- zend_hash_get_current_key_zval(fe_ht, key);
+ if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ ZVAL_MAKE_REF(value);
+ Z_ADDREF_P(value);
+ ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
+ } else {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
}
- zend_hash_move_forward(fe_ht);
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
- break;
-
- case ZEND_ITER_OBJECT:
+ do {
+ pos++;
+ if (pos >= fe_ht->nNumUsed) {
+ fe_ht->nInternalPointer = ptr->pos = INVALID_IDX;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ p = fe_ht->arData + pos;
+ } while (Z_TYPE(p->val) == IS_UNDEF ||
+ (Z_TYPE(p->val) == IS_INDIRECT &&
+ Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) ||
+ (EXPECTED(p->key != NULL) &&
+ zend_check_property_access(zobj, p->key TSRMLS_CC) == FAILURE));
+ fe_ht->nInternalPointer = ptr->pos = pos;
+ ptr->h = fe_ht->arData[pos].h;
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
/* !iter happens from exception */
if (iter && ++iter->index > 0) {
/* This could cause an endless loop if index becomes zero again.
@@ -14327,31 +16827,31 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* failure in get_current_data */
ZEND_VM_JMP(opline->op2.jmp_addr);
}
- if (key) {
+ if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
+ ZVAL_MAKE_REF(value);
+ Z_ADDREF_P(value);
+ ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
+ } else {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
if (iter->funcs->get_current_key) {
- iter->funcs->get_current_key(iter, key TSRMLS_CC);
+ iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var) TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(array_ref);
HANDLE_EXCEPTION();
}
} else {
- ZVAL_LONG(key, iter->index);
+ ZVAL_LONG(EX_VAR((opline+1)->result.var), iter->index);
}
}
- break;
- }
-
- if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
- ZVAL_MAKE_REF(value);
- Z_ADDREF_P(value);
- ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_NEXT_OPCODE();
+ }
} else {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ zend_error(E_WARNING, "Invalid argument supplied for foreach()");
+ ZEND_VM_JMP(opline->op2.jmp_addr);
}
-
- CHECK_EXCEPTION();
- ZEND_VM_INC_OPCODE();
- ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_EXIT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -14381,10 +16881,15 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
USE_OPLINE
zend_free_op free_op1;
zval *value;
+ int is_ref = 0;
SAVE_OPLINE();
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) {
+ is_ref = 1;
+ value = Z_REFVAL_P(value);
+ }
if (i_zend_is_true(value TSRMLS_CC)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
if (IS_VAR == IS_CONST) {
@@ -14393,6 +16898,9 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
} else if (IS_VAR == IS_CV) {
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
+ } else if (IS_VAR == IS_VAR && is_ref) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
+ zval_ptr_dtor_nogc(free_op1.var);
}
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -14402,7 +16910,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zend_free_op free_op1;
@@ -14411,7 +16919,10 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_
SAVE_OPLINE();
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (i_zend_is_true(value TSRMLS_CC)) {
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value));
+ zval_ptr_dtor_nogc(free_op1.var);
+ } else {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
if (IS_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
@@ -14420,50 +16931,6 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_
} else if (IS_VAR == IS_CV) {
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
- ZEND_VM_JMP(opline->op2.jmp_addr);
- }
-
- zval_ptr_dtor_nogc(free_op1.var);
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
- zend_free_op free_op1;
- zval *value;
-
- SAVE_OPLINE();
- value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (IS_VAR == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
- zval_copy_ctor_func(EX_VAR(opline->result.var));
- }
- } else if (IS_VAR == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
- zend_free_op free_op1;
- zval *value;
-
- SAVE_OPLINE();
- value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
-
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (IS_VAR == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
- zval_copy_ctor_func(EX_VAR(opline->result.var));
- }
- } else if (IS_VAR == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
ZEND_VM_NEXT_OPCODE();
}
@@ -14507,15 +16974,17 @@ static int ZEND_FASTCALL ZEND_STRLEN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
zend_string *str = zval_get_string(value);
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- STR_RELEASE(str);
+ zend_string_release(str);
} else if (Z_TYPE_P(value) == IS_OBJECT) {
zend_string *str;
+ zval tmp;
- if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) {
+ ZVAL_COPY(&tmp, value);
+ if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) {
goto strlen_error;
}
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- STR_RELEASE(str);
+ zval_dtor(&tmp);
} else {
strlen_error:
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
@@ -14570,8 +17039,8 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A
} else {
ZVAL_FALSE(EX_VAR(opline->result.var));
}
+ break;
EMPTY_SWITCH_DEFAULT_CASE()
-
}
zval_ptr_dtor_nogc(free_op1.var);
CHECK_EXCEPTION();
@@ -14862,7 +17331,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b
zval *value;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -14956,7 +17425,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
@@ -14971,7 +17440,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -15023,7 +17492,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar
value = opline->op2.zv;
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -15218,7 +17687,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t
property = opline->op2.zv;
retval = EX_VAR(opline->result.var);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -15309,7 +17778,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_
property = opline->op2.zv;
retval = EX_VAR(opline->result.var);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -15398,7 +17867,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -15413,7 +17882,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
zval_ptr_dtor_nogc(free_op1.var);
CHECK_EXCEPTION();
@@ -15436,8 +17905,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -15457,8 +17925,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -15480,7 +17947,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
}
if (IS_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -15561,7 +18028,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (EXPECTED(opline->extended_value == 0)) {
@@ -15570,7 +18037,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA
zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -15587,12 +18054,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -15624,12 +18091,15 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -15656,12 +18126,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -15717,13 +18187,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA
property = opline->op2.zv;
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -15742,12 +18212,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H
property = opline->op2.zv;
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -15800,12 +18270,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP
property = opline->op2.zv;
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -15826,12 +18299,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
property = opline->op2.zv;
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -15850,7 +18323,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
property_name = opline->op2.zv;
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -15871,7 +18344,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
SAVE_OPLINE();
object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
@@ -15889,34 +18362,30 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
zval *dim = opline->op2.zv;
zval *variable_ptr;
- zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC);
+ variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC);
- value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
- if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
- if (IS_TMP_FREE(free_op_data1)) {
- zval_dtor(value);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- FREE_OP_VAR_PTR(free_op_data2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ if (UNEXPECTED(variable_ptr != NULL)) {
+ zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
} else {
- if ((opline+1)->op1_type == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if ((opline+1)->op1_type == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
+ variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
} else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_IF_VAR(free_op_data1);
+ FREE_OP_IF_VAR(free_op_data1);
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
/* assign_dim has two opcodes! */
@@ -15936,9 +18405,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER
value = opline->op2.zv;
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, IS_CONST, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
if (0) {
zval_dtor(value);
}
@@ -15946,13 +18413,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- if (IS_CONST == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if (IS_CONST == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
- } else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
+ value = zend_assign_to_variable(variable_ptr, value, IS_CONST TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
@@ -16254,7 +18715,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
} else if (Z_STRLEN_P(opline->op2.zv) == sizeof("class")-1 && memcmp(Z_STRVAL_P(opline->op2.zv), "class", sizeof("class") - 1) == 0) {
/* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
ZVAL_STR(EX_VAR(opline->result.var), ce->name);
- STR_ADDREF(ce->name);
+ zend_string_addref(ce->name);
} else {
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
@@ -16274,7 +18735,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -16303,7 +18764,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC
zval *offset = opline->op2.zv;
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -16355,7 +18816,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -16461,10 +18922,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
zend_free_op free_op1;
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_VAR != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -16543,7 +19007,6 @@ numeric_index_dim:
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -16564,7 +19027,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = opline->op2.zv;
@@ -16669,7 +19132,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CONST_HANDLER(ZEND
zend_free_op free_op1;
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -16756,7 +19219,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -16848,7 +19311,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_
} else {
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -17243,7 +19706,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin
zval *value;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -17338,7 +19801,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
@@ -17353,7 +19816,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -17405,7 +19868,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_
value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -17600,7 +20063,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -17692,7 +20155,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -17792,7 +20255,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (EXPECTED(opline->extended_value == 0)) {
@@ -17801,7 +20264,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND
zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
}
zval_dtor(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -17818,12 +20281,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -17855,12 +20318,15 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
zval_dtor(free_op2.var);
@@ -17887,12 +20353,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -17949,13 +20415,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -17974,12 +20440,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -18033,12 +20499,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -18059,12 +20528,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -18083,7 +20552,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -18104,7 +20573,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
SAVE_OPLINE();
object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
@@ -18122,35 +20591,30 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zval *variable_ptr;
- zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC);
+ variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC);
zval_dtor(free_op2.var);
-
- value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
- if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
- if (IS_TMP_FREE(free_op_data1)) {
- zval_dtor(value);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- FREE_OP_VAR_PTR(free_op_data2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ if (UNEXPECTED(variable_ptr != NULL)) {
+ zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
} else {
- if ((opline+1)->op1_type == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if ((opline+1)->op1_type == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
+ variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
} else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_IF_VAR(free_op_data1);
+ FREE_OP_IF_VAR(free_op_data1);
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
/* assign_dim has two opcodes! */
@@ -18170,9 +20634,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A
value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, IS_TMP_VAR, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
if (1) {
zval_dtor(value);
}
@@ -18180,13 +20642,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- if (IS_TMP_VAR == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if (IS_TMP_VAR == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
- } else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
+ value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
@@ -18413,7 +20869,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -18442,7 +20898,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD
zend_free_op free_op2;
zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -18494,7 +20950,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -18528,10 +20984,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE
zend_free_op free_op1, free_op2;
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_VAR != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -18610,7 +21069,6 @@ numeric_index_dim:
zval_dtor(free_op2.var);
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -18631,7 +21089,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
@@ -18656,7 +21114,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_O
zend_free_op free_op1, free_op2;
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -18743,7 +21201,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -18837,7 +21295,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
} else {
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -19232,7 +21690,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin
zval *value;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -19327,7 +21785,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
@@ -19342,7 +21800,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -19394,7 +21852,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_
value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -19589,7 +22047,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -19681,7 +22139,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -19771,7 +22229,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -19786,7 +22244,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
zval_ptr_dtor_nogc(free_op1.var);
CHECK_EXCEPTION();
@@ -19809,8 +22267,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -19830,8 +22287,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -19853,7 +22309,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
}
if (IS_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -19934,7 +22390,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (EXPECTED(opline->extended_value == 0)) {
@@ -19943,7 +22399,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND
zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
}
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -19960,12 +22416,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -19997,12 +22453,15 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
zval_ptr_dtor_nogc(free_op2.var);
@@ -20029,12 +22488,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -20091,13 +22550,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -20116,12 +22575,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -20175,12 +22634,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -20201,12 +22663,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -20225,7 +22687,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -20246,7 +22708,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
SAVE_OPLINE();
object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
@@ -20264,35 +22726,30 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zval *variable_ptr;
- zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC);
+ variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
-
- value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
- if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
- if (IS_TMP_FREE(free_op_data1)) {
- zval_dtor(value);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- FREE_OP_VAR_PTR(free_op_data2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ if (UNEXPECTED(variable_ptr != NULL)) {
+ zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
} else {
- if ((opline+1)->op1_type == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if ((opline+1)->op1_type == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
+ variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
} else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_IF_VAR(free_op_data1);
+ FREE_OP_IF_VAR(free_op_data1);
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
/* assign_dim has two opcodes! */
@@ -20309,12 +22766,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A
zval *variable_ptr;
SAVE_OPLINE();
- value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+ value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, IS_VAR, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
if (0) {
zval_dtor(value);
}
@@ -20322,13 +22777,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- if (IS_VAR == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if (IS_VAR == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
- } else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
+ value = zend_assign_to_variable(variable_ptr, value, IS_VAR TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
@@ -20377,8 +22826,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
UNEXPECTED(!Z_ISREF_P(variable_ptr))) {
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
}
- if ((IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) ||
- (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET))) {
+ if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) ||
+ (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL))) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
}
if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) ||
@@ -20619,7 +23068,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -20648,7 +23097,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
zend_free_op free_op2;
zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -20700,7 +23149,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -20806,10 +23255,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
zend_free_op free_op1, free_op2;
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_VAR != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -20888,7 +23340,6 @@ numeric_index_dim:
zval_ptr_dtor_nogc(free_op2.var);
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -20909,7 +23360,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
@@ -21014,7 +23465,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_O
zend_free_op free_op1, free_op2;
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -21101,7 +23552,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -21195,7 +23646,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
} else {
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -21315,7 +23766,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*
zval *value;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -21409,7 +23860,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (*
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
@@ -21424,7 +23875,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (*
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -21476,7 +23927,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina
value = NULL;
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -21673,7 +24124,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -21688,7 +24139,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
zval_ptr_dtor_nogc(free_op1.var);
CHECK_EXCEPTION();
@@ -21711,8 +24162,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -21732,8 +24182,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -21755,7 +24204,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
}
if (IS_VAR != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -21819,7 +24268,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_H
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (EXPECTED(opline->extended_value == 0)) {
@@ -21828,7 +24277,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_H
zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -21845,12 +24294,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -21867,12 +24316,15 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -21899,7 +24351,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
SAVE_OPLINE();
object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
@@ -21917,34 +24369,30 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
zval *dim = NULL;
zval *variable_ptr;
- zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC);
+ variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC);
- value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
- if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
- if (IS_TMP_FREE(free_op_data1)) {
- zval_dtor(value);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- FREE_OP_VAR_PTR(free_op_data2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ if (UNEXPECTED(variable_ptr != NULL)) {
+ zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
} else {
- if ((opline+1)->op1_type == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if ((opline+1)->op1_type == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
+ variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
} else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_IF_VAR(free_op_data1);
+ FREE_OP_IF_VAR(free_op_data1);
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
/* assign_dim has two opcodes! */
@@ -22079,7 +24527,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -22108,7 +24556,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
zval *offset = NULL;
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -22160,7 +24608,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -22398,7 +24846,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
} else {
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -22778,7 +25226,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina
zval *value;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -22872,7 +25320,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
@@ -22887,7 +25335,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -22939,7 +25387,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -23134,7 +25582,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -23225,7 +25673,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -23324,7 +25772,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (EXPECTED(opline->extended_value == 0)) {
@@ -23333,7 +25781,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL
zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -23350,12 +25798,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -23387,12 +25835,15 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -23419,12 +25870,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -23480,13 +25931,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -23505,12 +25956,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -23563,12 +26014,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -23589,12 +26043,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -23613,7 +26067,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -23634,7 +26088,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
SAVE_OPLINE();
object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
@@ -23652,34 +26106,30 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
zval *variable_ptr;
- zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC);
+ variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC);
- value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
- if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
- if (IS_TMP_FREE(free_op_data1)) {
- zval_dtor(value);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- FREE_OP_VAR_PTR(free_op_data2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ if (UNEXPECTED(variable_ptr != NULL)) {
+ zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
} else {
- if ((opline+1)->op1_type == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if ((opline+1)->op1_type == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
+ variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
} else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_IF_VAR(free_op_data1);
+ FREE_OP_IF_VAR(free_op_data1);
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
/* assign_dim has two opcodes! */
@@ -23696,12 +26146,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR
zval *variable_ptr;
SAVE_OPLINE();
- value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+ value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, IS_CV, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
if (0) {
zval_dtor(value);
}
@@ -23709,13 +26157,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- if (IS_CV == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if (IS_CV == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
- } else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
+ value = zend_assign_to_variable(variable_ptr, value, IS_CV TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
@@ -23763,8 +26205,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
UNEXPECTED(!Z_ISREF_P(variable_ptr))) {
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
}
- if ((IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) ||
- (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET))) {
+ if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) ||
+ (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL))) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
}
if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) ||
@@ -24002,7 +26444,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -24031,7 +26473,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE
zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -24083,7 +26525,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -24117,10 +26559,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER
zend_free_op free_op1;
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_VAR != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -24199,7 +26644,6 @@ numeric_index_dim:
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -24220,7 +26664,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
@@ -24245,7 +26689,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OP
zend_free_op free_op1;
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -24332,7 +26776,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -24424,7 +26868,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
} else {
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -24624,7 +27068,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int
zval *value;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -24717,7 +27161,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_UNUSED == IS_VAR && !0) {
@@ -24732,7 +27176,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -24784,7 +27228,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi
value = opline->op2.zv;
var_ptr = NULL;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -24979,7 +27423,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde
property = opline->op2.zv;
retval = EX_VAR(opline->result.var);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -25070,7 +27514,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd
property = opline->op2.zv;
retval = EX_VAR(opline->result.var);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -25191,13 +27635,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE
property = opline->op2.zv;
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -25216,12 +27660,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD
property = opline->op2.zv;
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -25274,12 +27718,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND
property = opline->op2.zv;
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -25300,12 +27747,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OP
container = _get_obj_zval_ptr_unused(TSRMLS_C);
property = opline->op2.zv;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -25324,7 +27771,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_
object = _get_obj_zval_ptr_unused(TSRMLS_C);
property_name = opline->op2.zv;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -25531,7 +27978,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
} else if (Z_STRLEN_P(opline->op2.zv) == sizeof("class")-1 && memcmp(Z_STRVAL_P(opline->op2.zv), "class", sizeof("class") - 1) == 0) {
/* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
ZVAL_STR(EX_VAR(opline->result.var), ce->name);
- STR_ADDREF(ce->name);
+ zend_string_addref(ce->name);
} else {
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
@@ -25544,7 +27991,7 @@ constant_fetch_end:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -25578,10 +28025,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_UNUSED != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -25660,7 +28110,6 @@ numeric_index_dim:
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -25681,7 +28130,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = opline->op2.zv;
@@ -25706,7 +28155,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CONST_HANDLER(Z
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -25793,7 +28242,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -25885,7 +28334,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL
} else {
zval *value_ptr = NULL;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -25989,7 +28438,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*
zval *value;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -26083,7 +28532,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (*
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_UNUSED == IS_VAR && !0) {
@@ -26098,7 +28547,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (*
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -26150,7 +28599,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina
value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
var_ptr = NULL;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -26345,7 +28794,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -26437,7 +28886,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -26560,13 +29009,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -26585,12 +29034,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -26644,12 +29093,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -26670,12 +29122,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCO
container = _get_obj_zval_ptr_unused(TSRMLS_C);
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -26694,7 +29146,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA
object = _get_obj_zval_ptr_unused(TSRMLS_C);
property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -26824,7 +29276,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -26858,10 +29310,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN
zend_free_op free_op2;
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_UNUSED != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -26940,7 +29395,6 @@ numeric_index_dim:
zval_dtor(free_op2.var);
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -26961,7 +29415,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
@@ -26986,7 +29440,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEN
zend_free_op free_op2;
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -27073,7 +29527,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -27167,7 +29621,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER
} else {
zval *value_ptr = NULL;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -27271,7 +29725,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*
zval *value;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -27365,7 +29819,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (*
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_UNUSED == IS_VAR && !0) {
@@ -27380,7 +29834,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (*
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -27432,7 +29886,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina
value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
var_ptr = NULL;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -27627,7 +30081,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -27719,7 +30173,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -27842,13 +30296,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_H
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -27867,12 +30321,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -27926,12 +30380,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_O
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -27952,12 +30409,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCO
container = _get_obj_zval_ptr_unused(TSRMLS_C);
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -27976,7 +30433,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA
object = _get_obj_zval_ptr_unused(TSRMLS_C);
property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -28106,7 +30563,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -28140,10 +30597,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN
zend_free_op free_op2;
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_UNUSED != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -28222,7 +30682,6 @@ numeric_index_dim:
zval_ptr_dtor_nogc(free_op2.var);
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -28243,7 +30702,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
@@ -28268,7 +30727,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEN
zend_free_op free_op2;
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -28355,7 +30814,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -28449,7 +30908,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER
} else {
zval *value_ptr = NULL;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -28553,7 +31012,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int
zval *value;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -28646,7 +31105,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_UNUSED == IS_VAR && !0) {
@@ -28661,7 +31120,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -28713,7 +31172,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b
value = NULL;
var_ptr = NULL;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -28897,7 +31356,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPC
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -28965,7 +31424,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND
} else {
zval *value_ptr = NULL;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -29069,7 +31528,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b
zval *value;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -29162,7 +31621,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_UNUSED == IS_VAR && !0) {
@@ -29177,7 +31636,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -29229,7 +31688,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
var_ptr = NULL;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -29424,7 +31883,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -29515,7 +31974,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -29636,13 +32095,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -29661,12 +32120,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -29719,12 +32178,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -29745,12 +32207,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCOD
container = _get_obj_zval_ptr_unused(TSRMLS_C);
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -29769,7 +32231,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN
object = _get_obj_zval_ptr_unused(TSRMLS_C);
property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -29897,7 +32359,7 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -29931,10 +32393,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_UNUSED != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -30013,7 +32478,6 @@ numeric_index_dim:
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -30034,7 +32498,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
@@ -30059,7 +32523,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -30146,7 +32610,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -30238,7 +32702,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_
} else {
zval *value_ptr = NULL;
- if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -30368,6 +32832,10 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
SAVE_OPLINE();
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
fast_increment_function(var_ptr);
if (RETURN_VALUE_USED(opline)) {
@@ -30376,9 +32844,6 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
if (RETURN_VALUE_USED(opline)) {
ZVAL_NULL(EX_VAR(opline->result.var));
@@ -30422,6 +32887,10 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
SAVE_OPLINE();
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
fast_decrement_function(var_ptr);
if (RETURN_VALUE_USED(opline)) {
@@ -30430,9 +32899,6 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
if (RETURN_VALUE_USED(opline)) {
ZVAL_NULL(EX_VAR(opline->result.var));
@@ -30476,15 +32942,16 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
SAVE_OPLINE();
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
fast_increment_function(var_ptr);
ZEND_VM_NEXT_OPCODE();
}
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
ZVAL_NULL(EX_VAR(opline->result.var));
@@ -30529,15 +32996,16 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
SAVE_OPLINE();
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
+ }
+
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
fast_decrement_function(var_ptr);
ZEND_VM_NEXT_OPCODE();
}
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
- zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- }
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
ZVAL_NULL(EX_VAR(opline->result.var));
@@ -30820,7 +33288,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
retval_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
}
@@ -30916,10 +33384,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
(Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) &&
- ((!Z_REFCOUNTED_P(varptr) && Z_TYPE_P(varptr) != IS_STRING) ||
- Z_ISREF_P(varptr) ||
- Z_TYPE_P(varptr) == IS_OBJECT ||
- (Z_REFCOUNTED_P(varptr) && Z_REFCOUNT_P(varptr) == 1))) {
+ (Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) {
ZVAL_MAKE_REF(varptr);
if (IS_CV == IS_CV) {
@@ -30952,7 +33417,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
SAVE_OPLINE();
varptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(varptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(varptr == NULL)) {
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
}
@@ -31291,9 +33756,9 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
zend_file_handle file_handle;
char *resolved_path;
- resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+ resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename) TSRMLS_CC);
if (resolved_path) {
- failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, strlen(resolved_path));
+ failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path));
} else {
resolved_path = Z_STRVAL_P(inc_filename);
}
@@ -31306,7 +33771,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
file_handle.opened_path = estrdup(resolved_path);
}
- if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path))) {
+ if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) {
new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
@@ -31371,7 +33836,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
}
destroy_op_array(new_op_array TSRMLS_CC);
- efree(new_op_array);
+ efree_size(new_op_array, sizeof(zend_op_array));
if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
HANDLE_EXCEPTION();
@@ -31401,17 +33866,15 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ZVAL_DEREF(array_ptr);
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL_NOREF(array_ptr);
+ SEPARATE_ARRAY(array_ptr);
array_ref = array_ptr;
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
ZVAL_NEW_REF(array_ptr, array_ptr);
array_ref = array_ptr;
array_ptr = Z_REFVAL_P(array_ptr);
}
- } else if (Z_IMMUTABLE_P(array_ptr)) {
+ } else if (Z_IMMUTABLE_P(array_ptr) || Z_REFCOUNT_P(array_ptr) > 1) {
zval_copy_ctor(array_ptr);
- } else {
- SEPARATE_ZVAL_NOREF(array_ptr);
}
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
@@ -31422,9 +33885,6 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ce = Z_OBJCE_P(array_ptr);
if (!ce || ce->get_iterator == NULL) {
- if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL_NOREF(array_ptr);
- }
Z_ADDREF_P(array_ptr);
}
array_ref = array_ptr;
@@ -31471,15 +33931,23 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
ZVAL_DUP(&tmp, array_ref);
array_ptr = array_ref = &tmp;
- } else if (IS_CV == IS_CV) {
+ } else if (IS_CV == IS_CV || IS_CV == IS_VAR) {
if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) {
ZVAL_UNREF(array_ref);
array_ptr = array_ref;
}
- if (Z_IMMUTABLE_P(array_ptr)) {
+ if (Z_IMMUTABLE_P(array_ptr) ||
+ (Z_ISREF_P(array_ref) &&
+ Z_REFCOUNTED_P(array_ptr) &&
+ Z_REFCOUNT_P(array_ptr) > 1)) {
+ if (!Z_IMMUTABLE_P(array_ptr)) {
+ Z_DELREF_P(array_ptr);
+ }
zval_copy_ctor(array_ptr);
}
- Z_ADDREF_P(array_ref);
+ if (IS_CV == IS_CV) {
+ Z_ADDREF_P(array_ref);
+ }
}
}
}
@@ -31529,25 +33997,37 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
- zend_hash_internal_pointer_reset(fe_ht);
- if (ce) {
- zend_object *zobj = Z_OBJ_P(array_ptr);
- while (zend_hash_has_more_elements(fe_ht) == SUCCESS) {
- zend_string *str_key;
- ulong int_key;
- zend_uchar key_type;
-
- key_type = zend_hash_get_current_key(fe_ht, &str_key, &int_key, 0);
- if (key_type != HASH_KEY_NON_EXISTENT &&
- (key_type == HASH_KEY_IS_LONG ||
- zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS)) {
- break;
+ HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
+ HashPosition pos = 0;
+ Bucket *p;
+
+ while (1) {
+ if (pos >= fe_ht->nNumUsed) {
+ is_empty = 1;
+ if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+
}
- zend_hash_move_forward(fe_ht);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+ p = fe_ht->arData + pos;
+ if (Z_TYPE(p->val) == IS_UNDEF ||
+ (Z_TYPE(p->val) == IS_INDIRECT &&
+ Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
+ pos++;
+ continue;
+ }
+ if (!ce ||
+ !p->key ||
+ zend_check_property_access(Z_OBJ_P(array_ptr), p->key TSRMLS_CC) == SUCCESS) {
+ break;
}
+ pos++;
}
- is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, (HashPointer*)EX_VAR((opline+2)->op1.var));
+ fe_ht->nInternalPointer = pos;
+ ptr->pos = pos;
+ ptr->ht = fe_ht;
+ ptr->h = fe_ht->arData[pos].h;
+ is_empty = 0;
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
@@ -31591,10 +34071,15 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
USE_OPLINE
zval *value;
+ int is_ref = 0;
SAVE_OPLINE();
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) {
+ is_ref = 1;
+ value = Z_REFVAL_P(value);
+ }
if (i_zend_is_true(value TSRMLS_CC)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
if (IS_CV == IS_CONST) {
@@ -31603,6 +34088,9 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
} else if (IS_CV == IS_CV) {
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
+ } else if (IS_CV == IS_VAR && is_ref) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
+
}
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -31611,7 +34099,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -31620,7 +34108,10 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A
SAVE_OPLINE();
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
- if (i_zend_is_true(value TSRMLS_CC)) {
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value));
+
+ } else {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
if (IS_CV == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
@@ -31629,49 +34120,6 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A
} else if (IS_CV == IS_CV) {
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
- ZEND_VM_JMP(opline->op2.jmp_addr);
- }
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
-
- zval *value;
-
- SAVE_OPLINE();
- value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
-
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (IS_CV == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
- zval_copy_ctor_func(EX_VAR(opline->result.var));
- }
- } else if (IS_CV == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
-
- zval *value;
-
- SAVE_OPLINE();
- value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
-
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (IS_CV == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
- zval_copy_ctor_func(EX_VAR(opline->result.var));
- }
- } else if (IS_CV == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
ZEND_VM_NEXT_OPCODE();
}
@@ -31715,15 +34163,17 @@ static int ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
zend_string *str = zval_get_string(value);
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- STR_RELEASE(str);
+ zend_string_release(str);
} else if (Z_TYPE_P(value) == IS_OBJECT) {
zend_string *str;
+ zval tmp;
- if (parse_arg_object_to_str(value, &str, IS_STRING TSRMLS_CC) == FAILURE) {
+ ZVAL_COPY(&tmp, value);
+ if (parse_arg_object_to_str(&tmp, &str, IS_STRING TSRMLS_CC) == FAILURE) {
goto strlen_error;
}
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- STR_RELEASE(str);
+ zval_dtor(&tmp);
} else {
strlen_error:
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
@@ -31778,8 +34228,8 @@ static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR
} else {
ZVAL_FALSE(EX_VAR(opline->result.var));
}
+ break;
EMPTY_SWITCH_DEFAULT_CASE()
-
}
CHECK_EXCEPTION();
@@ -32070,7 +34520,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi
zval *value;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -32163,7 +34613,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_CV == IS_VAR && !0) {
@@ -32178,7 +34628,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -32230,7 +34680,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary
value = opline->op2.zv;
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -32425,7 +34875,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t
property = opline->op2.zv;
retval = EX_VAR(opline->result.var);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -32516,7 +34966,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t
property = opline->op2.zv;
retval = EX_VAR(opline->result.var);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -32605,7 +35055,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -32620,7 +35070,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_CV != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
CHECK_EXCEPTION();
@@ -32643,8 +35093,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -32664,8 +35113,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -32687,7 +35135,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
}
if (IS_CV != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -32768,7 +35216,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (EXPECTED(opline->extended_value == 0)) {
@@ -32777,7 +35225,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN
zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
}
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -32794,12 +35242,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -32831,12 +35279,15 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -32863,12 +35314,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -32924,13 +35375,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN
property = opline->op2.zv;
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -32949,12 +35400,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA
property = opline->op2.zv;
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -33007,12 +35458,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC
property = opline->op2.zv;
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -33033,12 +35487,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
property = opline->op2.zv;
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -33057,7 +35511,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
property_name = opline->op2.zv;
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -33078,7 +35532,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
SAVE_OPLINE();
object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
@@ -33096,34 +35550,30 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
zval *dim = opline->op2.zv;
zval *variable_ptr;
- zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC);
+ variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC);
- value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
- if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
- if (IS_TMP_FREE(free_op_data1)) {
- zval_dtor(value);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- FREE_OP_VAR_PTR(free_op_data2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ if (UNEXPECTED(variable_ptr != NULL)) {
+ zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
} else {
- if ((opline+1)->op1_type == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if ((opline+1)->op1_type == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
+ variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
} else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_IF_VAR(free_op_data1);
+ FREE_OP_IF_VAR(free_op_data1);
}
/* assign_dim has two opcodes! */
@@ -33143,9 +35593,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_
value = opline->op2.zv;
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, IS_CONST, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
if (0) {
zval_dtor(value);
}
@@ -33153,13 +35601,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- if (IS_CONST == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if (IS_CONST == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
- } else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
+ value = zend_assign_to_variable(variable_ptr, value, IS_CONST TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
@@ -33267,7 +35709,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -33296,7 +35738,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO
zval *offset = opline->op2.zv;
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -33348,7 +35790,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -33454,10 +35896,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_CV != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -33536,7 +35981,6 @@ numeric_index_dim:
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -33557,7 +36001,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = opline->op2.zv;
@@ -33662,7 +36106,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -33749,7 +36193,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -33841,7 +36285,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
} else {
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -34265,7 +36709,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina
zval *value;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -34359,7 +36803,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_CV == IS_VAR && !0) {
@@ -34374,7 +36818,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -34426,7 +36870,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o
value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -34621,7 +37065,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -34713,7 +37157,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -34813,7 +37257,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (EXPECTED(opline->extended_value == 0)) {
@@ -34822,7 +37266,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL
zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
}
zval_dtor(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -34839,12 +37283,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -34876,12 +37320,15 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
zval_dtor(free_op2.var);
@@ -34908,12 +37355,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -34970,13 +37417,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -34995,12 +37442,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -35054,12 +37501,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -35080,12 +37530,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -35104,7 +37554,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -35125,7 +37575,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
SAVE_OPLINE();
object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
@@ -35143,35 +37593,30 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zval *variable_ptr;
- zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC);
+ variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC);
zval_dtor(free_op2.var);
-
- value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
- if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
- if (IS_TMP_FREE(free_op_data1)) {
- zval_dtor(value);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- FREE_OP_VAR_PTR(free_op_data2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ if (UNEXPECTED(variable_ptr != NULL)) {
+ zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
} else {
- if ((opline+1)->op1_type == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if ((opline+1)->op1_type == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
+ variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
} else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_IF_VAR(free_op_data1);
+ FREE_OP_IF_VAR(free_op_data1);
}
/* assign_dim has two opcodes! */
@@ -35191,9 +37636,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, IS_TMP_VAR, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
if (1) {
zval_dtor(value);
}
@@ -35201,13 +37644,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- if (IS_TMP_VAR == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if (IS_TMP_VAR == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
- } else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
+ value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
@@ -35317,7 +37754,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -35346,7 +37783,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE
zend_free_op free_op2;
zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -35398,7 +37835,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -35432,10 +37869,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER
zend_free_op free_op2;
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_CV != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -35514,7 +37954,6 @@ numeric_index_dim:
zval_dtor(free_op2.var);
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -35535,7 +37974,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
@@ -35560,7 +37999,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OP
zend_free_op free_op2;
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -35647,7 +38086,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -35741,7 +38180,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
} else {
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -36135,7 +38574,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina
zval *value;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -36229,7 +38668,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_CV == IS_VAR && !0) {
@@ -36244,7 +38683,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -36296,7 +38735,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o
value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -36491,7 +38930,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -36583,7 +39022,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -36673,7 +39112,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -36688,7 +39127,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_CV != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
CHECK_EXCEPTION();
@@ -36711,8 +39150,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -36732,8 +39170,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -36755,7 +39192,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
}
if (IS_CV != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -36836,7 +39273,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (EXPECTED(opline->extended_value == 0)) {
@@ -36845,7 +39282,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL
zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
}
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -36862,12 +39299,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -36899,12 +39336,15 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
zval_ptr_dtor_nogc(free_op2.var);
@@ -36931,12 +39371,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -36993,13 +39433,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -37018,12 +39458,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -37077,12 +39517,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -37103,12 +39546,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -37127,7 +39570,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -37148,7 +39591,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
SAVE_OPLINE();
object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
@@ -37166,35 +39609,30 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zval *variable_ptr;
- zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC);
+ variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
-
- value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
- if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
- if (IS_TMP_FREE(free_op_data1)) {
- zval_dtor(value);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- FREE_OP_VAR_PTR(free_op_data2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ if (UNEXPECTED(variable_ptr != NULL)) {
+ zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
} else {
- if ((opline+1)->op1_type == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if ((opline+1)->op1_type == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
+ variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
} else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_IF_VAR(free_op_data1);
+ FREE_OP_IF_VAR(free_op_data1);
}
/* assign_dim has two opcodes! */
@@ -37211,12 +39649,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
zval *variable_ptr;
SAVE_OPLINE();
- value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+ value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, IS_VAR, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
if (0) {
zval_dtor(value);
}
@@ -37224,13 +39660,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- if (IS_VAR == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if (IS_VAR == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
- } else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
+ value = zend_assign_to_variable(variable_ptr, value, IS_VAR TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
@@ -37279,8 +39709,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
UNEXPECTED(!Z_ISREF_P(variable_ptr))) {
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
}
- if ((IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) ||
- (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET))) {
+ if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) ||
+ (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL))) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
}
if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) ||
@@ -37403,7 +39833,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -37432,7 +39862,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
zend_free_op free_op2;
zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -37484,7 +39914,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -37590,10 +40020,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
zend_free_op free_op2;
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_CV != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -37672,7 +40105,6 @@ numeric_index_dim:
zval_ptr_dtor_nogc(free_op2.var);
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -37693,7 +40125,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
@@ -37798,7 +40230,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OP
zend_free_op free_op2;
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -37885,7 +40317,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -37979,7 +40411,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
} else {
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -38098,7 +40530,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b
zval *value;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -38191,7 +40623,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_CV == IS_VAR && !0) {
@@ -38206,7 +40638,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -38258,7 +40690,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar
value = NULL;
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -38455,7 +40887,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
name = Z_STR_P(varname);
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
name = Z_STR_P(varname);
- STR_ADDREF(name);
+ zend_string_addref(name);
} else {
name = zval_get_string(varname);
}
@@ -38470,7 +40902,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
if (IS_CV != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
CHECK_EXCEPTION();
@@ -38493,8 +40925,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -38514,8 +40945,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
/* break missing intentionally */
case BP_VAR_IS:
- retval = EX_VAR(opline->result.var);
- ZVAL_NULL(retval);
+ retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
@@ -38537,7 +40967,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
}
if (IS_CV != IS_CONST) {
- STR_RELEASE(name);
+ zend_string_release(name);
}
ZEND_ASSERT(retval != NULL);
@@ -38601,7 +41031,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HA
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (EXPECTED(opline->extended_value == 0)) {
@@ -38610,7 +41040,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HA
zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
}
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -38627,12 +41057,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_H
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -38649,12 +41079,15 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -38681,7 +41114,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
SAVE_OPLINE();
object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
@@ -38699,34 +41132,30 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
zval *dim = NULL;
zval *variable_ptr;
- zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC);
+ variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC);
- value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
- if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
- if (IS_TMP_FREE(free_op_data1)) {
- zval_dtor(value);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- FREE_OP_VAR_PTR(free_op_data2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ if (UNEXPECTED(variable_ptr != NULL)) {
+ zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
} else {
- if ((opline+1)->op1_type == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if ((opline+1)->op1_type == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
+ variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
} else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_IF_VAR(free_op_data1);
+ FREE_OP_IF_VAR(free_op_data1);
}
/* assign_dim has two opcodes! */
@@ -38745,7 +41174,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -38774,7 +41203,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
zval *offset = NULL;
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -38826,7 +41255,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -39046,7 +41475,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_
} else {
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -39425,7 +41854,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar
zval *value;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
@@ -39518,7 +41947,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (IS_CV == IS_VAR && !0) {
@@ -39533,7 +41962,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar
var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
}
- if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -39585,7 +42014,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -39780,7 +42209,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -39871,7 +42300,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
retval = EX_VAR(opline->result.var);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
@@ -39970,7 +42399,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (EXPECTED(opline->extended_value == 0)) {
@@ -39979,7 +42408,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE
zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
}
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -39996,12 +42425,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -40033,12 +42462,15 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE
SAVE_OPLINE();
if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) {
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -40065,12 +42497,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -40126,13 +42558,13 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -40151,12 +42583,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -40209,12 +42641,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
+ }
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -40235,12 +42670,12 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
@@ -40259,7 +42694,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
@@ -40280,7 +42715,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
SAVE_OPLINE();
object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
@@ -40298,34 +42733,30 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
zval *variable_ptr;
- zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC);
+ variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC);
- value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
- if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
- if (IS_TMP_FREE(free_op_data1)) {
- zval_dtor(value);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- FREE_OP_VAR_PTR(free_op_data2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ if (UNEXPECTED(variable_ptr != NULL)) {
+ zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
} else {
- if ((opline+1)->op1_type == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if ((opline+1)->op1_type == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
+ variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
} else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+ }
+ FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_VAR_PTR(free_op_data2);
}
- FREE_OP_IF_VAR(free_op_data1);
+ FREE_OP_IF_VAR(free_op_data1);
}
/* assign_dim has two opcodes! */
@@ -40342,12 +42773,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
zval *variable_ptr;
SAVE_OPLINE();
- value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+ value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
- zend_assign_to_string_offset(variable_ptr, value, IS_CV, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
- } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
+ if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
if (0) {
zval_dtor(value);
}
@@ -40355,13 +42784,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- if (IS_CV == IS_TMP_VAR) {
- value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC);
- } else if (IS_CV == IS_CONST) {
- value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC);
- } else {
- value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC);
- }
+ value = zend_assign_to_variable(variable_ptr, value, IS_CV TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
@@ -40409,8 +42832,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
UNEXPECTED(!Z_ISREF_P(variable_ptr))) {
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
}
- if ((IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) ||
- (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET))) {
+ if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) ||
+ (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL))) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
}
if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) ||
@@ -40530,7 +42953,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
ZVAL_MAKE_REF(expr_ptr);
@@ -40559,7 +42982,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_
zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
zend_string *str;
- ulong hval;
+ zend_ulong hval;
add_again:
switch (Z_TYPE_P(offset)) {
@@ -40611,7 +43034,7 @@ str_index:
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
- zend_uint size;
+ uint32_t size;
USE_OPLINE
array = EX_VAR(opline->result.var);
@@ -40645,10 +43068,13 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_
zval *container;
zval *offset;
- ulong hval;
+ zend_ulong hval;
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
+ }
if (IS_CV != IS_UNUSED) {
ZVAL_DEREF(container);
SEPARATE_ZVAL_NOREF(container);
@@ -40727,7 +43153,6 @@ numeric_index_dim:
break;
case IS_STRING:
- case IS_STR_OFFSET:
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
default:
@@ -40748,7 +43173,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
}
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
@@ -40773,7 +43198,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPC
zval *container;
int result;
- ulong hval;
+ zend_ulong hval;
zval *offset;
SAVE_OPLINE();
@@ -40860,7 +43285,7 @@ num_index_prop:
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) {
+ if (offset->value.lval >= 0 && offset->value.lval < (zend_long)Z_STRLEN_P(container)) {
if ((opline->extended_value & ZEND_ISSET) ||
Z_STRVAL_P(container)[offset->value.lval] != '0') {
result = 1;
@@ -40952,7 +43377,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
} else {
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
}
@@ -43122,16 +45547,16 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_DIM_R_SPEC_CV_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER,
+ ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER,
+ ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER,
+ ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER,
+ ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER,
+ ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER,
+ ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER,
ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER,
ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER,
ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER,
@@ -43322,16 +45747,16 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_IS_SPEC_CV_VAR_HANDLER,
ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER,
+ ZEND_FETCH_DIM_IS_SPEC_CONST_TMP_HANDLER,
+ ZEND_FETCH_DIM_IS_SPEC_CONST_VAR_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER,
+ ZEND_FETCH_DIM_IS_SPEC_TMP_CONST_HANDLER,
+ ZEND_FETCH_DIM_IS_SPEC_TMP_TMP_HANDLER,
+ ZEND_FETCH_DIM_IS_SPEC_TMP_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_FETCH_DIM_IS_SPEC_TMP_CV_HANDLER,
ZEND_FETCH_DIM_IS_SPEC_VAR_CONST_HANDLER,
ZEND_FETCH_DIM_IS_SPEC_VAR_TMP_HANDLER,
ZEND_FETCH_DIM_IS_SPEC_VAR_VAR_HANDLER,
@@ -43347,16 +45772,16 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_DIM_IS_SPEC_CV_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER,
+ ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER,
+ ZEND_FETCH_OBJ_IS_SPEC_CONST_TMP_HANDLER,
+ ZEND_FETCH_OBJ_IS_SPEC_CONST_VAR_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER,
+ ZEND_FETCH_OBJ_IS_SPEC_TMP_CONST_HANDLER,
+ ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_HANDLER,
+ ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER,
ZEND_FETCH_OBJ_IS_SPEC_VAR_CONST_HANDLER,
ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER,
ZEND_FETCH_OBJ_IS_SPEC_VAR_VAR_HANDLER,
@@ -43397,16 +45822,16 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER,
ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER,
+ ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMP_HANDLER,
+ ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_VAR_HANDLER,
+ ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER,
+ ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER,
+ ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER,
+ ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMP_HANDLER,
+ ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_VAR_HANDLER,
+ ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER,
+ ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER,
ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER,
ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER,
ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER,
@@ -43422,16 +45847,16 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER,
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER,
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER,
+ ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER,
+ ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMP_HANDLER,
+ ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_VAR_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER,
+ ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER,
+ ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMP_HANDLER,
+ ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER,
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER,
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER,
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER,
@@ -43947,16 +46372,16 @@ void zend_init_opcodes_handlers(void)
ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER,
ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER,
+ ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMP_HANDLER,
+ ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_VAR_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER,
+ ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CONST_HANDLER,
+ ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_TMP_HANDLER,
+ ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CV_HANDLER,
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CONST_HANDLER,
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMP_HANDLER,
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_VAR_HANDLER,
@@ -44772,16 +47197,16 @@ void zend_init_opcodes_handlers(void)
ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER,
ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER,
ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER,
+ ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER,
+ ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMP_HANDLER,
+ ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_VAR_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER,
+ ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CONST_HANDLER,
+ ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMP_HANDLER,
+ ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CV_HANDLER,
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER,
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER,
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER,
@@ -44997,56 +47422,56 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
- ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
- ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
@@ -45301,7 +47726,7 @@ void zend_init_opcodes_handlers(void)
};
zend_opcode_handlers = (opcode_handler_t*)labels;
}
-static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op)
+static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op)
{
static const int zend_vm_decode[] = {
_UNUSED_CODE, /* 0 */
diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl
index 4825e02b53..58cbe09787 100644
--- a/Zend/zend_vm_execute.skl
+++ b/Zend/zend_vm_execute.skl
@@ -8,7 +8,6 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC)
{%INTERNAL_LABELS%}
- LOAD_REGS();
LOAD_OPLINE();
while (1) {
diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php
index 50506f566b..df4ac12d3a 100644
--- a/Zend/zend_vm_gen.php
+++ b/Zend/zend_vm_gen.php
@@ -305,8 +305,6 @@ $op1_free_op_var_ptr = array(
"UNUSED" => "",
"CV" => "",
);
-$op1_free_op_var_ptr_fast = $op1_free_op_var_ptr;
-$op1_free_op_var_ptr_fast["VAR"] = "zval_ptr_dtor_nogc(free_op1.var)";
$op2_free_op_var_ptr = array(
"ANY" => "if (free_op2.var) {zval_ptr_dtor_nogc(free_op2.var);}",
@@ -316,8 +314,6 @@ $op2_free_op_var_ptr = array(
"UNUSED" => "",
"CV" => "",
);
-$op2_free_op_var_ptr_fast = $op2_free_op_var_ptr;
-$op2_free_op_var_ptr_fast["VAR"] = "zval_ptr_dtor_nogc(free_op2.var)";
$list = array(); // list of opcode handlers and helpers in original order
$opcodes = array(); // opcode handlers by code
@@ -372,8 +368,7 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
$op1_get_obj_zval_ptr_ptr, $op2_get_obj_zval_ptr_ptr,
$op1_is_tmp_free, $op2_is_tmp_free, $op1_free, $op2_free,
$op1_free_op, $op2_free_op, $op1_free_op_if_var, $op2_free_op_if_var,
- $op1_free_op_var_ptr, $op2_free_op_var_ptr, $prefix,
- $op1_free_op_var_ptr_fast, $op2_free_op_var_ptr_fast;
+ $op1_free_op_var_ptr, $op2_free_op_var_ptr, $prefix;
// Specializing
$code = preg_replace(
@@ -404,8 +399,6 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
"/FREE_OP2_IF_VAR\(\)/",
"/FREE_OP1_VAR_PTR\(\)/",
"/FREE_OP2_VAR_PTR\(\)/",
- "/FREE_OP1_VAR_PTR_FAST\(\)/",
- "/FREE_OP2_VAR_PTR_FAST\(\)/",
"/^#ifdef\s+ZEND_VM_SPEC\s*\n/m",
"/^#ifndef\s+ZEND_VM_SPEC\s*\n/m",
"/\!defined\(ZEND_VM_SPEC\)/m",
@@ -444,8 +437,6 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
$op2_free_op_if_var[$op2],
$op1_free_op_var_ptr[$op1],
$op2_free_op_var_ptr[$op2],
- $op1_free_op_var_ptr_fast[$op1],
- $op2_free_op_var_ptr_fast[$op2],
($op1!="ANY"||$op2!="ANY")?"#if 1\n":"#if 0\n",
($op1!="ANY"||$op2!="ANY")?"#if 0\n":"#if 1\n",
($op1!="ANY"||$op2!="ANY")?"0":"1",
@@ -893,7 +884,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
if (ZEND_VM_OLD_EXECUTOR && $spec) {
out($f,"static int zend_vm_old_executor = 0;\n\n");
}
- out($f,"static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op);\n\n");
+ out($f,"static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);\n\n");
switch ($kind) {
case ZEND_VM_KIND_CALL:
out($f,"\n");
@@ -904,7 +895,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
out($f,"#undef SAVE_OPLINE\n");
out($f,"#define OPLINE EX(opline)\n");
out($f,"#define DCL_OPLINE\n");
- out($f,"#define USE_OPLINE zend_op *opline = EX(opline);\n");
+ out($f,"#define USE_OPLINE const zend_op *opline = EX(opline);\n");
out($f,"#define LOAD_OPLINE()\n");
out($f,"#define SAVE_OPLINE()\n");
out($f,"#undef CHECK_EXCEPTION\n");
@@ -913,7 +904,6 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
out($f,"#define CHECK_EXCEPTION() LOAD_OPLINE()\n");
out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
- out($f,"#define LOAD_REGS()\n");
out($f,"#define ZEND_VM_CONTINUE() return 0\n");
out($f,"#define ZEND_VM_RETURN() return -1\n");
out($f,"#define ZEND_VM_ENTER() return 1\n");
@@ -939,7 +929,6 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
out($f,"#define CHECK_EXCEPTION() LOAD_OPLINE()\n");
out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
- out($f,"#define LOAD_REGS()\n");
out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n");
out($f,"#define ZEND_VM_RETURN() return\n");
out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
@@ -971,7 +960,6 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
out($f,"#define HANDLE_EXCEPTION() goto ZEND_HANDLE_EXCEPTION_HANDLER\n");
out($f,"#define HANDLE_EXCEPTION_LEAVE() goto ZEND_HANDLE_EXCEPTION_HANDLER\n");
}
- out($f,"#define LOAD_REGS()\n");
out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n");
out($f,"#define ZEND_VM_RETURN() return\n");
out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
@@ -1342,7 +1330,7 @@ function gen_vm($def, $skel) {
}
// Generate zend_vm_get_opcode_handler() function
- out($f, "static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op)\n");
+ out($f, "static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op)\n");
out($f, "{\n");
if (!ZEND_VM_SPEC) {
out($f, "\treturn zend_opcode_handlers[opcode];\n");
@@ -1395,7 +1383,7 @@ function gen_vm($def, $skel) {
out($f,"#undef SAVE_OPLINE\n");
out($f,"#define OPLINE EX(opline)\n");
out($f,"#define DCL_OPLINE\n");
- out($f,"#define USE_OPLINE zend_op *opline = EX(opline);\n");
+ out($f,"#define USE_OPLINE const zend_op *opline = EX(opline);\n");
out($f,"#define LOAD_OPLINE()\n");
out($f,"#define SAVE_OPLINE()\n");
out($f,"#undef CHECK_EXCEPTION\n");
diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c
index 729f922963..8d86ce23f1 100644
--- a/Zend/zend_vm_opcodes.c
+++ b/Zend/zend_vm_opcodes.c
@@ -179,8 +179,8 @@ const char *zend_vm_opcodes_map[169] = {
"ZEND_ADD_TRAIT",
"ZEND_BIND_TRAITS",
"ZEND_SEPARATE",
- "ZEND_QM_ASSIGN_VAR",
- "ZEND_JMP_SET_VAR",
+ NULL,
+ NULL,
"ZEND_DISCARD_EXCEPTION",
"ZEND_YIELD",
"ZEND_GENERATOR_RETURN",
diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h
index 9274d3e044..70721b874b 100644
--- a/Zend/zend_vm_opcodes.h
+++ b/Zend/zend_vm_opcodes.h
@@ -170,8 +170,6 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);
#define ZEND_ADD_TRAIT 154
#define ZEND_BIND_TRAITS 155
#define ZEND_SEPARATE 156
-#define ZEND_QM_ASSIGN_VAR 157
-#define ZEND_JMP_SET_VAR 158
#define ZEND_DISCARD_EXCEPTION 159
#define ZEND_YIELD 160
#define ZEND_GENERATOR_RETURN 161