Browse Source

Namespaces

PECL
Dmitry Stogov 19 years ago
parent
commit
f32ffe9b43
  1. 1
      NEWS
  2. 34
      Zend/tests/ns_001.phpt
  3. 27
      Zend/tests/ns_002.phpt
  4. 12
      Zend/tests/ns_003.phpt
  5. 9
      Zend/tests/ns_004.phpt
  6. 12
      Zend/tests/ns_005.phpt
  7. 13
      Zend/tests/ns_006.phpt
  8. 13
      Zend/tests/ns_007.phpt
  9. 13
      Zend/tests/ns_008.phpt
  10. 11
      Zend/tests/ns_009.phpt
  11. 49
      Zend/tests/ns_010.phpt
  12. 24
      Zend/tests/ns_011.phpt
  13. 35
      Zend/tests/ns_012.phpt
  14. 13
      Zend/tests/ns_013.phpt
  15. 9
      Zend/tests/ns_014.phpt
  16. 14
      Zend/tests/ns_015.phpt
  17. 14
      Zend/tests/ns_016.phpt
  18. 14
      Zend/tests/ns_017.phpt
  19. 14
      Zend/tests/ns_018.phpt
  20. 12
      Zend/tests/ns_019.phpt
  21. 18
      Zend/tests/ns_020.phpt
  22. 23
      Zend/tests/ns_021.phpt
  23. 6
      Zend/tests/ns_022.inc
  24. 19
      Zend/tests/ns_022.phpt
  25. 11
      Zend/tests/ns_023.phpt
  26. 9
      Zend/tests/ns_024.phpt
  27. 24
      Zend/tests/ns_025.phpt
  28. 30
      Zend/tests/ns_026.phpt
  29. 11
      Zend/tests/ns_027.inc
  30. 24
      Zend/tests/ns_027.phpt
  31. 15
      Zend/tests/ns_028.inc
  32. 26
      Zend/tests/ns_028.phpt
  33. 12
      Zend/tests/ns_029.phpt
  34. 12
      Zend/tests/ns_030.phpt
  35. 21
      Zend/tests/ns_031.phpt
  36. 19
      Zend/tests/ns_032.phpt
  37. 8
      Zend/tests/ns_033.phpt
  38. 38
      Zend/tests/ns_034.phpt
  39. 24
      Zend/tests/ns_035.phpt
  40. 48
      Zend/tests/ns_036.phpt
  41. 49
      Zend/tests/ns_037.phpt
  42. 15
      Zend/tests/ns_038.phpt
  43. 23
      Zend/tests/ns_039.phpt
  44. 68
      Zend/tests/ns_040.phpt
  45. 22
      Zend/tests/ns_041.phpt
  46. 22
      Zend/tests/ns_042.phpt
  47. 11
      Zend/tests/ns_043.phpt
  48. 9
      Zend/tests/ns_044.phpt
  49. 11
      Zend/tests/ns_045.phpt
  50. 11
      Zend/tests/ns_046.phpt
  51. 11
      Zend/tests/ns_047.phpt
  52. 11
      Zend/tests/ns_048.phpt
  53. 9
      Zend/tests/ns_049.phpt
  54. 14
      Zend/tests/ns_050.phpt
  55. 12
      Zend/tests/ns_051.phpt
  56. 14
      Zend/tests/ns_052.phpt
  57. 13
      Zend/tests/ns_053.phpt
  58. 4
      Zend/zend.h
  59. 59
      Zend/zend_API.c
  60. 4
      Zend/zend_builtin_functions.c
  61. 501
      Zend/zend_compile.c
  62. 16
      Zend/zend_compile.h
  63. 189
      Zend/zend_constants.c
  64. 2
      Zend/zend_constants.h
  65. 168
      Zend/zend_execute_API.c
  66. 3
      Zend/zend_globals.h
  67. 53
      Zend/zend_language_parser.y
  68. 18
      Zend/zend_language_scanner.l
  69. 6
      Zend/zend_variables.c
  70. 164
      Zend/zend_vm_def.h
  71. 1637
      Zend/zend_vm_execute.h
  72. 1
      Zend/zend_vm_opcodes.h

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

