mirror of
https://github.com/php/php-src.git
synced 2024-11-27 03:44:07 +08:00
Namespaces
This commit is contained in:
parent
1674976346
commit
f32ffe9b43
1
NEWS
1
NEWS
@ -1,6 +1,7 @@
|
||||
PHP NEWS
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
?? ??? 20??, PHP 5.3.0
|
||||
- Added support for namespaces. (Dmitry, Stas)
|
||||
- Added support for dynamic access of static members using $foo::myFunc().
|
||||
(Etienne Kneuss)
|
||||
|
||||
|
34
Zend/tests/ns_001.phpt
Executable file
34
Zend/tests/ns_001.phpt
Executable file
@ -0,0 +1,34 @@
|
||||
--TEST--
|
||||
001: Class in namespace
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
class Foo {
|
||||
|
||||
function __construct() {
|
||||
echo __CLASS__,"\n";
|
||||
}
|
||||
|
||||
function bar() {
|
||||
echo __CLASS__,"\n";
|
||||
}
|
||||
|
||||
static function baz() {
|
||||
echo __CLASS__,"\n";
|
||||
}
|
||||
}
|
||||
|
||||
$x = new Foo;
|
||||
$x->bar();
|
||||
Foo::baz();
|
||||
$y = new test::ns1::Foo;
|
||||
$y->bar();
|
||||
test::ns1::Foo::baz();
|
||||
--EXPECT--
|
||||
test::ns1::Foo
|
||||
test::ns1::Foo
|
||||
test::ns1::Foo
|
||||
test::ns1::Foo
|
||||
test::ns1::Foo
|
||||
test::ns1::Foo
|
27
Zend/tests/ns_002.phpt
Executable file
27
Zend/tests/ns_002.phpt
Executable file
@ -0,0 +1,27 @@
|
||||
--TEST--
|
||||
002: Import in namespace
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
class Foo {
|
||||
static function bar() {
|
||||
echo __CLASS__,"\n";
|
||||
}
|
||||
}
|
||||
|
||||
import test::ns1::Foo as Bar;
|
||||
import test::ns1 as ns2;
|
||||
import test::ns1;
|
||||
|
||||
Foo::bar();
|
||||
test::ns1::Foo::bar();
|
||||
Bar::bar();
|
||||
ns2::Foo::bar();
|
||||
ns1::Foo::bar();
|
||||
--EXPECT--
|
||||
test::ns1::Foo
|
||||
test::ns1::Foo
|
||||
test::ns1::Foo
|
||||
test::ns1::Foo
|
||||
test::ns1::Foo
|
12
Zend/tests/ns_003.phpt
Executable file
12
Zend/tests/ns_003.phpt
Executable file
@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
003: Name conflict (ns name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
class Exception {
|
||||
}
|
||||
|
||||
echo get_class(new Exception()),"\n";
|
||||
--EXPECT--
|
||||
test::ns1::Exception
|
9
Zend/tests/ns_004.phpt
Executable file
9
Zend/tests/ns_004.phpt
Executable file
@ -0,0 +1,9 @@
|
||||
--TEST--
|
||||
004: Name conflict (php name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
echo get_class(new Exception()),"\n";
|
||||
--EXPECT--
|
||||
Exception
|
12
Zend/tests/ns_005.phpt
Executable file
12
Zend/tests/ns_005.phpt
Executable file
@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
005: Name conflict (php name in case if ns name exists)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
class Exception {
|
||||
}
|
||||
|
||||
echo get_class(new ::Exception()),"\n";
|
||||
--EXPECT--
|
||||
Exception
|
13
Zend/tests/ns_006.phpt
Executable file
13
Zend/tests/ns_006.phpt
Executable file
@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
006: Run-time name conflict (ns name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
class Exception {
|
||||
}
|
||||
|
||||
$x = "test::ns1::Exception";
|
||||
echo get_class(new $x),"\n";
|
||||
--EXPECT--
|
||||
test::ns1::Exception
|
13
Zend/tests/ns_007.phpt
Executable file
13
Zend/tests/ns_007.phpt
Executable file
@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
007: Run-time name conflict (php name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
class Exception {
|
||||
}
|
||||
|
||||
$x = "Exception";
|
||||
echo get_class(new $x),"\n";
|
||||
--EXPECT--
|
||||
Exception
|
13
Zend/tests/ns_008.phpt
Executable file
13
Zend/tests/ns_008.phpt
Executable file
@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
008: __NAMESPACE__ constant and runtime names (ns name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test;
|
||||
|
||||
class foo {
|
||||
}
|
||||
|
||||
$x = __NAMESPACE__ . "::foo";
|
||||
echo get_class(new $x),"\n";
|
||||
--EXPECT--
|
||||
test::foo
|
11
Zend/tests/ns_009.phpt
Executable file
11
Zend/tests/ns_009.phpt
Executable file
@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
009: __NAMESPACE__ constant and runtime names (php name)
|
||||
--FILE--
|
||||
<?php
|
||||
class foo {
|
||||
}
|
||||
|
||||
$x = __NAMESPACE__ . "::foo";
|
||||
echo get_class(new $x),"\n";
|
||||
--EXPECT--
|
||||
foo
|
49
Zend/tests/ns_010.phpt
Executable file
49
Zend/tests/ns_010.phpt
Executable file
@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
010: Accesing internal namespace class
|
||||
--FILE--
|
||||
<?php
|
||||
namespace X;
|
||||
import X as Y;
|
||||
class Foo {
|
||||
const C = "const ok\n";
|
||||
static $var = "var ok\n";
|
||||
function __construct() {
|
||||
echo "class ok\n";
|
||||
}
|
||||
static function bar() {
|
||||
echo "method ok\n";
|
||||
}
|
||||
}
|
||||
new Foo();
|
||||
new X::Foo();
|
||||
new Y::Foo();
|
||||
new ::X::Foo();
|
||||
Foo::bar();
|
||||
X::Foo::bar();
|
||||
Y::Foo::bar();
|
||||
::X::Foo::bar();
|
||||
echo Foo::C;
|
||||
echo X::Foo::C;
|
||||
echo Y::Foo::C;
|
||||
echo ::X::Foo::C;
|
||||
echo Foo::$var;
|
||||
echo X::Foo::$var;
|
||||
echo Y::Foo::$var;
|
||||
echo ::X::Foo::$var;
|
||||
--EXPECT--
|
||||
class ok
|
||||
class ok
|
||||
class ok
|
||||
class ok
|
||||
method ok
|
||||
method ok
|
||||
method ok
|
||||
method ok
|
||||
const ok
|
||||
const ok
|
||||
const ok
|
||||
const ok
|
||||
var ok
|
||||
var ok
|
||||
var ok
|
||||
var ok
|
24
Zend/tests/ns_011.phpt
Executable file
24
Zend/tests/ns_011.phpt
Executable file
@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
011: Function in namespace
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
function foo() {
|
||||
echo __FUNCTION__,"\n";
|
||||
}
|
||||
|
||||
foo();
|
||||
test::ns1::foo();
|
||||
bar();
|
||||
test::ns1::bar();
|
||||
|
||||
function bar() {
|
||||
echo __FUNCTION__,"\n";
|
||||
}
|
||||
|
||||
--EXPECT--
|
||||
test::ns1::foo
|
||||
test::ns1::foo
|
||||
test::ns1::bar
|
||||
test::ns1::bar
|
35
Zend/tests/ns_012.phpt
Executable file
35
Zend/tests/ns_012.phpt
Executable file
@ -0,0 +1,35 @@
|
||||
--TEST--
|
||||
012: Import in namespace and functions
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
function foo() {
|
||||
echo __FUNCTION__,"\n";
|
||||
}
|
||||
|
||||
import test::ns1 as ns2;
|
||||
import test as ns3;
|
||||
|
||||
foo();
|
||||
bar();
|
||||
test::ns1::foo();
|
||||
test::ns1::bar();
|
||||
ns2::foo();
|
||||
ns2::bar();
|
||||
ns3::ns1::foo();
|
||||
ns3::ns1::bar();
|
||||
|
||||
function bar() {
|
||||
echo __FUNCTION__,"\n";
|
||||
}
|
||||
|
||||
--EXPECT--
|
||||
test::ns1::foo
|
||||
test::ns1::bar
|
||||
test::ns1::foo
|
||||
test::ns1::bar
|
||||
test::ns1::foo
|
||||
test::ns1::bar
|
||||
test::ns1::foo
|
||||
test::ns1::bar
|
13
Zend/tests/ns_013.phpt
Executable file
13
Zend/tests/ns_013.phpt
Executable file
@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
013: Name conflict and functions (ns name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
function strlen($x) {
|
||||
return __FUNCTION__;
|
||||
}
|
||||
|
||||
echo strlen("Hello"),"\n";
|
||||
--EXPECT--
|
||||
test::ns1::strlen
|
9
Zend/tests/ns_014.phpt
Executable file
9
Zend/tests/ns_014.phpt
Executable file
@ -0,0 +1,9 @@
|
||||
--TEST--
|
||||
014: Name conflict and functions (php name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
echo strlen("Hello"),"\n";
|
||||
--EXPECT--
|
||||
5
|
14
Zend/tests/ns_015.phpt
Executable file
14
Zend/tests/ns_015.phpt
Executable file
@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
015: Name conflict and functions (php name in case if ns name exists)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
function strlen($x) {
|
||||
return __FUNCTION__;
|
||||
}
|
||||
|
||||
echo ::strlen("Hello"),"\n";
|
||||
--EXPECT--
|
||||
5
|
||||
|
14
Zend/tests/ns_016.phpt
Executable file
14
Zend/tests/ns_016.phpt
Executable file
@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
016: Run-time name conflict and functions (ns name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
function strlen($x) {
|
||||
return __FUNCTION__;
|
||||
}
|
||||
|
||||
$x = "test::ns1::strlen";
|
||||
echo $x("Hello"),"\n";
|
||||
--EXPECT--
|
||||
test::ns1::strlen
|
14
Zend/tests/ns_017.phpt
Executable file
14
Zend/tests/ns_017.phpt
Executable file
@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
017: Run-time name conflict and functions (php name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
function strlen($x) {
|
||||
return __FUNCTION__;
|
||||
}
|
||||
|
||||
$x = "strlen";
|
||||
echo $x("Hello"),"\n";
|
||||
--EXPECT--
|
||||
5
|
14
Zend/tests/ns_018.phpt
Executable file
14
Zend/tests/ns_018.phpt
Executable file
@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
018: __NAMESPACE__ constant and runtime names (ns name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test;
|
||||
|
||||
function foo() {
|
||||
return __FUNCTION__;
|
||||
}
|
||||
|
||||
$x = __NAMESPACE__ . "::foo";
|
||||
echo $x(),"\n";
|
||||
--EXPECT--
|
||||
test::foo
|
12
Zend/tests/ns_019.phpt
Executable file
12
Zend/tests/ns_019.phpt
Executable file
@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
019: __NAMESPACE__ constant and runtime names (php name)
|
||||
--FILE--
|
||||
<?php
|
||||
function foo() {
|
||||
return __FUNCTION__;
|
||||
}
|
||||
|
||||
$x = __NAMESPACE__ . "::foo";
|
||||
echo $x(),"\n";
|
||||
--EXPECT--
|
||||
foo
|
18
Zend/tests/ns_020.phpt
Executable file
18
Zend/tests/ns_020.phpt
Executable file
@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
020: Accesing internal namespace function
|
||||
--FILE--
|
||||
<?php
|
||||
namespace X;
|
||||
import X as Y;
|
||||
function foo() {
|
||||
echo __FUNCTION__,"\n";
|
||||
}
|
||||
foo();
|
||||
X::foo();
|
||||
Y::foo();
|
||||
::X::foo();
|
||||
--EXPECT--
|
||||
X::foo
|
||||
X::foo
|
||||
X::foo
|
||||
X::foo
|
23
Zend/tests/ns_021.phpt
Executable file
23
Zend/tests/ns_021.phpt
Executable file
@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
021: Name search priority (first look into namespace)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test;
|
||||
|
||||
class Test {
|
||||
static function foo() {
|
||||
echo __CLASS__,"::",__FUNCTION__,"\n";
|
||||
}
|
||||
}
|
||||
|
||||
function foo() {
|
||||
echo __FUNCTION__,"\n";
|
||||
}
|
||||
|
||||
foo();
|
||||
test::foo();
|
||||
test::test::foo();
|
||||
--EXPECT--
|
||||
test::foo
|
||||
test::foo
|
||||
test::Test::foo
|
6
Zend/tests/ns_022.inc
Executable file
6
Zend/tests/ns_022.inc
Executable file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
class Test {
|
||||
static function foo() {
|
||||
echo __CLASS__,"::",__FUNCTION__,"\n";
|
||||
}
|
||||
}
|
19
Zend/tests/ns_022.phpt
Executable file
19
Zend/tests/ns_022.phpt
Executable file
@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
022: Name search priority (first look into import, then into current namespace and then for class)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace a::b::c;
|
||||
|
||||
import a::b::c as test;
|
||||
|
||||
require "ns_022.inc";
|
||||
|
||||
function foo() {
|
||||
echo __FUNCTION__,"\n";
|
||||
}
|
||||
|
||||
test::foo();
|
||||
::test::foo();
|
||||
--EXPECT--
|
||||
a::b::c::foo
|
||||
Test::foo
|
11
Zend/tests/ns_023.phpt
Executable file
11
Zend/tests/ns_023.phpt
Executable file
@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
023: __NAMESPACE__ constant
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::foo;
|
||||
|
||||
var_dump(__NAMESPACE__);
|
||||
--EXPECT--
|
||||
string(9) "test::foo"
|
||||
--UEXPECT--
|
||||
unicode(9) "test::foo"
|
9
Zend/tests/ns_024.phpt
Executable file
9
Zend/tests/ns_024.phpt
Executable file
@ -0,0 +1,9 @@
|
||||
--TEST--
|
||||
024: __NAMESPACE__ constant out of namespace
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(__NAMESPACE__);
|
||||
--EXPECT--
|
||||
string(0) ""
|
||||
--UEXPECT--
|
||||
unicode(0) ""
|
24
Zend/tests/ns_025.phpt
Executable file
24
Zend/tests/ns_025.phpt
Executable file
@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
025: Name ambiguity (class name & part of namespace name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace Foo::Bar;
|
||||
|
||||
class Foo {
|
||||
function __construct() {
|
||||
echo __CLASS__,"\n";
|
||||
}
|
||||
static function Bar() {
|
||||
echo __CLASS__,"\n";
|
||||
}
|
||||
}
|
||||
|
||||
$x = new Foo;
|
||||
Foo::Bar();
|
||||
$x = new Foo::Bar::Foo;
|
||||
Foo::Bar::Foo::Bar();
|
||||
--EXPECT--
|
||||
Foo::Bar::Foo
|
||||
Foo::Bar::Foo
|
||||
Foo::Bar::Foo
|
||||
Foo::Bar::Foo
|
30
Zend/tests/ns_026.phpt
Executable file
30
Zend/tests/ns_026.phpt
Executable file
@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
026: Name ambiguity (class name & namespace name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace Foo;
|
||||
|
||||
class Foo {
|
||||
function __construct() {
|
||||
echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
|
||||
}
|
||||
static function Bar() {
|
||||
echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
|
||||
}
|
||||
}
|
||||
|
||||
function Bar() {
|
||||
echo "Func - ".__FUNCTION__."\n";
|
||||
}
|
||||
|
||||
$x = new Foo;
|
||||
Foo::Bar();
|
||||
$x = new Foo::Foo;
|
||||
Foo::Foo::Bar();
|
||||
::Foo::Bar();
|
||||
--EXPECT--
|
||||
Method - Foo::Foo::__construct
|
||||
Func - Foo::Bar
|
||||
Method - Foo::Foo::__construct
|
||||
Method - Foo::Foo::Bar
|
||||
Func - Foo::Bar
|
11
Zend/tests/ns_027.inc
Executable file
11
Zend/tests/ns_027.inc
Executable file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
namespace Foo::Bar;
|
||||
|
||||
class Foo {
|
||||
function __construct() {
|
||||
echo __CLASS__,"\n";
|
||||
}
|
||||
static function Bar() {
|
||||
echo __CLASS__,"\n";
|
||||
}
|
||||
}
|
24
Zend/tests/ns_027.phpt
Executable file
24
Zend/tests/ns_027.phpt
Executable file
@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
027: Name ambiguity (class name & part of extertnal namespace name)
|
||||
--FILE--
|
||||
<?php
|
||||
require "ns_027.inc";
|
||||
|
||||
class Foo {
|
||||
function __construct() {
|
||||
echo __CLASS__,"\n";
|
||||
}
|
||||
static function Bar() {
|
||||
echo __CLASS__,"\n";
|
||||
}
|
||||
}
|
||||
|
||||
$x = new Foo;
|
||||
Foo::Bar();
|
||||
$x = new Foo::Bar::Foo;
|
||||
Foo::Bar::Foo::Bar();
|
||||
--EXPECT--
|
||||
Foo
|
||||
Foo
|
||||
Foo::Bar::Foo
|
||||
Foo::Bar::Foo
|
15
Zend/tests/ns_028.inc
Executable file
15
Zend/tests/ns_028.inc
Executable file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace Foo;
|
||||
|
||||
class Foo {
|
||||
function __construct() {
|
||||
echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
|
||||
}
|
||||
static function Bar() {
|
||||
echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
|
||||
}
|
||||
}
|
||||
|
||||
function Bar() {
|
||||
echo "Func - ".__FUNCTION__."\n";
|
||||
}
|
26
Zend/tests/ns_028.phpt
Executable file
26
Zend/tests/ns_028.phpt
Executable file
@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
028: Name ambiguity (class name & external namespace name)
|
||||
--FILE--
|
||||
<?php
|
||||
require "ns_028.inc";
|
||||
|
||||
class Foo {
|
||||
function __construct() {
|
||||
echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
|
||||
}
|
||||
static function Bar() {
|
||||
echo "Method - ".__CLASS__."::".__FUNCTION__."\n";
|
||||
}
|
||||
}
|
||||
|
||||
$x = new Foo;
|
||||
Foo::Bar();
|
||||
$x = new Foo::Foo;
|
||||
Foo::Foo::Bar();
|
||||
::Foo::Bar();
|
||||
--EXPECT--
|
||||
Method - Foo::__construct
|
||||
Func - Foo::Bar
|
||||
Method - Foo::Foo::__construct
|
||||
Method - Foo::Foo::Bar
|
||||
Func - Foo::Bar
|
12
Zend/tests/ns_029.phpt
Executable file
12
Zend/tests/ns_029.phpt
Executable file
@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
029: Name ambiguity (class name & import name)
|
||||
--FILE--
|
||||
<?php
|
||||
import A::B as Foo;
|
||||
|
||||
class Foo {
|
||||
}
|
||||
|
||||
new Foo();
|
||||
--EXPECTF--
|
||||
Fatal error: Class name 'Foo' conflicts with import name in %sns_029.php on line 4
|
12
Zend/tests/ns_030.phpt
Executable file
12
Zend/tests/ns_030.phpt
Executable file
@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
030: Name ambiguity (import name & class name)
|
||||
--FILE--
|
||||
<?php
|
||||
class Foo {
|
||||
}
|
||||
|
||||
import A::B as Foo;
|
||||
|
||||
new Foo();
|
||||
--EXPECTF--
|
||||
Fatal error: Import name 'Foo' conflicts with defined class in %sns_030.php on line 5
|
21
Zend/tests/ns_031.phpt
Executable file
21
Zend/tests/ns_031.phpt
Executable file
@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
031: Namespace support for user functions (ns name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test;
|
||||
|
||||
class Test {
|
||||
static function foo() {
|
||||
echo __CLASS__,"::",__FUNCTION__,"\n";
|
||||
}
|
||||
}
|
||||
|
||||
function foo() {
|
||||
echo __FUNCTION__,"\n";
|
||||
}
|
||||
|
||||
call_user_func(__NAMESPACE__."::foo");
|
||||
call_user_func(__NAMESPACE__."::test::foo");
|
||||
--EXPECT--
|
||||
test::foo
|
||||
test::Test::foo
|
19
Zend/tests/ns_032.phpt
Executable file
19
Zend/tests/ns_032.phpt
Executable file
@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
032: Namespace support for user functions (php name)
|
||||
--FILE--
|
||||
<?php
|
||||
class Test {
|
||||
static function foo() {
|
||||
echo __CLASS__,"::",__FUNCTION__,"\n";
|
||||
}
|
||||
}
|
||||
|
||||
function foo() {
|
||||
echo __FUNCTION__,"\n";
|
||||
}
|
||||
|
||||
call_user_func(__NAMESPACE__."::foo");
|
||||
call_user_func(__NAMESPACE__."::test::foo");
|
||||
--EXPECT--
|
||||
foo
|
||||
Test::foo
|
8
Zend/tests/ns_033.phpt
Executable file
8
Zend/tests/ns_033.phpt
Executable file
@ -0,0 +1,8 @@
|
||||
--TEST--
|
||||
033: Import statement with non-compound name
|
||||
--FILE--
|
||||
<?php
|
||||
import A;
|
||||
--EXPECTF--
|
||||
Warning: The import statement with non-compound name 'A' has no effect in %sns_033.php on line 2
|
||||
|
38
Zend/tests/ns_034.phpt
Executable file
38
Zend/tests/ns_034.phpt
Executable file
@ -0,0 +1,38 @@
|
||||
--TEST--
|
||||
034: Support for namespaces in compile-time constant reference
|
||||
--FILE--
|
||||
<?php
|
||||
namespace A;
|
||||
import A as B;
|
||||
class Foo {
|
||||
const C = "ok\n";
|
||||
}
|
||||
function f1($x=Foo::C) {
|
||||
echo $x;
|
||||
}
|
||||
function f2($x=A::Foo::C) {
|
||||
echo $x;
|
||||
}
|
||||
function f3($x=B::Foo::C) {
|
||||
echo $x;
|
||||
}
|
||||
function f4($x=::A::Foo::C) {
|
||||
echo $x;
|
||||
}
|
||||
echo Foo::C;
|
||||
echo A::Foo::C;
|
||||
echo B::Foo::C;
|
||||
echo ::A::Foo::C;
|
||||
f1();
|
||||
f2();
|
||||
f3();
|
||||
f4();
|
||||
--EXPECT--
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
24
Zend/tests/ns_035.phpt
Executable file
24
Zend/tests/ns_035.phpt
Executable file
@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
035: Name ambiguity in compile-time constant reference (php name)
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("spl")) die("skip SPL is no available"); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
namespace A;
|
||||
function f1($x = ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
function f2($x = ::ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
var_dump(ArrayObject::STD_PROP_LIST);
|
||||
var_dump(::ArrayObject::STD_PROP_LIST);
|
||||
f1();
|
||||
f2();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(1)
|
||||
int(1)
|
||||
int(1)
|
||||
int(1)
|
48
Zend/tests/ns_036.phpt
Executable file
48
Zend/tests/ns_036.phpt
Executable file
@ -0,0 +1,48 @@
|
||||
--TEST--
|
||||
036: Name ambiguity in compile-time constant reference (ns name)
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("spl")) die("skip SPL is no available"); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
namespace A;
|
||||
import A as B;
|
||||
class ArrayObject {
|
||||
const STD_PROP_LIST = 2;
|
||||
}
|
||||
function f1($x = ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
function f2($x = ::ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
function f3($x = A::ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
function f4($x = B::ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
function f5($x = ::A::ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
var_dump(ArrayObject::STD_PROP_LIST);
|
||||
var_dump(::ArrayObject::STD_PROP_LIST);
|
||||
var_dump(A::ArrayObject::STD_PROP_LIST);
|
||||
var_dump(B::ArrayObject::STD_PROP_LIST);
|
||||
var_dump(::A::ArrayObject::STD_PROP_LIST);
|
||||
f1();
|
||||
f2();
|
||||
f3();
|
||||
f4();
|
||||
f5();
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
int(1)
|
||||
int(2)
|
||||
int(2)
|
||||
int(2)
|
||||
int(2)
|
||||
int(1)
|
||||
int(2)
|
||||
int(2)
|
||||
int(2)
|
49
Zend/tests/ns_037.phpt
Executable file
49
Zend/tests/ns_037.phpt
Executable file
@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
037: Name ambiguity (namespace name or namespace's class name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace X;
|
||||
import X as Y;
|
||||
class X {
|
||||
const C = "const ok\n";
|
||||
static $var = "var ok\n";
|
||||
function __construct() {
|
||||
echo "class ok\n";
|
||||
}
|
||||
static function bar() {
|
||||
echo "method ok\n";
|
||||
}
|
||||
}
|
||||
new X();
|
||||
new X::X();
|
||||
new Y::X();
|
||||
new ::X::X();
|
||||
X::bar();
|
||||
X::X::bar();
|
||||
Y::X::bar();
|
||||
::X::X::bar();
|
||||
echo X::C;
|
||||
echo X::X::C;
|
||||
echo Y::X::C;
|
||||
echo ::X::X::C;
|
||||
echo X::$var;
|
||||
echo X::X::$var;
|
||||
echo Y::X::$var;
|
||||
echo ::X::X::$var;
|
||||
--EXPECT--
|
||||
class ok
|
||||
class ok
|
||||
class ok
|
||||
class ok
|
||||
method ok
|
||||
method ok
|
||||
method ok
|
||||
method ok
|
||||
const ok
|
||||
const ok
|
||||
const ok
|
||||
const ok
|
||||
var ok
|
||||
var ok
|
||||
var ok
|
||||
var ok
|
15
Zend/tests/ns_038.phpt
Executable file
15
Zend/tests/ns_038.phpt
Executable file
@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
038: Name ambiguity (namespace name or internal class name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace Exception;
|
||||
function foo() {
|
||||
echo "ok\n";
|
||||
}
|
||||
Exception::foo();
|
||||
Exception::bar();
|
||||
--EXPECTF--
|
||||
ok
|
||||
|
||||
Fatal error: Call to undefined method Exception::bar() in %sns_038.php on line 7
|
||||
|
23
Zend/tests/ns_039.phpt
Normal file
23
Zend/tests/ns_039.phpt
Normal file
@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
039: Constant declaration
|
||||
--FILE--
|
||||
<?php
|
||||
const A = "ok";
|
||||
const B = A;
|
||||
const C = array("ok");
|
||||
const D = array(B);
|
||||
echo A . "\n";
|
||||
echo B . "\n";
|
||||
print_r(C);
|
||||
print_r(D);
|
||||
--EXPECT--
|
||||
ok
|
||||
ok
|
||||
Array
|
||||
(
|
||||
[0] => ok
|
||||
)
|
||||
Array
|
||||
(
|
||||
[0] => ok
|
||||
)
|
68
Zend/tests/ns_040.phpt
Normal file
68
Zend/tests/ns_040.phpt
Normal file
@ -0,0 +1,68 @@
|
||||
--TEST--
|
||||
040: Constant declaration and usage in namespace
|
||||
--FILE--
|
||||
<?php
|
||||
namespace X;
|
||||
import X as Y;
|
||||
const A = "ok\n";
|
||||
const B = A;
|
||||
const C = array(A);
|
||||
const D = array("aaa"=>A);
|
||||
const E = array(A=>"aaa\n");
|
||||
function f1($x=A) {
|
||||
echo $x;
|
||||
}
|
||||
function f2($x=X::A) {
|
||||
echo $x;
|
||||
}
|
||||
function f3($x=Y::A) {
|
||||
echo $x;
|
||||
}
|
||||
function f4($x=::X::A) {
|
||||
echo $x;
|
||||
}
|
||||
function f5($x=B) {
|
||||
echo $x;
|
||||
}
|
||||
function f6($x=array(A)) {
|
||||
echo $x[0];
|
||||
}
|
||||
function f7($x=array("aaa"=>A)) {
|
||||
echo $x["aaa"];
|
||||
}
|
||||
function f8($x=array(A=>"aaa\n")) {
|
||||
echo $x["ok\n"];
|
||||
}
|
||||
echo A;
|
||||
echo X::A;
|
||||
echo Y::A;
|
||||
echo ::X::A;
|
||||
f1();
|
||||
f2();
|
||||
f3();
|
||||
f4();
|
||||
echo B;
|
||||
$x = C; echo $x[0];
|
||||
$x = D; echo $x["aaa"];
|
||||
$x = E; echo $x["ok\n"];
|
||||
f5();
|
||||
f6();
|
||||
f7();
|
||||
f8();
|
||||
--EXPECT--
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
aaa
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
aaa
|
22
Zend/tests/ns_041.phpt
Normal file
22
Zend/tests/ns_041.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
041: Constants in namespace
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
const FOO = "ok\n";
|
||||
|
||||
echo(FOO);
|
||||
echo(test::ns1::FOO);
|
||||
echo(::test::ns1::FOO);
|
||||
echo(BAR);
|
||||
|
||||
const BAR = "ok\n";
|
||||
|
||||
--EXPECTF--
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
|
||||
Notice: Use of undefined constant BAR - assumed 'BAR' in %sns_041.php on line 9
|
||||
BAR
|
22
Zend/tests/ns_042.phpt
Normal file
22
Zend/tests/ns_042.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
042: Import in namespace and constants
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
const FOO = "ok\n";
|
||||
|
||||
import test::ns1 as ns2;
|
||||
import test as ns3;
|
||||
|
||||
echo FOO;
|
||||
echo test::ns1::FOO;
|
||||
echo ::test::ns1::FOO;
|
||||
echo ns2::FOO;
|
||||
echo ns3::ns1::FOO;
|
||||
--EXPECT--
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
11
Zend/tests/ns_043.phpt
Normal file
11
Zend/tests/ns_043.phpt
Normal file
@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
043: Name conflict and constants (ns name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
const INI_ALL = 0;
|
||||
|
||||
var_dump(INI_ALL);
|
||||
--EXPECT--
|
||||
int(0)
|
9
Zend/tests/ns_044.phpt
Normal file
9
Zend/tests/ns_044.phpt
Normal file
@ -0,0 +1,9 @@
|
||||
--TEST--
|
||||
044: Name conflict and constants (php name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
var_dump(INI_ALL);
|
||||
--EXPECT--
|
||||
int(7)
|
11
Zend/tests/ns_045.phpt
Normal file
11
Zend/tests/ns_045.phpt
Normal file
@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
045: Name conflict and constants (php name in case if ns name exists)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
const INI_ALL = 0;
|
||||
|
||||
var_dump(::INI_ALL);
|
||||
--EXPECT--
|
||||
int(7)
|
11
Zend/tests/ns_046.phpt
Normal file
11
Zend/tests/ns_046.phpt
Normal file
@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
046: Run-time name conflict and constants (ns name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
const INI_ALL = 0;
|
||||
|
||||
var_dump(constant("test::ns1::INI_ALL"));
|
||||
--EXPECT--
|
||||
int(0)
|
11
Zend/tests/ns_047.phpt
Normal file
11
Zend/tests/ns_047.phpt
Normal file
@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
047: Run-time name conflict and constants (php name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
const INI_ALL = 0;
|
||||
|
||||
var_dump(constant("INI_ALL"));
|
||||
--EXPECT--
|
||||
int(7)
|
11
Zend/tests/ns_048.phpt
Normal file
11
Zend/tests/ns_048.phpt
Normal file
@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
048: __NAMESPACE__ constant and runtime names (ns name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
const FOO = 0;
|
||||
|
||||
var_dump(constant(__NAMESPACE__ . "::FOO"));
|
||||
--EXPECT--
|
||||
int(0)
|
9
Zend/tests/ns_049.phpt
Normal file
9
Zend/tests/ns_049.phpt
Normal file
@ -0,0 +1,9 @@
|
||||
--TEST--
|
||||
049: __NAMESPACE__ constant and runtime names (php name)
|
||||
--FILE--
|
||||
<?php
|
||||
const FOO = 0;
|
||||
|
||||
var_dump(constant(__NAMESPACE__ . "::FOO"));
|
||||
--EXPECT--
|
||||
int(0)
|
14
Zend/tests/ns_050.phpt
Normal file
14
Zend/tests/ns_050.phpt
Normal file
@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
050: Name conflict and compile-time constants (ns name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
const INI_ALL = 0;
|
||||
|
||||
function foo($x = INI_ALL) {
|
||||
var_dump($x);
|
||||
}
|
||||
foo();
|
||||
--EXPECT--
|
||||
int(0)
|
12
Zend/tests/ns_051.phpt
Normal file
12
Zend/tests/ns_051.phpt
Normal file
@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
051: Name conflict and compile-time constants (php name)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
function foo($x = INI_ALL) {
|
||||
var_dump($x);
|
||||
}
|
||||
foo();
|
||||
--EXPECT--
|
||||
int(7)
|
14
Zend/tests/ns_052.phpt
Normal file
14
Zend/tests/ns_052.phpt
Normal file
@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
052: Name conflict and compile-time constants (php name in case if ns name exists)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
const INI_ALL = 0;
|
||||
|
||||
function foo($x = ::INI_ALL) {
|
||||
var_dump($x);
|
||||
}
|
||||
foo();
|
||||
--EXPECT--
|
||||
int(7)
|
13
Zend/tests/ns_053.phpt
Normal file
13
Zend/tests/ns_053.phpt
Normal file
@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
053: Run-time constant definition
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test::ns1;
|
||||
|
||||
define(__NAMESPACE__ . '::NAME', basename(__FILE__));
|
||||
echo NAME."\n";
|
||||
echo test::ns1::NAME."\n";
|
||||
--EXPECT--
|
||||
ns_053.php
|
||||
ns_053.php
|
||||
|
@ -422,7 +422,9 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
|
||||
#define IS_CONSTANT_ARRAY 9
|
||||
|
||||
/* Ugly hack to support constants as static array indices */
|
||||
#define IS_CONSTANT_INDEX 0x80
|
||||
#define IS_CONSTANT_TYPE_MASK 0x0f
|
||||
#define IS_CONSTANT_RT_NS_CHECK 0x10
|
||||
#define IS_CONSTANT_INDEX 0x80
|
||||
|
||||
|
||||
/* overloaded elements data types */
|
||||
|
@ -2143,19 +2143,40 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze
|
||||
*ce_ptr = NULL;
|
||||
*fptr_ptr = NULL;
|
||||
|
||||
if ((colon = strstr(Z_STRVAL_P(callable), "::")) != NULL) {
|
||||
|
||||
if (!ce_org) {
|
||||
/* Skip leading :: */
|
||||
if (Z_STRVAL_P(callable)[0] == ':' &&
|
||||
Z_STRVAL_P(callable)[1] == ':') {
|
||||
mlen = Z_STRLEN_P(callable) - 2;
|
||||
lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + 2, mlen);
|
||||
} else {
|
||||
mlen = Z_STRLEN_P(callable);
|
||||
lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen);
|
||||
}
|
||||
/* Check if function with given name exists.
|
||||
This may be a compound name that includes namespace name */
|
||||
if (zend_hash_find(EG(function_table), lmname, mlen+1, (void**)&fptr) == SUCCESS) {
|
||||
*fptr_ptr = fptr;
|
||||
efree(lmname);
|
||||
return 1;
|
||||
}
|
||||
efree(lmname);
|
||||
}
|
||||
|
||||
/* Split name into class/namespace and method/function names */
|
||||
if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
|
||||
colon > Z_STRVAL_P(callable) &&
|
||||
*(colon-1) == ':') {
|
||||
colon--;
|
||||
clen = colon - Z_STRVAL_P(callable);
|
||||
mlen = Z_STRLEN_P(callable) - clen - 2;
|
||||
lcname = zend_str_tolower_dup(Z_STRVAL_P(callable), clen);
|
||||
/* caution: lcname is not '\0' terminated */
|
||||
if (clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) {
|
||||
*ce_ptr = EG(scope);
|
||||
} else if (clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) {
|
||||
*ce_ptr = EG(scope) ? EG(scope)->parent : NULL;
|
||||
} else if (zend_lookup_class(Z_STRVAL_P(callable), clen, &pce TSRMLS_CC) == SUCCESS) {
|
||||
*ce_ptr = *pce;
|
||||
}
|
||||
efree(lcname);
|
||||
lmname = colon + 2;
|
||||
}
|
||||
if (colon != NULL) {
|
||||
/* This is a compound name.
|
||||
Try to fetch class and then find static method. */
|
||||
*ce_ptr = zend_fetch_class(Z_STRVAL_P(callable), clen, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
|
||||
if (!*ce_ptr) {
|
||||
return 0;
|
||||
}
|
||||
@ -2164,15 +2185,15 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze
|
||||
return 0;
|
||||
}
|
||||
lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + clen + 2, mlen);
|
||||
} else {
|
||||
} else if (ce_org) {
|
||||
/* Try to fetch find static method of given class. */
|
||||
mlen = Z_STRLEN_P(callable);
|
||||
lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen);
|
||||
if (ce_org) {
|
||||
ftable = &ce_org->function_table;
|
||||
*ce_ptr = ce_org;
|
||||
} else {
|
||||
ftable = EG(function_table);
|
||||
}
|
||||
lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
|
||||
ftable = &ce_org->function_table;
|
||||
*ce_ptr = ce_org;
|
||||
} else {
|
||||
/* We already checked for plain function before. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
retval = zend_hash_find(ftable, lmname, mlen+1, (void**)&fptr) == SUCCESS ? 1 : 0;
|
||||
|
@ -543,7 +543,7 @@ ZEND_FUNCTION(defined)
|
||||
}
|
||||
|
||||
convert_to_string_ex(var);
|
||||
if (zend_get_constant(Z_STRVAL_PP(var), Z_STRLEN_PP(var), &c TSRMLS_CC)) {
|
||||
if (zend_get_constant_ex(Z_STRVAL_PP(var), Z_STRLEN_PP(var), &c, NULL, 0 TSRMLS_CC)) {
|
||||
zval_dtor(&c);
|
||||
RETURN_TRUE;
|
||||
} else {
|
||||
@ -744,7 +744,7 @@ static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *re
|
||||
|
||||
/* this is necessary to make it able to work with default array
|
||||
* properties, returned to user */
|
||||
if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || Z_TYPE_P(prop_copy) == IS_CONSTANT) {
|
||||
if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
|
||||
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
@ -138,6 +138,8 @@ void zend_init_compiler_data_structures(TSRMLS_D)
|
||||
CG(handle_op_arrays) = 1;
|
||||
CG(in_compilation) = 0;
|
||||
CG(start_lineno) = 0;
|
||||
CG(current_namespace) = NULL;
|
||||
CG(current_import) = NULL;
|
||||
init_compiler_declarables(TSRMLS_C);
|
||||
zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC);
|
||||
|
||||
@ -384,13 +386,15 @@ void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC)
|
||||
fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
|
||||
}
|
||||
|
||||
void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC)
|
||||
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;
|
||||
|
||||
zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
|
||||
zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
|
||||
if (result->op_type == IS_CV) {
|
||||
init_op(&opline TSRMLS_CC);
|
||||
@ -404,7 +408,7 @@ void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC)
|
||||
opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[result->u.var].name);
|
||||
opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[result->u.var].name_len;
|
||||
SET_UNUSED(opline.op2);
|
||||
opline.op2 = *class_znode;
|
||||
opline.op2 = class_node;
|
||||
opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
|
||||
*result = opline.result;
|
||||
|
||||
@ -424,13 +428,13 @@ void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC)
|
||||
opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[opline_ptr->op1.u.var].name);
|
||||
opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
|
||||
SET_UNUSED(opline.op2);
|
||||
opline.op2 = *class_znode;
|
||||
opline.op2 = class_node;
|
||||
opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
|
||||
opline_ptr->op1 = opline.result;
|
||||
|
||||
zend_llist_prepend_element(fetch_list_ptr, &opline);
|
||||
} else {
|
||||
opline_ptr->op2 = *class_znode;
|
||||
opline_ptr->op2 = class_node;
|
||||
opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
|
||||
}
|
||||
}
|
||||
@ -1170,6 +1174,19 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
|
||||
} else {
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
|
||||
if (CG(current_namespace)) {
|
||||
/* Prefix function name with current namespcae name */
|
||||
znode tmp;
|
||||
|
||||
tmp.u.constant = *CG(current_namespace);
|
||||
zval_copy_ctor(&tmp.u.constant);
|
||||
zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
|
||||
op_array.function_name = Z_STRVAL(tmp.u.constant);
|
||||
efree(lcname);
|
||||
name_len = Z_STRLEN(tmp.u.constant);
|
||||
lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
|
||||
}
|
||||
|
||||
opline->opcode = ZEND_DECLARE_FUNCTION;
|
||||
opline->op1.op_type = IS_CONST;
|
||||
build_runtime_defined_function_key(&opline->op1.u.constant, lcname, name_len TSRMLS_CC);
|
||||
@ -1328,14 +1345,31 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
|
||||
}
|
||||
|
||||
|
||||
int zend_do_begin_function_call(znode *function_name TSRMLS_DC)
|
||||
int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC)
|
||||
{
|
||||
zend_function *function;
|
||||
char *lcname;
|
||||
int prefix_len = 0;
|
||||
|
||||
if (check_namespace && CG(current_namespace)) {
|
||||
/* We assume we call function from the current namespace
|
||||
if it is not prefixed. */
|
||||
znode tmp;
|
||||
|
||||
tmp.op_type = IS_CONST;
|
||||
tmp.u.constant = *CG(current_namespace);
|
||||
zval_copy_ctor(&tmp.u.constant);
|
||||
zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
|
||||
*function_name = tmp;
|
||||
|
||||
/* In run-time PHP will check for function with full name and
|
||||
internal function with short name */
|
||||
prefix_len = Z_STRLEN_P(CG(current_namespace)) + 2;
|
||||
}
|
||||
|
||||
lcname = zend_str_tolower_dup(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
|
||||
if (zend_hash_find(CG(function_table), lcname, function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) {
|
||||
zend_do_begin_dynamic_function_call(function_name TSRMLS_CC);
|
||||
zend_do_begin_dynamic_function_call(function_name, prefix_len TSRMLS_CC);
|
||||
efree(lcname);
|
||||
return 1; /* Dynamic */
|
||||
}
|
||||
@ -1408,7 +1442,7 @@ void zend_do_clone(znode *result, znode *expr TSRMLS_DC)
|
||||
}
|
||||
|
||||
|
||||
void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC)
|
||||
void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC)
|
||||
{
|
||||
unsigned char *ptr = NULL;
|
||||
zend_op *opline;
|
||||
@ -1418,12 +1452,98 @@ void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC)
|
||||
opline->op2 = *function_name;
|
||||
opline->extended_value = 0;
|
||||
|
||||
SET_UNUSED(opline->op1);
|
||||
if (prefix_len) {
|
||||
/* In run-time PHP will check for function with full name and
|
||||
internal function with short name */
|
||||
opline->op1.op_type = IS_CONST;
|
||||
ZVAL_LONG(&opline->op1.u.constant, prefix_len);
|
||||
} else {
|
||||
SET_UNUSED(opline->op1);
|
||||
}
|
||||
|
||||
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
|
||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||
}
|
||||
|
||||
void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_name TSRMLS_DC)
|
||||
{
|
||||
char *compound;
|
||||
char *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 cotains namespace prefix */
|
||||
if (Z_TYPE(class_name->u.constant) == IS_STRING &&
|
||||
Z_STRVAL(class_name->u.constant)[0] == ':') {
|
||||
/* The STRING name has "::" prefix */
|
||||
Z_STRLEN(class_name->u.constant) -= 2;
|
||||
memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+2, Z_STRLEN(class_name->u.constant)+1);
|
||||
Z_STRVAL(class_name->u.constant) = erealloc(
|
||||
Z_STRVAL(class_name->u.constant),
|
||||
Z_STRLEN(class_name->u.constant) + 1);
|
||||
} else if (CG(current_import)) {
|
||||
len = compound - Z_STRVAL(class_name->u.constant);
|
||||
lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), len);
|
||||
/* Check if first part of compound name is an import name */
|
||||
if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
|
||||
/* Substitute import name */
|
||||
tmp.op_type = IS_CONST;
|
||||
tmp.u.constant = **ns;
|
||||
zval_copy_ctor(&tmp.u.constant);
|
||||
len += 2;
|
||||
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;
|
||||
}
|
||||
efree(lcname);
|
||||
}
|
||||
} else if (CG(current_import) || CG(current_namespace)) {
|
||||
/* this is a plain name (without ::) */
|
||||
lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
|
||||
|
||||
if (CG(current_import) &&
|
||||
zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns) == SUCCESS) {
|
||||
/* The given name is an import name. Substitute it. */
|
||||
zval_dtor(&class_name->u.constant);
|
||||
class_name->u.constant = **ns;
|
||||
zval_copy_ctor(&class_name->u.constant);
|
||||
} else if (CG(current_namespace)) {
|
||||
zend_class_entry **pce;
|
||||
|
||||
if (check_ns_name) {
|
||||
char *ns_lcname = zend_str_tolower_dup(Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
|
||||
|
||||
if (Z_STRLEN_P(CG(current_namespace)) == Z_STRLEN(class_name->u.constant) &&
|
||||
memcmp(lcname, ns_lcname, Z_STRLEN(class_name->u.constant)) == 0) {
|
||||
/* The given name is equal to name of current namespace.
|
||||
PHP will need to perform additional cheks at run-time to
|
||||
determine if we assume namespace or class name. */
|
||||
*fetch_type |= ZEND_FETCH_CLASS_RT_NS_NAME;
|
||||
}
|
||||
efree(ns_lcname);
|
||||
}
|
||||
|
||||
if (zend_hash_find(CG(class_table), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&pce) == SUCCESS &&
|
||||
(*pce)->type == ZEND_INTERNAL_CLASS) {
|
||||
/* There is an internal class with the same name exists.
|
||||
PHP will need to perform additional cheks at run-time to
|
||||
determine if we assume class in current namespace or
|
||||
internal one. */
|
||||
*fetch_type |= ZEND_FETCH_CLASS_RT_NS_CHECK;
|
||||
}
|
||||
tmp.op_type = IS_CONST;
|
||||
tmp.u.constant = *CG(current_namespace);
|
||||
zval_copy_ctor(&tmp.u.constant);
|
||||
zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
|
||||
*class_name = tmp;
|
||||
}
|
||||
efree(lcname);
|
||||
}
|
||||
}
|
||||
|
||||
void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC)
|
||||
{
|
||||
@ -1449,6 +1569,7 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC)
|
||||
zval_dtor(&class_name->u.constant);
|
||||
break;
|
||||
default:
|
||||
zend_resolve_class_name(class_name, &opline->extended_value, 0 TSRMLS_CC);
|
||||
opline->op2 = *class_name;
|
||||
break;
|
||||
}
|
||||
@ -1457,7 +1578,7 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC)
|
||||
}
|
||||
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||
opline->result.u.EA.type = opline->extended_value;
|
||||
opline->result.op_type = IS_CONST; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
|
||||
opline->result.op_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
|
||||
*result = opline->result;
|
||||
}
|
||||
|
||||
@ -1482,26 +1603,71 @@ void zend_do_fetch_class_name(znode *result, znode *class_name_entry, znode *cla
|
||||
|
||||
void zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC)
|
||||
{
|
||||
znode class_node;
|
||||
unsigned char *ptr = NULL;
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
zend_op *opline;
|
||||
ulong fetch_type = 0;
|
||||
|
||||
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
|
||||
opline->op1 = *class_name;
|
||||
opline->op2 = *method_name;
|
||||
|
||||
if (opline->op2.op_type == IS_CONST) {
|
||||
char *lcname = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
|
||||
if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(opline->op2.u.constant) &&
|
||||
if (method_name->op_type == IS_CONST) {
|
||||
char *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(&opline->op2.u.constant);
|
||||
SET_UNUSED(opline->op2);
|
||||
zval_dtor(&method_name->u.constant);
|
||||
SET_UNUSED(*method_name);
|
||||
efree(lcname);
|
||||
} else {
|
||||
efree(opline->op2.u.constant.value.str.val);
|
||||
opline->op2.u.constant.value.str.val = lcname;
|
||||
efree(Z_STRVAL(method_name->u.constant));
|
||||
Z_STRVAL(method_name->u.constant) = lcname;
|
||||
}
|
||||
}
|
||||
|
||||
if (class_name->op_type == IS_CONST &&
|
||||
method_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))) {
|
||||
fetch_type = ZEND_FETCH_CLASS_GLOBAL;
|
||||
zend_resolve_class_name(class_name, &fetch_type, 1 TSRMLS_CC);
|
||||
class_node = *class_name;
|
||||
} else {
|
||||
zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
|
||||
}
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
|
||||
opline->extended_value = fetch_type & ~ZEND_FETCH_CLASS_RT_NS_NAME;
|
||||
opline->op1 = class_node;
|
||||
opline->op2 = *method_name;
|
||||
|
||||
if (class_node.op_type == IS_CONST &&
|
||||
method_name->op_type == IS_CONST) {
|
||||
/* Prebuild ns::func name to speedup run-time check.
|
||||
The additional names are stored in additional OP_DATA opcode. */
|
||||
char *nsname, *fname;
|
||||
unsigned int nsname_len, len;
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_OP_DATA;
|
||||
opline->op1.op_type = IS_CONST;
|
||||
SET_UNUSED(opline->op2);
|
||||
|
||||
nsname = Z_STRVAL(class_node.u.constant);
|
||||
nsname_len = Z_STRLEN(class_node.u.constant);
|
||||
if (fetch_type & ZEND_FETCH_CLASS_RT_NS_NAME) {
|
||||
/* Remove namespace name */
|
||||
nsname = (char *)memchr(nsname, ':', nsname_len) + 2;
|
||||
nsname_len -= (nsname - Z_STRVAL(class_node.u.constant));
|
||||
}
|
||||
len = nsname_len + 2 + Z_STRLEN(method_name->u.constant);
|
||||
fname = emalloc(len + 1);
|
||||
memcpy(fname, nsname, nsname_len);
|
||||
fname[nsname_len] = ':';
|
||||
fname[nsname_len + 1] = ':';
|
||||
memcpy(fname + nsname_len + 2,
|
||||
Z_STRVAL(method_name->u.constant),
|
||||
Z_STRLEN(method_name->u.constant)+1);
|
||||
zend_str_tolower(fname, len);
|
||||
opline->extended_value = zend_hash_func(fname, len + 1);
|
||||
ZVAL_STRINGL(&opline->op1.u.constant, fname, len, 0);
|
||||
}
|
||||
|
||||
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
|
||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||
}
|
||||
@ -1779,11 +1945,15 @@ void zend_do_try(znode *try_token TSRMLS_DC)
|
||||
}
|
||||
|
||||
|
||||
void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, zend_bool first_catch TSRMLS_DC)
|
||||
void zend_do_begin_catch(znode *try_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC)
|
||||
{
|
||||
long catch_op_number = get_next_op_number(CG(active_op_array));
|
||||
long catch_op_number;
|
||||
zend_op *opline;
|
||||
znode catch_class;
|
||||
|
||||
zend_do_fetch_class(&catch_class, class_name TSRMLS_CC);
|
||||
|
||||
catch_op_number = get_next_op_number(CG(active_op_array));
|
||||
if (catch_op_number > 0) {
|
||||
opline = &CG(active_op_array)->opcodes[catch_op_number-1];
|
||||
if (opline->opcode == ZEND_FETCH_CLASS) {
|
||||
@ -1791,9 +1961,13 @@ void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var,
|
||||
}
|
||||
}
|
||||
|
||||
if (first_catch) {
|
||||
first_catch->u.opline_num = catch_op_number;
|
||||
}
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_CATCH;
|
||||
opline->op1 = *catch_class;
|
||||
opline->op1 = catch_class;
|
||||
/* SET_UNUSED(opline->op1); */ /* FIXME: Define IS_CLASS or something like that */
|
||||
opline->op2 = *catch_var;
|
||||
opline->op1.u.EA.type = 0; /* 1 means it's the last catch in the block */
|
||||
@ -2798,6 +2972,24 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
|
||||
zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val);
|
||||
}
|
||||
|
||||
/* Class name must not conflict with import names */
|
||||
if (CG(current_import) &&
|
||||
zend_hash_exists(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1)) {
|
||||
zend_error(E_COMPILE_ERROR, "Class name '%s' conflicts with import name", Z_STRVAL(class_name->u.constant));
|
||||
}
|
||||
|
||||
if (CG(current_namespace)) {
|
||||
/* Prefix class name with name of current namespace */
|
||||
znode tmp;
|
||||
|
||||
tmp.u.constant = *CG(current_namespace);
|
||||
zval_copy_ctor(&tmp.u.constant);
|
||||
zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
|
||||
class_name = &tmp;
|
||||
efree(lcname);
|
||||
lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
|
||||
}
|
||||
|
||||
new_class_entry = emalloc(sizeof(zend_class_entry));
|
||||
new_class_entry->type = ZEND_USER_CLASS;
|
||||
new_class_entry->name = class_name->u.constant.value.str.val;
|
||||
@ -2910,11 +3102,13 @@ void zend_do_end_class_declaration(znode *class_token, znode *parent_token TSRML
|
||||
}
|
||||
|
||||
|
||||
void zend_do_implements_interface(znode *interface_znode TSRMLS_DC)
|
||||
void zend_do_implements_interface(znode *interface_name TSRMLS_DC)
|
||||
{
|
||||
znode interface_node;
|
||||
zend_op *opline;
|
||||
|
||||
switch (interface_znode->u.EA.type) {
|
||||
zend_do_fetch_class(&interface_node, interface_name TSRMLS_CC);
|
||||
switch (interface_node.u.EA.type) {
|
||||
case ZEND_FETCH_CLASS_SELF:
|
||||
zend_error(E_COMPILE_ERROR, "Cannot use 'self' as interface name as it is reserved");
|
||||
break;
|
||||
@ -2934,7 +3128,7 @@ void zend_do_implements_interface(znode *interface_znode TSRMLS_DC)
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_ADD_INTERFACE;
|
||||
opline->op1 = CG(implementing_class);
|
||||
opline->op2 = *interface_znode;
|
||||
opline->op2 = interface_node;
|
||||
opline->extended_value = CG(active_class_entry)->num_interfaces++;
|
||||
}
|
||||
|
||||
@ -3204,7 +3398,7 @@ void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_lis
|
||||
*result = CG(active_op_array)->opcodes[new_token->u.opline_num].result;
|
||||
}
|
||||
|
||||
static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC)
|
||||
static zend_constant* zend_get_ct_const(zval *const_name TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_constant *c = NULL;
|
||||
|
||||
@ -3213,14 +3407,27 @@ static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC)
|
||||
|
||||
if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name)+1, (void **) &c)==SUCCESS) {
|
||||
if ((c->flags & CONST_CS) && memcmp(c->name, Z_STRVAL_P(const_name), Z_STRLEN_P(const_name))!=0) {
|
||||
c = NULL;
|
||||
efree(lookup_name);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
c = NULL;
|
||||
efree(lookup_name);
|
||||
return NULL;
|
||||
}
|
||||
efree(lookup_name);
|
||||
}
|
||||
if (c && (c->flags & CONST_CT_SUBST)) {
|
||||
if (c->flags & CONST_CT_SUBST) {
|
||||
return c;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_constant *c = zend_get_ct_const(const_name TSRMLS_CC);
|
||||
|
||||
if (c) {
|
||||
zval_dtor(const_name);
|
||||
result->op_type = IS_CONST;
|
||||
result->u.constant = c->value;
|
||||
@ -3230,26 +3437,62 @@ static int zend_constant_ct_subst(znode *result, zval *const_name TSRMLS_DC)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode TSRMLS_DC)
|
||||
void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
ulong fetch_type = 0;
|
||||
znode tmp;
|
||||
|
||||
switch (mode) {
|
||||
case ZEND_CT:
|
||||
if (constant_container) {
|
||||
if (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, &fetch_type, 1 TSRMLS_CC);
|
||||
}
|
||||
zend_do_fetch_class_name(NULL, constant_container, constant_name TSRMLS_CC);
|
||||
*result = *constant_container;
|
||||
result->u.constant.type = IS_CONSTANT;
|
||||
result->u.constant.type = IS_CONSTANT | fetch_type;
|
||||
} else if (!zend_constant_ct_subst(result, &constant_name->u.constant TSRMLS_CC)) {
|
||||
if (check_namespace && CG(current_namespace)) {
|
||||
/* We assume we use constant from the current namespace
|
||||
if it is not prefixed. */
|
||||
tmp.op_type = IS_CONST;
|
||||
tmp.u.constant = *CG(current_namespace);
|
||||
zval_copy_ctor(&tmp.u.constant);
|
||||
zend_do_build_namespace_name(&tmp, &tmp, constant_name TSRMLS_CC);
|
||||
*constant_name = tmp;
|
||||
fetch_type = IS_CONSTANT_RT_NS_CHECK;
|
||||
}
|
||||
*result = *constant_name;
|
||||
result->u.constant.type = IS_CONSTANT;
|
||||
result->u.constant.type = IS_CONSTANT | fetch_type;
|
||||
}
|
||||
break;
|
||||
case ZEND_RT:
|
||||
if (constant_container ||
|
||||
!zend_constant_ct_subst(result, &constant_name->u.constant TSRMLS_CC)) {
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
zend_op *opline;
|
||||
|
||||
if (constant_container) {
|
||||
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, &fetch_type, 1 TSRMLS_CC);
|
||||
} else {
|
||||
zend_do_fetch_class(&tmp, constant_container TSRMLS_CC);
|
||||
constant_container = &tmp;
|
||||
}
|
||||
} else if (check_namespace && CG(current_namespace)) {
|
||||
/* We assume we use constant from the current namespace
|
||||
if it is not prefixed. */
|
||||
tmp.op_type = IS_CONST;
|
||||
tmp.u.constant = *CG(current_namespace);
|
||||
zval_copy_ctor(&tmp.u.constant);
|
||||
constant_container = &tmp;
|
||||
fetch_type = IS_CONSTANT_RT_NS_CHECK;
|
||||
}
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_FETCH_CONSTANT;
|
||||
opline->extended_value = fetch_type & ~ZEND_FETCH_CLASS_RT_NS_NAME;
|
||||
opline->result.op_type = IS_TMP_VAR;
|
||||
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||
if (constant_container) {
|
||||
@ -3259,6 +3502,35 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
|
||||
}
|
||||
opline->op2 = *constant_name;
|
||||
*result = opline->result;
|
||||
|
||||
if (opline->op1.op_type == IS_CONST) {
|
||||
/* Prebuild ns::func name to speedup run-time check.
|
||||
The additional names are stored in additional OP_DATA opcode. */
|
||||
char *nsname;
|
||||
unsigned int nsname_len;
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_OP_DATA;
|
||||
opline->op1.op_type = IS_CONST;
|
||||
SET_UNUSED(opline->op2);
|
||||
|
||||
nsname = Z_STRVAL(constant_container->u.constant);
|
||||
nsname_len = Z_STRLEN(constant_container->u.constant);
|
||||
if (fetch_type & ZEND_FETCH_CLASS_RT_NS_NAME) {
|
||||
/* Remove namespace name */
|
||||
nsname = (char *)memchr(nsname, ':', nsname_len) + 2;
|
||||
nsname_len -= (nsname - Z_STRVAL(constant_container->u.constant));
|
||||
}
|
||||
|
||||
Z_TYPE(opline->op1.u.constant) = IS_STRING;
|
||||
Z_STRVAL(opline->op1.u.constant) = emalloc(nsname_len + 2 + Z_STRLEN(constant_name->u.constant) + 1);
|
||||
zend_str_tolower_copy(Z_STRVAL(opline->op1.u.constant), nsname, nsname_len);
|
||||
Z_STRVAL(opline->op1.u.constant)[nsname_len] = ':';
|
||||
Z_STRVAL(opline->op1.u.constant)[nsname_len+1] = ':';
|
||||
memcpy(Z_STRVAL(opline->op1.u.constant)+nsname_len+2, Z_STRVAL(constant_name->u.constant), Z_STRLEN(constant_name->u.constant) + 1);
|
||||
Z_STRLEN(opline->op1.u.constant) = nsname_len + 2 + Z_STRLEN(constant_name->u.constant);
|
||||
opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3346,7 +3618,7 @@ void zend_do_add_static_array_element(znode *result, znode *offset, znode *expr)
|
||||
ALLOC_ZVAL(element);
|
||||
*element = expr->u.constant;
|
||||
if (offset) {
|
||||
switch (offset->u.constant.type) {
|
||||
switch (offset->u.constant.type & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_CONSTANT:
|
||||
/* Ugly hack to denote that this value has a constant index */
|
||||
Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
|
||||
@ -4222,10 +4494,10 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
|
||||
int zend_get_class_fetch_type(const char *class_name, uint class_name_len)
|
||||
{
|
||||
if ((class_name_len == sizeof("self")-1) &&
|
||||
!memcmp(class_name, "self", sizeof("self"))) {
|
||||
!memcmp(class_name, "self", sizeof("self")-1)) {
|
||||
return ZEND_FETCH_CLASS_SELF;
|
||||
} else if ((class_name_len == sizeof("parent")-1) &&
|
||||
!memcmp(class_name, "parent", sizeof("parent"))) {
|
||||
!memcmp(class_name, "parent", sizeof("parent")-1)) {
|
||||
return ZEND_FETCH_CLASS_PARENT;
|
||||
} else {
|
||||
return ZEND_FETCH_CLASS_DEFAULT;
|
||||
@ -4240,6 +4512,159 @@ ZEND_API char* zend_get_compiled_variable_name(zend_op_array *op_array, zend_uin
|
||||
return op_array->vars[var].name;
|
||||
}
|
||||
|
||||
void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
int len;
|
||||
|
||||
if (prefix) {
|
||||
*result = *prefix;
|
||||
} else {
|
||||
result->op_type = IS_CONST;
|
||||
Z_TYPE(result->u.constant) = IS_STRING;
|
||||
Z_STRVAL(result->u.constant) = NULL;
|
||||
Z_STRLEN(result->u.constant) = 0;
|
||||
}
|
||||
len = Z_STRLEN(result->u.constant) + 2 + Z_STRLEN(name->u.constant);
|
||||
Z_STRVAL(result->u.constant) = erealloc(Z_STRVAL(result->u.constant), len + 1);
|
||||
Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)] = ':';
|
||||
Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)+1] = ':';
|
||||
memcpy(Z_STRVAL(result->u.constant)+Z_STRLEN(result->u.constant)+2,
|
||||
Z_STRVAL(name->u.constant),
|
||||
Z_STRLEN(name->u.constant)+1);
|
||||
Z_STRLEN(result->u.constant) = len;
|
||||
zval_dtor(&name->u.constant);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_namespace(znode *name TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *lcname;
|
||||
|
||||
if (CG(active_op_array)->last > 0) {
|
||||
/* ignore ZEND_EXT_STMT */
|
||||
int num = CG(active_op_array)->last;
|
||||
while (num > 0 &&
|
||||
CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT) {
|
||||
--num;
|
||||
}
|
||||
if (num > 0) {
|
||||
zend_error(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script");
|
||||
}
|
||||
}
|
||||
if (CG(current_namespace)) {
|
||||
zend_error(E_COMPILE_ERROR, "Namespace cannot be declared twice");
|
||||
}
|
||||
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(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant));
|
||||
}
|
||||
efree(lcname);
|
||||
|
||||
ALLOC_ZVAL(CG(current_namespace));
|
||||
*CG(current_namespace) = name->u.constant;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_import(znode *ns_name, znode *new_name TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *lcname;
|
||||
zval *name, *ns, tmp;
|
||||
zend_bool warn = 0;
|
||||
|
||||
if (!CG(current_import)) {
|
||||
CG(current_import) = emalloc(sizeof(HashTable));
|
||||
zend_hash_init(CG(current_import), 0, NULL, ZVAL_PTR_DTOR, 0);
|
||||
}
|
||||
|
||||
ALLOC_ZVAL(ns);
|
||||
*ns = ns_name->u.constant;
|
||||
if (new_name) {
|
||||
name = &new_name->u.constant;
|
||||
} else {
|
||||
char *p;
|
||||
|
||||
/* The form "import A::B" is eqivalent to "import A::B as B".
|
||||
So we extract the last part of compound name ti use as a new_name */
|
||||
name = &tmp;
|
||||
p = zend_memrchr(Z_STRVAL_P(ns), ':', Z_STRLEN_P(ns));
|
||||
if (p) {
|
||||
ZVAL_STRING(name, p+1, 1);
|
||||
} else {
|
||||
*name = *ns;
|
||||
zval_copy_ctor(name);
|
||||
warn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
lcname = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
|
||||
|
||||
if (((Z_STRLEN_P(name) == sizeof("self")-1) &&
|
||||
!memcmp(lcname, "self", sizeof("self")-1)) ||
|
||||
((Z_STRLEN_P(name) == sizeof("parent")-1) &&
|
||||
!memcmp(lcname, "parent", sizeof("parent")-1))) {
|
||||
zend_error(E_COMPILE_ERROR, "Cannot use '%s' as import name", Z_STRVAL_P(name));
|
||||
}
|
||||
|
||||
if (zend_hash_exists(CG(class_table), lcname, Z_STRLEN_P(name)+1)) {
|
||||
zend_error(E_COMPILE_ERROR, "Import name '%s' conflicts with defined class", Z_STRVAL_P(name));
|
||||
}
|
||||
|
||||
if (zend_hash_add(CG(current_import), lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
|
||||
zend_error(E_COMPILE_ERROR, "Cannot reuse import name");
|
||||
}
|
||||
if (warn) {
|
||||
zend_error(E_WARNING, "The import statement with non-compound name '%s' has no effect", Z_STRVAL_P(name));
|
||||
}
|
||||
efree(lcname);
|
||||
zval_dtor(name);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_op *opline;
|
||||
|
||||
if (zend_get_ct_const(&name->u.constant TSRMLS_CC)) {
|
||||
zend_error(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", Z_STRVAL(name->u.constant));
|
||||
}
|
||||
|
||||
if (CG(current_namespace)) {
|
||||
/* Prefix constant name with name of current namespace */
|
||||
znode tmp;
|
||||
|
||||
tmp.op_type = IS_CONST;
|
||||
tmp.u.constant = *CG(current_namespace);
|
||||
Z_STRVAL(tmp.u.constant) = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), Z_STRLEN(tmp.u.constant));
|
||||
zend_do_build_namespace_name(&tmp, &tmp, name TSRMLS_CC);
|
||||
*name = tmp;
|
||||
}
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_DECLARE_CONST;
|
||||
SET_UNUSED(opline->result);
|
||||
opline->op1 = *name;
|
||||
opline->op2 = *value;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_end_compilation(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
if (CG(current_namespace)) {
|
||||
zval_dtor(CG(current_namespace));
|
||||
efree(CG(current_namespace));
|
||||
CG(current_namespace) = NULL;
|
||||
}
|
||||
if (CG(current_import)) {
|
||||
zend_hash_destroy(CG(current_import));
|
||||
efree(CG(current_import));
|
||||
CG(current_import) = NULL;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
@ -399,10 +399,10 @@ int zend_do_verify_access_types(znode *current_access_type, 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(znode *function_token TSRMLS_DC);
|
||||
void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, znode *class_type, znode *varname, zend_bool pass_by_reference TSRMLS_DC);
|
||||
int zend_do_begin_function_call(znode *function_name 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 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_fetch_class_name(znode *result, znode *class_entry, znode *class_name TSRMLS_DC);
|
||||
void zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC);
|
||||
@ -411,7 +411,7 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
|
||||
void zend_do_handle_exception(TSRMLS_D);
|
||||
|
||||
void zend_do_try(znode *try_token TSRMLS_DC);
|
||||
void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, zend_bool first_catch TSRMLS_DC);
|
||||
void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, znode *first_catch TSRMLS_DC);
|
||||
void zend_do_end_catch(znode *try_token TSRMLS_DC);
|
||||
void zend_do_throw(znode *expr TSRMLS_DC);
|
||||
|
||||
@ -458,7 +458,7 @@ 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, znode *new_token, znode *argument_list TSRMLS_DC);
|
||||
|
||||
void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode 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);
|
||||
|
||||
@ -504,6 +504,12 @@ void zend_do_ticks(TSRMLS_D);
|
||||
|
||||
void zend_do_abstract_method(znode *function_name, znode *modifiers, 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_namespace(znode *name TSRMLS_DC);
|
||||
void zend_do_import(znode *name, znode *new_name TSRMLS_DC);
|
||||
void zend_do_end_compilation(TSRMLS_D);
|
||||
|
||||
ZEND_API void function_add_ref(zend_function *function);
|
||||
|
||||
#define INITIAL_OP_ARRAY_SIZE 64
|
||||
@ -591,6 +597,8 @@ int zendlex(znode *zendlval TSRMLS_DC);
|
||||
#define ZEND_FETCH_CLASS_GLOBAL 4
|
||||
#define ZEND_FETCH_CLASS_AUTO 5
|
||||
#define ZEND_FETCH_CLASS_INTERFACE 6
|
||||
#define ZEND_FETCH_CLASS_RT_NS_CHECK 0x20
|
||||
#define ZEND_FETCH_CLASS_RT_NS_NAME 0x40
|
||||
#define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80
|
||||
|
||||
/* variable parsing type (compile-time) */
|
||||
|
@ -213,87 +213,29 @@ ZEND_API void zend_register_string_constant(char *name, uint name_len, char *str
|
||||
}
|
||||
|
||||
|
||||
ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC)
|
||||
ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC)
|
||||
{
|
||||
zend_constant *c;
|
||||
int retval = 1;
|
||||
char *lookup_name;
|
||||
char *colon;
|
||||
|
||||
if ((colon = memchr(name, ':', name_len)) && colon[1] == ':') {
|
||||
/* class constant */
|
||||
zend_class_entry **ce = NULL;
|
||||
int class_name_len = colon-name;
|
||||
int const_name_len = name_len - class_name_len - 2;
|
||||
char *constant_name = colon+2;
|
||||
zval **ret_constant;
|
||||
char *class_name;
|
||||
|
||||
if (!scope) {
|
||||
if (EG(in_execution)) {
|
||||
scope = EG(scope);
|
||||
} else {
|
||||
scope = CG(active_class_entry);
|
||||
}
|
||||
}
|
||||
|
||||
class_name = estrndup(name, class_name_len);
|
||||
|
||||
if (class_name_len == sizeof("self")-1 && strcmp(class_name, "self") == 0) {
|
||||
if (scope) {
|
||||
ce = &scope;
|
||||
} else {
|
||||
zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
|
||||
retval = 0;
|
||||
}
|
||||
} else if (class_name_len == sizeof("parent")-1 && strcmp(class_name, "parent") == 0) {
|
||||
if (!scope) {
|
||||
zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
|
||||
} else if (!scope->parent) {
|
||||
zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
|
||||
} else {
|
||||
ce = &scope->parent;
|
||||
}
|
||||
} else {
|
||||
if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS) {
|
||||
retval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval && ce) {
|
||||
if (zend_hash_find(&((*ce)->constants_table), constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
|
||||
retval = 0;
|
||||
}
|
||||
} else {
|
||||
zend_error(E_ERROR, "Class '%s' not found", class_name);
|
||||
retval = 0;
|
||||
}
|
||||
efree(class_name);
|
||||
|
||||
if (retval) {
|
||||
zval_update_constant_ex(ret_constant, (void*)1, *ce TSRMLS_CC);
|
||||
*result = **ret_constant;
|
||||
zval_copy_ctor(result);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
|
||||
lookup_name = estrndup(name, name_len);
|
||||
zend_str_tolower(lookup_name, name_len);
|
||||
|
||||
lookup_name = zend_str_tolower_dup(name, name_len);
|
||||
|
||||
if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) {
|
||||
if ((c->flags & CONST_CS) && memcmp(c->name, name, name_len)!=0) {
|
||||
if ((c->flags & CONST_CS) && memcmp(c->name, name, name_len) != 0) {
|
||||
retval=0;
|
||||
}
|
||||
} else {
|
||||
char haltoff[] = "__COMPILER_HALT_OFFSET__";
|
||||
static char haltoff[] = "__COMPILER_HALT_OFFSET__";
|
||||
|
||||
if (!EG(in_execution)) {
|
||||
retval = 0;
|
||||
} else if (name_len == sizeof("__COMPILER_HALT_OFFSET__") - 1 && memcmp(haltoff, name, name_len) == 0) {
|
||||
} else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
|
||||
!memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
|
||||
char *cfilename, *haltname;
|
||||
int len, clen;
|
||||
|
||||
cfilename = zend_get_executed_filename(TSRMLS_C);
|
||||
clen = strlen(cfilename);
|
||||
/* check for __COMPILER_HALT_OFFSET__ */
|
||||
@ -306,7 +248,7 @@ ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_
|
||||
}
|
||||
pefree(haltname, 0);
|
||||
} else {
|
||||
retval = 0;
|
||||
retval=0;
|
||||
}
|
||||
}
|
||||
efree(lookup_name);
|
||||
@ -322,9 +264,122 @@ ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC)
|
||||
ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC)
|
||||
{
|
||||
return zend_get_constant_ex(name, name_len, result, NULL TSRMLS_CC);
|
||||
zend_constant *c;
|
||||
int retval = 1;
|
||||
char *colon;
|
||||
|
||||
/* Skip leading :: */
|
||||
if (name[0] == ':' && name[1] == ':') {
|
||||
name += 2;
|
||||
name_len -= 2;
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
|
||||
if ((colon = zend_memrchr(name, ':', name_len)) &&
|
||||
colon > name &&
|
||||
*(colon-1) == ':') {
|
||||
/* compound constant name */
|
||||
zend_class_entry *ce = NULL;
|
||||
int class_name_len = colon - name - 1;
|
||||
int const_name_len = name_len - class_name_len - 2;
|
||||
char *constant_name = constant_name = colon + 1;
|
||||
char *class_name = estrndup(name, class_name_len);
|
||||
char *lcname = zend_str_tolower_dup(class_name, class_name_len);
|
||||
zval **ret_constant;
|
||||
|
||||
if (!scope) {
|
||||
if (EG(in_execution)) {
|
||||
scope = EG(scope);
|
||||
} else {
|
||||
scope = CG(active_class_entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (class_name_len == sizeof("self")-1 &&
|
||||
!memcmp(lcname, "self", sizeof("self")-1)) {
|
||||
if (scope) {
|
||||
ce = scope;
|
||||
} else {
|
||||
zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
|
||||
retval = 0;
|
||||
}
|
||||
efree(lcname);
|
||||
} else if (class_name_len == sizeof("parent")-1 &&
|
||||
!memcmp(lcname, "parent", sizeof("parent")-1)) {
|
||||
if (!scope) {
|
||||
zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
|
||||
} else if (!scope->parent) {
|
||||
zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
|
||||
} else {
|
||||
ce = scope->parent;
|
||||
}
|
||||
efree(lcname);
|
||||
} else {
|
||||
/* Check for namespace constant */
|
||||
char *nsname;
|
||||
unsigned int nsname_len;
|
||||
|
||||
/* Concatenate lowercase namespace name and constant name */
|
||||
lcname = erealloc(lcname, class_name_len + 2 + const_name_len + 1);
|
||||
lcname[class_name_len] = ':';
|
||||
lcname[class_name_len+1] = ':';
|
||||
memcpy(lcname + class_name_len + 2, constant_name, const_name_len + 1);
|
||||
|
||||
nsname = lcname;
|
||||
nsname_len = class_name_len + 2 + const_name_len;
|
||||
if (flags & ZEND_FETCH_CLASS_RT_NS_NAME) {
|
||||
nsname = (char *)memchr(nsname, ':', nsname_len) + 2;
|
||||
nsname_len -= (nsname - lcname);
|
||||
}
|
||||
|
||||
if (zend_hash_find(EG(zend_constants), nsname, nsname_len+1, (void **) &c) == SUCCESS) {
|
||||
efree(lcname);
|
||||
efree(class_name);
|
||||
*result = c->value;
|
||||
zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC);
|
||||
zval_copy_ctor(result);
|
||||
result->refcount = 1;
|
||||
result->is_ref = 0;
|
||||
return 1;
|
||||
}
|
||||
efree(lcname);
|
||||
|
||||
/* Check for class */
|
||||
ce = zend_fetch_class(class_name, class_name_len, flags TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (retval && ce) {
|
||||
if (zend_hash_find(&ce->constants_table, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
|
||||
retval = 0;
|
||||
}
|
||||
} else {
|
||||
if ((flags & ZEND_FETCH_CLASS_RT_NS_NAME) == 0) {
|
||||
if ((flags & IS_CONSTANT_RT_NS_CHECK) != 0) {
|
||||
name = constant_name;
|
||||
name_len = const_name_len;
|
||||
efree(class_name);
|
||||
retval = 1;
|
||||
return zend_get_constant(name, name_len, result TSRMLS_CC);
|
||||
}
|
||||
zend_error(E_ERROR, "Class '%s' not found", class_name);
|
||||
}
|
||||
retval = 0;
|
||||
}
|
||||
efree(class_name);
|
||||
|
||||
if (retval) {
|
||||
zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
|
||||
*result = **ret_constant;
|
||||
zval_copy_ctor(result);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
return zend_get_constant(name, name_len, result TSRMLS_CC);
|
||||
}
|
||||
|
||||
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
|
||||
|
@ -56,7 +56,7 @@ int zend_shutdown_constants(TSRMLS_D);
|
||||
void zend_register_standard_constants(TSRMLS_D);
|
||||
void clean_non_persistent_constants(TSRMLS_D);
|
||||
ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC);
|
||||
ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC);
|
||||
ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC);
|
||||
ZEND_API void zend_register_long_constant(char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC);
|
||||
ZEND_API void zend_register_double_constant(char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC);
|
||||
ZEND_API void zend_register_string_constant(char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC);
|
||||
|
@ -461,7 +461,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
|
||||
|
||||
if (IS_CONSTANT_VISITED(p)) {
|
||||
zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
|
||||
} else if (Z_TYPE_P(p) == IS_CONSTANT) {
|
||||
} else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
|
||||
int refcount;
|
||||
zend_uchar is_ref;
|
||||
|
||||
@ -473,7 +473,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
|
||||
refcount = p->refcount;
|
||||
is_ref = p->is_ref;
|
||||
|
||||
if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope TSRMLS_CC)) {
|
||||
if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_TYPE_P(p) TSRMLS_CC)) {
|
||||
if ((colon = memchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p))) && colon[1] == ':') {
|
||||
zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
|
||||
}
|
||||
@ -515,7 +515,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
|
||||
zend_hash_move_forward(Z_ARRVAL_P(p));
|
||||
continue;
|
||||
}
|
||||
if (!zend_get_constant_ex(str_index, str_index_len-1, &const_value, scope TSRMLS_CC)) {
|
||||
if (!zend_get_constant_ex(str_index, str_index_len-1, &const_value, scope, 0 TSRMLS_CC)) {
|
||||
if ((colon = memchr(str_index, ':', str_index_len-1)) && colon[1] == ':') {
|
||||
zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
|
||||
}
|
||||
@ -636,6 +636,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
int call_via_handler = 0;
|
||||
char *fname, *colon;
|
||||
int fname_len;
|
||||
char *lcname;
|
||||
|
||||
*fci->retval_ptr_ptr = NULL;
|
||||
|
||||
@ -766,68 +767,76 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
|
||||
fname = Z_STRVAL_P(fci->function_name);
|
||||
fname_len = Z_STRLEN_P(fci->function_name);
|
||||
if ((colon = strstr(fname, "::")) != NULL) {
|
||||
int clen = colon - fname;
|
||||
int mlen = fname_len - clen - 2;
|
||||
zend_class_entry **pce, *ce_child = NULL;
|
||||
if (zend_lookup_class(fname, clen, &pce TSRMLS_CC) == SUCCESS) {
|
||||
ce_child = *pce;
|
||||
} else {
|
||||
char *lcname = zend_str_tolower_dup(fname, clen);
|
||||
/* caution: lcname is not '\0' terminated */
|
||||
if (calling_scope) {
|
||||
if (clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) {
|
||||
ce_child = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
|
||||
} else if (clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) {
|
||||
ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL;
|
||||
}
|
||||
}
|
||||
efree(lcname);
|
||||
}
|
||||
if (!ce_child) {
|
||||
zend_error(E_ERROR, "Cannot call method %s() or method does not exist", fname);
|
||||
return FAILURE;
|
||||
}
|
||||
check_scope_or_static = calling_scope;
|
||||
fci->function_table = &ce_child->function_table;
|
||||
calling_scope = ce_child;
|
||||
fname = fname + clen + 2;
|
||||
fname_len = mlen;
|
||||
if (fname[0] == ':' && fname[1] == ':') {
|
||||
fname += 2;
|
||||
fname_len -=2;
|
||||
}
|
||||
|
||||
if (fci->object_pp) {
|
||||
if (Z_OBJ_HT_PP(fci->object_pp)->get_method == NULL) {
|
||||
zend_error(E_ERROR, "Object does not support method calls");
|
||||
}
|
||||
EX(function_state).function =
|
||||
Z_OBJ_HT_PP(fci->object_pp)->get_method(fci->object_pp, fname, fname_len TSRMLS_CC);
|
||||
if (EX(function_state).function && calling_scope != EX(function_state).function->common.scope) {
|
||||
char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
|
||||
if (zend_hash_find(&calling_scope->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
|
||||
efree(function_name_lc);
|
||||
zend_error(E_ERROR, "Cannot call method %s::%s() or method does not exist", calling_scope->name, fname);
|
||||
}
|
||||
efree(function_name_lc);
|
||||
}
|
||||
} else if (calling_scope) {
|
||||
char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
|
||||
|
||||
EX(function_state).function =
|
||||
zend_std_get_static_method(calling_scope, function_name_lc, fname_len TSRMLS_CC);
|
||||
efree(function_name_lc);
|
||||
if (check_scope_or_static && EX(function_state).function
|
||||
&& !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)
|
||||
&& !instanceof_function(check_scope_or_static, calling_scope TSRMLS_CC)) {
|
||||
zend_error(E_ERROR, "Cannot call method %s() of class %s which is not a derived from %s", fname, calling_scope->name, check_scope_or_static->name);
|
||||
return FAILURE;
|
||||
}
|
||||
lcname = zend_str_tolower_dup(fname, fname_len);
|
||||
EX(function_state).function = NULL;
|
||||
if (!fci->object_pp &&
|
||||
zend_hash_find(fci->function_table, lcname, fname_len+1, (void**)&EX(function_state).function) == SUCCESS) {
|
||||
efree(lcname);
|
||||
} else {
|
||||
char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
|
||||
efree(lcname);
|
||||
if ((colon = zend_memrchr(fname, ':', fname_len)) != NULL &&
|
||||
colon > fname &&
|
||||
*(colon-1) == ':') {
|
||||
int clen = colon - fname - 1;
|
||||
int mlen = fname_len - clen - 2;
|
||||
|
||||
if (zend_hash_find(fci->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
|
||||
EX(function_state).function = NULL;
|
||||
zend_class_entry **pce, *ce_child = NULL;
|
||||
if (zend_lookup_class(fname, clen, &pce TSRMLS_CC) == SUCCESS) {
|
||||
ce_child = *pce;
|
||||
} else {
|
||||
char *lcname = zend_str_tolower_dup(fname, clen);
|
||||
/* caution: lcname is not '\0' terminated */
|
||||
if (calling_scope) {
|
||||
if (clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) {
|
||||
ce_child = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
|
||||
} else if (clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) {
|
||||
ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL;
|
||||
}
|
||||
}
|
||||
efree(lcname);
|
||||
}
|
||||
if (!ce_child) {
|
||||
zend_error(E_ERROR, "Cannot call method %s() or method does not exist", fname);
|
||||
return FAILURE;
|
||||
}
|
||||
check_scope_or_static = calling_scope;
|
||||
fci->function_table = &ce_child->function_table;
|
||||
calling_scope = ce_child;
|
||||
fname = fname + clen + 2;
|
||||
fname_len = mlen;
|
||||
}
|
||||
|
||||
if (fci->object_pp) {
|
||||
if (Z_OBJ_HT_PP(fci->object_pp)->get_method == NULL) {
|
||||
zend_error(E_ERROR, "Object does not support method calls");
|
||||
}
|
||||
EX(function_state).function =
|
||||
Z_OBJ_HT_PP(fci->object_pp)->get_method(fci->object_pp, fname, fname_len TSRMLS_CC);
|
||||
if (EX(function_state).function && calling_scope != EX(function_state).function->common.scope) {
|
||||
char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
|
||||
if (zend_hash_find(&calling_scope->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
|
||||
efree(function_name_lc);
|
||||
zend_error(E_ERROR, "Cannot call method %s::%s() or method does not exist", calling_scope->name, fname);
|
||||
}
|
||||
efree(function_name_lc);
|
||||
}
|
||||
} else if (calling_scope) {
|
||||
char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
|
||||
|
||||
EX(function_state).function =
|
||||
zend_std_get_static_method(calling_scope, function_name_lc, fname_len TSRMLS_CC);
|
||||
efree(function_name_lc);
|
||||
if (check_scope_or_static && EX(function_state).function
|
||||
&& !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)
|
||||
&& !instanceof_function(check_scope_or_static, calling_scope TSRMLS_CC)) {
|
||||
zend_error(E_ERROR, "Cannot call method %s() of class %s which is not a derived from %s", fname, calling_scope->name, check_scope_or_static->name);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
efree(function_name_lc);
|
||||
}
|
||||
|
||||
if (EX(function_state).function == NULL) {
|
||||
@ -1033,6 +1042,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
|
||||
zval *retval_ptr = NULL;
|
||||
int retval;
|
||||
char *lc_name;
|
||||
char *lc_free;
|
||||
zval *exception;
|
||||
char dummy = 1;
|
||||
zend_fcall_info fcall_info;
|
||||
@ -1042,11 +1052,16 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
lc_name = do_alloca(name_length + 1);
|
||||
lc_free = lc_name = do_alloca(name_length + 1);
|
||||
zend_str_tolower_copy(lc_name, name, name_length);
|
||||
|
||||
if (lc_name[0] == ':' && lc_name[1] == ':') {
|
||||
lc_name += 2;
|
||||
name_length -= 2;
|
||||
}
|
||||
|
||||
if (zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce) == SUCCESS) {
|
||||
free_alloca(lc_name);
|
||||
free_alloca(lc_free);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -1054,7 +1069,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
|
||||
* (doesn't impact fuctionality of __autoload()
|
||||
*/
|
||||
if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
|
||||
free_alloca(lc_name);
|
||||
free_alloca(lc_free);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@ -1064,7 +1079,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
|
||||
}
|
||||
|
||||
if (zend_hash_add(EG(in_autoload), lc_name, name_length+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
|
||||
free_alloca(lc_name);
|
||||
free_alloca(lc_free);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@ -1102,12 +1117,12 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
|
||||
|
||||
if (retval == FAILURE) {
|
||||
EG(exception) = exception;
|
||||
free_alloca(lc_name);
|
||||
free_alloca(lc_free);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (EG(exception) && exception) {
|
||||
free_alloca(lc_name);
|
||||
free_alloca(lc_free);
|
||||
zend_error(E_ERROR, "Function %s(%s) threw an exception of type '%s'", ZEND_AUTOLOAD_FUNC_NAME, name, Z_OBJCE_P(EG(exception))->name);
|
||||
return FAILURE;
|
||||
}
|
||||
@ -1119,7 +1134,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
|
||||
}
|
||||
|
||||
retval = zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce);
|
||||
free_alloca(lc_name);
|
||||
free_alloca(lc_free);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -1475,6 +1490,7 @@ zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len,
|
||||
{
|
||||
zend_class_entry **pce;
|
||||
int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0;
|
||||
int rt_ns_check = (fetch_type & ZEND_FETCH_CLASS_RT_NS_CHECK) ? 1 : 0;
|
||||
|
||||
fetch_type = fetch_type & ~ZEND_FETCH_CLASS_NO_AUTOLOAD;
|
||||
check_fetch_type:
|
||||
@ -1501,8 +1517,30 @@ check_fetch_type:
|
||||
break;
|
||||
}
|
||||
|
||||
if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC)==FAILURE) {
|
||||
if (zend_lookup_class_ex(class_name, class_name_len, (!rt_ns_check & use_autoload), &pce TSRMLS_CC)==FAILURE) {
|
||||
if (rt_ns_check) {
|
||||
/* Check if we have internal class with the same name */
|
||||
char *php_name;
|
||||
uint php_name_len;
|
||||
|
||||
php_name = zend_memrchr(class_name, ':', class_name_len);
|
||||
if (php_name) {
|
||||
php_name++;
|
||||
php_name_len = class_name_len-(php_name-class_name);
|
||||
php_name = zend_str_tolower_dup(php_name, php_name_len);
|
||||
if (zend_hash_find(EG(class_table), php_name, php_name_len+1, (void **) &pce) == SUCCESS &&
|
||||
(*pce)->type == ZEND_INTERNAL_CLASS) {
|
||||
efree(php_name);
|
||||
return *pce;
|
||||
}
|
||||
efree(php_name);
|
||||
}
|
||||
}
|
||||
if (use_autoload) {
|
||||
if (rt_ns_check &&
|
||||
zend_lookup_class_ex(class_name, class_name_len, 1, &pce TSRMLS_CC)==SUCCESS) {
|
||||
return *pce;
|
||||
}
|
||||
if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
|
||||
zend_error(E_ERROR, "Interface '%s' not found", class_name);
|
||||
} else {
|
||||
|
@ -130,6 +130,9 @@ struct _zend_compiler_globals {
|
||||
char *doc_comment;
|
||||
zend_uint doc_comment_len;
|
||||
|
||||
zval *current_namespace;
|
||||
HashTable *current_import;
|
||||
|
||||
#ifdef ZEND_MULTIBYTE
|
||||
zend_encoding **script_encoding_list;
|
||||
int script_encoding_list_size;
|
||||
|
@ -143,11 +143,14 @@
|
||||
%token T_DOLLAR_OPEN_CURLY_BRACES
|
||||
%token T_CURLY_OPEN
|
||||
%token T_PAAMAYIM_NEKUDOTAYIM
|
||||
%token T_NAMESPACE
|
||||
%token T_IMPORT
|
||||
%token T_NS_C
|
||||
|
||||
%% /* Rules */
|
||||
|
||||
start:
|
||||
top_statement_list
|
||||
top_statement_list { zend_do_end_compilation(TSRMLS_C); }
|
||||
;
|
||||
|
||||
top_statement_list:
|
||||
@ -155,14 +158,26 @@ top_statement_list:
|
||||
| /* empty */
|
||||
;
|
||||
|
||||
namespace_name:
|
||||
T_STRING { $$ = $1; }
|
||||
| namespace_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
top_statement:
|
||||
statement
|
||||
| function_declaration_statement { zend_do_early_binding(TSRMLS_C); }
|
||||
| class_declaration_statement { zend_do_early_binding(TSRMLS_C); }
|
||||
| T_HALT_COMPILER '(' ')' ';' { zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
|
||||
| T_HALT_COMPILER '(' ')' ';' { zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
|
||||
| T_NAMESPACE namespace_name ';' { zend_do_namespace(&$2 TSRMLS_CC); }
|
||||
| T_IMPORT namespace_name ';' { zend_do_import(&$2, NULL TSRMLS_CC); }
|
||||
| T_IMPORT namespace_name T_AS T_STRING ';' { zend_do_import(&$2, &$4 TSRMLS_CC); }
|
||||
| constant_declaration ';'
|
||||
;
|
||||
|
||||
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); }
|
||||
;
|
||||
|
||||
inner_statement_list:
|
||||
inner_statement_list { zend_do_extended_info(TSRMLS_C); } inner_statement { HANDLE_INTERACTIVE(); }
|
||||
@ -225,7 +240,7 @@ unticked_statement:
|
||||
| T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
|
||||
T_CATCH '(' { zend_initialize_try_catch_element(&$1 TSRMLS_CC); }
|
||||
fully_qualified_class_name { zend_do_first_catch(&$7 TSRMLS_CC); }
|
||||
T_VARIABLE ')' { zend_do_begin_catch(&$1, &$9, &$11, 1 TSRMLS_CC); }
|
||||
T_VARIABLE ')' { zend_do_begin_catch(&$1, &$9, &$11, &$7 TSRMLS_CC); }
|
||||
'{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
|
||||
additional_catches { zend_do_mark_last_catch(&$7, &$18 TSRMLS_CC); }
|
||||
| T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); }
|
||||
@ -244,7 +259,7 @@ non_empty_additional_catches:
|
||||
|
||||
|
||||
additional_catch:
|
||||
T_CATCH '(' fully_qualified_class_name { $$.u.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
|
||||
T_CATCH '(' fully_qualified_class_name { $$.u.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); }
|
||||
;
|
||||
|
||||
|
||||
@ -307,7 +322,7 @@ class_entry_type:
|
||||
|
||||
extends_from:
|
||||
/* empty */ { $$.op_type = IS_UNUSED; }
|
||||
| T_EXTENDS fully_qualified_class_name { $$ = $2; }
|
||||
| T_EXTENDS fully_qualified_class_name { zend_do_fetch_class(&$$, &$2 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
interface_entry:
|
||||
@ -621,9 +636,12 @@ expr_without_variable:
|
||||
;
|
||||
|
||||
function_call:
|
||||
T_STRING '(' { $2.u.opline_num = zend_do_begin_function_call(&$1 TSRMLS_CC); }
|
||||
T_STRING '(' { $2.u.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); }
|
||||
function_call_parameter_list
|
||||
')' { zend_do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
|
||||
| T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { $3.u.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); }
|
||||
function_call_parameter_list
|
||||
')' { zend_do_end_function_call(&$2, &$$, &$5, 0, $3.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
|
||||
| fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
|
||||
function_call_parameter_list
|
||||
')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
|
||||
@ -636,17 +654,19 @@ function_call:
|
||||
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(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, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
|
||||
| variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1 TSRMLS_CC); }
|
||||
| variable_without_objects '(' { zend_do_end_variable_parse(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, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
|
||||
;
|
||||
|
||||
fully_qualified_class_name:
|
||||
T_STRING { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
|
||||
T_STRING { $$ = $1; }
|
||||
| T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, NULL, &$2 TSRMLS_CC); }
|
||||
| fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
class_name_reference:
|
||||
T_STRING { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
|
||||
fully_qualified_class_name { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
|
||||
| dynamic_class_name_reference { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
@ -691,12 +711,14 @@ common_scalar:
|
||||
| T_CLASS_C { $$ = $1; }
|
||||
| T_METHOD_C { $$ = $1; }
|
||||
| T_FUNC_C { $$ = $1; }
|
||||
| T_NS_C { $$ = $1; }
|
||||
;
|
||||
|
||||
|
||||
static_scalar: /* compile-time evaluated scalars */
|
||||
common_scalar { $$ = $1; }
|
||||
| T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT TSRMLS_CC); }
|
||||
| T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); }
|
||||
| T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); }
|
||||
| '+' static_scalar { $$ = $2; }
|
||||
| '-' static_scalar { zval minus_one; Z_TYPE(minus_one) = IS_LONG; Z_LVAL(minus_one) = -1; mul_function(&$2.u.constant, &$2.u.constant, &minus_one TSRMLS_CC); $$ = $2; }
|
||||
| T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
|
||||
@ -704,11 +726,12 @@ static_scalar: /* compile-time evaluated scalars */
|
||||
;
|
||||
|
||||
static_class_constant:
|
||||
T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT TSRMLS_CC); }
|
||||
fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
scalar:
|
||||
T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT TSRMLS_CC); }
|
||||
T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC); }
|
||||
| T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); }
|
||||
| T_STRING_VARNAME { $$ = $1; }
|
||||
| class_constant { $$ = $1; }
|
||||
| common_scalar { $$ = $1; }
|
||||
@ -792,7 +815,7 @@ static_member:
|
||||
;
|
||||
|
||||
variable_class_name:
|
||||
reference_variable { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
|
||||
reference_variable { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); $$=$1;; }
|
||||
;
|
||||
|
||||
base_variable_with_function_calls:
|
||||
@ -917,8 +940,8 @@ isset_variables:
|
||||
;
|
||||
|
||||
class_constant:
|
||||
fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); }
|
||||
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); }
|
||||
fully_qualified_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); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
@ -1198,6 +1198,14 @@ HEREDOC_CHARS ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({
|
||||
return T_REQUIRE_ONCE;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"namespace" {
|
||||
return T_NAMESPACE;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"import" {
|
||||
return T_IMPORT;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"use" {
|
||||
return T_USE;
|
||||
}
|
||||
@ -1543,6 +1551,16 @@ HEREDOC_CHARS ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({
|
||||
return T_FILE;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"__NAMESPACE__" {
|
||||
if (CG(current_namespace)) {
|
||||
*zendlval = *CG(current_namespace);
|
||||
zval_copy_ctor(zendlval);
|
||||
} else {
|
||||
ZVAL_EMPTY_STRING(zendlval);
|
||||
}
|
||||
return T_NS_C;
|
||||
}
|
||||
|
||||
<INITIAL>(([^<]|"<"[^?%s<]){1,400})|"<s"|"<" {
|
||||
#ifdef ZEND_MULTIBYTE
|
||||
if (SCNG(output_filter)) {
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
{
|
||||
switch (zvalue->type & ~IS_CONSTANT_INDEX) {
|
||||
switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_STRING:
|
||||
case IS_CONSTANT:
|
||||
CHECK_ZVAL_STRING_REL(zvalue);
|
||||
@ -73,7 +73,7 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
|
||||
ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
{
|
||||
switch (zvalue->type & ~IS_CONSTANT_INDEX) {
|
||||
switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_STRING:
|
||||
case IS_CONSTANT:
|
||||
CHECK_ZVAL_STRING_REL(zvalue);
|
||||
@ -103,7 +103,7 @@ ZEND_API void zval_add_ref(zval **p)
|
||||
|
||||
ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
{
|
||||
switch (zvalue->type) {
|
||||
switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
|
||||
case IS_RESOURCE: {
|
||||
TSRMLS_FETCH();
|
||||
|
||||
|
@ -1730,7 +1730,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, ANY, CONST|TMP|VAR|UNUSED|CV)
|
||||
ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUSED|CV)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zval *function_name;
|
||||
@ -1738,7 +1738,25 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, ANY, CONST|TMP|VAR|UNUSED|CV)
|
||||
|
||||
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
|
||||
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
if (OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
|
||||
/* try a function in namespace */
|
||||
zend_op *op_data = opline+1;
|
||||
|
||||
ZEND_VM_INC_OPCODE();
|
||||
|
||||
if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==SUCCESS) {
|
||||
EX(object) = NULL;
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
/* no function found. try a static method in class */
|
||||
ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
}
|
||||
if(OP2_TYPE != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
int function_name_strlen;
|
||||
@ -1818,10 +1836,29 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
|
||||
function_name_strlen = function_name->value.str.len;
|
||||
}
|
||||
|
||||
lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
|
||||
if (OP2_TYPE != IS_CONST &&
|
||||
function_name_strval[0] == ':' &&
|
||||
function_name_strval[1] == ':') {
|
||||
|
||||
function_name_strlen -= 2;
|
||||
lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
|
||||
} else {
|
||||
lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
|
||||
}
|
||||
if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
|
||||
efree(lcname);
|
||||
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
|
||||
|
||||
if (OP2_TYPE == IS_CONST && opline->op1.op_type == IS_CONST) {
|
||||
function_name_strlen -= Z_LVAL(opline->op1.u.constant);
|
||||
lcname = zend_str_tolower_dup(function_name_strval + Z_LVAL(opline->op1.u.constant), function_name_strlen);
|
||||
if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE ||
|
||||
function->type != ZEND_INTERNAL_FUNCTION) {
|
||||
efree(lcname);
|
||||
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
|
||||
}
|
||||
} else {
|
||||
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
|
||||
}
|
||||
}
|
||||
|
||||
efree(lcname);
|
||||
@ -2366,7 +2403,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
|
||||
zend_free_op free_res;
|
||||
|
||||
if (zend_ptr_stack_get_arg(arg_num, (void **) ¶m TSRMLS_CC)==FAILURE) {
|
||||
if (Z_TYPE(opline->op2.u.constant) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) {
|
||||
if ((Z_TYPE(opline->op2.u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) {
|
||||
zval *default_value;
|
||||
|
||||
ALLOC_ZVAL(default_value);
|
||||
@ -2582,49 +2619,71 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, CONST|UNUSED, CONST)
|
||||
ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_class_entry *ce = NULL;
|
||||
zval **value;
|
||||
|
||||
if (OP1_TYPE == IS_UNUSED) {
|
||||
/* This seems to be a reminant of namespaces
|
||||
if (EG(scope)) {
|
||||
ce = EG(scope);
|
||||
if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
|
||||
zval_update_constant(value, (void *) 1 TSRMLS_CC);
|
||||
EX_T(opline->result.u.var).tmp_var = **value;
|
||||
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (!zend_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
|
||||
if (!zend_get_constant(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
|
||||
opline->op2.u.constant.value.str.val,
|
||||
opline->op2.u.constant.value.str.val);
|
||||
Z_STRVAL(opline->op2.u.constant),
|
||||
Z_STRVAL(opline->op2.u.constant));
|
||||
EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
|
||||
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
|
||||
zend_class_entry *old_scope = EG(scope);
|
||||
|
||||
EG(scope) = ce;
|
||||
zval_update_constant(value, (void *) 1 TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
EX_T(opline->result.u.var).tmp_var = **value;
|
||||
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
|
||||
} else {
|
||||
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", opline->op2.u.constant.value.str.val);
|
||||
}
|
||||
zend_class_entry *ce;
|
||||
zval **value;
|
||||
|
||||
if (OP1_TYPE == IS_CONST) {
|
||||
zend_op *op_data = opline + 1;
|
||||
zend_constant *c;
|
||||
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
ZEND_VM_INC_OPCODE();
|
||||
|
||||
/* try a constant in namespace */
|
||||
if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
|
||||
EX_T(opline->result.u.var).tmp_var = c->value;
|
||||
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
} else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
|
||||
if (!zend_get_constant(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
|
||||
Z_STRVAL(opline->op2.u.constant),
|
||||
Z_STRVAL(opline->op2.u.constant));
|
||||
EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
|
||||
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
/* no constant found. try a constant in class */
|
||||
ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
|
||||
if (!ce) {
|
||||
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
|
||||
}
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
}
|
||||
|
||||
if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
|
||||
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
|
||||
Z_TYPE_PP(value) == IS_CONSTANT) {
|
||||
zend_class_entry *old_scope = EG(scope);
|
||||
|
||||
EG(scope) = ce;
|
||||
zval_update_constant(value, (void *) 1 TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
}
|
||||
EX_T(opline->result.u.var).tmp_var = **value;
|
||||
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
|
||||
} else {
|
||||
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
|
||||
}
|
||||
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUSED|CV)
|
||||
@ -3846,4 +3905,39 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_free_op free_op1, free_op2;
|
||||
zval *name = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
||||
zval *val = GET_OP2_ZVAL_PTR(BP_VAR_R);
|
||||
zend_constant c;
|
||||
|
||||
if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
|
||||
zval tmp = *val;
|
||||
zval *tmp_ptr = &tmp;
|
||||
|
||||
if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
|
||||
zval_copy_ctor(&tmp);
|
||||
}
|
||||
INIT_PZVAL(&tmp);
|
||||
zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
|
||||
c.value = *tmp_ptr;
|
||||
} else {
|
||||
c.value = *val;
|
||||
zval_copy_ctor(&c.value);
|
||||
}
|
||||
c.flags = CONST_CS; /* non persistent, case sensetive */
|
||||
c.name = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
|
||||
c.name_len = Z_STRLEN_P(name)+1;
|
||||
c.module_number = PHP_USER_CONSTANT;
|
||||
|
||||
if (zend_register_constant(&c TSRMLS_CC) == FAILURE) {
|
||||
}
|
||||
|
||||
FREE_OP1();
|
||||
FREE_OP2();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -141,6 +141,7 @@
|
||||
#define ZEND_DECLARE_INHERITED_CLASS 140
|
||||
#define ZEND_DECLARE_FUNCTION 141
|
||||
#define ZEND_RAISE_ABSTRACT_ERROR 142
|
||||
#define ZEND_DECLARE_CONST 143
|
||||
#define ZEND_ADD_INTERFACE 144
|
||||
#define ZEND_VERIFY_ABSTRACT_CLASS 146
|
||||
#define ZEND_ASSIGN_DIM 147
|
||||
|
Loading…
Reference in New Issue
Block a user