Namespaces

This commit is contained in:
Dmitry Stogov 2007-09-28 19:52:53 +00:00
parent 1674976346
commit f32ffe9b43
72 changed files with 3152 additions and 677 deletions

1
NEWS
View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,6 @@
<?php
class Test {
static function foo() {
echo __CLASS__,"::",__FUNCTION__,"\n";
}
}

19
Zend/tests/ns_022.phpt Executable file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View File

@ -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 */

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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) */

View File

@ -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)

View File

@ -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);

View File

@ -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 {

View File

@ -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;

View File

@ -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); }
;
%%

View File

@ -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)) {

View File

@ -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();

View File

@ -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 **) &param 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

View File

@ -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