19
Zend/tests/ns_022.phpt

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4
Zend/zend.h

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

59
Zend/zend_API.c

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

4
Zend/zend_builtin_functions.c

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

501
Zend/zend_compile.c

@ -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);
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
opline->op1 = *class_name;
opline->op2 = *method_name;
zend_op *opline;
ulong fetch_type = 0;
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

16
Zend/zend_compile.h

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

189
Zend/zend_constants.c

@ -213,21 +213,82 @@ 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;
if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
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) {
retval=0;
}
} else {
static char haltoff[] = "__COMPILER_HALT_OFFSET__";
if (!EG(in_execution)) {
retval = 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__ */
zend_mangle_property_name(&haltname, &len, haltoff,
sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) {
retval = 1;
} else {
retval=0;
}
pefree(haltname, 0);
} else {
retval=0;
}
}
efree(lookup_name);
}
if (retval) {
*result = c->value;
zval_copy_ctor(result);
result->refcount = 1;
result->is_ref = 0;
}
return retval;
}
ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope, ulong flags TSRMLS_DC)
{
zend_constant *c;
int retval = 1;
char *colon;
if ((colon = memchr(name, ':', name_len)) && colon[1] == ':') {
/* class constant */
zend_class_entry **ce = NULL;
int class_name_len = colon-name;
/* 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 = colon+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;
char *class_name;
if (!scope) {
if (EG(in_execution)) {
@ -236,42 +297,81 @@ ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_
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 (class_name_len == sizeof("self")-1 &&
!memcmp(lcname, "self", sizeof("self")-1)) {
if (scope) {
ce = &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) {
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 if (!scope->parent) {
zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
} else {
ce = &scope->parent;
ce = scope->parent;
}
efree(lcname);
} else {
if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS) {
retval = 0;
/* 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) {
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);
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);
zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
*result = **ret_constant;
zval_copy_ctor(result);
}
@ -279,52 +379,7 @@ ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_
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);
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) {
retval=0;
}
} else {
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) {
char *cfilename, *haltname;
int len, clen;
cfilename = zend_get_executed_filename(TSRMLS_C);
clen = strlen(cfilename);
/* check for __COMPILER_HALT_OFFSET__ */
zend_mangle_property_name(&haltname, &len, haltoff,
sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) {
retval = 1;
} else {
retval=0;
}
pefree(haltname, 0);
} else {
retval = 0;
}
}
efree(lookup_name);
}
if (retval) {
*result = c->value;
zval_copy_ctor(result);
result->refcount = 1;
result->is_ref = 0;
}
return retval;
}
ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC)
{
return zend_get_constant_ex(name, name_len, result, NULL TSRMLS_CC);
return zend_get_constant(name, name_len, result TSRMLS_CC);
}
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)

2
Zend/zend_constants.h

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

168
Zend/zend_execute_API.c

@ -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;
if (fname[0] == ':' && fname[1] == ':') {
fname += 2;
fname_len -=2;
}
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 {
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;
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);
}
efree(lcname);
}
if (!ce_child) {
zend_error(E_ERROR, "Cannot call method %s() or method does not exist", fname);
return FAILURE;
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;
}
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) {
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);
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;
}
} else {
char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
} else if (calling_scope) {
char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
if (zend_hash_find(fci->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
EX(function_state).function = NULL;
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 {

3
Zend/zend_globals.h

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

53
Zend/zend_language_parser.y

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

18
Zend/zend_language_scanner.l

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

6
Zend/zend_variables.c

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

164
Zend/zend_vm_def.h

@ -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();
}
} else {
zend_class_entry *ce;
zval **value;
if (OP1_TYPE == IS_CONST) {
zend_op *op_data = opline + 1;
zend_constant *c;
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;
}
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);
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'", Z_STRVAL(opline->op2.u.constant));
}
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_VM_NEXT_OPCODE();
}
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)

1637
Zend/zend_vm_execute.h
File diff suppressed because it is too large
View File

1
Zend/zend_vm_opcodes.h

@ -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…
Cancel
Save